1 package org.simantics.spreadsheet.ui;
3 import java.awt.BorderLayout;
5 import java.awt.Dimension;
6 import java.awt.FlowLayout;
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;
31 import java.util.Properties;
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;
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;
86 @SuppressWarnings({ "rawtypes", "unchecked" })
87 public class SpreadsheetModel {
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 };
95 public SpreadsheetModel(Adaptable serverInterface, ActiveSelectionProvider selectionProvider) {
97 this.serverInterface = serverInterface;
98 this.clientModel = new ClientModelImpl();
99 this.selectionProvider = selectionProvider;
103 public ClientModel getClientModel() {
107 public SpreadsheetTable getTable() {
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;
135 private ItemListener itemListener = null;
136 private ItemListener sheetsListener = null;
137 private ItemListener initialConditionsListener = null;
139 private JComboBox initialConditions;
140 private JButton saveIc;
141 private JButton context;
142 private JToggleButton operationMode;
144 private JCheckBox iterationEnabled;
145 private JTextField iterationLimit;
147 public JComponent createComponent(final INode node) {
149 Properties props = serverInterface.getAdapter(Properties.class);
151 boolean addExpressionField = props == null || "true".equalsIgnoreCase(props.getProperty(SpreadsheetModelProperties.SHEET_EXPRESSION_VISIBLE, "true"));
153 final JPanel panel = new JPanel(new BorderLayout());
155 final DefaultListModel lm = new DefaultListModel() {
157 private static final long serialVersionUID = 5246691801867533053L;
159 public Object getElementAt(int index) {
160 Object result = super.getElementAt(index);
161 if(result instanceof String) return result;
162 else return "" + (index + 1);
167 if (addExpressionField) {
169 foreground = new JButton();
170 foreground.setToolTipText("Assign foreground color to selection");
173 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/paintbrush.png"));
174 foreground.setIcon(new ImageIcon(img));
175 } catch (IOException ex) {
177 foreground.addActionListener(new ActionListener() {
179 public void actionPerformed(ActionEvent e) {
181 Color c = JColorChooser.showDialog(foreground, "asd", Colors.awt(Colors.rgb(0, 0, 0)));
184 RGB.Integer color = Colors.integerRGB(c);
186 editSelection(ClientModel.FOREGROUND, color, RGB.Integer.BINDING);
190 background = new JButton();
191 background.setToolTipText("Assign background color to selection");
194 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/paintcan.png"));
195 background.setIcon(new ImageIcon(img));
196 } catch (IOException ex) {
199 background.addActionListener(new ActionListener() {
201 public void actionPerformed(ActionEvent e) {
203 Color c = JColorChooser.showDialog(background, "asd", Colors.awt(Colors.rgb(0, 0, 0)));
207 RGB.Integer color = Colors.integerRGB(c);
209 editSelection(ClientModel.BACKGROUND, color, RGB.Integer.BINDING);
213 String[] availableInitialConditions = clientModel.getPossiblePropertyAt(ClientModel.STATES, ClientModel.STATES_AVAILABLE);
214 String currentInitialCondition = clientModel.getPossiblePropertyAt(ClientModel.STATES, ClientModel.STATES_CURRENT);
216 initialConditions = new JComboBox<>();
217 for(String sheet : availableInitialConditions)
218 initialConditions.addItem(sheet);
220 initialConditions.setSelectedItem(currentInitialCondition);
222 initialConditionsListener = new ItemListener() {
224 public void itemStateChanged(ItemEvent arg0) {
226 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
228 if(arg0.getStateChange() == ItemEvent.SELECTED)
229 editor.edit(null, ClientModel.STATES, ClientModel.STATES_CURRENT, arg0.getItem(), null, null);
234 initialConditions.addItemListener(initialConditionsListener);
236 saveIc = new JButton();
237 saveIc.setText("Save IC");
238 saveIc.setToolTipText("Save current Initial Condition");
239 saveIc.addActionListener(new ActionListener() {
242 public void actionPerformed(ActionEvent e) {
244 SheetCommands commands = serverInterface.getAdapter(SheetCommands.class);
245 commands.saveState();
249 font = new JButton();
250 font.setToolTipText("Assign font to selection");
252 font.addActionListener(new ActionListener() {
254 public void actionPerformed(ActionEvent e) {
255 JFontChooser fontChooser = new JFontChooser();
256 int result = fontChooser.showDialog(font);
257 if (result == JFontChooser.OK_OPTION) {
259 Font font = fontChooser.getSelectedFont();
260 System.out.println("Selected Font : " + font);
262 org.simantics.datatypes.literal.Font f = Fonts.fromAWT(font);
264 editSelection(ClientModel.FONT, f, org.simantics.datatypes.literal.Font.BINDING);
270 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/font.png"));
271 font.setIcon(new ImageIcon(img));
272 } catch (IOException ex) {
275 align_left = new JButton();
276 align_left.setToolTipText("Align selection to left");
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) {
284 align_left.addActionListener(new ActionListener() {
286 public void actionPerformed(ActionEvent e) {
287 editSelectionAlignment(0, null);
291 align_hcenter = new JButton();
292 align_hcenter.setToolTipText("Align selection horizontally to center");
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) {
300 align_hcenter.addActionListener(new ActionListener() {
302 public void actionPerformed(ActionEvent e) {
303 editSelectionAlignment(1, null);
307 align_right = new JButton();
308 align_right.setToolTipText("Align selection to right");
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) {
316 align_right.addActionListener(new ActionListener() {
318 public void actionPerformed(ActionEvent e) {
319 editSelectionAlignment(2, null);
323 align_top = new JButton();
324 align_top.setToolTipText("Align selection to top");
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) {
332 align_top.addActionListener(new ActionListener() {
334 public void actionPerformed(ActionEvent e) {
335 editSelectionAlignment(null, 0);
339 align_vcenter = new JButton();
340 align_vcenter.setToolTipText("Align selection vertically to center");
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) {
348 align_vcenter.addActionListener(new ActionListener() {
350 public void actionPerformed(ActionEvent e) {
351 editSelectionAlignment(null, 1);
355 align_bottom = new JButton();
356 align_bottom.setToolTipText("Align selection to bottom");
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) {
364 align_bottom.addActionListener(new ActionListener() {
366 public void actionPerformed(ActionEvent e) {
367 editSelectionAlignment(null, 2);
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() {
379 Map<String,Integer> work = new HashMap<String,Integer>();
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);
388 void setCurrent(String location, int border) {
389 work.put(location, border);
393 public void actionPerformed(ActionEvent e) {
397 int index = borders.getSelectedIndex();
399 final int[] selectedColumns = table.getSelectedColumns();
400 final int[] selectedRows = table.getSelectedRows();
402 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
403 if(editor == null) return;
405 for(int col : selectedColumns) {
406 for(int row : selectedRows) {
408 String location = SpreadsheetUtils.cellName(row, col);
413 String left = SpreadsheetUtils.cellName(row, col-1);
414 setCurrent(left, getCurrent(left, row, col-1) & 2);
417 String up = SpreadsheetUtils.cellName(row-1, col);
418 setCurrent(up, getCurrent(up, row-1, col) & 1);
420 setCurrent(location, 0);
423 else if(index == 1) {
424 setCurrent(location, getCurrent(location, row, col) | 2);
427 else if(index == 2) {
429 String up = SpreadsheetUtils.cellName(row-1, col);
430 setCurrent(up, getCurrent(up, row-1, col) | 2);
434 else if(index == 3) {
436 String left = SpreadsheetUtils.cellName(row, col-1);
437 setCurrent(left, getCurrent(left, row, col-1) | 1);
441 else if(index == 4) {
442 setCurrent(location, getCurrent(location, row, col) | 1);
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);
455 transaction.commit();
461 lock = new JButton();
462 lock.setToolTipText("Lock selection");
465 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/lock.png"));
466 lock.setIcon(new ImageIcon(img));
467 } catch (IOException ex) {
470 lock.addActionListener(new ActionListener() {
472 public void actionPerformed(ActionEvent e) {
473 editSelection(ClientModel.LOCKED, true, Bindings.BOOLEAN);
477 unlock = new JButton();
478 unlock.setToolTipText("Unlock selection");
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) {
486 unlock.addActionListener(new ActionListener() {
488 public void actionPerformed(ActionEvent e) {
489 editSelection(ClientModel.LOCKED, false, Bindings.BOOLEAN);
493 merge = new JButton();
494 merge.setToolTipText("Merge cells");
497 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/link.png"));
498 merge.setIcon(new ImageIcon(img));
499 } catch (IOException ex) {
502 merge.addActionListener(new ActionListener() {
504 public void actionPerformed(ActionEvent e) {
506 final int[] selectedColumns = table.getSelectedColumns();
507 final int[] selectedRows = table.getSelectedRows();
509 if (isRectangularSelection(table)) {
511 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
512 if(editor == null) return;
514 OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);
515 Transaction transaction = editor.startTransaction(mode);
517 Rectangle selection = new Rectangle(selectedColumns[0], selectedRows[0], selectedColumns.length, selectedRows.length);
518 List<Rectangle> spans = clientModel.getSpans();
520 boolean found = true;
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);
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);
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);
541 if (selection.width > 1) {
542 editor.edit(transaction, location, ClientModel.COLUMN_SPAN, selection.width, Bindings.INTEGER, null);
544 transaction.commit();
547 //ShowMessage.showError(, message);
548 Display.getDefault().asyncExec(new Runnable() {
550 ShowMessage.showWarning("Merging cells failed", "Selected range is not rectangular.");
557 unmerge = new JButton();
558 unmerge.setToolTipText("Unmerge cells");
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) {
566 unmerge.addActionListener(new ActionListener() {
568 public void actionPerformed(ActionEvent e) {
570 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
571 if(editor == null) return;
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();
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);
587 inputSource = new JComboBox();
588 for(String source : availableSources)
589 inputSource.addItem(source);
591 sheets = new JComboBox();
592 for(String sheet : availableSheets)
593 sheets.addItem(sheet);
595 sheets.setSelectedItem(currentSheet);
597 sheetsListener = new ItemListener() {
600 public void itemStateChanged(ItemEvent arg0) {
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,
611 itemListener = new ItemListener() {
614 public void itemStateChanged(ItemEvent arg0) {
616 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
618 if(arg0.getStateChange() == ItemEvent.SELECTED)
619 editor.edit(null, ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, arg0.getItem(), null, null);
626 inputSource.addItemListener(itemListener);
628 new DropTarget(inputSource,DnDConstants.ACTION_COPY_OR_MOVE,new DropTargetListener() {
631 public void dropActionChanged(DropTargetDragEvent arg0) {
632 // TODO Auto-generated method stub
637 public void drop(DropTargetDropEvent dtde) {
640 Transferable transferable = dtde.getTransferable();
642 if( transferable.isDataFlavorSupported(
643 LocalObjectTransferable.FLAVOR ) ) {
645 dtde.acceptDrop( DnDConstants.ACTION_MOVE );
647 transferable.getTransferData(LocalObjectTransferable.FLAVOR );
648 Object obj = LocalObjectTransfer.getTransfer().getObject();
650 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
652 editor.edit(null, ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, obj, null, null);
655 dtde.getDropTargetContext().dropComplete( true );
661 } catch( IOException exception ) {
662 exception.printStackTrace();
664 } catch( UnsupportedFlavorException ufException ) {
665 ufException.printStackTrace();
672 public void dragOver(DropTargetDragEvent arg0) {
673 // TODO Auto-generated method stub
678 public void dragExit(DropTargetEvent arg0) {
679 // TODO Auto-generated method stub
684 public void dragEnter(DropTargetDragEvent arg0) {
685 // TODO Auto-generated method stub
691 expression = new JTextField();
692 etl = new ExpressionTextListener(expression, serverInterface.getAdapter(CellEditor.class));
693 expression.addFocusListener(etl);
694 expression.addKeyListener(etl);
696 //Large default size so that the expression field is clearly visible
697 expression.setPreferredSize(new Dimension(600, 32));
699 sheets.addItemListener(sheetsListener);
702 context = new JButton("Change context");
704 context.addActionListener(new ActionListener() {
707 public void actionPerformed(ActionEvent e) {
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);
714 editor.edit(null, ClientModel.CONTEXT, ClientModel.CONTEXT_CURRENT, result, null, null);
720 OperationMode currentMode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);
722 if (currentMode.equals(OperationMode.OPERATION))
723 text = "Operation Mode";
726 operationMode = new JToggleButton(text);
727 operationMode.addActionListener(new ActionListener() {
730 public void actionPerformed(ActionEvent e) {
732 OperationMode currentMode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);
733 OperationMode newMode;
735 if (currentMode.equals(OperationMode.OPERATION)) {
736 System.err.println("Current mode is operation");
737 newMode = OperationMode.EDIT_MODE;
738 newText = "Edit Mode";
740 System.err.println("Current mode is read-only");
741 newMode = OperationMode.OPERATION;
742 newText = "Operation Mode";
744 System.err.println("Setting new text " + newText + " to replace old " + operationMode.getText());
745 operationMode.setText(newText);
747 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
749 editor.edit(null, ClientModel.MODE, ClientModel.MODE_CURRENT, newMode, null, null);
754 iterationEnabled = new JCheckBox("Iteration Enabled");
755 iterationEnabled.addActionListener(new ActionListener() {
758 public void actionPerformed(ActionEvent e) {
759 System.out.println("state is " + iterationEnabled.isSelected());
760 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
762 editor.edit(null, ClientModel.ITERATION_ENABLED, ClientModel.ITERATION_ENABLED, iterationEnabled.isSelected(), null, null);
767 iterationLimit = new JTextField("100");
768 iterationLimit.setEnabled(false);
769 iterationLimit.addActionListener(new ActionListener() {
772 public void actionPerformed(ActionEvent e) {
779 Font font = new Font("Courier", Font.PLAIN, 14);
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) {
785 private static final long serialVersionUID = 4553572254034185984L;
788 protected void mouseDragFinished() {
790 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
791 if(editor == null) return;
793 TableColumn column = table.getTableHeader().getResizingColumn();
794 if(column == null) return;
796 int[] current = clientModel.getColumnWidths();
797 if(column.getModelIndex() >= current.length) {
798 current = Arrays.copyOf(current, column.getModelIndex()+1);
801 current[column.getModelIndex()] = column.getWidth();
803 editor.edit(null, ClientModel.HEADERS, ClientModel.HEADERS_COL_WIDTHS, current, Bindings.INT_ARRAY, null);
809 ((ClientTableModel)table.getModel()).setModel(this);
811 InputMap im = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
812 Action deleteAction = new AbstractAction() {
813 private static final long serialVersionUID = 428343700053346645L;
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);
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);
839 @SuppressWarnings("unused")
840 DropTarget dropTarget = new DropTarget(table,
841 new TableDropTargetListener(table, serverInterface, clientModel));
843 if(serverInterface != null)
844 excel = new ExcelAdapter(table, clientModel, serverInterface, parsers);
846 table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
848 table.setColumnSelectionAllowed(true);
850 rowHeader.setFixedCellWidth(40);
852 rowHeader.setCellRenderer(new RowHeaderRenderer(table));
853 rowHeader.setBackground(DefaultLookup.GRAY);
855 table.getModel().addTableModelListener(new TableModelListener() {
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);
867 JScrollPaneSG scroll = new JScrollPaneSG(table, node);
869 scroll.setRowHeaderView(rowHeader);
871 table.getParent().setBackground(DefaultLookup.GRAY);
872 table.getTableHeader().setBackground(DefaultLookup.GRAY);
873 rowHeader.getParent().setBackground(DefaultLookup.GRAY);
874 scroll.getViewport().setBackground(DefaultLookup.GRAY);
876 table.getTableHeader().setDefaultRenderer(new ColumnHeaderRenderer());
878 scroll.setBackground(DefaultLookup.GRAY);
880 if(selectionProvider != null) {
882 SelectionListener listener = new SelectionListener(table, expression, etl, selectionProvider, serverInterface, clientModel);
883 table.getSelectionModel().addListSelectionListener(listener);
884 table.getColumnModel().getSelectionModel()
885 .addListSelectionListener(listener);
889 table.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
892 public void columnSelectionChanged(ListSelectionEvent e) {
893 // System.out.println("columnSelectionChanged " + e);
897 public void columnRemoved(TableColumnModelEvent e) {
898 // System.out.println("columnRemoved " + e);
902 public void columnMoved(TableColumnModelEvent e) {
903 // System.out.println("columnMoved " + e);
907 public void columnMarginChanged(ChangeEvent e) {
908 columnMarginsDirty = true;
912 public void columnAdded(TableColumnModelEvent e) {
913 // System.out.println("columnAdded " + e);
918 new TableRowResizer(table) {
921 public void onResize(int row, int height) {
925 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
926 if(editor == null) return;
928 int[] current = clientModel.getRowHeights();
929 if(row >= current.length) {
930 current = Arrays.copyOf(current, row+1);
933 current[row] = height;
935 editor.edit(null, ClientModel.HEADERS, ClientModel.HEADERS_ROW_HEIGHTS, current, Bindings.INT_ARRAY, null);
937 rowHeader.setCellRenderer(new RowHeaderRenderer(table));
943 if (addExpressionField) {
945 JPanel tools = new JPanel(new WrapLayout(FlowLayout.LEADING, 0, 0));
946 panel.add(tools, BorderLayout.PAGE_START);
948 tools.add(this.font);
950 tools.add(foreground);
952 tools.add(background);
954 tools.add(align_left);
955 tools.add(align_hcenter);
956 tools.add(align_right);
958 tools.add(align_top);
959 tools.add(align_vcenter);
960 tools.add(align_bottom);
970 tools.add(inputSource);
974 tools.add(initialConditions);
980 tools.add(operationMode);
982 tools.add(iterationEnabled);
984 tools.add(iterationLimit);
986 tools.add(expression);
989 panel.add(scroll, BorderLayout.CENTER);
995 private boolean isRectangularSelection(SpreadsheetTable table) {
996 int[] selectedColumns = table.getSelectedColumns();
997 int[] selectedRows = table.getSelectedRows();
999 if ((selectedColumns.length == 0) || (selectedRows.length == 0)) {
1003 for (int row = 0; row < selectedRows.length - 1; row++) {
1004 if (selectedRows[row + 1] != selectedRows[row] + 1) {
1009 for (int column = 0; column < selectedColumns.length - 1; column++) {
1010 if (selectedColumns[column + 1] != selectedColumns[column] + 1) {
1018 private void editSelection(String property, Object value, Binding binding) {
1019 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
1020 if(editor == null) return;
1022 // Transaction transaction = editor.startTransaction();
1023 editSelection(editor, null, property, value, binding);
1024 // transaction.commit();
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);
1037 private void editSelectionAlignment(Integer horizontal, Integer vertical) {
1038 final int[] selectedColumns = table.getSelectedColumns();
1039 final int[] selectedRows = table.getSelectedRows();
1041 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
1042 if(editor == null) return;
1044 // Transaction transaction = editor.startTransaction();
1045 for(int col : selectedColumns) {
1046 for(int row : selectedRows) {
1047 String location = SpreadsheetUtils.cellName(row, col);
1049 CellValue value = (CellValue)table.getValueAt(row, col);
1050 int align = value != null ? value.align : 0;
1052 if (horizontal != null) {
1053 align = (align & 12) + horizontal;
1055 if (vertical != null) {
1056 align = (align & 3) + (vertical << 2);
1059 // editor.edit(transaction, location, ClientModel.ALIGN, align, Bindings.INTEGER);
1060 editor.edit(null, location, ClientModel.ALIGN, align, Bindings.INTEGER, null);
1064 // transaction.commit();
1067 public ClientModel getClientInterface() {
1073 public void setSources() {
1074 // If expression fields are not visible, do nothing.
1075 if (inputSource == null)
1078 String[] available = (String[])getClientModel().getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_AVAILABLE);
1079 String current = (String)getClientModel().getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_CURRENT);
1081 inputSource.removeItemListener(itemListener);
1082 inputSource.removeAllItems();
1083 for(String a : available)
1084 inputSource.addItem(a);
1085 inputSource.setSelectedItem(current);
1086 inputSource.addItemListener(itemListener);