package org.simantics.spreadsheet.ui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Font; import java.awt.Frame; import java.awt.Image; import java.awt.Rectangle; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.DefaultListModel; import javax.swing.ImageIcon; import javax.swing.InputMap; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JColorChooser; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.JToggleButton; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.TableColumn; import org.eclipse.core.runtime.Platform; import org.eclipse.swt.widgets.Display; import org.simantics.databoard.Bindings; import org.simantics.databoard.binding.Binding; import org.simantics.datatypes.literal.RGB; import org.simantics.scenegraph.INode; import org.simantics.scenegraph.swing.JScrollPaneSG; import org.simantics.spreadsheet.Adaptable; import org.simantics.spreadsheet.CellEditor; import org.simantics.spreadsheet.CellEditor.Transaction; import org.simantics.spreadsheet.ClientModel; import org.simantics.spreadsheet.ClientModel.OperationMode; import org.simantics.spreadsheet.SheetCommands; import org.simantics.spreadsheet.common.cell.Parsers; import org.simantics.spreadsheet.common.cell.StringCellParser; import org.simantics.spreadsheet.event.model.RemoveCellHandler; import org.simantics.spreadsheet.util.SpreadsheetUtils; import org.simantics.ui.colors.Colors; import org.simantics.ui.dnd.LocalObjectTransfer; import org.simantics.ui.dnd.LocalObjectTransferable; import org.simantics.ui.fonts.Fonts; import org.simantics.utils.ui.dialogs.ShowMessage; import org.simantics.utils.ui.awt.WrapLayout; import org.simantics.utils.ui.jface.ActiveSelectionProvider; @SuppressWarnings({ "rawtypes", "unchecked" }) public class SpreadsheetModel { final private Adaptable serverInterface; final private ClientModel clientModel; final private ActiveSelectionProvider selectionProvider; protected Clipboard system; protected StringCellParser[] parsers = new StringCellParser[] { Parsers.COMMAND_PARSER, Parsers.EXPRESSION_PARSER, Parsers.TEXT_PARSER }; public SpreadsheetModel(Adaptable serverInterface, ActiveSelectionProvider selectionProvider) { this.serverInterface = serverInterface; this.clientModel = new ClientModelImpl(); this.selectionProvider = selectionProvider; } public ClientModel getClientModel() { return clientModel; } public SpreadsheetTable getTable() { return table; } private JTextField expression; private JButton foreground; private JButton background; private JButton font; private JButton align_left; private JButton align_hcenter; private JButton align_right; private JButton align_top; private JButton align_vcenter; private JButton align_bottom; private JComboBox borders; public JComboBox inputSource; public JComboBox sheets; private JButton lock; private JButton unlock; private JButton merge; private JButton unmerge; private ExpressionTextListener etl; private SpreadsheetTable table; @SuppressWarnings("unused") private ExcelAdapter excel; @SuppressWarnings("unused") private boolean columnMarginsDirty = false; private ItemListener itemListener = null; private ItemListener sheetsListener = null; private ItemListener initialConditionsListener = null; private JComboBox initialConditions; private JButton saveIc; private JButton context; private JToggleButton operationMode; private JCheckBox iterationEnabled; private JTextField iterationLimit; public JComponent createComponent(final INode node) { Properties props = serverInterface.getAdapter(Properties.class); boolean addExpressionField = props == null || "true".equalsIgnoreCase(props.getProperty(SpreadsheetModelProperties.SHEET_EXPRESSION_VISIBLE, "true")); final JPanel panel = new JPanel(new BorderLayout()); final DefaultListModel lm = new DefaultListModel() { private static final long serialVersionUID = 5246691801867533053L; public Object getElementAt(int index) { Object result = super.getElementAt(index); if(result instanceof String) return result; else return "" + (index + 1); } }; if (addExpressionField) { foreground = new JButton(); foreground.setToolTipText("Assign foreground color to selection"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/paintbrush.png")); foreground.setIcon(new ImageIcon(img)); } catch (IOException ex) { } foreground.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Color c = JColorChooser.showDialog(foreground, "asd", Colors.awt(Colors.rgb(0, 0, 0))); if (c == null) return; RGB.Integer color = Colors.integerRGB(c); editSelection(ClientModel.FOREGROUND, color, RGB.Integer.BINDING); } }); background = new JButton(); background.setToolTipText("Assign background color to selection"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/paintcan.png")); background.setIcon(new ImageIcon(img)); } catch (IOException ex) { } background.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Color c = JColorChooser.showDialog(background, "asd", Colors.awt(Colors.rgb(0, 0, 0))); if (c == null) return; RGB.Integer color = Colors.integerRGB(c); editSelection(ClientModel.BACKGROUND, color, RGB.Integer.BINDING); } }); String[] availableInitialConditions = clientModel.getPossiblePropertyAt(ClientModel.STATES, ClientModel.STATES_AVAILABLE); String currentInitialCondition = clientModel.getPossiblePropertyAt(ClientModel.STATES, ClientModel.STATES_CURRENT); initialConditions = new JComboBox<>(); for(String sheet : availableInitialConditions) initialConditions.addItem(sheet); initialConditions.setSelectedItem(currentInitialCondition); initialConditionsListener = new ItemListener() { @Override public void itemStateChanged(ItemEvent arg0) { CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor != null) { if(arg0.getStateChange() == ItemEvent.SELECTED) editor.edit(null, ClientModel.STATES, ClientModel.STATES_CURRENT, arg0.getItem(), null, null); } } }; initialConditions.addItemListener(initialConditionsListener); saveIc = new JButton(); saveIc.setText("Save IC"); saveIc.setToolTipText("Save current Initial Condition"); saveIc.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { SheetCommands commands = serverInterface.getAdapter(SheetCommands.class); commands.saveState(); } }); font = new JButton(); font.setToolTipText("Assign font to selection"); font.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JFontChooser fontChooser = new JFontChooser(); int result = fontChooser.showDialog(font); if (result == JFontChooser.OK_OPTION) { Font font = fontChooser.getSelectedFont(); System.out.println("Selected Font : " + font); org.simantics.datatypes.literal.Font f = Fonts.fromAWT(font); editSelection(ClientModel.FONT, f, org.simantics.datatypes.literal.Font.BINDING); } } }); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/font.png")); font.setIcon(new ImageIcon(img)); } catch (IOException ex) { } align_left = new JButton(); align_left.setToolTipText("Align selection to left"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_left.png")); align_left.setIcon(new ImageIcon(img)); } catch (IOException ex) { } align_left.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { editSelectionAlignment(0, null); } }); align_hcenter = new JButton(); align_hcenter.setToolTipText("Align selection horizontally to center"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_center.png")); align_hcenter.setIcon(new ImageIcon(img)); } catch (IOException ex) { } align_hcenter.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { editSelectionAlignment(1, null); } }); align_right = new JButton(); align_right.setToolTipText("Align selection to right"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_right.png")); align_right.setIcon(new ImageIcon(img)); } catch (IOException ex) { } align_right.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { editSelectionAlignment(2, null); } }); align_top = new JButton(); align_top.setToolTipText("Align selection to top"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_top.png")); align_top.setIcon(new ImageIcon(img)); } catch (IOException ex) { } align_top.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { editSelectionAlignment(null, 0); } }); align_vcenter = new JButton(); align_vcenter.setToolTipText("Align selection vertically to center"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_middle.png")); align_vcenter.setIcon(new ImageIcon(img)); } catch (IOException ex) { } align_vcenter.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { editSelectionAlignment(null, 1); } }); align_bottom = new JButton(); align_bottom.setToolTipText("Align selection to bottom"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/shape_align_bottom.png")); align_bottom.setIcon(new ImageIcon(img)); } catch (IOException ex) { } align_bottom.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { editSelectionAlignment(null, 2); } }); borders = new JComboBox(); borders.addItem("No borders"); borders.addItem("Bottom border"); borders.addItem("Top border"); borders.addItem("Left border"); borders.addItem("Right border"); borders.addActionListener(new ActionListener() { Map work = new HashMap(); int getCurrent(String location, int row, int column) { CellValue value = (CellValue)table.getValueAt(row, column); int border = value != null ? value.border : 0; work.put(location, border); return border; } void setCurrent(String location, int border) { work.put(location, border); } @Override public void actionPerformed(ActionEvent e) { work.clear(); int index = borders.getSelectedIndex(); final int[] selectedColumns = table.getSelectedColumns(); final int[] selectedRows = table.getSelectedRows(); CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor == null) return; for(int col : selectedColumns) { for(int row : selectedRows) { String location = SpreadsheetUtils.cellName(row, col); // No if(index == 0) { if(col > 0) { String left = SpreadsheetUtils.cellName(row, col-1); setCurrent(left, getCurrent(left, row, col-1) & 2); } if(row > 0) { String up = SpreadsheetUtils.cellName(row-1, col); setCurrent(up, getCurrent(up, row-1, col) & 1); } setCurrent(location, 0); } // Bottom else if(index == 1) { setCurrent(location, getCurrent(location, row, col) | 2); } // Top else if(index == 2) { if(row > 0) { String up = SpreadsheetUtils.cellName(row-1, col); setCurrent(up, getCurrent(up, row-1, col) | 2); } } // Left else if(index == 3) { if(col > 0) { String left = SpreadsheetUtils.cellName(row, col-1); setCurrent(left, getCurrent(left, row, col-1) | 1); } } // Right else if(index == 4) { setCurrent(location, getCurrent(location, row, col) | 1); } } } OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT); Transaction transaction = editor.startTransaction(mode); for(Map.Entry entry : work.entrySet()) { String location = entry.getKey(); Integer border = entry.getValue(); editor.edit(transaction, location, ClientModel.BORDER, border, Bindings.INTEGER, null); } transaction.commit(); } }); lock = new JButton(); lock.setToolTipText("Lock selection"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/lock.png")); lock.setIcon(new ImageIcon(img)); } catch (IOException ex) { } lock.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { editSelection(ClientModel.LOCKED, true, Bindings.BOOLEAN); } }); unlock = new JButton(); unlock.setToolTipText("Unlock selection"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/lock_open.png")); unlock.setIcon(new ImageIcon(img)); } catch (IOException ex) { } unlock.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { editSelection(ClientModel.LOCKED, false, Bindings.BOOLEAN); } }); merge = new JButton(); merge.setToolTipText("Merge cells"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/link.png")); merge.setIcon(new ImageIcon(img)); } catch (IOException ex) { } merge.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final int[] selectedColumns = table.getSelectedColumns(); final int[] selectedRows = table.getSelectedRows(); if (isRectangularSelection(table)) { CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor == null) return; OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT); Transaction transaction = editor.startTransaction(mode); Rectangle selection = new Rectangle(selectedColumns[0], selectedRows[0], selectedColumns.length, selectedRows.length); List spans = clientModel.getSpans(); boolean found = true; while (found) { found = false; Iterator iter = spans.iterator(); while (iter.hasNext()) { Rectangle span = iter.next(); if (selection.intersects(span)) { selection = selection.union(span); found = true; String location = SpreadsheetUtils.cellName(span.y, span.x); editor.edit(transaction, location, ClientModel.ROW_SPAN, 1, Bindings.INTEGER, null); editor.edit(transaction, location, ClientModel.COLUMN_SPAN, 1, Bindings.INTEGER, null); iter.remove(); } } } String location = SpreadsheetUtils.cellName(selection.y, selection.x); if (selection.height > 1) { editor.edit(transaction, location, ClientModel.ROW_SPAN, selection.height, Bindings.INTEGER, null); } if (selection.width > 1) { editor.edit(transaction, location, ClientModel.COLUMN_SPAN, selection.width, Bindings.INTEGER, null); } transaction.commit(); } else { //ShowMessage.showError(, message); Display.getDefault().asyncExec(new Runnable() { public void run() { ShowMessage.showWarning("Merging cells failed", "Selected range is not rectangular."); } }); } } }); unmerge = new JButton(); unmerge.setToolTipText("Unmerge cells"); try { Image img = ImageIO.read(Platform.getBundle("com.famfamfam.silk").getResource("icons/link_break.png")); unmerge.setIcon(new ImageIcon(img)); } catch (IOException ex) { } unmerge.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor == null) return; OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT); Transaction transaction = editor.startTransaction(mode); editSelection(editor, transaction, ClientModel.ROW_SPAN, 1, Bindings.INTEGER); editSelection(editor, transaction, ClientModel.COLUMN_SPAN, 1, Bindings.INTEGER); transaction.commit(); } }); String[] availableSources = clientModel.getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_AVAILABLE); String[] availableSheets = clientModel.getPossiblePropertyAt(ClientModel.SHEETS, ClientModel.SHEETS_AVAILABLE); String currentSheet = clientModel.getPossiblePropertyAt(ClientModel.SHEETS, ClientModel.SHEETS_CURRENT); @SuppressWarnings("unused") String currentSource = clientModel.getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_CURRENT); inputSource = new JComboBox(); for(String source : availableSources) inputSource.addItem(source); sheets = new JComboBox(); for(String sheet : availableSheets) sheets.addItem(sheet); sheets.setSelectedItem(currentSheet); sheetsListener = new ItemListener() { @Override public void itemStateChanged(ItemEvent arg0) { CellEditor editor = serverInterface.getAdapter(CellEditor.class); if (editor != null) { if (arg0.getStateChange() == ItemEvent.SELECTED) editor.edit(null, ClientModel.SHEETS, ClientModel.SHEETS_CURRENT, arg0.getItem(), null, null); } } }; itemListener = new ItemListener() { @Override public void itemStateChanged(ItemEvent arg0) { CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor != null) { if(arg0.getStateChange() == ItemEvent.SELECTED) editor.edit(null, ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, arg0.getItem(), null, null); } } }; inputSource.addItemListener(itemListener); new DropTarget(inputSource,DnDConstants.ACTION_COPY_OR_MOVE,new DropTargetListener() { @Override public void dropActionChanged(DropTargetDragEvent arg0) { // TODO Auto-generated method stub } @Override public void drop(DropTargetDropEvent dtde) { try { Transferable transferable = dtde.getTransferable(); if( transferable.isDataFlavorSupported( LocalObjectTransferable.FLAVOR ) ) { dtde.acceptDrop( DnDConstants.ACTION_MOVE ); transferable.getTransferData(LocalObjectTransferable.FLAVOR ); Object obj = LocalObjectTransfer.getTransfer().getObject(); CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor != null) { editor.edit(null, ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, obj, null, null); } dtde.getDropTargetContext().dropComplete( true ); } else { dtde.rejectDrop(); } } catch( IOException exception ) { exception.printStackTrace(); dtde.rejectDrop(); } catch( UnsupportedFlavorException ufException ) { ufException.printStackTrace(); dtde.rejectDrop(); } } @Override public void dragOver(DropTargetDragEvent arg0) { // TODO Auto-generated method stub } @Override public void dragExit(DropTargetEvent arg0) { // TODO Auto-generated method stub } @Override public void dragEnter(DropTargetDragEvent arg0) { // TODO Auto-generated method stub } }); expression = new JTextField(); etl = new ExpressionTextListener(expression, serverInterface.getAdapter(CellEditor.class)); expression.addFocusListener(etl); expression.addKeyListener(etl); sheets.addItemListener(sheetsListener); context = new JButton("Change context"); context.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Frame frame = (Frame) SwingUtilities.getRoot(context); String result = JOptionPane.showInputDialog(frame, "Context URI"); if (result != null && !result.isEmpty()) { CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor != null) { editor.edit(null, ClientModel.CONTEXT, ClientModel.CONTEXT_CURRENT, result, null, null); } } } }); OperationMode currentMode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT); String text; if (currentMode.equals(OperationMode.OPERATION)) text = "Operation Mode"; else text = "Edit Mode"; operationMode = new JToggleButton(text); operationMode.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { OperationMode currentMode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT); OperationMode newMode; String newText; if (currentMode.equals(OperationMode.OPERATION)) { System.err.println("Current mode is operation"); newMode = OperationMode.EDIT_MODE; newText = "Edit Mode"; } else { System.err.println("Current mode is read-only"); newMode = OperationMode.OPERATION; newText = "Operation Mode"; } System.err.println("Setting new text " + newText + " to replace old " + operationMode.getText()); operationMode.setText(newText); CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor != null) { editor.edit(null, ClientModel.MODE, ClientModel.MODE_CURRENT, newMode, null, null); } } }); iterationEnabled = new JCheckBox("Iteration Enabled"); iterationEnabled.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("state is " + iterationEnabled.isSelected()); CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor != null) { editor.edit(null, ClientModel.ITERATION_ENABLED, ClientModel.ITERATION_ENABLED, iterationEnabled.isSelected(), null, null); } } }); iterationLimit = new JTextField("100"); iterationLimit.setEnabled(false); iterationLimit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { } }); } Font font = new Font("Courier", Font.PLAIN, 14); UIManager.put(SpreadsheetTable.uiClassID, SpreadsheetTableUI.class.getCanonicalName()); final JList rowHeader = new JList(lm); table = new SpreadsheetTable(node, (CellEditor)serverInterface.getAdapter(CellEditor.class), clientModel, lm, rowHeader) { private static final long serialVersionUID = 4553572254034185984L; @Override protected void mouseDragFinished() { CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor == null) return; TableColumn column = table.getTableHeader().getResizingColumn(); if(column == null) return; int[] current = clientModel.getColumnWidths(); if(column.getModelIndex() >= current.length) { current = Arrays.copyOf(current, column.getModelIndex()+1); } current[column.getModelIndex()] = column.getWidth(); editor.edit(null, ClientModel.HEADERS, ClientModel.HEADERS_COL_WIDTHS, current, Bindings.INT_ARRAY, null); } }; ((ClientTableModel)table.getModel()).setModel(this); InputMap im = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); Action deleteAction = new AbstractAction() { private static final long serialVersionUID = 428343700053346645L; @SuppressWarnings("unused") public void actionPerformed(ActionEvent ae) { System.out.println("deleteaction"); RemoveCellHandler removeHandler = serverInterface.getAdapter(RemoveCellHandler.class); int[] rowSelection = table.getSelectedRows(); int[] columnSelection = table.getSelectedColumns(); for (int i = 0; i < columnSelection.length; i++) { for (int j = 0; j < rowSelection.length; j++) { int row = rowSelection[j]; int column = columnSelection[i]; System.out.println("deleteaction " + row + " " + column); Object cell = table.getValueAt(row, column); // RemoveHandler remove = cell.getAdapter(RemoveHandler.class); // remove.handle(); } } } }; KeyStroke delete = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), delete); table.getActionMap().put(im.get(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)), deleteAction); table.setFont(font); @SuppressWarnings("unused") DropTarget dropTarget = new DropTarget(table, new TableDropTargetListener(table, serverInterface, clientModel)); if(serverInterface != null) excel = new ExcelAdapter(table, clientModel, serverInterface, parsers); table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); table.setColumnSelectionAllowed(true); rowHeader.setFixedCellWidth(40); rowHeader.setCellRenderer(new RowHeaderRenderer(table)); rowHeader.setBackground(DefaultLookup.GRAY); table.getModel().addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent e) { int currentRows = rowHeader.getModel().getSize(); int tableRows = table.getModel().getRowCount(); if(currentRows != tableRows) { lm.setSize(tableRows); } } }); JScrollPaneSG scroll = new JScrollPaneSG(table, node); scroll.setRowHeaderView(rowHeader); table.getParent().setBackground(DefaultLookup.GRAY); table.getTableHeader().setBackground(DefaultLookup.GRAY); rowHeader.getParent().setBackground(DefaultLookup.GRAY); scroll.getViewport().setBackground(DefaultLookup.GRAY); table.getTableHeader().setDefaultRenderer(new ColumnHeaderRenderer()); scroll.setBackground(DefaultLookup.GRAY); if(selectionProvider != null) { SelectionListener listener = new SelectionListener(table, expression, etl, selectionProvider, serverInterface, clientModel); table.getSelectionModel().addListSelectionListener(listener); table.getColumnModel().getSelectionModel() .addListSelectionListener(listener); } table.getColumnModel().addColumnModelListener(new TableColumnModelListener() { @Override public void columnSelectionChanged(ListSelectionEvent e) { // System.out.println("columnSelectionChanged " + e); } @Override public void columnRemoved(TableColumnModelEvent e) { // System.out.println("columnRemoved " + e); } @Override public void columnMoved(TableColumnModelEvent e) { // System.out.println("columnMoved " + e); } @Override public void columnMarginChanged(ChangeEvent e) { columnMarginsDirty = true; } @Override public void columnAdded(TableColumnModelEvent e) { // System.out.println("columnAdded " + e); } }); new TableRowResizer(table) { @Override public void onResize(int row, int height) { if(row < 0) return; CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor == null) return; int[] current = clientModel.getRowHeights(); if(row >= current.length) { current = Arrays.copyOf(current, row+1); } current[row] = height; editor.edit(null, ClientModel.HEADERS, ClientModel.HEADERS_ROW_HEIGHTS, current, Bindings.INT_ARRAY, null); rowHeader.setCellRenderer(new RowHeaderRenderer(table)); } }; if (addExpressionField) { JPanel tools = new JPanel(new WrapLayout(FlowLayout.LEADING, 0, 0)); panel.add(tools, BorderLayout.PAGE_START); tools.add(this.font); tools.add(foreground); tools.add(background); tools.add(align_left); tools.add(align_hcenter); tools.add(align_right); tools.add(align_top); tools.add(align_vcenter); tools.add(align_bottom); tools.add(borders); tools.add(lock); tools.add(unlock); tools.add(merge); tools.add(unmerge); tools.add(inputSource); tools.add(sheets); tools.add(initialConditions); tools.add(saveIc); tools.add(context); tools.add(operationMode); tools.add(iterationEnabled); tools.add(iterationLimit); tools.add(expression); } panel.add(scroll, BorderLayout.CENTER); return panel; } private boolean isRectangularSelection(SpreadsheetTable table) { int[] selectedColumns = table.getSelectedColumns(); int[] selectedRows = table.getSelectedRows(); if ((selectedColumns.length == 0) || (selectedRows.length == 0)) { return false; } for (int row = 0; row < selectedRows.length - 1; row++) { if (selectedRows[row + 1] != selectedRows[row] + 1) { return false; } } for (int column = 0; column < selectedColumns.length - 1; column++) { if (selectedColumns[column + 1] != selectedColumns[column] + 1) { return false; } } return true; } private void editSelection(String property, Object value, Binding binding) { CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor == null) return; // Transaction transaction = editor.startTransaction(); editSelection(editor, null, property, value, binding); // transaction.commit(); } private void editSelection(CellEditor editor, Transaction transaction, String property, Object value, Binding binding) { for(int col : table.getSelectedColumns()) { for(int row : table.getSelectedRows()) { String location = SpreadsheetUtils.cellName(row, col); editor.edit(transaction, location, property, value, binding, null); } } } private void editSelectionAlignment(Integer horizontal, Integer vertical) { final int[] selectedColumns = table.getSelectedColumns(); final int[] selectedRows = table.getSelectedRows(); CellEditor editor = serverInterface.getAdapter(CellEditor.class); if(editor == null) return; // Transaction transaction = editor.startTransaction(); for(int col : selectedColumns) { for(int row : selectedRows) { String location = SpreadsheetUtils.cellName(row, col); CellValue value = (CellValue)table.getValueAt(row, col); int align = value != null ? value.align : 0; if (horizontal != null) { align = (align & 12) + horizontal; } if (vertical != null) { align = (align & 3) + (vertical << 2); } // editor.edit(transaction, location, ClientModel.ALIGN, align, Bindings.INTEGER); editor.edit(null, location, ClientModel.ALIGN, align, Bindings.INTEGER, null); } } // transaction.commit(); } public ClientModel getClientInterface() { return clientModel; } public void setSources() { // If expression fields are not visible, do nothing. if (inputSource == null) return; String[] available = (String[])getClientModel().getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_AVAILABLE); String current = (String)getClientModel().getPossiblePropertyAt(ClientModel.SOURCES, ClientModel.SOURCES_CURRENT); inputSource.removeItemListener(itemListener); inputSource.removeAllItems(); for(String a : available) inputSource.addItem(a); inputSource.setSelectedItem(current); inputSource.addItemListener(itemListener); } }