]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ExcelAdapter.java
Adopt spreadsheet changes made in Balas development
[simantics/platform.git] / bundles / org.simantics.spreadsheet.ui / src / org / simantics / spreadsheet / ui / ExcelAdapter.java
1 package org.simantics.spreadsheet.ui;
2
3 import java.awt.Toolkit;
4 import java.awt.datatransfer.Clipboard;
5 import java.awt.datatransfer.ClipboardOwner;
6 import java.awt.datatransfer.DataFlavor;
7 import java.awt.datatransfer.StringSelection;
8 import java.awt.datatransfer.Transferable;
9 import java.awt.datatransfer.UnsupportedFlavorException;
10 import java.awt.event.ActionEvent;
11 import java.awt.event.ActionListener;
12 import java.awt.event.KeyEvent;
13 import java.io.IOException;
14 import java.util.ArrayList;
15 import java.util.regex.Pattern;
16
17 import javax.swing.JComponent;
18 import javax.swing.JOptionPane;
19 import javax.swing.JTable;
20 import javax.swing.KeyStroke;
21
22 import org.simantics.databoard.Bindings;
23 import org.simantics.databoard.binding.mutable.MutableVariant;
24 import org.simantics.databoard.binding.mutable.Variant;
25 import org.simantics.spreadsheet.Adaptable;
26 import org.simantics.spreadsheet.CellEditor;
27 import org.simantics.spreadsheet.ClientModel;
28 import org.simantics.spreadsheet.OperationMode;
29 import org.simantics.spreadsheet.Range;
30 import org.simantics.spreadsheet.Spreadsheets;
31 import org.simantics.spreadsheet.Transaction;
32 import org.simantics.spreadsheet.common.cell.StringCellParser;
33 import org.simantics.spreadsheet.util.SpreadsheetUtils;
34 import org.simantics.utils.threads.logger.ITask;
35 import org.simantics.utils.threads.logger.ThreadLogger;
36
37 /**
38  * ExcelAdapter enables Copy-Paste Clipboard functionality on JTables.
39  * The clipboard data format used by the adapter is compatible with
40  * the clipboard format used by Excel. This provides for clipboard
41  * interoperability between enabled JTables and Excel.
42  */
43 public class ExcelAdapter implements ActionListener {
44
45         final private JTable table;
46         final private ClientModel model;
47         //final private SheetManipulator manager;
48         final private CellEditor editor;
49         final static private Pattern newline = Pattern.compile("\n");
50         final static private Pattern tab = Pattern.compile("\t");
51         final private StringCellParser[] parsers;
52
53 //      public boolean ownClipboard = false;
54         private Object clipboard = null;
55         private ClipboardOwner clipboardOwner = null;
56         private String rowstring, value;
57
58         public ExcelAdapter(JTable table, ClientModel model, Adaptable serverInterface, StringCellParser[] parsers) {
59
60                 this.table = table;
61                 this.model = model;
62                 //this.manager = serverInterface.getAdapter(SheetManipulator.class);
63                 this.editor = serverInterface.getAdapter(CellEditor.class);
64                 this.parsers = parsers;
65
66                 //            system = Toolkit.getDefaultToolkit().getSystemClipboard();
67
68                 KeyStroke copy = KeyStroke.getKeyStroke(KeyEvent.VK_C,ActionEvent.CTRL_MASK,false);
69                 // Identifying the copy KeyStroke user can modify this
70                 // to copy on some other Key combination.
71                 KeyStroke paste = KeyStroke.getKeyStroke(KeyEvent.VK_V,ActionEvent.CTRL_MASK,false);
72                 // Identifying the Paste KeyStroke user can modify this
73                 //to copy on some other Key combination.
74                 table.registerKeyboardAction(this,"Copy",copy,JComponent.WHEN_FOCUSED);
75                 table.registerKeyboardAction(this,"Paste",paste,JComponent.WHEN_FOCUSED);
76
77         }
78         //              /**
79         //               * Public Accessor methods for the Table on which this adapter acts.
80         //               */
81         //              public JTable getJTable() {return jTable1;}
82         //              public void setJTable(JTable jTable1) {this.jTable1=jTable1;}
83         /**
84          * This method is activated on the Keystrokes we are listening to
85          * in this implementation. Here it listens for Copy and Paste ActionCommands.
86          * Selections comprising non-adjacent cells result in invalid selection and
87          * then copy action cannot be performed.
88          * Paste is done by aligning the upper left corner of the selection with the
89          * 1st element in the current selection of the JTable.
90          */
91         public void actionPerformed(ActionEvent e)
92         {
93
94                 Clipboard system = Toolkit.getDefaultToolkit().getSystemClipboard();
95
96                 if (e.getActionCommand().compareTo("Copy")==0)
97                 {
98
99                         // Check to ensure we have selected only a contiguous block of
100                         // cells
101                         int numcols=table.getSelectedColumnCount();
102                         int numrows=table.getSelectedRowCount();
103                         if (numcols == 0 || numrows == 0)
104                                 return;
105
106                         int[] rowsselected=table.getSelectedRows();
107                         int[] colsselected=table.getSelectedColumns();
108                         if (!((numrows-1==rowsselected[rowsselected.length-1]-rowsselected[0] &&
109                                         numrows==rowsselected.length) &&
110                                         (numcols-1==colsselected[colsselected.length-1]-colsselected[0] &&
111                                         numcols==colsselected.length)))
112                         {
113                                 JOptionPane.showMessageDialog(null, "Invalid Copy Selection",
114                                                 "Invalid Copy Selection",
115                                                 JOptionPane.ERROR_MESSAGE);
116                                 return;
117                         }
118
119                         Object[] rows = new Object[numrows];
120                         for (int i=0;i<numrows;i++)     {
121                                 Object[] cols = new Object[numcols];
122                                 rows[i] = cols;
123                                 for (int j=0;j<numcols;j++)     {
124                                         cols[j] = SpreadsheetUtils.getLabel(model, rowsselected[i],colsselected[j]);
125                                 }
126                         }
127
128                         StringBuilder builder = new StringBuilder();
129                         for(int i=0;i<rows.length;i++) {
130                                 Object[] cols = (Object[])rows[i];
131                                 for(int j=0;j<cols.length;j++) {
132                                         if(j>0) builder.append("\t");
133                                         Object value=(Object)cols[j];
134                                         if(value != null) {
135                                                 builder.append(value.toString());
136                                         }
137                                 }
138                                 builder.append("\n");
139                         }
140                         
141                         clipboard = new Range(rowsselected[0],rowsselected[0]+numrows-1,colsselected[0],colsselected[0]+numcols-1);
142                         clipboardOwner = new ClipboardOwner() {
143                                 
144                                 @Override
145                                 public void lostOwnership(Clipboard arg0, Transferable arg1) {
146                                         if(clipboardOwner == this) {
147                                                 clipboardOwner = null;
148                                                 clipboard = null;
149                                         }
150                                 }
151                                 
152                         };
153
154                         system.setContents(new StringSelection(builder.toString()), clipboardOwner);
155
156                 }
157                 if (e.getActionCommand().compareTo("Paste")==0)
158                 {
159                         int[] selectedRows = table.getSelectedRows();
160                         int[] selectedColumns = table.getSelectedColumns();
161                         if (selectedRows.length == 0 || selectedColumns.length == 0)
162                                 return;
163                         int startRow = selectedRows[0];
164                         int startCol = selectedColumns[0];
165
166                         if(clipboardOwner == null) {
167                                 
168                                 //if(manager == null) return;
169                                 if(editor == null) return;
170
171                                 String trstring = null;
172                                 try {
173                                         trstring = (String)(system.getContents(this).getTransferData(DataFlavor.stringFlavor));
174                                 } catch (UnsupportedFlavorException e1) {
175                                         e1.printStackTrace();
176                                 } catch (IOException e1) {
177                                         e1.printStackTrace();
178                                 }
179
180                                 if(trstring == null || trstring.isEmpty()) return;
181
182                                 ITask task = ThreadLogger.getInstance().begin("Spreadsheet.paste");
183
184                                 /*
185                                  * Analyse the target area. No computed cells are allowed. Collect cells to remove.
186                                  */
187
188                                 ArrayList<String> removals = new ArrayList<String>();
189                                 
190                                 String[] rows = newline.split(trstring);
191                                 for(int i=0;i<rows.length;i++) {
192                                         String[] cols = tab.split(rows[i]);
193                                         for(int j=0;j<cols.length;j++) {
194                                                 value=cols[j];
195                                                 if (value.length() > 0 && startRow+i< table.getRowCount()  &&
196                                                                 startCol+j< table.getColumnCount()) {
197
198                                                         CellValue cell = (CellValue)table.getValueAt(startRow+i, startCol+j);
199                                                         if(cell.label != null) {
200                                                                 String location = Spreadsheets.cellName(startRow+i, startCol+j);
201                                                                 Boolean computed = model.getPropertyAt(location, ClientModel.COMPUTED);
202                                                                 if(computed != null && computed) return;
203                                                                 removals.add(location);
204                                                         }
205
206                                                 }
207                                         }
208                                 }
209                                 
210                                 /*
211                                  * Create the cell data
212                                  * 
213                                  */
214
215                                 Transaction tr = editor.startTransaction(OperationMode.OPERATION);
216                                 
217                                 for(int i=0;i<rows.length;i++) {
218                                         String[] cols = tab.split(rows[i]);
219                                         for(int j=0;j<cols.length;j++) {
220                                                 value=cols[j];
221                                                 if (value.length() > 0 && startRow+i< table.getRowCount()  &&
222                                                                 startCol+j< table.getColumnCount()) {
223
224                                                         if (value.startsWith("=")) {
225                                                                 editor.edit(tr, Spreadsheets.cellName(startRow+i, startCol+j), ClientModel.CONTENT_EXPRESSION, value, Bindings.STRING, null);
226                                                         } else {
227                                                                 editor.edit(tr, Spreadsheets.cellName(startRow+i, startCol+j), Variant.ofInstance(value), null);
228                                                         }
229
230                                                 }
231                                         }
232                                 }
233                                 
234                                 tr.commit();
235
236                                 task.finish();
237
238                         } else {
239
240                                 Range from = (Range)clipboard;
241                                 Range to = new Range(startRow, startRow+from.height()-1, startCol, startCol+from.width()-1);
242                                 
243                                 Transaction tr = editor.startTransaction(OperationMode.OPERATION);
244
245                                 for(int i=0;i<from.height();i++) {
246                                         for(int j=0;j<from.width();j++) {
247                                                 String fromCell = Spreadsheets.cellName(from.startRow+i, from.startColumn+j);
248                                                 String toCell = Spreadsheets.cellName(to.startRow+i, to.startColumn+j);
249                                                 Object obj = model.getPropertyAt(fromCell, "content");
250                                                 if (obj == null)
251                                                     continue;
252                                                 MutableVariant variant = SpreadsheetUtils.createVariant();
253                                                 System.out.println("asdasd fromCell toCell " + fromCell + " " + toCell);
254                                                 editor.copy(tr, fromCell, variant, null);
255                                                 editor.edit(tr, toCell, variant, null);
256                                         }
257                                 }
258                                 
259                                 tr.commit();                            
260
261                         }
262                 }
263         }
264 }