1 package org.simantics.spreadsheet.ui;
\r
3 import java.awt.Toolkit;
\r
4 import java.awt.datatransfer.Clipboard;
\r
5 import java.awt.datatransfer.ClipboardOwner;
\r
6 import java.awt.datatransfer.DataFlavor;
\r
7 import java.awt.datatransfer.StringSelection;
\r
8 import java.awt.datatransfer.Transferable;
\r
9 import java.awt.datatransfer.UnsupportedFlavorException;
\r
10 import java.awt.event.ActionEvent;
\r
11 import java.awt.event.ActionListener;
\r
12 import java.awt.event.KeyEvent;
\r
13 import java.io.IOException;
\r
14 import java.util.ArrayList;
\r
15 import java.util.regex.Pattern;
\r
17 import javax.swing.JComponent;
\r
18 import javax.swing.JOptionPane;
\r
19 import javax.swing.JTable;
\r
20 import javax.swing.KeyStroke;
\r
22 import org.simantics.databoard.Bindings;
\r
23 import org.simantics.databoard.binding.mutable.MutableVariant;
\r
24 import org.simantics.databoard.binding.mutable.Variant;
\r
25 import org.simantics.spreadsheet.Adaptable;
\r
26 import org.simantics.spreadsheet.CellEditor;
\r
27 import org.simantics.spreadsheet.CellEditor.Transaction;
\r
28 import org.simantics.spreadsheet.ClientModel.OperationMode;
\r
29 import org.simantics.spreadsheet.ClientModel;
\r
30 import org.simantics.spreadsheet.Range;
\r
31 import org.simantics.spreadsheet.common.cell.StringCellParser;
\r
32 import org.simantics.spreadsheet.util.SpreadsheetUtils;
\r
33 import org.simantics.utils.threads.logger.ITask;
\r
34 import org.simantics.utils.threads.logger.ThreadLogger;
\r
37 * ExcelAdapter enables Copy-Paste Clipboard functionality on JTables.
\r
38 * The clipboard data format used by the adapter is compatible with
\r
39 * the clipboard format used by Excel. This provides for clipboard
\r
40 * interoperability between enabled JTables and Excel.
\r
42 public class ExcelAdapter implements ActionListener {
\r
44 final private JTable table;
\r
45 final private ClientModel model;
\r
46 //final private SheetManipulator manager;
\r
47 final private CellEditor editor;
\r
48 final static private Pattern newline = Pattern.compile("\n");
\r
49 final static private Pattern tab = Pattern.compile("\t");
\r
50 final private StringCellParser[] parsers;
\r
52 // public boolean ownClipboard = false;
\r
53 private Object clipboard = null;
\r
54 private ClipboardOwner clipboardOwner = null;
\r
55 private String rowstring, value;
\r
57 public ExcelAdapter(JTable table, ClientModel model, Adaptable serverInterface, StringCellParser[] parsers) {
\r
61 //this.manager = serverInterface.getAdapter(SheetManipulator.class);
\r
62 this.editor = serverInterface.getAdapter(CellEditor.class);
\r
63 this.parsers = parsers;
\r
65 // system = Toolkit.getDefaultToolkit().getSystemClipboard();
\r
67 KeyStroke copy = KeyStroke.getKeyStroke(KeyEvent.VK_C,ActionEvent.CTRL_MASK,false);
\r
68 // Identifying the copy KeyStroke user can modify this
\r
69 // to copy on some other Key combination.
\r
70 KeyStroke paste = KeyStroke.getKeyStroke(KeyEvent.VK_V,ActionEvent.CTRL_MASK,false);
\r
71 // Identifying the Paste KeyStroke user can modify this
\r
72 //to copy on some other Key combination.
\r
73 table.registerKeyboardAction(this,"Copy",copy,JComponent.WHEN_FOCUSED);
\r
74 table.registerKeyboardAction(this,"Paste",paste,JComponent.WHEN_FOCUSED);
\r
78 // * Public Accessor methods for the Table on which this adapter acts.
\r
80 // public JTable getJTable() {return jTable1;}
\r
81 // public void setJTable(JTable jTable1) {this.jTable1=jTable1;}
\r
83 * This method is activated on the Keystrokes we are listening to
\r
84 * in this implementation. Here it listens for Copy and Paste ActionCommands.
\r
85 * Selections comprising non-adjacent cells result in invalid selection and
\r
86 * then copy action cannot be performed.
\r
87 * Paste is done by aligning the upper left corner of the selection with the
\r
88 * 1st element in the current selection of the JTable.
\r
90 public void actionPerformed(ActionEvent e)
\r
93 Clipboard system = Toolkit.getDefaultToolkit().getSystemClipboard();
\r
95 if (e.getActionCommand().compareTo("Copy")==0)
\r
98 // Check to ensure we have selected only a contiguous block of
\r
100 int numcols=table.getSelectedColumnCount();
\r
101 int numrows=table.getSelectedRowCount();
\r
102 if (numcols == 0 || numrows == 0)
\r
105 int[] rowsselected=table.getSelectedRows();
\r
106 int[] colsselected=table.getSelectedColumns();
\r
107 if (!((numrows-1==rowsselected[rowsselected.length-1]-rowsselected[0] &&
\r
108 numrows==rowsselected.length) &&
\r
109 (numcols-1==colsselected[colsselected.length-1]-colsselected[0] &&
\r
110 numcols==colsselected.length)))
\r
112 JOptionPane.showMessageDialog(null, "Invalid Copy Selection",
\r
113 "Invalid Copy Selection",
\r
114 JOptionPane.ERROR_MESSAGE);
\r
118 Object[] rows = new Object[numrows];
\r
119 for (int i=0;i<numrows;i++) {
\r
120 Object[] cols = new Object[numcols];
\r
122 for (int j=0;j<numcols;j++) {
\r
123 cols[j] = SpreadsheetUtils.getLabel(model, rowsselected[i],colsselected[j]);
\r
127 StringBuilder builder = new StringBuilder();
\r
128 for(int i=0;i<rows.length;i++) {
\r
129 Object[] cols = (Object[])rows[i];
\r
130 for(int j=0;j<cols.length;j++) {
\r
131 if(j>0) builder.append("\t");
\r
132 Object value=(Object)cols[j];
\r
133 if(value != null) {
\r
134 builder.append(value.toString());
\r
137 builder.append("\n");
\r
140 clipboard = new Range(rowsselected[0],rowsselected[0]+numrows-1,colsselected[0],colsselected[0]+numcols-1);
\r
141 clipboardOwner = new ClipboardOwner() {
\r
144 public void lostOwnership(Clipboard arg0, Transferable arg1) {
\r
145 if(clipboardOwner == this) {
\r
146 clipboardOwner = null;
\r
153 system.setContents(new StringSelection(builder.toString()), clipboardOwner);
\r
156 if (e.getActionCommand().compareTo("Paste")==0)
\r
158 int[] selectedRows = table.getSelectedRows();
\r
159 int[] selectedColumns = table.getSelectedColumns();
\r
160 if (selectedRows.length == 0 || selectedColumns.length == 0)
\r
162 int startRow = selectedRows[0];
\r
163 int startCol = selectedColumns[0];
\r
165 if(clipboardOwner == null) {
\r
167 //if(manager == null) return;
\r
168 if(editor == null) return;
\r
170 String trstring = null;
\r
172 trstring = (String)(system.getContents(this).getTransferData(DataFlavor.stringFlavor));
\r
173 } catch (UnsupportedFlavorException e1) {
\r
174 e1.printStackTrace();
\r
175 } catch (IOException e1) {
\r
176 e1.printStackTrace();
\r
179 if(trstring == null || trstring.isEmpty()) return;
\r
181 ITask task = ThreadLogger.getInstance().begin("Spreadsheet.paste");
\r
184 * Analyse the target area. No computed cells are allowed. Collect cells to remove.
\r
187 ArrayList<String> removals = new ArrayList<String>();
\r
189 String[] rows = newline.split(trstring);
\r
190 for(int i=0;i<rows.length;i++) {
\r
191 String[] cols = tab.split(rows[i]);
\r
192 for(int j=0;j<cols.length;j++) {
\r
194 if (value.length() > 0 && startRow+i< table.getRowCount() &&
\r
195 startCol+j< table.getColumnCount()) {
\r
197 CellValue cell = (CellValue)table.getValueAt(startRow+i, startCol+j);
\r
198 if(cell.label != null) {
\r
199 String location = SpreadsheetUtils.cellName(startRow+i, startCol+j);
\r
200 Boolean computed = model.getPropertyAt(location, ClientModel.COMPUTED);
\r
201 if(computed != null && computed) return;
\r
202 removals.add(location);
\r
210 * Create the cell data
\r
214 Transaction tr = editor.startTransaction(OperationMode.OPERATION);
\r
216 for(int i=0;i<rows.length;i++) {
\r
217 String[] cols = tab.split(rows[i]);
\r
218 for(int j=0;j<cols.length;j++) {
\r
220 if (value.length() > 0 && startRow+i< table.getRowCount() &&
\r
221 startCol+j< table.getColumnCount()) {
\r
223 if (value.startsWith("=")) {
\r
224 editor.edit(tr, SpreadsheetUtils.cellName(startRow+i, startCol+j), ClientModel.CONTENT_EXPRESSION, value, Bindings.STRING, null);
\r
226 editor.edit(tr, SpreadsheetUtils.cellName(startRow+i, startCol+j), Variant.ofInstance(value), null);
\r
239 Range from = (Range)clipboard;
\r
240 Range to = new Range(startRow, startRow+from.height()-1, startCol, startCol+from.width()-1);
\r
242 Transaction tr = editor.startTransaction(OperationMode.OPERATION);
\r
244 for(int i=0;i<from.height();i++) {
\r
245 for(int j=0;j<from.width();j++) {
\r
246 String fromCell = SpreadsheetUtils.cellName(from.startRow+i, from.startColumn+j);
\r
247 String toCell = SpreadsheetUtils.cellName(to.startRow+i, to.startColumn+j);
\r
248 Object obj = model.getPropertyAt(fromCell, "content");
\r
251 MutableVariant variant = SpreadsheetUtils.createVariant();
\r
252 System.out.println("asdasd fromCell toCell " + fromCell + " " + toCell);
\r
253 editor.copy(tr, fromCell, variant, null);
\r
254 editor.edit(tr, toCell, variant, null);
\r