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