]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/SpreadsheetModel.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.spreadsheet.ui / src / org / simantics / spreadsheet / ui / SpreadsheetModel.java
diff --git a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/SpreadsheetModel.java b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/SpreadsheetModel.java
new file mode 100644 (file)
index 0000000..9b4ef34
--- /dev/null
@@ -0,0 +1,1116 @@
+package org.simantics.spreadsheet.ui;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.Color;\r
+import java.awt.Font;\r
+import java.awt.Frame;\r
+import java.awt.GridBagConstraints;\r
+import java.awt.GridBagLayout;\r
+import java.awt.Image;\r
+import java.awt.Rectangle;\r
+import java.awt.datatransfer.Clipboard;\r
+import java.awt.datatransfer.Transferable;\r
+import java.awt.datatransfer.UnsupportedFlavorException;\r
+import java.awt.dnd.DnDConstants;\r
+import java.awt.dnd.DropTarget;\r
+import java.awt.dnd.DropTargetDragEvent;\r
+import java.awt.dnd.DropTargetDropEvent;\r
+import java.awt.dnd.DropTargetEvent;\r
+import java.awt.dnd.DropTargetListener;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.awt.event.ItemEvent;\r
+import java.awt.event.ItemListener;\r
+import java.awt.event.KeyEvent;\r
+import java.io.IOException;\r
+import java.util.Arrays;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Properties;\r
+\r
+import javax.imageio.ImageIO;\r
+import javax.swing.AbstractAction;\r
+import javax.swing.Action;\r
+import javax.swing.DefaultListModel;\r
+import javax.swing.ImageIcon;\r
+import javax.swing.InputMap;\r
+import javax.swing.JButton;\r
+import javax.swing.JCheckBox;\r
+import javax.swing.JColorChooser;\r
+import javax.swing.JComboBox;\r
+import javax.swing.JComponent;\r
+import javax.swing.JList;\r
+import javax.swing.JOptionPane;\r
+import javax.swing.JPanel;\r
+import javax.swing.JTable;\r
+import javax.swing.JTextField;\r
+import javax.swing.JToggleButton;\r
+import javax.swing.KeyStroke;\r
+import javax.swing.SwingUtilities;\r
+import javax.swing.UIManager;\r
+import javax.swing.event.ChangeEvent;\r
+import javax.swing.event.ListSelectionEvent;\r
+import javax.swing.event.TableColumnModelEvent;\r
+import javax.swing.event.TableColumnModelListener;\r
+import javax.swing.event.TableModelEvent;\r
+import javax.swing.event.TableModelListener;\r
+import javax.swing.table.TableColumn;\r
+\r
+import org.eclipse.core.runtime.Platform;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.datatypes.literal.RGB;\r
+import org.simantics.scenegraph.INode;\r
+import org.simantics.scenegraph.swing.JScrollPaneSG;\r
+import org.simantics.spreadsheet.Adaptable;\r
+import org.simantics.spreadsheet.CellEditor;\r
+import org.simantics.spreadsheet.CellEditor.Transaction;\r
+import org.simantics.spreadsheet.ClientModel;\r
+import org.simantics.spreadsheet.ClientModel.OperationMode;\r
+import org.simantics.spreadsheet.SheetCommands;\r
+import org.simantics.spreadsheet.common.cell.Parsers;\r
+import org.simantics.spreadsheet.common.cell.StringCellParser;\r
+import org.simantics.spreadsheet.event.model.RemoveCellHandler;\r
+import org.simantics.spreadsheet.util.SpreadsheetUtils;\r
+import org.simantics.ui.colors.Colors;\r
+import org.simantics.ui.dnd.LocalObjectTransfer;\r
+import org.simantics.ui.dnd.LocalObjectTransferable;\r
+import org.simantics.ui.fonts.Fonts;\r
+import org.simantics.utils.ui.dialogs.ShowMessage;\r
+import org.simantics.utils.ui.jface.ActiveSelectionProvider;\r
+\r
+@SuppressWarnings({ "rawtypes", "unchecked" })\r
+public class SpreadsheetModel {\r
+\r
+       final private Adaptable serverInterface;\r
+       final private ClientModel clientModel;\r
+       final private ActiveSelectionProvider selectionProvider;\r
+       protected Clipboard system;\r
+       protected StringCellParser[] parsers =  new StringCellParser[] { Parsers.COMMAND_PARSER, Parsers.EXPRESSION_PARSER, Parsers.TEXT_PARSER };\r
+\r
+       public SpreadsheetModel(Adaptable serverInterface, ActiveSelectionProvider selectionProvider) {\r
+\r
+               this.serverInterface = serverInterface;\r
+               this.clientModel = new ClientModelImpl();\r
+               this.selectionProvider = selectionProvider;\r
+\r
+       }\r
+\r
+       public ClientModel getClientModel() {\r
+               return clientModel;\r
+       }\r
+\r
+       public SpreadsheetTable getTable() {\r
+               return table;\r
+       }\r
+\r
+       private JTextField expression;\r
+       private JButton foreground;\r
+       private JButton background;\r
+       private JButton font;\r
+       private JButton align_left;\r
+       private JButton align_hcenter;\r
+       private JButton align_right;\r
+       private JButton align_top;\r
+       private JButton align_vcenter;\r
+       private JButton align_bottom;\r
+       private JComboBox borders;\r
+       public JComboBox inputSource;\r
+       public JComboBox sheets;\r
+       private JButton lock;\r
+       private JButton unlock;\r
+       private JButton merge;\r
+       private JButton unmerge;\r
+       private ExpressionTextListener etl;\r
+       private SpreadsheetTable table;\r
+       @SuppressWarnings("unused")\r
+       private ExcelAdapter excel;\r
+       @SuppressWarnings("unused")\r
+       private boolean columnMarginsDirty = false;\r
+       \r
+       private ItemListener itemListener = null;\r
+       private ItemListener sheetsListener = null;\r
+       private ItemListener initialConditionsListener = null;\r
+       \r
+       private JComboBox initialConditions;\r
+    private JButton saveIc;\r
+    private JButton context;\r
+    private JToggleButton operationMode;\r
+    \r
+    private JCheckBox iterationEnabled;\r
+    private JTextField iterationLimit;\r
+\r
+       public JComponent createComponent(final INode node) {\r
+\r
+               Properties props = serverInterface.getAdapter(Properties.class);\r
+               \r
+               boolean addExpressionField = props == null || "true".equalsIgnoreCase(props.getProperty(SpreadsheetModelProperties.SHEET_EXPRESSION_VISIBLE, "true"));\r
+\r
+               final JPanel panel = new JPanel(new BorderLayout());\r
+               \r
+               final DefaultListModel lm = new DefaultListModel() {\r
+\r
+                       private static final long serialVersionUID = 5246691801867533053L;\r
+\r
+                       public Object getElementAt(int index) {\r
+                               Object result = super.getElementAt(index);\r
+                               if(result instanceof String) return result; \r
+                               else return "" + (index + 1);\r
+                       }\r
+\r
+               };\r
+\r
+               if (addExpressionField) {\r
+                       \r
+                       foreground = new JButton();\r
+                       foreground.setToolTipText("Assign foreground color to selection");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/paintbrush.png"));\r
+                               foreground.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+                       foreground.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       \r
+                                       Color c = JColorChooser.showDialog(foreground, "asd", Colors.awt(Colors.rgb(0, 0, 0)));\r
+                                       if (c == null)\r
+                                           return;\r
+                                       RGB.Integer color = Colors.integerRGB(c);\r
+\r
+                                       editSelection(ClientModel.FOREGROUND, color, RGB.Integer.BINDING);\r
+                               }\r
+                       });\r
+\r
+                       background = new JButton();\r
+                       background.setToolTipText("Assign background color to selection");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/paintcan.png"));\r
+                               background.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+                       \r
+                       background.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       \r
+                                       Color c = JColorChooser.showDialog(background, "asd", Colors.awt(Colors.rgb(0, 0, 0)));\r
+                                       if (c == null)\r
+                                           return;\r
+\r
+                                       RGB.Integer color = Colors.integerRGB(c);\r
+\r
+                                       editSelection(ClientModel.BACKGROUND, color, RGB.Integer.BINDING);\r
+                               }\r
+                       });\r
+                       \r
+                       String[] availableInitialConditions = clientModel.getPossiblePropertyAt(ClientModel.STATES, ClientModel.STATES_AVAILABLE);\r
+                       String currentInitialCondition = clientModel.getPossiblePropertyAt(ClientModel.STATES, ClientModel.STATES_CURRENT);\r
+                       \r
+                       initialConditions = new JComboBox<>();\r
+                       for(String sheet : availableInitialConditions)\r
+                           initialConditions.addItem(sheet);\r
+                       \r
+                       initialConditions.setSelectedItem(currentInitialCondition);\r
+                       \r
+                       initialConditionsListener = new ItemListener() {\r
+                           @Override\r
+                public void itemStateChanged(ItemEvent arg0) {\r
+                        \r
+                    CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+                    if(editor != null) {\r
+                        if(arg0.getStateChange() == ItemEvent.SELECTED)\r
+                            editor.edit(null, ClientModel.STATES, ClientModel.STATES_CURRENT, arg0.getItem(), null, null);\r
+                    }\r
+                }\r
+            };\r
+            \r
+            initialConditions.addItemListener(initialConditionsListener);\r
+\r
+                       saveIc = new JButton();\r
+                       saveIc.setText("Save IC");\r
+                       saveIc.setToolTipText("Save current Initial Condition");\r
+                       saveIc.addActionListener(new ActionListener() {\r
+                \r
+                @Override\r
+                public void actionPerformed(ActionEvent e) {\r
+                    \r
+                    SheetCommands commands = serverInterface.getAdapter(SheetCommands.class);\r
+                    commands.saveState();\r
+                }\r
+            });\r
+                       \r
+                       font = new JButton();\r
+                       font.setToolTipText("Assign font to selection");\r
+                       \r
+                       font.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       JFontChooser fontChooser = new JFontChooser();\r
+                                       int result = fontChooser.showDialog(font);\r
+                                       if (result == JFontChooser.OK_OPTION) {\r
+                                               \r
+                                               Font font = fontChooser.getSelectedFont(); \r
+                                               System.out.println("Selected Font : " + font);\r
+\r
+                                               org.simantics.datatypes.literal.Font f = Fonts.fromAWT(font);\r
+\r
+                                               editSelection(ClientModel.FONT, f, org.simantics.datatypes.literal.Font.BINDING);\r
+                                       }\r
+                               }\r
+                       });\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/font.png"));\r
+                               font.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+\r
+                       align_left = new JButton();\r
+                       align_left.setToolTipText("Align selection to left");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_left.png"));\r
+                               align_left.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+\r
+                       align_left.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       editSelectionAlignment(0, null);\r
+                               }\r
+                       });\r
+                       \r
+                       align_hcenter = new JButton();\r
+                       align_hcenter.setToolTipText("Align selection horizontally to center");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_center.png"));\r
+                               align_hcenter.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+\r
+                       align_hcenter.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       editSelectionAlignment(1, null);\r
+                               }\r
+                       });             \r
+                       \r
+                       align_right = new JButton();\r
+                       align_right.setToolTipText("Align selection to right");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_right.png"));\r
+                               align_right.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+\r
+                       align_right.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       editSelectionAlignment(2, null);\r
+                               }\r
+                       });             \r
+                       \r
+                       align_top = new JButton();\r
+                       align_top.setToolTipText("Align selection to top");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_top.png"));\r
+                               align_top.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+\r
+                       align_top.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       editSelectionAlignment(null, 0);\r
+                               }\r
+                       });             \r
+                       \r
+                       align_vcenter = new JButton();\r
+                       align_vcenter.setToolTipText("Align selection vertically to center");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_middle.png"));\r
+                               align_vcenter.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+\r
+                       align_vcenter.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       editSelectionAlignment(null, 1);\r
+                               }\r
+                       });             \r
+                       \r
+                       align_bottom = new JButton();\r
+                       align_bottom.setToolTipText("Align selection to bottom");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_bottom.png"));\r
+                               align_bottom.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+\r
+                       align_bottom.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       editSelectionAlignment(null, 2);\r
+                               }\r
+                       });             \r
+                       \r
+                       borders = new JComboBox();\r
+                       borders.addItem("No borders");\r
+                       borders.addItem("Bottom border");\r
+                       borders.addItem("Top border");\r
+                       borders.addItem("Left border");\r
+                       borders.addItem("Right border");\r
+                       borders.addActionListener(new ActionListener() {\r
+\r
+                               Map<String,Integer> work = new HashMap<String,Integer>();\r
+                               \r
+                               int getCurrent(String location, int row, int column) {\r
+                                       CellValue value = (CellValue)table.getValueAt(row, column);\r
+                                       int border = value != null ? value.border : 0;\r
+                                       work.put(location, border);\r
+                                       return border;\r
+                               }\r
+                               \r
+                               void setCurrent(String location, int border) {\r
+                                       work.put(location, border);\r
+                               }\r
+                               \r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       \r
+                                       work.clear();\r
+                                       \r
+                                       int index = borders.getSelectedIndex();\r
+                                       \r
+                                       final int[] selectedColumns = table.getSelectedColumns();\r
+                                       final int[] selectedRows = table.getSelectedRows();\r
+\r
+                                       CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+                                       if(editor == null) return;\r
+                                       \r
+                                       for(int col : selectedColumns) {\r
+                                               for(int row : selectedRows) {\r
+                                                       \r
+                                                       String location = SpreadsheetUtils.cellName(row, col);\r
+                                                       \r
+                                                       // No\r
+                                                       if(index == 0) {\r
+                                                               if(col > 0) {\r
+                                                                       String left = SpreadsheetUtils.cellName(row, col-1);\r
+                                                                       setCurrent(left, getCurrent(left, row, col-1) & 2);\r
+                                                               }\r
+                                                               if(row > 0) {\r
+                                                                       String up = SpreadsheetUtils.cellName(row-1, col);\r
+                                                                       setCurrent(up, getCurrent(up, row-1, col) & 1);\r
+                                                               }\r
+                                                               setCurrent(location, 0);\r
+                                                       }\r
+                                                       // Bottom\r
+                                                       else if(index == 1) {\r
+                                                               setCurrent(location, getCurrent(location, row, col) | 2);\r
+                                                       }\r
+                                                       // Top\r
+                                                       else if(index == 2) {\r
+                                                               if(row > 0) {\r
+                                                                       String up = SpreadsheetUtils.cellName(row-1, col);\r
+                                                                       setCurrent(up, getCurrent(up, row-1, col) | 2);\r
+                                                               }\r
+                                                       }\r
+                                                       // Left\r
+                                                       else if(index == 3) {\r
+                                                               if(col > 0) {\r
+                                                                       String left = SpreadsheetUtils.cellName(row, col-1);\r
+                                                                       setCurrent(left, getCurrent(left, row, col-1) | 1);\r
+                                                               }\r
+                                                       }\r
+                                                       // Right\r
+                                                       else if(index == 4) {\r
+                                                               setCurrent(location, getCurrent(location, row, col) | 1);\r
+                                                       }\r
+                                                       \r
+                                               }\r
+                                               \r
+                                       }\r
+                                       OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
+                                       Transaction transaction = editor.startTransaction(mode);\r
+                                       for(Map.Entry<String, Integer> entry : work.entrySet()) {\r
+                                               String location = entry.getKey();\r
+                                               Integer border = entry.getValue();\r
+                                               editor.edit(transaction, location, ClientModel.BORDER, border, Bindings.INTEGER, null);\r
+                                       }\r
+                                       transaction.commit();\r
+                                       \r
+                               }\r
+                       });\r
+                       \r
+                       \r
+                       lock = new JButton();\r
+                       lock.setToolTipText("Lock selection");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/lock.png"));\r
+                               lock.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+                       \r
+                       lock.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       editSelection(ClientModel.LOCKED, true, Bindings.BOOLEAN);\r
+                               }\r
+                       });\r
+\r
+                       unlock = new JButton();\r
+                       unlock.setToolTipText("Unlock selection");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/lock_open.png"));\r
+                               unlock.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+                       \r
+                       unlock.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       editSelection(ClientModel.LOCKED, false, Bindings.BOOLEAN);\r
+                               }\r
+                       });\r
+                       \r
+                       merge = new JButton();\r
+                       merge.setToolTipText("Merge cells");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/link.png"));\r
+                               merge.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+                       \r
+                       merge.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       \r
+                                       final int[] selectedColumns = table.getSelectedColumns();\r
+                                       final int[] selectedRows = table.getSelectedRows();\r
+\r
+                                       if (isRectangularSelection(table)) {\r
+                                       \r
+                                               CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+                                               if(editor == null) return;\r
+                                               \r
+                                               OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
+                                               Transaction transaction = editor.startTransaction(mode);\r
+                                               \r
+                                               Rectangle selection = new Rectangle(selectedColumns[0], selectedRows[0], selectedColumns.length, selectedRows.length);\r
+                                               List<Rectangle> spans = clientModel.getSpans();\r
+                                               \r
+                                               boolean found = true;\r
+                                               while (found) {\r
+                                                       found = false;\r
+                                                       Iterator<Rectangle> iter = spans.iterator();\r
+                                                       while (iter.hasNext()) {\r
+                                                               Rectangle span = iter.next();\r
+                                                               if (selection.intersects(span)) {\r
+                                                                       selection = selection.union(span);\r
+                                                                       found = true;\r
+                                                                       String location = SpreadsheetUtils.cellName(span.y, span.x);\r
+                                                                       editor.edit(transaction, location, ClientModel.ROW_SPAN, 1, Bindings.INTEGER, null);\r
+                                                                       editor.edit(transaction, location, ClientModel.COLUMN_SPAN, 1, Bindings.INTEGER, null);\r
+                                                                       iter.remove();\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+                                               \r
+                                               String location = SpreadsheetUtils.cellName(selection.y, selection.x);\r
+                                               if (selection.height > 1) {\r
+                                                       editor.edit(transaction, location, ClientModel.ROW_SPAN, selection.height, Bindings.INTEGER, null);\r
+                                               }\r
+                                               if (selection.width > 1) {\r
+                                                       editor.edit(transaction, location, ClientModel.COLUMN_SPAN, selection.width, Bindings.INTEGER, null);\r
+                                               }\r
+                                               transaction.commit();\r
+                                               \r
+                                       } else {\r
+                                               //ShowMessage.showError(, message);\r
+                                               Display.getDefault().asyncExec(new Runnable() {\r
+                                                       public void run() {\r
+                                                               ShowMessage.showWarning("Merging cells failed", "Selected range is not rectangular.");\r
+                                                       }\r
+                                               });\r
+                                       }\r
+                               }\r
+                       });\r
+                       \r
+                       unmerge = new JButton();\r
+                       unmerge.setToolTipText("Unmerge cells");\r
+                       \r
+                       try {\r
+                               Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/link_break.png"));\r
+                               unmerge.setIcon(new ImageIcon(img));\r
+                       } catch (IOException ex) {\r
+                       }\r
+                       \r
+                       unmerge.addActionListener(new ActionListener() {\r
+                               @Override\r
+                               public void actionPerformed(ActionEvent e) {\r
+                                       \r
+                                       CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+                                       if(editor == null) return;\r
+                                       \r
+                                       OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
+                                       Transaction transaction = editor.startTransaction(mode);\r
+                                       editSelection(editor, transaction, ClientModel.ROW_SPAN, 1, Bindings.INTEGER);\r
+                                       editSelection(editor, transaction, ClientModel.COLUMN_SPAN, 1, Bindings.INTEGER);\r
+                                       transaction.commit();\r
+                               }\r
+                       });\r
+                       \r
+                       String[] availableSources = clientModel.getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_AVAILABLE);\r
+                       String[] availableSheets = clientModel.getPossiblePropertyAt(ClientModel.SHEETS, ClientModel.SHEETS_AVAILABLE);\r
+                       String currentSheet = clientModel.getPossiblePropertyAt(ClientModel.SHEETS, ClientModel.SHEETS_CURRENT);\r
+                       @SuppressWarnings("unused")\r
+                       String currentSource = clientModel.getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_CURRENT);\r
+                       \r
+                       inputSource = new JComboBox();\r
+                       for(String source : availableSources)\r
+                               inputSource.addItem(source);\r
+\r
+                       sheets = new JComboBox();\r
+                       for(String sheet : availableSheets)\r
+                               sheets.addItem(sheet);\r
+                       \r
+            sheets.setSelectedItem(currentSheet);\r
+\r
+            sheetsListener = new ItemListener() {\r
+\r
+                @Override\r
+                public void itemStateChanged(ItemEvent arg0) {\r
+\r
+                    CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+                    if (editor != null) {\r
+                        if (arg0.getStateChange() == ItemEvent.SELECTED)\r
+                            editor.edit(null, ClientModel.SHEETS, ClientModel.SHEETS_CURRENT, arg0.getItem(), null,\r
+                                    null);\r
+                    }\r
+                }\r
+            };\r
+\r
+                       itemListener = new ItemListener() {\r
+                               \r
+                               @Override\r
+                               public void itemStateChanged(ItemEvent arg0) {\r
+                                       \r
+                                       CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+                                       if(editor != null) {\r
+                                               if(arg0.getStateChange() == ItemEvent.SELECTED)\r
+                                                       editor.edit(null, ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, arg0.getItem(), null, null);\r
+                                       }\r
+\r
+                               }\r
+                               \r
+                       };\r
+                       \r
+                       inputSource.addItemListener(itemListener);\r
+                       \r
+                       new DropTarget(inputSource,DnDConstants.ACTION_COPY_OR_MOVE,new DropTargetListener() {\r
+                               \r
+                               @Override\r
+                               public void dropActionChanged(DropTargetDragEvent arg0) {\r
+                                       // TODO Auto-generated method stub\r
+                                       \r
+                               }\r
+                               \r
+                               @Override\r
+                               public void drop(DropTargetDropEvent dtde) {\r
+                                       \r
+                       try {\r
+                           Transferable transferable = dtde.getTransferable();\r
+                           \r
+                           if( transferable.isDataFlavorSupported( \r
+                                   LocalObjectTransferable.FLAVOR ) ) {\r
+                               \r
+                               dtde.acceptDrop( DnDConstants.ACTION_MOVE );\r
+                               \r
+                               transferable.getTransferData(LocalObjectTransferable.FLAVOR );\r
+                               Object obj = LocalObjectTransfer.getTransfer().getObject();\r
+                               \r
+                                               CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+                                               if(editor != null) {\r
+                                                       editor.edit(null, ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, obj, null, null);\r
+                                               }\r
+                               \r
+                               dtde.getDropTargetContext().dropComplete( true );\r
+                               \r
+                           }\r
+                           else {\r
+                               dtde.rejectDrop();\r
+                           }\r
+                       } catch( IOException exception ) {\r
+                           exception.printStackTrace();\r
+                           dtde.rejectDrop();\r
+                       } catch( UnsupportedFlavorException ufException ) {\r
+                           ufException.printStackTrace();\r
+                           dtde.rejectDrop();\r
+                       }\r
+                                       \r
+                               }\r
+                               \r
+                               @Override\r
+                               public void dragOver(DropTargetDragEvent arg0) {\r
+                                       // TODO Auto-generated method stub\r
+                                       \r
+                               }\r
+                               \r
+                               @Override\r
+                               public void dragExit(DropTargetEvent arg0) {\r
+                                       // TODO Auto-generated method stub\r
+                                       \r
+                               }\r
+                               \r
+                               @Override\r
+                               public void dragEnter(DropTargetDragEvent arg0) {\r
+                                       // TODO Auto-generated method stub\r
+                                       \r
+                               }\r
+                               \r
+                       });\r
+                       \r
+                       expression = new JTextField();\r
+                       etl = new ExpressionTextListener(expression, serverInterface.getAdapter(CellEditor.class));\r
+                       expression.addFocusListener(etl);\r
+                       expression.addKeyListener(etl);\r
+                       \r
+                    sheets.addItemListener(sheetsListener);\r
+\r
+                       \r
+                       context = new JButton("Change context");\r
+                       \r
+                       context.addActionListener(new ActionListener() {\r
+                           \r
+                           @Override\r
+                           public void actionPerformed(ActionEvent e) {\r
+                               \r
+                               Frame frame = (Frame) SwingUtilities.getRoot(context);\r
+                               String result = JOptionPane.showInputDialog(frame, "Context URI");\r
+                               if (result != null && !result.isEmpty()) {\r
+                                   CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+                                   if(editor != null) {\r
+                                       editor.edit(null, ClientModel.CONTEXT, ClientModel.CONTEXT_CURRENT, result, null, null);\r
+                                   }\r
+                               }\r
+                           }\r
+                       });\r
+                       \r
+                       OperationMode currentMode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
+                       String text;\r
+                       if (currentMode.equals(OperationMode.OPERATION))\r
+                           text = "Operation Mode";\r
+                       else\r
+                           text = "Edit Mode";\r
+                       operationMode = new JToggleButton(text);\r
+                       operationMode.addActionListener(new ActionListener() {\r
+                           \r
+                           @Override\r
+                           public void actionPerformed(ActionEvent e) {\r
+                               \r
+                               OperationMode currentMode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
+                               OperationMode newMode;\r
+                               String newText;\r
+                               if (currentMode.equals(OperationMode.OPERATION)) {\r
+                                   System.err.println("Current mode is operation");\r
+                                   newMode = OperationMode.EDIT_MODE;\r
+                                   newText = "Edit Mode";\r
+                               } else {\r
+                                   System.err.println("Current mode is read-only");\r
+                                   newMode = OperationMode.OPERATION;\r
+                                   newText = "Operation Mode";\r
+                               }\r
+                               System.err.println("Setting new text " + newText + " to replace old " + operationMode.getText());\r
+                               operationMode.setText(newText);\r
+                               \r
+                               CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+                               if(editor != null) {\r
+                                   editor.edit(null, ClientModel.MODE, ClientModel.MODE_CURRENT, newMode, null, null);\r
+                               }\r
+                           }\r
+                       });\r
+                       \r
+                       iterationEnabled = new JCheckBox("Iteration Enabled");\r
+                       iterationEnabled.addActionListener(new ActionListener() {\r
+                           \r
+                           @Override\r
+                           public void actionPerformed(ActionEvent e) {\r
+                               System.out.println("state is " + iterationEnabled.isSelected());\r
+                           }\r
+                       });\r
+                       \r
+                       iterationLimit = new JTextField("100");\r
+                       iterationLimit.setEnabled(false);\r
+                       iterationLimit.addActionListener(new ActionListener() {\r
+                           \r
+                           @Override\r
+                           public void actionPerformed(ActionEvent e) {\r
+                               \r
+                           }\r
+                       });\r
+\r
+               }\r
+               \r
+               Font font = new Font("Courier", Font.PLAIN, 14);\r
+\r
+               UIManager.put(SpreadsheetTable.uiClassID, SpreadsheetTableUI.class.getCanonicalName());\r
+               final JList rowHeader = new JList(lm);\r
+               table = new SpreadsheetTable(node, (CellEditor)serverInterface.getAdapter(CellEditor.class), clientModel, lm, rowHeader) {\r
+                       \r
+                       private static final long serialVersionUID = 4553572254034185984L;\r
+\r
+                       @Override\r
+                       protected void mouseDragFinished() {\r
+                               \r
+                               CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+                               if(editor == null) return;\r
+\r
+                               TableColumn column = table.getTableHeader().getResizingColumn();\r
+                               if(column == null) return;\r
+\r
+                               int[] current = clientModel.getColumnWidths();\r
+                               if(column.getModelIndex() >= current.length) {\r
+                                       current = Arrays.copyOf(current, column.getModelIndex()+1);\r
+                               }\r
+\r
+                               current[column.getModelIndex()] = column.getWidth();\r
+\r
+                               editor.edit(null, ClientModel.HEADERS, ClientModel.HEADERS_COL_WIDTHS, current, Bindings.INT_ARRAY, null);\r
+                               \r
+                       }\r
+                       \r
+               };\r
+\r
+               ((ClientTableModel)table.getModel()).setModel(this);\r
+\r
+               InputMap im = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);\r
+               Action deleteAction = new AbstractAction() {\r
+                       private static final long serialVersionUID = 428343700053346645L;\r
+\r
+                       @SuppressWarnings("unused")\r
+                       public void actionPerformed(ActionEvent ae) {\r
+                               System.out.println("deleteaction");\r
+                               RemoveCellHandler removeHandler = serverInterface.getAdapter(RemoveCellHandler.class);\r
+                               int[] rowSelection = table.getSelectedRows();\r
+                               int[] columnSelection = table.getSelectedColumns();\r
+                               for (int i = 0; i < columnSelection.length; i++) {\r
+                                       for (int j = 0; j < rowSelection.length; j++) {\r
+                                               int row = rowSelection[j];\r
+                                               int column = columnSelection[i];\r
+                                               System.out.println("deleteaction " + row + " " + column);\r
+                                               Object cell = table.getValueAt(row, column);\r
+                                               //                                  RemoveHandler remove = cell.getAdapter(RemoveHandler.class);\r
+                                               //                                  remove.handle();\r
+                                       }\r
+                               }\r
+                       }\r
+               };\r
+               KeyStroke delete = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);\r
+               im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), delete);\r
+               table.getActionMap().put(im.get(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)), deleteAction);\r
+\r
+               table.setFont(font);\r
+\r
+               @SuppressWarnings("unused")\r
+               DropTarget dropTarget = new DropTarget(table,\r
+                               new TableDropTargetListener(table, serverInterface, clientModel));\r
+\r
+               if(serverInterface != null)\r
+                       excel = new ExcelAdapter(table, clientModel, serverInterface, parsers);\r
+\r
+               table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);\r
+\r
+               table.setColumnSelectionAllowed(true);\r
+               \r
+               rowHeader.setFixedCellWidth(40);\r
+\r
+               rowHeader.setCellRenderer(new RowHeaderRenderer(table));\r
+               rowHeader.setBackground(DefaultLookup.GRAY);\r
+\r
+               table.getModel().addTableModelListener(new TableModelListener() {\r
+\r
+                       @Override\r
+                       public void tableChanged(TableModelEvent e) {\r
+                               int currentRows = rowHeader.getModel().getSize();\r
+                               int tableRows = table.getModel().getRowCount();\r
+                               if(currentRows != tableRows) {\r
+                                       lm.setSize(tableRows);\r
+                               }\r
+                       }\r
+               });\r
+\r
+               JScrollPaneSG scroll = new JScrollPaneSG(table, node);\r
+\r
+               scroll.setRowHeaderView(rowHeader);\r
+\r
+               table.getParent().setBackground(DefaultLookup.GRAY);\r
+               table.getTableHeader().setBackground(DefaultLookup.GRAY);\r
+               rowHeader.getParent().setBackground(DefaultLookup.GRAY);\r
+               scroll.getViewport().setBackground(DefaultLookup.GRAY);\r
+\r
+               table.getTableHeader().setDefaultRenderer(new ColumnHeaderRenderer());\r
+\r
+               scroll.setBackground(DefaultLookup.GRAY);\r
+\r
+               if(selectionProvider != null) {\r
+\r
+                       SelectionListener listener = new SelectionListener(table, expression, etl, selectionProvider, serverInterface, clientModel);\r
+                       table.getSelectionModel().addListSelectionListener(listener);\r
+                       table.getColumnModel().getSelectionModel()\r
+                       .addListSelectionListener(listener);\r
+\r
+               }\r
+               \r
+               table.getColumnModel().addColumnModelListener(new TableColumnModelListener() {\r
+\r
+                       @Override\r
+                       public void columnSelectionChanged(ListSelectionEvent e) {\r
+                               //                    System.out.println("columnSelectionChanged " + e);\r
+                       }\r
+\r
+                       @Override\r
+                       public void columnRemoved(TableColumnModelEvent e) {\r
+                               //                    System.out.println("columnRemoved " + e);\r
+                       }\r
+\r
+                       @Override\r
+                       public void columnMoved(TableColumnModelEvent e) {\r
+                               //                    System.out.println("columnMoved " + e);\r
+                       }\r
+\r
+                       @Override\r
+                       public void columnMarginChanged(ChangeEvent e) {\r
+                               columnMarginsDirty = true;\r
+                       }\r
+\r
+                       @Override\r
+                       public void columnAdded(TableColumnModelEvent e) {\r
+                               //                    System.out.println("columnAdded " + e);\r
+                       }\r
+\r
+               });\r
+               \r
+               new TableRowResizer(table) {\r
+                       \r
+                       @Override\r
+                       public void onResize(int row, int height) {\r
+                               \r
+                               if(row < 0) return;\r
+                               \r
+                               CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+                               if(editor == null) return;\r
+\r
+                               int[] current = clientModel.getRowHeights();\r
+                               if(row >= current.length) {\r
+                                       current = Arrays.copyOf(current, row+1);\r
+                               }\r
+\r
+                               current[row] = height;\r
+\r
+                               editor.edit(null, ClientModel.HEADERS, ClientModel.HEADERS_ROW_HEIGHTS, current, Bindings.INT_ARRAY, null);\r
+                               \r
+                               rowHeader.setCellRenderer(new RowHeaderRenderer(table));\r
+                               \r
+                       }\r
+                       \r
+               };\r
+               \r
+               if (addExpressionField) {\r
+                       \r
+                       JPanel tools = new JPanel(new GridBagLayout());\r
+                       panel.add(tools, BorderLayout.PAGE_START);\r
+\r
+                       GridBagConstraints c = new GridBagConstraints();                        \r
+\r
+                       c.gridx = 0;\r
+               c.anchor = GridBagConstraints.WEST;\r
+                       tools.add(this.font, c);\r
+\r
+                       c.gridx = 1;\r
+                       tools.add(foreground, c);\r
+\r
+                       c.gridx = 2;\r
+                       tools.add(background, c);\r
+\r
+                       c.gridx = 3;\r
+                       tools.add(align_left, c);\r
+                       c.gridx = 4;\r
+                       tools.add(align_hcenter, c);\r
+                       c.gridx = 5;\r
+                       tools.add(align_right, c);\r
+\r
+                       c.gridx = 6;\r
+                       tools.add(align_top, c);\r
+                       c.gridx = 7;\r
+                       tools.add(align_vcenter, c);\r
+                       c.gridx = 8;\r
+                       tools.add(align_bottom, c);\r
+\r
+                       c.gridx = 9;\r
+                       tools.add(borders, c);\r
+\r
+                       c.gridx = 10;\r
+                       tools.add(lock, c);\r
+                       c.gridx = 11;\r
+                       tools.add(unlock, c);\r
+\r
+                       c.gridx = 12;\r
+                       tools.add(merge, c);\r
+                       c.gridx = 13;\r
+                       tools.add(unmerge, c);\r
+                       \r
+                       c.gridx = 14;\r
+                       tools.add(inputSource, c);\r
+\r
+                       c.gridx = 15;\r
+                       tools.add(sheets, c);\r
+\r
+                       c.gridx = 16;\r
+                       tools.add(initialConditions, c);\r
+                       \r
+                       c.gridx = 17;\r
+                       tools.add(saveIc, c);\r
+                       \r
+                       c.gridx = 18;\r
+                       tools.add(context, c);\r
+                       \r
+                       c.gridx = 19;\r
+                       tools.add(operationMode, c);\r
+                       \r
+                       c.gridx = 20;\r
+                       tools.add(iterationEnabled, c);\r
+                       \r
+                       c.gridx = 21;\r
+                       tools.add(iterationLimit, c);\r
+\r
+                       c.gridx = 0;\r
+                       c.gridy = 1;\r
+                       c.gridwidth = 22;\r
+               c.gridheight = 1;\r
+               c.weighty = 0.0;\r
+               c.weightx = 1.0;\r
+               c.fill = GridBagConstraints.HORIZONTAL;\r
+\r
+                       tools.add(expression,c);\r
+                       \r
+               }\r
+               panel.add(scroll, BorderLayout.CENTER);\r
+\r
+               return panel;\r
+\r
+       }\r
+\r
+       private boolean isRectangularSelection(SpreadsheetTable table) {\r
+               int[] selectedColumns = table.getSelectedColumns();\r
+               int[] selectedRows = table.getSelectedRows();\r
+\r
+               if ((selectedColumns.length == 0) || (selectedRows.length == 0)) {\r
+                       return false;\r
+               }\r
+               \r
+               for (int row = 0; row < selectedRows.length - 1; row++) {\r
+                       if (selectedRows[row + 1] != selectedRows[row] + 1) {\r
+                               return false;\r
+                       }\r
+               }\r
+               \r
+               for (int column = 0; column < selectedColumns.length - 1; column++) {\r
+                       if (selectedColumns[column + 1] != selectedColumns[column] + 1) {\r
+                               return false;\r
+                       }\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       private void editSelection(String property, Object value, Binding binding) { \r
+               CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+               if(editor == null) return;\r
+               \r
+//             Transaction transaction = editor.startTransaction();\r
+               editSelection(editor, null, property, value, binding);\r
+//             transaction.commit();\r
+       }\r
+\r
+       private void editSelection(CellEditor editor, Transaction transaction, String property, Object value, Binding binding) { \r
+               for(int col : table.getSelectedColumns()) {\r
+                       for(int row : table.getSelectedRows()) {\r
+                               String location = SpreadsheetUtils.cellName(row, col);\r
+                               editor.edit(transaction, location, property, value, binding, null);\r
+                       }\r
+               }\r
+       }\r
+       \r
+       \r
+       private void editSelectionAlignment(Integer horizontal, Integer vertical) {\r
+               final int[] selectedColumns = table.getSelectedColumns();\r
+               final int[] selectedRows = table.getSelectedRows();\r
+       \r
+               CellEditor editor = serverInterface.getAdapter(CellEditor.class);\r
+               if(editor == null) return;\r
+       \r
+//             Transaction transaction = editor.startTransaction(); \r
+               for(int col : selectedColumns) {\r
+                       for(int row : selectedRows) {\r
+                               String location = SpreadsheetUtils.cellName(row, col);\r
+                               \r
+                               CellValue value = (CellValue)table.getValueAt(row, col);\r
+                               int align = value != null ? value.align : 0;\r
+                               \r
+                               if (horizontal != null) {\r
+                                       align = (align & 12) + horizontal;\r
+                               }\r
+                               if (vertical != null) {\r
+                                       align = (align & 3) + (vertical << 2);\r
+                               }\r
+\r
+//                             editor.edit(transaction, location, ClientModel.ALIGN, align, Bindings.INTEGER);\r
+                               editor.edit(null, location, ClientModel.ALIGN, align, Bindings.INTEGER, null);\r
+                               \r
+                       }\r
+               }\r
+//             transaction.commit();\r
+       }\r
+       \r
+       public ClientModel getClientInterface() {\r
+\r
+               return clientModel;\r
+\r
+       }\r
+\r
+       public void setSources() {\r
+               // If expression fields are not visible, do nothing.\r
+               if (inputSource == null)\r
+                       return;\r
+\r
+               String[] available = (String[])getClientModel().getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_AVAILABLE);\r
+               String current = (String)getClientModel().getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_CURRENT);\r
+               \r
+               inputSource.removeItemListener(itemListener);\r
+               inputSource.removeAllItems();\r
+               for(String a : available)\r
+                       inputSource.addItem(a);\r
+               inputSource.setSelectedItem(current);\r
+               inputSource.addItemListener(itemListener);\r
+               \r
+       }\r
+\r
+\r
+}
\ No newline at end of file