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