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