1 /*******************************************************************************
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * VTT Technical Research Centre of Finland - initial API and implementation
10 *******************************************************************************/
11 package org.simantics.spreadsheet.ui;
13 import java.awt.Color;
15 import java.util.concurrent.atomic.AtomicBoolean;
17 import javax.swing.table.DefaultTableModel;
19 import org.simantics.spreadsheet.ClientModel;
20 import org.simantics.spreadsheet.ClientModel.ClientModelListener;
21 import org.simantics.spreadsheet.OperationMode;
22 import org.simantics.spreadsheet.Spreadsheets;
23 import org.simantics.spreadsheet.solver.SpreadsheetStyle;
24 import org.simantics.spreadsheet.util.SpreadsheetUtils;
25 import org.simantics.ui.colors.Colors;
26 import org.simantics.ui.fonts.Fonts;
27 import org.simantics.utils.threads.AWTThread;
29 final public class ClientTableModel extends DefaultTableModel {
31 private static final long serialVersionUID = 226747623479756815L;
32 private final ClientModel model;
34 public ClientTableModel(ClientModel model) {
38 public void setModel(final SpreadsheetModel model) {
40 final SpreadsheetTable table = model.getTable();
42 this.model.addListener(new ClientModelListener() {
44 private AtomicBoolean dirtyStructure = new AtomicBoolean(false);
45 private AtomicBoolean dirtyHeaderSizes = new AtomicBoolean(false);
46 private AtomicBoolean dirtyValues = new AtomicBoolean(false);
47 private AtomicBoolean dirtySources = new AtomicBoolean(false);
50 public void columnLabels(String[] labels) {
51 dirtyStructure.set(true);
55 public void rowLabels(String[] labels) {
56 dirtyStructure.set(true);
60 public void rows(int amount) {
61 dirtyStructure.set(true);
65 public void columns(int amount) {
66 dirtyStructure.set(true);
70 public void sources(final String[] available, final String current) {
71 dirtySources.set(true);
75 public void columnWidths(int[] widths) {
76 dirtyHeaderSizes.set(true);
80 public void cleared(String location) {
81 dirtyValues.set(true);
85 public void propertyChange(String location, String property, Object value) {
86 dirtyValues.set(true);
92 final boolean structure = dirtyStructure.compareAndSet(true, false);
93 final boolean values = dirtyValues.compareAndSet(true, false);
94 final boolean headerSizes = dirtyHeaderSizes.compareAndSet(true, false);
95 final boolean sources = dirtySources.compareAndSet(true, false);
98 AWTThread.getThreadAccess().asyncExec(new Runnable() {
108 if (Spreadsheet.DEBUG)
109 System.out.println("ClientTableModel.ClientModelListener.flush: structure=" + structure + ", values=" + values + ", headerSizes=" + headerSizes);
111 if(structure || values || headerSizes) {
113 AWTThread.getThreadAccess().asyncExec(new Runnable() {
118 int[] cc = table.getSelectedColumns();
119 int[] rc = table.getSelectedRows();
121 if(structure) fireTableStructureChanged();
122 if(values) fireTableDataChanged();
125 table.applyHeaderSizes(ClientTableModel.this.model);
127 if(rc.length == 1 && cc.length == 1) {
128 table.setColumnSelectionInterval(cc[0], cc[0]);
129 table.setRowSelectionInterval(rc[0], rc[0]);
145 public Object getValueAt(int row, int column) {
146 String location = Spreadsheets.cellName(row, column);
148 // System.out.println("CellValue for location " + location);
150 Color foregroundColor = null;
151 Color backgroundColor = null;
155 String formatString = null;
157 SpreadsheetStyle style = model.getPropertyAt(location, "style");
159 foregroundColor = style.foreground != null ? Colors.awt(style.foreground) : null;
160 backgroundColor = style.background != null ? Colors.awt(style.background) : null;
161 font = style.font != null ? Fonts.awt(style.font) : null;
162 alignValue = style.align;
163 borderValue = style.border;
165 formatString = style.formatString;
166 formatIndex = style.formatIndex;
169 Boolean editable = model.getPropertyAt(location, "editable");
170 boolean editableValue = editable != null ? editable : false;
172 OperationMode currentMode = model.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);
173 if (!OperationMode.OPERATION.equals(currentMode))
174 editableValue = true;
176 return new CellValue(SpreadsheetUtils.getFormattedLabel(model, row, column, formatIndex, formatString), font, foregroundColor, backgroundColor, borderValue, alignValue, editableValue);
180 public int getColumnCount() {
181 return model.getColumns();
185 public String getColumnName(int column) {
186 String[] names = model.getPropertyAt(ClientModel.HEADERS, ClientModel.HEADERS_COL_LABELS);
187 if(column < names.length) return names[column];
188 else return super.getColumnName(column);
192 public int getRowCount() {
193 //TODO: haxx for initialization
194 if(model == null) return 0;
195 return model.getRows();
198 // void applyHeaderSizes() {
202 //// synchronized void applyDimensions() {
204 //// boolean fitRows = model.getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_FIT_ROWS);
205 //// boolean fitColumns = model.getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_FIT_COLS);
207 //// int currentRows = getRowCount();
208 //// int currentCols = getColumnCount();
210 //// int maxRow = model.getRows();
211 //// int maxColumn = model.getColumns();
213 //// int rowCount = model.getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_ROW_COUNT);
214 //// int columnCount = model.getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_COL_COUNT);
216 //// if(Spreadsheet.DEBUG) {
217 //// System.out.println("SimpleContainerTableModel.applyDimensions " + Thread.currentThread().getName());
218 //// System.out.println("-current model rows " + currentRows);
219 //// System.out.println("-current model cols " + currentCols);
220 ////// if(listener != null) {
221 ////// System.out.println("-current table rows " + table.getRowModel().getSize());
222 ////// System.out.println("-current table cols " + table.getColumnModel().getColumnCount());
224 //// System.out.println("-target rows " + rowCount);
225 //// System.out.println("-target cols " + columnCount);
226 //// System.out.println("-fit rows " + fitRows);
227 //// System.out.println("-fit cols " + fitColumns);
231 //// if(maxRow != currentRows) {
232 //// setRowCount(maxRow);
233 //// if(table != null) table.getRowModel().setSize(maxRow);
234 //// setColumnWidths();
237 //// if(rowCount != currentRows) {
238 //// setRowCount(rowCount);
239 //// if(table != null) table.getRowModel().setSize(rowCount);
240 //// setColumnWidths();
243 //// if(fitColumns) {
244 //// if(maxColumn != currentCols) {
245 //// setColumnCount(maxColumn);
246 ////// applyLabels();
247 //// setColumnWidths();
250 //// if(columnCount != currentCols) {
251 //// setColumnCount(columnCount);
252 ////// applyLabels();
253 //// setColumnWidths();
259 //// private synchronized void applyLabels() {
261 //// if(Spreadsheet.DEBUG) System.out.println("SimpleContainerTableModel.applyLabels");
263 //// for(Map.Entry<String, HashMap<String, Object>> e : cells.entrySet()) {
264 //// String location = e.getKey();
265 //// Range r = SpreadsheetUtils.decodeCellAbsolute(location);
266 //// if(r.startRow >= getRowCount() || r.startColumn >= getColumnCount()) continue;
267 //// String label = (String)e.getValue().get("Label");
268 //// if(Spreadsheet.DEBUG) System.out.println("setLabel '" + label + "' at " + location + " " + getRowCount() + " " + getColumnCount());
269 //// setValueAt(label, r.startRow, r.startColumn);
274 // private synchronized void setColumnWidths() {
276 // if(Spreadsheet.DEBUG) System.out.println("SimpleContainerTableModel.setColumnWidths");
278 // if(table != null) {
280 // int[] columnWidths = model.getPropertyAt(ClientModel.HEADERS, ClientModel.HEADERS_COL_WIDTHS);
282 // int columnCount = table.getColumnModel().getColumnCount();
284 // for(int i = 0; i < columnWidths.length && i < columnCount ; i++)
286 // TableColumn column = table.getColumnModel().getColumn(i);
287 // int preferred = columnWidths[i];
289 // column.setPreferredWidth(preferred);
296 // synchronized String[] createColumnIdentifiers(String[] defined) {
298 // int currentCols = getColumnCount();
299 // String[] identifiers = new String[currentCols];
301 // for(;i<defined.length && i<currentCols;i++) {
302 // identifiers[i] = defined[i];
304 // for(;i<currentCols;i++) {
305 // identifiers[i] = SpreadsheetUtils.columnName(i);
307 // return identifiers;
312 // public String getColumnName(int column) {
313 // new Exception("getColumnName " + column).printStackTrace();
314 // String[] names = model.getPropertyAt(ClientModel.HEADERS, ClientModel.HEADERS_COL_LABELS);
315 // if(column < names.length) return names[column];
316 // else return super.getColumnName(column);
319 // synchronized void applyHeaders() {
321 // AWTThread.getThreadAccess().asyncExec(new Runnable() {
324 // public void run() {
326 // String[] columnLabels = model.getPropertyAt(ClientModel.HEADERS, ClientModel.HEADERS_COL_LABELS);
327 // String[] filledColumnLabels = createColumnIdentifiers(columnLabels);
328 // String[] rowLabels = model.getPropertyAt(ClientModel.HEADERS, ClientModel.HEADERS_ROW_LABELS);
330 // if(Spreadsheet.DEBUG) {
331 // System.out.println("SimpleContainerTableModel.applyHeaders");
332 // System.out.println("-columnLabels=" + Arrays.toString(columnLabels));
333 // System.out.println("-filledColumnLabels=" + Arrays.toString(filledColumnLabels));
334 // System.out.println("-rowLabels=" + Arrays.toString(rowLabels));
337 // setColumnIdentifiers(filledColumnLabels);
339 //// if(listener != null) {
340 //// listener.rowLabels(rowLabels);
343 // if(table != null) {
344 // table.getRowModel().ensureCapacity(rowLabels.length);
346 // for(;i<rowLabels.length && i<table.getRowModel().size();i++) {
347 // table.getRowModel().setElementAt(rowLabels[i], i);
349 // for(;i<rowLabels.length;i++) {
350 // table.getRowModel().addElement(rowLabels[i]);