]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/SpreadsheetModel.java
Added some enforcement of immutability to structural user component UI's.
[simantics/platform.git] / bundles / org.simantics.spreadsheet.ui / src / org / simantics / spreadsheet / ui / SpreadsheetModel.java
1 package org.simantics.spreadsheet.ui;\r
2 \r
3 import java.awt.BorderLayout;\r
4 import java.awt.Color;\r
5 import java.awt.Font;\r
6 import java.awt.Frame;\r
7 import java.awt.GridBagConstraints;\r
8 import java.awt.GridBagLayout;\r
9 import java.awt.Image;\r
10 import java.awt.Rectangle;\r
11 import java.awt.datatransfer.Clipboard;\r
12 import java.awt.datatransfer.Transferable;\r
13 import java.awt.datatransfer.UnsupportedFlavorException;\r
14 import java.awt.dnd.DnDConstants;\r
15 import java.awt.dnd.DropTarget;\r
16 import java.awt.dnd.DropTargetDragEvent;\r
17 import java.awt.dnd.DropTargetDropEvent;\r
18 import java.awt.dnd.DropTargetEvent;\r
19 import java.awt.dnd.DropTargetListener;\r
20 import java.awt.event.ActionEvent;\r
21 import java.awt.event.ActionListener;\r
22 import java.awt.event.ItemEvent;\r
23 import java.awt.event.ItemListener;\r
24 import java.awt.event.KeyEvent;\r
25 import java.io.IOException;\r
26 import java.util.Arrays;\r
27 import java.util.HashMap;\r
28 import java.util.Iterator;\r
29 import java.util.List;\r
30 import java.util.Map;\r
31 import java.util.Properties;\r
32 \r
33 import javax.imageio.ImageIO;\r
34 import javax.swing.AbstractAction;\r
35 import javax.swing.Action;\r
36 import javax.swing.DefaultListModel;\r
37 import javax.swing.ImageIcon;\r
38 import javax.swing.InputMap;\r
39 import javax.swing.JButton;\r
40 import javax.swing.JCheckBox;\r
41 import javax.swing.JColorChooser;\r
42 import javax.swing.JComboBox;\r
43 import javax.swing.JComponent;\r
44 import javax.swing.JList;\r
45 import javax.swing.JOptionPane;\r
46 import javax.swing.JPanel;\r
47 import javax.swing.JTable;\r
48 import javax.swing.JTextField;\r
49 import javax.swing.JToggleButton;\r
50 import javax.swing.KeyStroke;\r
51 import javax.swing.SwingUtilities;\r
52 import javax.swing.UIManager;\r
53 import javax.swing.event.ChangeEvent;\r
54 import javax.swing.event.ListSelectionEvent;\r
55 import javax.swing.event.TableColumnModelEvent;\r
56 import javax.swing.event.TableColumnModelListener;\r
57 import javax.swing.event.TableModelEvent;\r
58 import javax.swing.event.TableModelListener;\r
59 import javax.swing.table.TableColumn;\r
60 \r
61 import org.eclipse.core.runtime.Platform;\r
62 import org.eclipse.swt.widgets.Display;\r
63 import org.simantics.databoard.Bindings;\r
64 import org.simantics.databoard.binding.Binding;\r
65 import org.simantics.datatypes.literal.RGB;\r
66 import org.simantics.scenegraph.INode;\r
67 import org.simantics.scenegraph.swing.JScrollPaneSG;\r
68 import org.simantics.spreadsheet.Adaptable;\r
69 import org.simantics.spreadsheet.CellEditor;\r
70 import org.simantics.spreadsheet.CellEditor.Transaction;\r
71 import org.simantics.spreadsheet.ClientModel;\r
72 import org.simantics.spreadsheet.ClientModel.OperationMode;\r
73 import org.simantics.spreadsheet.SheetCommands;\r
74 import org.simantics.spreadsheet.common.cell.Parsers;\r
75 import org.simantics.spreadsheet.common.cell.StringCellParser;\r
76 import org.simantics.spreadsheet.event.model.RemoveCellHandler;\r
77 import org.simantics.spreadsheet.util.SpreadsheetUtils;\r
78 import org.simantics.ui.colors.Colors;\r
79 import org.simantics.ui.dnd.LocalObjectTransfer;\r
80 import org.simantics.ui.dnd.LocalObjectTransferable;\r
81 import org.simantics.ui.fonts.Fonts;\r
82 import org.simantics.utils.ui.dialogs.ShowMessage;\r
83 import org.simantics.utils.ui.jface.ActiveSelectionProvider;\r
84 \r
85 @SuppressWarnings({ "rawtypes", "unchecked" })\r
86 public class SpreadsheetModel {\r
87 \r
88         final private Adaptable serverInterface;\r
89         final private ClientModel clientModel;\r
90         final private ActiveSelectionProvider selectionProvider;\r
91         protected Clipboard system;\r
92         protected StringCellParser[] parsers =  new StringCellParser[] { Parsers.COMMAND_PARSER, Parsers.EXPRESSION_PARSER, Parsers.TEXT_PARSER };\r
93 \r
94         public SpreadsheetModel(Adaptable serverInterface, ActiveSelectionProvider selectionProvider) {\r
95 \r
96                 this.serverInterface = serverInterface;\r
97                 this.clientModel = new ClientModelImpl();\r
98                 this.selectionProvider = selectionProvider;\r
99 \r
100         }\r
101 \r
102         public ClientModel getClientModel() {\r
103                 return clientModel;\r
104         }\r
105 \r
106         public SpreadsheetTable getTable() {\r
107                 return table;\r
108         }\r
109 \r
110         private JTextField expression;\r
111         private JButton foreground;\r
112         private JButton background;\r
113         private JButton font;\r
114         private JButton align_left;\r
115         private JButton align_hcenter;\r
116         private JButton align_right;\r
117         private JButton align_top;\r
118         private JButton align_vcenter;\r
119         private JButton align_bottom;\r
120         private JComboBox borders;\r
121         public JComboBox inputSource;\r
122         public JComboBox sheets;\r
123         private JButton lock;\r
124         private JButton unlock;\r
125         private JButton merge;\r
126         private JButton unmerge;\r
127         private ExpressionTextListener etl;\r
128         private SpreadsheetTable table;\r
129         @SuppressWarnings("unused")\r
130         private ExcelAdapter excel;\r
131         @SuppressWarnings("unused")\r
132         private boolean columnMarginsDirty = false;\r
133         \r
134         private ItemListener itemListener = null;\r
135         private ItemListener sheetsListener = null;\r
136         private ItemListener initialConditionsListener = null;\r
137         \r
138         private JComboBox initialConditions;\r
139     private JButton saveIc;\r
140     private JButton context;\r
141     private JToggleButton operationMode;\r
142     \r
143     private JCheckBox iterationEnabled;\r
144     private JTextField iterationLimit;\r
145 \r
146         public JComponent createComponent(final INode node) {\r
147 \r
148                 Properties props = serverInterface.getAdapter(Properties.class);\r
149                 \r
150                 boolean addExpressionField = props == null || "true".equalsIgnoreCase(props.getProperty(SpreadsheetModelProperties.SHEET_EXPRESSION_VISIBLE, "true"));\r
151 \r
152                 final JPanel panel = new JPanel(new BorderLayout());\r
153                 \r
154                 final DefaultListModel lm = new DefaultListModel() {\r
155 \r
156                         private static final long serialVersionUID = 5246691801867533053L;\r
157 \r
158                         public Object getElementAt(int index) {\r
159                                 Object result = super.getElementAt(index);\r
160                                 if(result instanceof String) return result; \r
161                                 else return "" + (index + 1);\r
162                         }\r
163 \r
164                 };\r
165 \r
166                 if (addExpressionField) {\r
167                         \r
168                         foreground = new JButton();\r
169                         foreground.setToolTipText("Assign foreground color to selection");\r
170                         \r
171                         try {\r
172                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/paintbrush.png"));\r
173                                 foreground.setIcon(new ImageIcon(img));\r
174                         } catch (IOException ex) {\r
175                         }\r
176                         foreground.addActionListener(new ActionListener() {\r
177                                 @Override\r
178                                 public void actionPerformed(ActionEvent e) {\r
179                                         \r
180                                         Color c = JColorChooser.showDialog(foreground, "asd", Colors.awt(Colors.rgb(0, 0, 0)));\r
181                                         if (c == null)\r
182                                             return;\r
183                                         RGB.Integer color = Colors.integerRGB(c);\r
184 \r
185                                         editSelection(ClientModel.FOREGROUND, color, RGB.Integer.BINDING);\r
186                                 }\r
187                         });\r
188 \r
189                         background = new JButton();\r
190                         background.setToolTipText("Assign background color to selection");\r
191                         \r
192                         try {\r
193                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/paintcan.png"));\r
194                                 background.setIcon(new ImageIcon(img));\r
195                         } catch (IOException ex) {\r
196                         }\r
197                         \r
198                         background.addActionListener(new ActionListener() {\r
199                                 @Override\r
200                                 public void actionPerformed(ActionEvent e) {\r
201                                         \r
202                                         Color c = JColorChooser.showDialog(background, "asd", Colors.awt(Colors.rgb(0, 0, 0)));\r
203                                         if (c == null)\r
204                                             return;\r
205 \r
206                                         RGB.Integer color = Colors.integerRGB(c);\r
207 \r
208                                         editSelection(ClientModel.BACKGROUND, color, RGB.Integer.BINDING);\r
209                                 }\r
210                         });\r
211                         \r
212                         String[] availableInitialConditions = clientModel.getPossiblePropertyAt(ClientModel.STATES, ClientModel.STATES_AVAILABLE);\r
213                         String currentInitialCondition = clientModel.getPossiblePropertyAt(ClientModel.STATES, ClientModel.STATES_CURRENT);\r
214                         \r
215                         initialConditions = new JComboBox<>();\r
216                         for(String sheet : availableInitialConditions)\r
217                             initialConditions.addItem(sheet);\r
218                         \r
219                         initialConditions.setSelectedItem(currentInitialCondition);\r
220                         \r
221                         initialConditionsListener = new ItemListener() {\r
222                             @Override\r
223                 public void itemStateChanged(ItemEvent arg0) {\r
224                         \r
225                     CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
226                     if(editor != null) {\r
227                         if(arg0.getStateChange() == ItemEvent.SELECTED)\r
228                             editor.edit(null, ClientModel.STATES, ClientModel.STATES_CURRENT, arg0.getItem(), null, null);\r
229                     }\r
230                 }\r
231             };\r
232             \r
233             initialConditions.addItemListener(initialConditionsListener);\r
234 \r
235                         saveIc = new JButton();\r
236                         saveIc.setText("Save IC");\r
237                         saveIc.setToolTipText("Save current Initial Condition");\r
238                         saveIc.addActionListener(new ActionListener() {\r
239                 \r
240                 @Override\r
241                 public void actionPerformed(ActionEvent e) {\r
242                     \r
243                     SheetCommands commands = serverInterface.getAdapter(SheetCommands.class);\r
244                     commands.saveState();\r
245                 }\r
246             });\r
247                         \r
248                         font = new JButton();\r
249                         font.setToolTipText("Assign font to selection");\r
250                         \r
251                         font.addActionListener(new ActionListener() {\r
252                                 @Override\r
253                                 public void actionPerformed(ActionEvent e) {\r
254                                         JFontChooser fontChooser = new JFontChooser();\r
255                                         int result = fontChooser.showDialog(font);\r
256                                         if (result == JFontChooser.OK_OPTION) {\r
257                                                 \r
258                                                 Font font = fontChooser.getSelectedFont(); \r
259                                                 System.out.println("Selected Font : " + font);\r
260 \r
261                                                 org.simantics.datatypes.literal.Font f = Fonts.fromAWT(font);\r
262 \r
263                                                 editSelection(ClientModel.FONT, f, org.simantics.datatypes.literal.Font.BINDING);\r
264                                         }\r
265                                 }\r
266                         });\r
267                         \r
268                         try {\r
269                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/font.png"));\r
270                                 font.setIcon(new ImageIcon(img));\r
271                         } catch (IOException ex) {\r
272                         }\r
273 \r
274                         align_left = new JButton();\r
275                         align_left.setToolTipText("Align selection to left");\r
276                         \r
277                         try {\r
278                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_left.png"));\r
279                                 align_left.setIcon(new ImageIcon(img));\r
280                         } catch (IOException ex) {\r
281                         }\r
282 \r
283                         align_left.addActionListener(new ActionListener() {\r
284                                 @Override\r
285                                 public void actionPerformed(ActionEvent e) {\r
286                                         editSelectionAlignment(0, null);\r
287                                 }\r
288                         });\r
289                         \r
290                         align_hcenter = new JButton();\r
291                         align_hcenter.setToolTipText("Align selection horizontally to center");\r
292                         \r
293                         try {\r
294                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_center.png"));\r
295                                 align_hcenter.setIcon(new ImageIcon(img));\r
296                         } catch (IOException ex) {\r
297                         }\r
298 \r
299                         align_hcenter.addActionListener(new ActionListener() {\r
300                                 @Override\r
301                                 public void actionPerformed(ActionEvent e) {\r
302                                         editSelectionAlignment(1, null);\r
303                                 }\r
304                         });             \r
305                         \r
306                         align_right = new JButton();\r
307                         align_right.setToolTipText("Align selection to right");\r
308                         \r
309                         try {\r
310                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_right.png"));\r
311                                 align_right.setIcon(new ImageIcon(img));\r
312                         } catch (IOException ex) {\r
313                         }\r
314 \r
315                         align_right.addActionListener(new ActionListener() {\r
316                                 @Override\r
317                                 public void actionPerformed(ActionEvent e) {\r
318                                         editSelectionAlignment(2, null);\r
319                                 }\r
320                         });             \r
321                         \r
322                         align_top = new JButton();\r
323                         align_top.setToolTipText("Align selection to top");\r
324                         \r
325                         try {\r
326                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_top.png"));\r
327                                 align_top.setIcon(new ImageIcon(img));\r
328                         } catch (IOException ex) {\r
329                         }\r
330 \r
331                         align_top.addActionListener(new ActionListener() {\r
332                                 @Override\r
333                                 public void actionPerformed(ActionEvent e) {\r
334                                         editSelectionAlignment(null, 0);\r
335                                 }\r
336                         });             \r
337                         \r
338                         align_vcenter = new JButton();\r
339                         align_vcenter.setToolTipText("Align selection vertically to center");\r
340                         \r
341                         try {\r
342                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_middle.png"));\r
343                                 align_vcenter.setIcon(new ImageIcon(img));\r
344                         } catch (IOException ex) {\r
345                         }\r
346 \r
347                         align_vcenter.addActionListener(new ActionListener() {\r
348                                 @Override\r
349                                 public void actionPerformed(ActionEvent e) {\r
350                                         editSelectionAlignment(null, 1);\r
351                                 }\r
352                         });             \r
353                         \r
354                         align_bottom = new JButton();\r
355                         align_bottom.setToolTipText("Align selection to bottom");\r
356                         \r
357                         try {\r
358                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_bottom.png"));\r
359                                 align_bottom.setIcon(new ImageIcon(img));\r
360                         } catch (IOException ex) {\r
361                         }\r
362 \r
363                         align_bottom.addActionListener(new ActionListener() {\r
364                                 @Override\r
365                                 public void actionPerformed(ActionEvent e) {\r
366                                         editSelectionAlignment(null, 2);\r
367                                 }\r
368                         });             \r
369                         \r
370                         borders = new JComboBox();\r
371                         borders.addItem("No borders");\r
372                         borders.addItem("Bottom border");\r
373                         borders.addItem("Top border");\r
374                         borders.addItem("Left border");\r
375                         borders.addItem("Right border");\r
376                         borders.addActionListener(new ActionListener() {\r
377 \r
378                                 Map<String,Integer> work = new HashMap<String,Integer>();\r
379                                 \r
380                                 int getCurrent(String location, int row, int column) {\r
381                                         CellValue value = (CellValue)table.getValueAt(row, column);\r
382                                         int border = value != null ? value.border : 0;\r
383                                         work.put(location, border);\r
384                                         return border;\r
385                                 }\r
386                                 \r
387                                 void setCurrent(String location, int border) {\r
388                                         work.put(location, border);\r
389                                 }\r
390                                 \r
391                                 @Override\r
392                                 public void actionPerformed(ActionEvent e) {\r
393                                         \r
394                                         work.clear();\r
395                                         \r
396                                         int index = borders.getSelectedIndex();\r
397                                         \r
398                                         final int[] selectedColumns = table.getSelectedColumns();\r
399                                         final int[] selectedRows = table.getSelectedRows();\r
400 \r
401                                         CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
402                                         if(editor == null) return;\r
403                                         \r
404                                         for(int col : selectedColumns) {\r
405                                                 for(int row : selectedRows) {\r
406                                                         \r
407                                                         String location = SpreadsheetUtils.cellName(row, col);\r
408                                                         \r
409                                                         // No\r
410                                                         if(index == 0) {\r
411                                                                 if(col > 0) {\r
412                                                                         String left = SpreadsheetUtils.cellName(row, col-1);\r
413                                                                         setCurrent(left, getCurrent(left, row, col-1) & 2);\r
414                                                                 }\r
415                                                                 if(row > 0) {\r
416                                                                         String up = SpreadsheetUtils.cellName(row-1, col);\r
417                                                                         setCurrent(up, getCurrent(up, row-1, col) & 1);\r
418                                                                 }\r
419                                                                 setCurrent(location, 0);\r
420                                                         }\r
421                                                         // Bottom\r
422                                                         else if(index == 1) {\r
423                                                                 setCurrent(location, getCurrent(location, row, col) | 2);\r
424                                                         }\r
425                                                         // Top\r
426                                                         else if(index == 2) {\r
427                                                                 if(row > 0) {\r
428                                                                         String up = SpreadsheetUtils.cellName(row-1, col);\r
429                                                                         setCurrent(up, getCurrent(up, row-1, col) | 2);\r
430                                                                 }\r
431                                                         }\r
432                                                         // Left\r
433                                                         else if(index == 3) {\r
434                                                                 if(col > 0) {\r
435                                                                         String left = SpreadsheetUtils.cellName(row, col-1);\r
436                                                                         setCurrent(left, getCurrent(left, row, col-1) | 1);\r
437                                                                 }\r
438                                                         }\r
439                                                         // Right\r
440                                                         else if(index == 4) {\r
441                                                                 setCurrent(location, getCurrent(location, row, col) | 1);\r
442                                                         }\r
443                                                         \r
444                                                 }\r
445                                                 \r
446                                         }\r
447                                         OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
448                                         Transaction transaction = editor.startTransaction(mode);\r
449                                         for(Map.Entry<String, Integer> entry : work.entrySet()) {\r
450                                                 String location = entry.getKey();\r
451                                                 Integer border = entry.getValue();\r
452                                                 editor.edit(transaction, location, ClientModel.BORDER, border, Bindings.INTEGER, null);\r
453                                         }\r
454                                         transaction.commit();\r
455                                         \r
456                                 }\r
457                         });\r
458                         \r
459                         \r
460                         lock = new JButton();\r
461                         lock.setToolTipText("Lock selection");\r
462                         \r
463                         try {\r
464                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/lock.png"));\r
465                                 lock.setIcon(new ImageIcon(img));\r
466                         } catch (IOException ex) {\r
467                         }\r
468                         \r
469                         lock.addActionListener(new ActionListener() {\r
470                                 @Override\r
471                                 public void actionPerformed(ActionEvent e) {\r
472                                         editSelection(ClientModel.LOCKED, true, Bindings.BOOLEAN);\r
473                                 }\r
474                         });\r
475 \r
476                         unlock = new JButton();\r
477                         unlock.setToolTipText("Unlock selection");\r
478                         \r
479                         try {\r
480                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/lock_open.png"));\r
481                                 unlock.setIcon(new ImageIcon(img));\r
482                         } catch (IOException ex) {\r
483                         }\r
484                         \r
485                         unlock.addActionListener(new ActionListener() {\r
486                                 @Override\r
487                                 public void actionPerformed(ActionEvent e) {\r
488                                         editSelection(ClientModel.LOCKED, false, Bindings.BOOLEAN);\r
489                                 }\r
490                         });\r
491                         \r
492                         merge = new JButton();\r
493                         merge.setToolTipText("Merge cells");\r
494                         \r
495                         try {\r
496                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/link.png"));\r
497                                 merge.setIcon(new ImageIcon(img));\r
498                         } catch (IOException ex) {\r
499                         }\r
500                         \r
501                         merge.addActionListener(new ActionListener() {\r
502                                 @Override\r
503                                 public void actionPerformed(ActionEvent e) {\r
504                                         \r
505                                         final int[] selectedColumns = table.getSelectedColumns();\r
506                                         final int[] selectedRows = table.getSelectedRows();\r
507 \r
508                                         if (isRectangularSelection(table)) {\r
509                                         \r
510                                                 CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
511                                                 if(editor == null) return;\r
512                                                 \r
513                                                 OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
514                                                 Transaction transaction = editor.startTransaction(mode);\r
515                                                 \r
516                                                 Rectangle selection = new Rectangle(selectedColumns[0], selectedRows[0], selectedColumns.length, selectedRows.length);\r
517                                                 List<Rectangle> spans = clientModel.getSpans();\r
518                                                 \r
519                                                 boolean found = true;\r
520                                                 while (found) {\r
521                                                         found = false;\r
522                                                         Iterator<Rectangle> iter = spans.iterator();\r
523                                                         while (iter.hasNext()) {\r
524                                                                 Rectangle span = iter.next();\r
525                                                                 if (selection.intersects(span)) {\r
526                                                                         selection = selection.union(span);\r
527                                                                         found = true;\r
528                                                                         String location = SpreadsheetUtils.cellName(span.y, span.x);\r
529                                                                         editor.edit(transaction, location, ClientModel.ROW_SPAN, 1, Bindings.INTEGER, null);\r
530                                                                         editor.edit(transaction, location, ClientModel.COLUMN_SPAN, 1, Bindings.INTEGER, null);\r
531                                                                         iter.remove();\r
532                                                                 }\r
533                                                         }\r
534                                                 }\r
535                                                 \r
536                                                 String location = SpreadsheetUtils.cellName(selection.y, selection.x);\r
537                                                 if (selection.height > 1) {\r
538                                                         editor.edit(transaction, location, ClientModel.ROW_SPAN, selection.height, Bindings.INTEGER, null);\r
539                                                 }\r
540                                                 if (selection.width > 1) {\r
541                                                         editor.edit(transaction, location, ClientModel.COLUMN_SPAN, selection.width, Bindings.INTEGER, null);\r
542                                                 }\r
543                                                 transaction.commit();\r
544                                                 \r
545                                         } else {\r
546                                                 //ShowMessage.showError(, message);\r
547                                                 Display.getDefault().asyncExec(new Runnable() {\r
548                                                         public void run() {\r
549                                                                 ShowMessage.showWarning("Merging cells failed", "Selected range is not rectangular.");\r
550                                                         }\r
551                                                 });\r
552                                         }\r
553                                 }\r
554                         });\r
555                         \r
556                         unmerge = new JButton();\r
557                         unmerge.setToolTipText("Unmerge cells");\r
558                         \r
559                         try {\r
560                                 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/link_break.png"));\r
561                                 unmerge.setIcon(new ImageIcon(img));\r
562                         } catch (IOException ex) {\r
563                         }\r
564                         \r
565                         unmerge.addActionListener(new ActionListener() {\r
566                                 @Override\r
567                                 public void actionPerformed(ActionEvent e) {\r
568                                         \r
569                                         CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
570                                         if(editor == null) return;\r
571                                         \r
572                                         OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
573                                         Transaction transaction = editor.startTransaction(mode);\r
574                                         editSelection(editor, transaction, ClientModel.ROW_SPAN, 1, Bindings.INTEGER);\r
575                                         editSelection(editor, transaction, ClientModel.COLUMN_SPAN, 1, Bindings.INTEGER);\r
576                                         transaction.commit();\r
577                                 }\r
578                         });\r
579                         \r
580                         String[] availableSources = clientModel.getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_AVAILABLE);\r
581                         String[] availableSheets = clientModel.getPossiblePropertyAt(ClientModel.SHEETS, ClientModel.SHEETS_AVAILABLE);\r
582                         String currentSheet = clientModel.getPossiblePropertyAt(ClientModel.SHEETS, ClientModel.SHEETS_CURRENT);\r
583                         @SuppressWarnings("unused")\r
584                         String currentSource = clientModel.getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_CURRENT);\r
585                         \r
586                         inputSource = new JComboBox();\r
587                         for(String source : availableSources)\r
588                                 inputSource.addItem(source);\r
589 \r
590                         sheets = new JComboBox();\r
591                         for(String sheet : availableSheets)\r
592                                 sheets.addItem(sheet);\r
593                         \r
594             sheets.setSelectedItem(currentSheet);\r
595 \r
596             sheetsListener = new ItemListener() {\r
597 \r
598                 @Override\r
599                 public void itemStateChanged(ItemEvent arg0) {\r
600 \r
601                     CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
602                     if (editor != null) {\r
603                         if (arg0.getStateChange() == ItemEvent.SELECTED)\r
604                             editor.edit(null, ClientModel.SHEETS, ClientModel.SHEETS_CURRENT, arg0.getItem(), null,\r
605                                     null);\r
606                     }\r
607                 }\r
608             };\r
609 \r
610                         itemListener = new ItemListener() {\r
611                                 \r
612                                 @Override\r
613                                 public void itemStateChanged(ItemEvent arg0) {\r
614                                         \r
615                                         CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
616                                         if(editor != null) {\r
617                                                 if(arg0.getStateChange() == ItemEvent.SELECTED)\r
618                                                         editor.edit(null, ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, arg0.getItem(), null, null);\r
619                                         }\r
620 \r
621                                 }\r
622                                 \r
623                         };\r
624                         \r
625                         inputSource.addItemListener(itemListener);\r
626                         \r
627                         new DropTarget(inputSource,DnDConstants.ACTION_COPY_OR_MOVE,new DropTargetListener() {\r
628                                 \r
629                                 @Override\r
630                                 public void dropActionChanged(DropTargetDragEvent arg0) {\r
631                                         // TODO Auto-generated method stub\r
632                                         \r
633                                 }\r
634                                 \r
635                                 @Override\r
636                                 public void drop(DropTargetDropEvent dtde) {\r
637                                         \r
638                         try {\r
639                             Transferable transferable = dtde.getTransferable();\r
640                             \r
641                             if( transferable.isDataFlavorSupported( \r
642                                     LocalObjectTransferable.FLAVOR ) ) {\r
643                                 \r
644                                 dtde.acceptDrop( DnDConstants.ACTION_MOVE );\r
645                                 \r
646                                 transferable.getTransferData(LocalObjectTransferable.FLAVOR );\r
647                                 Object obj = LocalObjectTransfer.getTransfer().getObject();\r
648                                 \r
649                                                 CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
650                                                 if(editor != null) {\r
651                                                         editor.edit(null, ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, obj, null, null);\r
652                                                 }\r
653                                 \r
654                                 dtde.getDropTargetContext().dropComplete( true );\r
655                                 \r
656                             }\r
657                             else {\r
658                                 dtde.rejectDrop();\r
659                             }\r
660                         } catch( IOException exception ) {\r
661                             exception.printStackTrace();\r
662                             dtde.rejectDrop();\r
663                         } catch( UnsupportedFlavorException ufException ) {\r
664                             ufException.printStackTrace();\r
665                             dtde.rejectDrop();\r
666                         }\r
667                                         \r
668                                 }\r
669                                 \r
670                                 @Override\r
671                                 public void dragOver(DropTargetDragEvent arg0) {\r
672                                         // TODO Auto-generated method stub\r
673                                         \r
674                                 }\r
675                                 \r
676                                 @Override\r
677                                 public void dragExit(DropTargetEvent arg0) {\r
678                                         // TODO Auto-generated method stub\r
679                                         \r
680                                 }\r
681                                 \r
682                                 @Override\r
683                                 public void dragEnter(DropTargetDragEvent arg0) {\r
684                                         // TODO Auto-generated method stub\r
685                                         \r
686                                 }\r
687                                 \r
688                         });\r
689                         \r
690                         expression = new JTextField();\r
691                         etl = new ExpressionTextListener(expression, serverInterface.getAdapter(CellEditor.class));\r
692                         expression.addFocusListener(etl);\r
693                         expression.addKeyListener(etl);\r
694                         \r
695                      sheets.addItemListener(sheetsListener);\r
696 \r
697                         \r
698                         context = new JButton("Change context");\r
699                         \r
700                         context.addActionListener(new ActionListener() {\r
701                             \r
702                             @Override\r
703                             public void actionPerformed(ActionEvent e) {\r
704                                 \r
705                                 Frame frame = (Frame) SwingUtilities.getRoot(context);\r
706                                 String result = JOptionPane.showInputDialog(frame, "Context URI");\r
707                                 if (result != null && !result.isEmpty()) {\r
708                                     CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
709                                     if(editor != null) {\r
710                                         editor.edit(null, ClientModel.CONTEXT, ClientModel.CONTEXT_CURRENT, result, null, null);\r
711                                     }\r
712                                 }\r
713                             }\r
714                         });\r
715                         \r
716                         OperationMode currentMode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
717                         String text;\r
718                         if (currentMode.equals(OperationMode.OPERATION))\r
719                             text = "Operation Mode";\r
720                         else\r
721                             text = "Edit Mode";\r
722                         operationMode = new JToggleButton(text);\r
723                         operationMode.addActionListener(new ActionListener() {\r
724                             \r
725                             @Override\r
726                             public void actionPerformed(ActionEvent e) {\r
727                                 \r
728                                 OperationMode currentMode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
729                                 OperationMode newMode;\r
730                                 String newText;\r
731                                 if (currentMode.equals(OperationMode.OPERATION)) {\r
732                                     System.err.println("Current mode is operation");\r
733                                     newMode = OperationMode.EDIT_MODE;\r
734                                     newText = "Edit Mode";\r
735                                 } else {\r
736                                     System.err.println("Current mode is read-only");\r
737                                     newMode = OperationMode.OPERATION;\r
738                                     newText = "Operation Mode";\r
739                                 }\r
740                                 System.err.println("Setting new text " + newText + " to replace old " + operationMode.getText());\r
741                                 operationMode.setText(newText);\r
742                                 \r
743                                 CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
744                                 if(editor != null) {\r
745                                     editor.edit(null, ClientModel.MODE, ClientModel.MODE_CURRENT, newMode, null, null);\r
746                                 }\r
747                             }\r
748                         });\r
749                         \r
750                         iterationEnabled = new JCheckBox("Iteration Enabled");\r
751                         iterationEnabled.addActionListener(new ActionListener() {\r
752                             \r
753                             @Override\r
754                             public void actionPerformed(ActionEvent e) {\r
755                                 System.out.println("state is " + iterationEnabled.isSelected());\r
756                             }\r
757                         });\r
758                         \r
759                         iterationLimit = new JTextField("100");\r
760                         iterationLimit.setEnabled(false);\r
761                         iterationLimit.addActionListener(new ActionListener() {\r
762                             \r
763                             @Override\r
764                             public void actionPerformed(ActionEvent e) {\r
765                                 \r
766                             }\r
767                         });\r
768 \r
769                 }\r
770                 \r
771                 Font font = new Font("Courier", Font.PLAIN, 14);\r
772 \r
773                 UIManager.put(SpreadsheetTable.uiClassID, SpreadsheetTableUI.class.getCanonicalName());\r
774                 final JList rowHeader = new JList(lm);\r
775                 table = new SpreadsheetTable(node, (CellEditor)serverInterface.getAdapter(CellEditor.class), clientModel, lm, rowHeader) {\r
776                         \r
777                         private static final long serialVersionUID = 4553572254034185984L;\r
778 \r
779                         @Override\r
780                         protected void mouseDragFinished() {\r
781                                 \r
782                                 CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
783                                 if(editor == null) return;\r
784 \r
785                                 TableColumn column = table.getTableHeader().getResizingColumn();\r
786                                 if(column == null) return;\r
787 \r
788                                 int[] current = clientModel.getColumnWidths();\r
789                                 if(column.getModelIndex() >= current.length) {\r
790                                         current = Arrays.copyOf(current, column.getModelIndex()+1);\r
791                                 }\r
792 \r
793                                 current[column.getModelIndex()] = column.getWidth();\r
794 \r
795                                 editor.edit(null, ClientModel.HEADERS, ClientModel.HEADERS_COL_WIDTHS, current, Bindings.INT_ARRAY, null);\r
796                                 \r
797                         }\r
798                         \r
799                 };\r
800 \r
801                 ((ClientTableModel)table.getModel()).setModel(this);\r
802 \r
803                 InputMap im = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);\r
804                 Action deleteAction = new AbstractAction() {\r
805                         private static final long serialVersionUID = 428343700053346645L;\r
806 \r
807                         @SuppressWarnings("unused")\r
808                         public void actionPerformed(ActionEvent ae) {\r
809                                 System.out.println("deleteaction");\r
810                                 RemoveCellHandler removeHandler = serverInterface.getAdapter(RemoveCellHandler.class);\r
811                                 int[] rowSelection = table.getSelectedRows();\r
812                                 int[] columnSelection = table.getSelectedColumns();\r
813                                 for (int i = 0; i < columnSelection.length; i++) {\r
814                                         for (int j = 0; j < rowSelection.length; j++) {\r
815                                                 int row = rowSelection[j];\r
816                                                 int column = columnSelection[i];\r
817                                                 System.out.println("deleteaction " + row + " " + column);\r
818                                                 Object cell = table.getValueAt(row, column);\r
819                                                 //                                  RemoveHandler remove = cell.getAdapter(RemoveHandler.class);\r
820                                                 //                                  remove.handle();\r
821                                         }\r
822                                 }\r
823                         }\r
824                 };\r
825                 KeyStroke delete = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);\r
826                 im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), delete);\r
827                 table.getActionMap().put(im.get(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)), deleteAction);\r
828 \r
829                 table.setFont(font);\r
830 \r
831                 @SuppressWarnings("unused")\r
832                 DropTarget dropTarget = new DropTarget(table,\r
833                                 new TableDropTargetListener(table, serverInterface, clientModel));\r
834 \r
835                 if(serverInterface != null)\r
836                         excel = new ExcelAdapter(table, clientModel, serverInterface, parsers);\r
837 \r
838                 table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);\r
839 \r
840                 table.setColumnSelectionAllowed(true);\r
841                 \r
842                 rowHeader.setFixedCellWidth(40);\r
843 \r
844                 rowHeader.setCellRenderer(new RowHeaderRenderer(table));\r
845                 rowHeader.setBackground(DefaultLookup.GRAY);\r
846 \r
847                 table.getModel().addTableModelListener(new TableModelListener() {\r
848 \r
849                         @Override\r
850                         public void tableChanged(TableModelEvent e) {\r
851                                 int currentRows = rowHeader.getModel().getSize();\r
852                                 int tableRows = table.getModel().getRowCount();\r
853                                 if(currentRows != tableRows) {\r
854                                         lm.setSize(tableRows);\r
855                                 }\r
856                         }\r
857                 });\r
858 \r
859                 JScrollPaneSG scroll = new JScrollPaneSG(table, node);\r
860 \r
861                 scroll.setRowHeaderView(rowHeader);\r
862 \r
863                 table.getParent().setBackground(DefaultLookup.GRAY);\r
864                 table.getTableHeader().setBackground(DefaultLookup.GRAY);\r
865                 rowHeader.getParent().setBackground(DefaultLookup.GRAY);\r
866                 scroll.getViewport().setBackground(DefaultLookup.GRAY);\r
867 \r
868                 table.getTableHeader().setDefaultRenderer(new ColumnHeaderRenderer());\r
869 \r
870                 scroll.setBackground(DefaultLookup.GRAY);\r
871 \r
872                 if(selectionProvider != null) {\r
873 \r
874                         SelectionListener listener = new SelectionListener(table, expression, etl, selectionProvider, serverInterface, clientModel);\r
875                         table.getSelectionModel().addListSelectionListener(listener);\r
876                         table.getColumnModel().getSelectionModel()\r
877                         .addListSelectionListener(listener);\r
878 \r
879                 }\r
880                 \r
881                 table.getColumnModel().addColumnModelListener(new TableColumnModelListener() {\r
882 \r
883                         @Override\r
884                         public void columnSelectionChanged(ListSelectionEvent e) {\r
885                                 //                    System.out.println("columnSelectionChanged " + e);\r
886                         }\r
887 \r
888                         @Override\r
889                         public void columnRemoved(TableColumnModelEvent e) {\r
890                                 //                    System.out.println("columnRemoved " + e);\r
891                         }\r
892 \r
893                         @Override\r
894                         public void columnMoved(TableColumnModelEvent e) {\r
895                                 //                    System.out.println("columnMoved " + e);\r
896                         }\r
897 \r
898                         @Override\r
899                         public void columnMarginChanged(ChangeEvent e) {\r
900                                 columnMarginsDirty = true;\r
901                         }\r
902 \r
903                         @Override\r
904                         public void columnAdded(TableColumnModelEvent e) {\r
905                                 //                    System.out.println("columnAdded " + e);\r
906                         }\r
907 \r
908                 });\r
909                 \r
910                 new TableRowResizer(table) {\r
911                         \r
912                         @Override\r
913                         public void onResize(int row, int height) {\r
914                                 \r
915                                 if(row < 0) return;\r
916                                 \r
917                                 CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
918                                 if(editor == null) return;\r
919 \r
920                                 int[] current = clientModel.getRowHeights();\r
921                                 if(row >= current.length) {\r
922                                         current = Arrays.copyOf(current, row+1);\r
923                                 }\r
924 \r
925                                 current[row] = height;\r
926 \r
927                                 editor.edit(null, ClientModel.HEADERS, ClientModel.HEADERS_ROW_HEIGHTS, current, Bindings.INT_ARRAY, null);\r
928                                 \r
929                                 rowHeader.setCellRenderer(new RowHeaderRenderer(table));\r
930                                 \r
931                         }\r
932                         \r
933                 };\r
934                 \r
935                 if (addExpressionField) {\r
936                         \r
937                         JPanel tools = new JPanel(new GridBagLayout());\r
938                         panel.add(tools, BorderLayout.PAGE_START);\r
939 \r
940                         GridBagConstraints c = new GridBagConstraints();                        \r
941 \r
942                         c.gridx = 0;\r
943                 c.anchor = GridBagConstraints.WEST;\r
944                         tools.add(this.font, c);\r
945 \r
946                         c.gridx = 1;\r
947                         tools.add(foreground, c);\r
948 \r
949                         c.gridx = 2;\r
950                         tools.add(background, c);\r
951 \r
952                         c.gridx = 3;\r
953                         tools.add(align_left, c);\r
954                         c.gridx = 4;\r
955                         tools.add(align_hcenter, c);\r
956                         c.gridx = 5;\r
957                         tools.add(align_right, c);\r
958 \r
959                         c.gridx = 6;\r
960                         tools.add(align_top, c);\r
961                         c.gridx = 7;\r
962                         tools.add(align_vcenter, c);\r
963                         c.gridx = 8;\r
964                         tools.add(align_bottom, c);\r
965 \r
966                         c.gridx = 9;\r
967                         tools.add(borders, c);\r
968 \r
969                         c.gridx = 10;\r
970                         tools.add(lock, c);\r
971                         c.gridx = 11;\r
972                         tools.add(unlock, c);\r
973 \r
974                         c.gridx = 12;\r
975                         tools.add(merge, c);\r
976                         c.gridx = 13;\r
977                         tools.add(unmerge, c);\r
978                         \r
979                         c.gridx = 14;\r
980                         tools.add(inputSource, c);\r
981 \r
982                         c.gridx = 15;\r
983                         tools.add(sheets, c);\r
984 \r
985                         c.gridx = 16;\r
986                         tools.add(initialConditions, c);\r
987                         \r
988                         c.gridx = 17;\r
989                         tools.add(saveIc, c);\r
990                         \r
991                         c.gridx = 18;\r
992                         tools.add(context, c);\r
993                         \r
994                         c.gridx = 19;\r
995                         tools.add(operationMode, c);\r
996                         \r
997                         c.gridx = 20;\r
998                         tools.add(iterationEnabled, c);\r
999                         \r
1000                         c.gridx = 21;\r
1001                         tools.add(iterationLimit, c);\r
1002 \r
1003                         c.gridx = 0;\r
1004                         c.gridy = 1;\r
1005                         c.gridwidth = 22;\r
1006                 c.gridheight = 1;\r
1007                 c.weighty = 0.0;\r
1008                 c.weightx = 1.0;\r
1009                 c.fill = GridBagConstraints.HORIZONTAL;\r
1010 \r
1011                         tools.add(expression,c);\r
1012                         \r
1013                 }\r
1014                 panel.add(scroll, BorderLayout.CENTER);\r
1015 \r
1016                 return panel;\r
1017 \r
1018         }\r
1019 \r
1020         private boolean isRectangularSelection(SpreadsheetTable table) {\r
1021                 int[] selectedColumns = table.getSelectedColumns();\r
1022                 int[] selectedRows = table.getSelectedRows();\r
1023 \r
1024                 if ((selectedColumns.length == 0) || (selectedRows.length == 0)) {\r
1025                         return false;\r
1026                 }\r
1027                 \r
1028                 for (int row = 0; row < selectedRows.length - 1; row++) {\r
1029                         if (selectedRows[row + 1] != selectedRows[row] + 1) {\r
1030                                 return false;\r
1031                         }\r
1032                 }\r
1033                 \r
1034                 for (int column = 0; column < selectedColumns.length - 1; column++) {\r
1035                         if (selectedColumns[column + 1] != selectedColumns[column] + 1) {\r
1036                                 return false;\r
1037                         }\r
1038                 }\r
1039                 \r
1040                 return true;\r
1041         }\r
1042         \r
1043         private void editSelection(String property, Object value, Binding binding) { \r
1044                 CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
1045                 if(editor == null) return;\r
1046                 \r
1047 //              Transaction transaction = editor.startTransaction();\r
1048                 editSelection(editor, null, property, value, binding);\r
1049 //              transaction.commit();\r
1050         }\r
1051 \r
1052         private void editSelection(CellEditor editor, Transaction transaction, String property, Object value, Binding binding) { \r
1053                 for(int col : table.getSelectedColumns()) {\r
1054                         for(int row : table.getSelectedRows()) {\r
1055                                 String location = SpreadsheetUtils.cellName(row, col);\r
1056                                 editor.edit(transaction, location, property, value, binding, null);\r
1057                         }\r
1058                 }\r
1059         }\r
1060         \r
1061         \r
1062         private void editSelectionAlignment(Integer horizontal, Integer vertical) {\r
1063                 final int[] selectedColumns = table.getSelectedColumns();\r
1064                 final int[] selectedRows = table.getSelectedRows();\r
1065         \r
1066                 CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
1067                 if(editor == null) return;\r
1068         \r
1069 //              Transaction transaction = editor.startTransaction(); \r
1070                 for(int col : selectedColumns) {\r
1071                         for(int row : selectedRows) {\r
1072                                 String location = SpreadsheetUtils.cellName(row, col);\r
1073                                 \r
1074                                 CellValue value = (CellValue)table.getValueAt(row, col);\r
1075                                 int align = value != null ? value.align : 0;\r
1076                                 \r
1077                                 if (horizontal != null) {\r
1078                                         align = (align & 12) + horizontal;\r
1079                                 }\r
1080                                 if (vertical != null) {\r
1081                                         align = (align & 3) + (vertical << 2);\r
1082                                 }\r
1083 \r
1084 //                              editor.edit(transaction, location, ClientModel.ALIGN, align, Bindings.INTEGER);\r
1085                                 editor.edit(null, location, ClientModel.ALIGN, align, Bindings.INTEGER, null);\r
1086                                 \r
1087                         }\r
1088                 }\r
1089 //              transaction.commit();\r
1090         }\r
1091         \r
1092         public ClientModel getClientInterface() {\r
1093 \r
1094                 return clientModel;\r
1095 \r
1096         }\r
1097 \r
1098         public void setSources() {\r
1099                 // If expression fields are not visible, do nothing.\r
1100                 if (inputSource == null)\r
1101                         return;\r
1102 \r
1103                 String[] available = (String[])getClientModel().getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_AVAILABLE);\r
1104                 String current = (String)getClientModel().getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_CURRENT);\r
1105                 \r
1106                 inputSource.removeItemListener(itemListener);\r
1107                 inputSource.removeAllItems();\r
1108                 for(String a : available)\r
1109                         inputSource.addItem(a);\r
1110                 inputSource.setSelectedItem(current);\r
1111                 inputSource.addItemListener(itemListener);\r
1112                 \r
1113         }\r
1114 \r
1115 \r
1116 }