1 package org.simantics.spreadsheet.ui;
3 import java.awt.BorderLayout;
5 import java.awt.FlowLayout;
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;
30 import java.util.Properties;
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;
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;
85 @SuppressWarnings({ "rawtypes", "unchecked" })
86 public class SpreadsheetModel {
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 };
94 public SpreadsheetModel(Adaptable serverInterface, ActiveSelectionProvider selectionProvider) {
96 this.serverInterface = serverInterface;
97 this.clientModel = new ClientModelImpl();
98 this.selectionProvider = selectionProvider;
102 public ClientModel getClientModel() {
106 public SpreadsheetTable getTable() {
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;
134 private ItemListener itemListener = null;
135 private ItemListener sheetsListener = null;
136 private ItemListener initialConditionsListener = null;
138 private JComboBox initialConditions;
139 private JButton saveIc;
140 private JButton context;
141 private JToggleButton operationMode;
143 private JCheckBox iterationEnabled;
144 private JTextField iterationLimit;
146 public JComponent createComponent(final INode node) {
148 Properties props = serverInterface.getAdapter(Properties.class);
150 boolean addExpressionField = props == null || "true".equalsIgnoreCase(props.getProperty(SpreadsheetModelProperties.SHEET_EXPRESSION_VISIBLE, "true"));
152 final JPanel panel = new JPanel(new BorderLayout());
154 final DefaultListModel lm = new DefaultListModel() {
156 private static final long serialVersionUID = 5246691801867533053L;
158 public Object getElementAt(int index) {
159 Object result = super.getElementAt(index);
160 if(result instanceof String) return result;
161 else return "" + (index + 1);
166 if (addExpressionField) {
168 foreground = new JButton();
169 foreground.setToolTipText("Assign foreground color to selection");
172 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/paintbrush.png"));
173 foreground.setIcon(new ImageIcon(img));
174 } catch (IOException ex) {
176 foreground.addActionListener(new ActionListener() {
178 public void actionPerformed(ActionEvent e) {
180 Color c = JColorChooser.showDialog(foreground, "asd", Colors.awt(Colors.rgb(0, 0, 0)));
183 RGB.Integer color = Colors.integerRGB(c);
185 editSelection(ClientModel.FOREGROUND, color, RGB.Integer.BINDING);
189 background = new JButton();
190 background.setToolTipText("Assign background color to selection");
193 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/paintcan.png"));
194 background.setIcon(new ImageIcon(img));
195 } catch (IOException ex) {
198 background.addActionListener(new ActionListener() {
200 public void actionPerformed(ActionEvent e) {
202 Color c = JColorChooser.showDialog(background, "asd", Colors.awt(Colors.rgb(0, 0, 0)));
206 RGB.Integer color = Colors.integerRGB(c);
208 editSelection(ClientModel.BACKGROUND, color, RGB.Integer.BINDING);
212 String[] availableInitialConditions = clientModel.getPossiblePropertyAt(ClientModel.STATES, ClientModel.STATES_AVAILABLE);
213 String currentInitialCondition = clientModel.getPossiblePropertyAt(ClientModel.STATES, ClientModel.STATES_CURRENT);
215 initialConditions = new JComboBox<>();
216 for(String sheet : availableInitialConditions)
217 initialConditions.addItem(sheet);
219 initialConditions.setSelectedItem(currentInitialCondition);
221 initialConditionsListener = new ItemListener() {
223 public void itemStateChanged(ItemEvent arg0) {
225 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
227 if(arg0.getStateChange() == ItemEvent.SELECTED)
228 editor.edit(null, ClientModel.STATES, ClientModel.STATES_CURRENT, arg0.getItem(), null, null);
233 initialConditions.addItemListener(initialConditionsListener);
235 saveIc = new JButton();
236 saveIc.setText("Save IC");
237 saveIc.setToolTipText("Save current Initial Condition");
238 saveIc.addActionListener(new ActionListener() {
241 public void actionPerformed(ActionEvent e) {
243 SheetCommands commands = serverInterface.getAdapter(SheetCommands.class);
244 commands.saveState();
248 font = new JButton();
249 font.setToolTipText("Assign font to selection");
251 font.addActionListener(new ActionListener() {
253 public void actionPerformed(ActionEvent e) {
254 JFontChooser fontChooser = new JFontChooser();
255 int result = fontChooser.showDialog(font);
256 if (result == JFontChooser.OK_OPTION) {
258 Font font = fontChooser.getSelectedFont();
259 System.out.println("Selected Font : " + font);
261 org.simantics.datatypes.literal.Font f = Fonts.fromAWT(font);
263 editSelection(ClientModel.FONT, f, org.simantics.datatypes.literal.Font.BINDING);
269 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/font.png"));
270 font.setIcon(new ImageIcon(img));
271 } catch (IOException ex) {
274 align_left = new JButton();
275 align_left.setToolTipText("Align selection to left");
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) {
283 align_left.addActionListener(new ActionListener() {
285 public void actionPerformed(ActionEvent e) {
286 editSelectionAlignment(0, null);
290 align_hcenter = new JButton();
291 align_hcenter.setToolTipText("Align selection horizontally to center");
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) {
299 align_hcenter.addActionListener(new ActionListener() {
301 public void actionPerformed(ActionEvent e) {
302 editSelectionAlignment(1, null);
306 align_right = new JButton();
307 align_right.setToolTipText("Align selection to right");
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) {
315 align_right.addActionListener(new ActionListener() {
317 public void actionPerformed(ActionEvent e) {
318 editSelectionAlignment(2, null);
322 align_top = new JButton();
323 align_top.setToolTipText("Align selection to top");
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) {
331 align_top.addActionListener(new ActionListener() {
333 public void actionPerformed(ActionEvent e) {
334 editSelectionAlignment(null, 0);
338 align_vcenter = new JButton();
339 align_vcenter.setToolTipText("Align selection vertically to center");
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) {
347 align_vcenter.addActionListener(new ActionListener() {
349 public void actionPerformed(ActionEvent e) {
350 editSelectionAlignment(null, 1);
354 align_bottom = new JButton();
355 align_bottom.setToolTipText("Align selection to bottom");
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) {
363 align_bottom.addActionListener(new ActionListener() {
365 public void actionPerformed(ActionEvent e) {
366 editSelectionAlignment(null, 2);
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() {
378 Map<String,Integer> work = new HashMap<String,Integer>();
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);
387 void setCurrent(String location, int border) {
388 work.put(location, border);
392 public void actionPerformed(ActionEvent e) {
396 int index = borders.getSelectedIndex();
398 final int[] selectedColumns = table.getSelectedColumns();
399 final int[] selectedRows = table.getSelectedRows();
401 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
402 if(editor == null) return;
404 for(int col : selectedColumns) {
405 for(int row : selectedRows) {
407 String location = SpreadsheetUtils.cellName(row, col);
412 String left = SpreadsheetUtils.cellName(row, col-1);
413 setCurrent(left, getCurrent(left, row, col-1) & 2);
416 String up = SpreadsheetUtils.cellName(row-1, col);
417 setCurrent(up, getCurrent(up, row-1, col) & 1);
419 setCurrent(location, 0);
422 else if(index == 1) {
423 setCurrent(location, getCurrent(location, row, col) | 2);
426 else if(index == 2) {
428 String up = SpreadsheetUtils.cellName(row-1, col);
429 setCurrent(up, getCurrent(up, row-1, col) | 2);
433 else if(index == 3) {
435 String left = SpreadsheetUtils.cellName(row, col-1);
436 setCurrent(left, getCurrent(left, row, col-1) | 1);
440 else if(index == 4) {
441 setCurrent(location, getCurrent(location, row, col) | 1);
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);
454 transaction.commit();
460 lock = new JButton();
461 lock.setToolTipText("Lock selection");
464 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/lock.png"));
465 lock.setIcon(new ImageIcon(img));
466 } catch (IOException ex) {
469 lock.addActionListener(new ActionListener() {
471 public void actionPerformed(ActionEvent e) {
472 editSelection(ClientModel.LOCKED, true, Bindings.BOOLEAN);
476 unlock = new JButton();
477 unlock.setToolTipText("Unlock selection");
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) {
485 unlock.addActionListener(new ActionListener() {
487 public void actionPerformed(ActionEvent e) {
488 editSelection(ClientModel.LOCKED, false, Bindings.BOOLEAN);
492 merge = new JButton();
493 merge.setToolTipText("Merge cells");
496 Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/link.png"));
497 merge.setIcon(new ImageIcon(img));
498 } catch (IOException ex) {
501 merge.addActionListener(new ActionListener() {
503 public void actionPerformed(ActionEvent e) {
505 final int[] selectedColumns = table.getSelectedColumns();
506 final int[] selectedRows = table.getSelectedRows();
508 if (isRectangularSelection(table)) {
510 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
511 if(editor == null) return;
513 OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);
514 Transaction transaction = editor.startTransaction(mode);
516 Rectangle selection = new Rectangle(selectedColumns[0], selectedRows[0], selectedColumns.length, selectedRows.length);
517 List<Rectangle> spans = clientModel.getSpans();
519 boolean found = true;
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);
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);
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);
540 if (selection.width > 1) {
541 editor.edit(transaction, location, ClientModel.COLUMN_SPAN, selection.width, Bindings.INTEGER, null);
543 transaction.commit();
546 //ShowMessage.showError(, message);
547 Display.getDefault().asyncExec(new Runnable() {
549 ShowMessage.showWarning("Merging cells failed", "Selected range is not rectangular.");
556 unmerge = new JButton();
557 unmerge.setToolTipText("Unmerge cells");
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) {
565 unmerge.addActionListener(new ActionListener() {
567 public void actionPerformed(ActionEvent e) {
569 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
570 if(editor == null) return;
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();
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);
586 inputSource = new JComboBox();
587 for(String source : availableSources)
588 inputSource.addItem(source);
590 sheets = new JComboBox();
591 for(String sheet : availableSheets)
592 sheets.addItem(sheet);
594 sheets.setSelectedItem(currentSheet);
596 sheetsListener = new ItemListener() {
599 public void itemStateChanged(ItemEvent arg0) {
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,
610 itemListener = new ItemListener() {
613 public void itemStateChanged(ItemEvent arg0) {
615 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
617 if(arg0.getStateChange() == ItemEvent.SELECTED)
618 editor.edit(null, ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, arg0.getItem(), null, null);
625 inputSource.addItemListener(itemListener);
627 new DropTarget(inputSource,DnDConstants.ACTION_COPY_OR_MOVE,new DropTargetListener() {
630 public void dropActionChanged(DropTargetDragEvent arg0) {
631 // TODO Auto-generated method stub
636 public void drop(DropTargetDropEvent dtde) {
639 Transferable transferable = dtde.getTransferable();
641 if( transferable.isDataFlavorSupported(
642 LocalObjectTransferable.FLAVOR ) ) {
644 dtde.acceptDrop( DnDConstants.ACTION_MOVE );
646 transferable.getTransferData(LocalObjectTransferable.FLAVOR );
647 Object obj = LocalObjectTransfer.getTransfer().getObject();
649 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
651 editor.edit(null, ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, obj, null, null);
654 dtde.getDropTargetContext().dropComplete( true );
660 } catch( IOException exception ) {
661 exception.printStackTrace();
663 } catch( UnsupportedFlavorException ufException ) {
664 ufException.printStackTrace();
671 public void dragOver(DropTargetDragEvent arg0) {
672 // TODO Auto-generated method stub
677 public void dragExit(DropTargetEvent arg0) {
678 // TODO Auto-generated method stub
683 public void dragEnter(DropTargetDragEvent arg0) {
684 // TODO Auto-generated method stub
690 expression = new JTextField();
691 etl = new ExpressionTextListener(expression, serverInterface.getAdapter(CellEditor.class));
692 expression.addFocusListener(etl);
693 expression.addKeyListener(etl);
695 sheets.addItemListener(sheetsListener);
698 context = new JButton("Change context");
700 context.addActionListener(new ActionListener() {
703 public void actionPerformed(ActionEvent e) {
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);
710 editor.edit(null, ClientModel.CONTEXT, ClientModel.CONTEXT_CURRENT, result, null, null);
716 OperationMode currentMode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);
718 if (currentMode.equals(OperationMode.OPERATION))
719 text = "Operation Mode";
722 operationMode = new JToggleButton(text);
723 operationMode.addActionListener(new ActionListener() {
726 public void actionPerformed(ActionEvent e) {
728 OperationMode currentMode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);
729 OperationMode newMode;
731 if (currentMode.equals(OperationMode.OPERATION)) {
732 System.err.println("Current mode is operation");
733 newMode = OperationMode.EDIT_MODE;
734 newText = "Edit Mode";
736 System.err.println("Current mode is read-only");
737 newMode = OperationMode.OPERATION;
738 newText = "Operation Mode";
740 System.err.println("Setting new text " + newText + " to replace old " + operationMode.getText());
741 operationMode.setText(newText);
743 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
745 editor.edit(null, ClientModel.MODE, ClientModel.MODE_CURRENT, newMode, null, null);
750 iterationEnabled = new JCheckBox("Iteration Enabled");
751 iterationEnabled.addActionListener(new ActionListener() {
754 public void actionPerformed(ActionEvent e) {
755 System.out.println("state is " + iterationEnabled.isSelected());
756 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
758 editor.edit(null, ClientModel.ITERATION_ENABLED, ClientModel.ITERATION_ENABLED, iterationEnabled.isSelected(), null, null);
763 iterationLimit = new JTextField("100");
764 iterationLimit.setEnabled(false);
765 iterationLimit.addActionListener(new ActionListener() {
768 public void actionPerformed(ActionEvent e) {
775 Font font = new Font("Courier", Font.PLAIN, 14);
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) {
781 private static final long serialVersionUID = 4553572254034185984L;
784 protected void mouseDragFinished() {
786 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
787 if(editor == null) return;
789 TableColumn column = table.getTableHeader().getResizingColumn();
790 if(column == null) return;
792 int[] current = clientModel.getColumnWidths();
793 if(column.getModelIndex() >= current.length) {
794 current = Arrays.copyOf(current, column.getModelIndex()+1);
797 current[column.getModelIndex()] = column.getWidth();
799 editor.edit(null, ClientModel.HEADERS, ClientModel.HEADERS_COL_WIDTHS, current, Bindings.INT_ARRAY, null);
805 ((ClientTableModel)table.getModel()).setModel(this);
807 InputMap im = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
808 Action deleteAction = new AbstractAction() {
809 private static final long serialVersionUID = 428343700053346645L;
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);
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);
835 @SuppressWarnings("unused")
836 DropTarget dropTarget = new DropTarget(table,
837 new TableDropTargetListener(table, serverInterface, clientModel));
839 if(serverInterface != null)
840 excel = new ExcelAdapter(table, clientModel, serverInterface, parsers);
842 table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
844 table.setColumnSelectionAllowed(true);
846 rowHeader.setFixedCellWidth(40);
848 rowHeader.setCellRenderer(new RowHeaderRenderer(table));
849 rowHeader.setBackground(DefaultLookup.GRAY);
851 table.getModel().addTableModelListener(new TableModelListener() {
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);
863 JScrollPaneSG scroll = new JScrollPaneSG(table, node);
865 scroll.setRowHeaderView(rowHeader);
867 table.getParent().setBackground(DefaultLookup.GRAY);
868 table.getTableHeader().setBackground(DefaultLookup.GRAY);
869 rowHeader.getParent().setBackground(DefaultLookup.GRAY);
870 scroll.getViewport().setBackground(DefaultLookup.GRAY);
872 table.getTableHeader().setDefaultRenderer(new ColumnHeaderRenderer());
874 scroll.setBackground(DefaultLookup.GRAY);
876 if(selectionProvider != null) {
878 SelectionListener listener = new SelectionListener(table, expression, etl, selectionProvider, serverInterface, clientModel);
879 table.getSelectionModel().addListSelectionListener(listener);
880 table.getColumnModel().getSelectionModel()
881 .addListSelectionListener(listener);
885 table.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
888 public void columnSelectionChanged(ListSelectionEvent e) {
889 // System.out.println("columnSelectionChanged " + e);
893 public void columnRemoved(TableColumnModelEvent e) {
894 // System.out.println("columnRemoved " + e);
898 public void columnMoved(TableColumnModelEvent e) {
899 // System.out.println("columnMoved " + e);
903 public void columnMarginChanged(ChangeEvent e) {
904 columnMarginsDirty = true;
908 public void columnAdded(TableColumnModelEvent e) {
909 // System.out.println("columnAdded " + e);
914 new TableRowResizer(table) {
917 public void onResize(int row, int height) {
921 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
922 if(editor == null) return;
924 int[] current = clientModel.getRowHeights();
925 if(row >= current.length) {
926 current = Arrays.copyOf(current, row+1);
929 current[row] = height;
931 editor.edit(null, ClientModel.HEADERS, ClientModel.HEADERS_ROW_HEIGHTS, current, Bindings.INT_ARRAY, null);
933 rowHeader.setCellRenderer(new RowHeaderRenderer(table));
939 if (addExpressionField) {
941 JPanel tools = new JPanel(new WrapLayout(FlowLayout.LEADING, 0, 0));
942 panel.add(tools, BorderLayout.PAGE_START);
944 tools.add(this.font);
946 tools.add(foreground);
948 tools.add(background);
950 tools.add(align_left);
951 tools.add(align_hcenter);
952 tools.add(align_right);
954 tools.add(align_top);
955 tools.add(align_vcenter);
956 tools.add(align_bottom);
966 tools.add(inputSource);
970 tools.add(initialConditions);
976 tools.add(operationMode);
978 tools.add(iterationEnabled);
980 tools.add(iterationLimit);
982 tools.add(expression);
985 panel.add(scroll, BorderLayout.CENTER);
991 private boolean isRectangularSelection(SpreadsheetTable table) {
992 int[] selectedColumns = table.getSelectedColumns();
993 int[] selectedRows = table.getSelectedRows();
995 if ((selectedColumns.length == 0) || (selectedRows.length == 0)) {
999 for (int row = 0; row < selectedRows.length - 1; row++) {
1000 if (selectedRows[row + 1] != selectedRows[row] + 1) {
1005 for (int column = 0; column < selectedColumns.length - 1; column++) {
1006 if (selectedColumns[column + 1] != selectedColumns[column] + 1) {
1014 private void editSelection(String property, Object value, Binding binding) {
1015 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
1016 if(editor == null) return;
1018 // Transaction transaction = editor.startTransaction();
1019 editSelection(editor, null, property, value, binding);
1020 // transaction.commit();
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);
1033 private void editSelectionAlignment(Integer horizontal, Integer vertical) {
1034 final int[] selectedColumns = table.getSelectedColumns();
1035 final int[] selectedRows = table.getSelectedRows();
1037 CellEditor editor = serverInterface.getAdapter(CellEditor.class);
1038 if(editor == null) return;
1040 // Transaction transaction = editor.startTransaction();
1041 for(int col : selectedColumns) {
1042 for(int row : selectedRows) {
1043 String location = SpreadsheetUtils.cellName(row, col);
1045 CellValue value = (CellValue)table.getValueAt(row, col);
1046 int align = value != null ? value.align : 0;
1048 if (horizontal != null) {
1049 align = (align & 12) + horizontal;
1051 if (vertical != null) {
1052 align = (align & 3) + (vertical << 2);
1055 // editor.edit(transaction, location, ClientModel.ALIGN, align, Bindings.INTEGER);
1056 editor.edit(null, location, ClientModel.ALIGN, align, Bindings.INTEGER, null);
1060 // transaction.commit();
1063 public ClientModel getClientInterface() {
1069 public void setSources() {
1070 // If expression fields are not visible, do nothing.
1071 if (inputSource == null)
1074 String[] available = (String[])getClientModel().getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_AVAILABLE);
1075 String current = (String)getClientModel().getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_CURRENT);
1077 inputSource.removeItemListener(itemListener);
1078 inputSource.removeAllItems();
1079 for(String a : available)
1080 inputSource.addItem(a);
1081 inputSource.setSelectedItem(current);
1082 inputSource.addItemListener(itemListener);