]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ExcelAdapter.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.spreadsheet.ui / src / org / simantics / spreadsheet / ui / ExcelAdapter.java
1 package org.simantics.spreadsheet.ui;\r
2 \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
16 \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
21 \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
35 \r
36 /**\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
41  */\r
42 public class ExcelAdapter implements ActionListener {\r
43 \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
51 \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
56 \r
57         public ExcelAdapter(JTable table, ClientModel model, Adaptable serverInterface, StringCellParser[] parsers) {\r
58 \r
59                 this.table = table;\r
60                 this.model = model;\r
61                 //this.manager = serverInterface.getAdapter(SheetManipulator.class);\r
62                 this.editor = serverInterface.getAdapter(CellEditor.class);\r
63                 this.parsers = parsers;\r
64 \r
65                 //            system = Toolkit.getDefaultToolkit().getSystemClipboard();\r
66 \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
75 \r
76         }\r
77         //              /**\r
78         //               * Public Accessor methods for the Table on which this adapter acts.\r
79         //               */\r
80         //              public JTable getJTable() {return jTable1;}\r
81         //              public void setJTable(JTable jTable1) {this.jTable1=jTable1;}\r
82         /**\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
89          */\r
90         public void actionPerformed(ActionEvent e)\r
91         {\r
92 \r
93                 Clipboard system = Toolkit.getDefaultToolkit().getSystemClipboard();\r
94 \r
95                 if (e.getActionCommand().compareTo("Copy")==0)\r
96                 {\r
97 \r
98                         // Check to ensure we have selected only a contiguous block of\r
99                         // cells\r
100                         int numcols=table.getSelectedColumnCount();\r
101                         int numrows=table.getSelectedRowCount();\r
102                         if (numcols == 0 || numrows == 0)\r
103                                 return;\r
104 \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
111                         {\r
112                                 JOptionPane.showMessageDialog(null, "Invalid Copy Selection",\r
113                                                 "Invalid Copy Selection",\r
114                                                 JOptionPane.ERROR_MESSAGE);\r
115                                 return;\r
116                         }\r
117 \r
118                         Object[] rows = new Object[numrows];\r
119                         for (int i=0;i<numrows;i++)     {\r
120                                 Object[] cols = new Object[numcols];\r
121                                 rows[i] = cols;\r
122                                 for (int j=0;j<numcols;j++)     {\r
123                                         cols[j] = SpreadsheetUtils.getLabel(model, rowsselected[i],colsselected[j]);\r
124                                 }\r
125                         }\r
126 \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
135                                         }\r
136                                 }\r
137                                 builder.append("\n");\r
138                         }\r
139                         \r
140                         clipboard = new Range(rowsselected[0],rowsselected[0]+numrows-1,colsselected[0],colsselected[0]+numcols-1);\r
141                         clipboardOwner = new ClipboardOwner() {\r
142                                 \r
143                                 @Override\r
144                                 public void lostOwnership(Clipboard arg0, Transferable arg1) {\r
145                                         if(clipboardOwner == this) {\r
146                                                 clipboardOwner = null;\r
147                                                 clipboard = null;\r
148                                         }\r
149                                 }\r
150                                 \r
151                         };\r
152 \r
153                         system.setContents(new StringSelection(builder.toString()), clipboardOwner);\r
154 \r
155                 }\r
156                 if (e.getActionCommand().compareTo("Paste")==0)\r
157                 {\r
158                         int[] selectedRows = table.getSelectedRows();\r
159                         int[] selectedColumns = table.getSelectedColumns();\r
160                         if (selectedRows.length == 0 || selectedColumns.length == 0)\r
161                                 return;\r
162                         int startRow = selectedRows[0];\r
163                         int startCol = selectedColumns[0];\r
164 \r
165                         if(clipboardOwner == null) {\r
166                                 \r
167                                 //if(manager == null) return;\r
168                                 if(editor == null) return;\r
169 \r
170                                 String trstring = null;\r
171                                 try {\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
177                                 }\r
178 \r
179                                 if(trstring == null || trstring.isEmpty()) return;\r
180 \r
181                                 ITask task = ThreadLogger.getInstance().begin("Spreadsheet.paste");\r
182 \r
183                                 /*\r
184                                  * Analyse the target area. No computed cells are allowed. Collect cells to remove.\r
185                                  */\r
186 \r
187                                 ArrayList<String> removals = new ArrayList<String>();\r
188                                 \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
193                                                 value=cols[j];\r
194                                                 if (value.length() > 0 && startRow+i< table.getRowCount()  &&\r
195                                                                 startCol+j< table.getColumnCount()) {\r
196 \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
203                                                         }\r
204 \r
205                                                 }\r
206                                         }\r
207                                 }\r
208                                 \r
209                                 /*\r
210                                  * Create the cell data\r
211                                  * \r
212                                  */\r
213 \r
214                                 Transaction tr = editor.startTransaction(OperationMode.OPERATION);\r
215                                 \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
219                                                 value=cols[j];\r
220                                                 if (value.length() > 0 && startRow+i< table.getRowCount()  &&\r
221                                                                 startCol+j< table.getColumnCount()) {\r
222 \r
223                                                         if (value.startsWith("=")) {\r
224                                                                 editor.edit(tr, SpreadsheetUtils.cellName(startRow+i, startCol+j), ClientModel.CONTENT_EXPRESSION, value, Bindings.STRING, null);\r
225                                                         } else {\r
226                                                                 editor.edit(tr, SpreadsheetUtils.cellName(startRow+i, startCol+j), Variant.ofInstance(value), null);\r
227                                                         }\r
228 \r
229                                                 }\r
230                                         }\r
231                                 }\r
232                                 \r
233                                 tr.commit();\r
234 \r
235                                 task.finish();\r
236 \r
237                         } else {\r
238 \r
239                                 Range from = (Range)clipboard;\r
240                                 Range to = new Range(startRow, startRow+from.height()-1, startCol, startCol+from.width()-1);\r
241                                 \r
242                                 Transaction tr = editor.startTransaction(OperationMode.OPERATION);\r
243 \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
249                                                 if (obj == null)\r
250                                                     continue;\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
255                                         }\r
256                                 }\r
257                                 \r
258                                 tr.commit();                            \r
259 \r
260                         }\r
261                 }\r
262         }\r
263 }