1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.spreadsheet.ui;
\r
14 import java.awt.Font;
\r
15 import java.awt.Point;
\r
16 import java.awt.Rectangle;
\r
17 import java.awt.event.KeyEvent;
\r
18 import java.util.Arrays;
\r
20 import javax.swing.DefaultListModel;
\r
21 import javax.swing.JList;
\r
22 import javax.swing.KeyStroke;
\r
23 import javax.swing.event.ChangeEvent;
\r
24 import javax.swing.event.ListSelectionEvent;
\r
25 import javax.swing.table.TableCellEditor;
\r
26 import javax.swing.table.TableColumn;
\r
27 import javax.swing.table.TableColumnModel;
\r
29 import org.simantics.scenegraph.INode;
\r
30 import org.simantics.scenegraph.swing.JTableSG;
\r
31 import org.simantics.spreadsheet.CellEditor;
\r
32 import org.simantics.spreadsheet.ClientModel;
\r
33 import org.simantics.spreadsheet.ClientModel.OperationMode;
\r
35 public class SpreadsheetTable extends JTableSG {
\r
37 public static final String uiClassID = "SpreadsheetTableUI";
\r
39 final private CellEditor cellEditor;
\r
40 private ClientModel clientModel;
\r
41 private final DefaultListModel rowModel;
\r
42 private final JList rowHeader;
\r
44 private static final long serialVersionUID = -4592686559195294773L;
\r
47 public int getRowHeight() {
\r
48 Font font = getFont();
\r
50 return font.getSize() + 4;
\r
52 return super.getRowHeight();
\r
57 public SpreadsheetTable(final INode node, final CellEditor cellEditor, final ClientModel clientModel, final DefaultListModel rowModel) {
\r
59 super(new ClientTableModel(clientModel), node);
\r
61 this.rowHeader = null;
\r
62 this.cellEditor = cellEditor;
\r
63 this.clientModel = clientModel;
\r
64 this.rowModel = rowModel;
\r
66 // ((ClientTableModel)getModel()).setTable(this);
\r
68 // InputMap im = this.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
\r
69 // Action deleteAction = new AbstractAction() {
\r
70 // public void actionPerformed(ActionEvent ae) {
\r
71 // System.out.println("deleteaction");
\r
72 // RemoveCellHandler removeHandler = serverInterface.getAdapter(RemoveCellHandler.class);
\r
73 // int[] rowSelection = getSelectedRows();
\r
74 // int[] columnSelection = getSelectedColumns();
\r
75 // for (int i = 0; i < columnSelection.length; i++) {
\r
76 // for (int j = 0; j < rowSelection.length; j++) {
\r
77 // int row = rowSelection[j];
\r
78 // int column = columnSelection[i];
\r
79 // System.out.println("deleteaction " + row + " " + column);
\r
80 // Object cell = getValueAt(row, column);
\r
81 //// RemoveHandler remove = cell.getAdapter(RemoveHandler.class);
\r
82 //// remove.handle();
\r
87 // KeyStroke delete = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
\r
88 // im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), delete);
\r
89 // getActionMap().put(im.get(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)), deleteAction);
\r
91 setDefaultRenderer(Object.class, new Renderer());
\r
98 public SpreadsheetTable(final INode node, final CellEditor cellEditor, final ClientModel clientModel, final DefaultListModel rowModel, JList rowHeader) {
\r
100 super(new ClientTableModel(clientModel), node);
\r
102 this.rowHeader = rowHeader;
\r
103 this.cellEditor = cellEditor;
\r
104 this.clientModel = clientModel;
\r
105 this.rowModel = rowModel;
\r
106 setDefaultRenderer(Object.class, new Renderer());
\r
108 setShowGrid(false);
\r
114 public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
\r
115 if (clientModel != null) {
\r
116 Rectangle span = clientModel.getSpan(row, column);
\r
117 if (span != null) {
\r
118 Rectangle rect1 = super.getCellRect(span.y, span.x, includeSpacing);
\r
119 Rectangle rect2 = super.getCellRect(span.y + span.height - 1, span.x + span.width - 1, includeSpacing);
\r
120 return rect1.union(rect2);
\r
123 return super.getCellRect(row, column, includeSpacing);
\r
127 public String getUIClassID() {
\r
132 public int rowAtPoint(Point p) {
\r
133 int row = super.rowAtPoint(p);
\r
137 int column = super.columnAtPoint(p);
\r
138 Rectangle span = clientModel.getSpan(row, column);
\r
139 if (span != null) {
\r
147 public int columnAtPoint(Point p) {
\r
148 int column = super.columnAtPoint(p);
\r
149 if (column == -1) {
\r
152 int row = super.rowAtPoint(p);
\r
153 Rectangle span = clientModel.getSpan(row, column);
\r
154 if (span != null) {
\r
162 public void valueChanged(ListSelectionEvent e) {
\r
163 super.valueChanged(e);
\r
168 public void columnSelectionChanged(ListSelectionEvent e) {
\r
169 super.columnSelectionChanged(e);
\r
174 public ClientModel getClientModel() {
\r
175 return clientModel;
\r
178 // wrapper function for SpreadsheetTableUI
\r
179 protected int rowAtPointWithoutSpan(Point p) {
\r
180 return super.rowAtPoint(p);
\r
183 // wrapper function for SpreadsheetTableUI
\r
184 protected int columnAtPointWithoutSpan(Point p) {
\r
185 return super.columnAtPoint(p);
\r
189 protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
\r
190 // turn off edit but still can cause actions
\r
191 if (e.getKeyCode()==KeyEvent.VK_DELETE) {
\r
192 //System.out.println("processKeyBinding delete");
\r
193 this.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
\r
194 boolean retvalue = super.processKeyBinding(ks, e, condition, pressed);
\r
195 this.putClientProperty("JTable.autoStartsEdit", Boolean.TRUE);
\r
198 boolean retValue = super.processKeyBinding(ks, e, condition, pressed);
\r
203 public TableCellEditor getCellEditor(int row, int column) {
\r
205 // CellEditor editor = serverInterface.getAdapter(CellEditor.class);
\r
206 if(cellEditor == null) return null;
\r
208 boolean editable = false;
\r
209 OperationMode mode = clientModel.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);
\r
210 if (!OperationMode.OPERATION.equals(mode))
\r
214 CellValue cellValue = (CellValue)getValueAt(row, column);
\r
215 editable = cellValue.editable;
\r
217 String initial = ((CellValue)getValueAt(row, column)).label;
\r
218 return new TextTableCellEditor(row, column, initial, cellEditor, clientModel);
\r
226 public void editingStopped(ChangeEvent e) {
\r
227 // Take in the new value
\r
228 SpreadsheetCellEditor editor = (SpreadsheetCellEditor)getCellEditor();
\r
229 if (editor != null) {
\r
230 int[] rc = getSelectedRows();
\r
233 if(rc.length == 1 && rc[0] < getRowCount() - 1)
\r
234 setRowSelectionInterval(rc[0]+1, rc[0]+1);
\r
238 public void applyRowLabels(String[] rowLabels) {
\r
240 if(Spreadsheet.DEBUG) System.out.println("Apply row labels: " + Arrays.toString(rowLabels));
\r
242 rowModel.ensureCapacity(rowLabels.length);
\r
244 for(;i<rowLabels.length && i<rowModel.size();i++) {
\r
245 rowModel.setElementAt(rowLabels[i], i);
\r
247 for(;i<rowLabels.length;i++) {
\r
248 rowModel.addElement(rowLabels[i]);
\r
253 public void applyHeaderSizes(ClientModel clientModel) {
\r
255 // TODO: initialization haxx
\r
256 if(clientModel == null) return;
\r
258 int[] rows = clientModel.getPropertyAt(ClientModel.HEADERS, ClientModel.HEADERS_ROW_HEIGHTS);
\r
259 int[] cols = clientModel.getPropertyAt(ClientModel.HEADERS, ClientModel.HEADERS_COL_WIDTHS);
\r
261 for(int i = 0; i < getColumnModel().getColumnCount() && i < cols.length ; i++) {
\r
262 TableColumn column = getColumnModel().getColumn(i);
\r
263 int preferred = cols[i];
\r
265 column.setPreferredWidth(preferred);
\r
268 if(rowHeader!=null)
\r
269 rowHeader.setCellRenderer(new RowHeaderRenderer(this));
\r
271 for(int i = 0; i<getRowCount() && i<rows.length ;i++) {
\r
273 setRowHeight(i, rows[i]);
\r
279 public void createDefaultColumnsFromModel() {
\r
280 super.createDefaultColumnsFromModel();
\r
281 applyHeaderSizes(clientModel);
\r
285 protected TableColumnModel createDefaultColumnModel() {
\r
286 TableColumnModel model = super.createDefaultColumnModel();
\r
287 model.setColumnMargin(0);
\r