-/*******************************************************************************\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.spreadsheet.ui;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-\r
-import java.awt.Rectangle;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.concurrent.CopyOnWriteArrayList;\r
-\r
-import org.simantics.spreadsheet.ClientModel;\r
-import org.simantics.spreadsheet.util.SpreadsheetUtils;\r
-import org.simantics.utils.datastructures.Pair;\r
-import org.simantics.utils.datastructures.collections.CollectionUtils;\r
-\r
-public class ClientModelImpl implements ClientModel {\r
- \r
- final private Map<String, Map<String, Object>> properties = new THashMap<String, Map<String, Object>>();\r
- final private Map<String, Map<String, Object>> cells = new THashMap<String, Map<String, Object>>();\r
- \r
- private int maxRow = 0;\r
- private int maxColumn = 0;\r
- \r
- private Set<String> clears = new HashSet<String>();\r
-// private ArrayList<Triple<String, String, Object>> modifications = new ArrayList<Triple<String, String, Object>>();\r
- \r
- private ArrayList<String> modLocation = new ArrayList<String>();\r
- private ArrayList<String> modProperty = new ArrayList<String>();\r
- private ArrayList<Object> modValue = new ArrayList<Object>();\r
- private Map<Long, Rectangle> spanMap = new HashMap<Long, Rectangle>();\r
- \r
- public ClientModelImpl() {\r
-\r
- if(Spreadsheet.DEBUG) System.out.println("SimpleContainerTableModel.init");\r
-\r
- Map<String, Object> sheetDimensions = new THashMap<String, Object>();\r
- Map<String, Object> headers = new THashMap<String, Object>();\r
- Map<String, Object> excel = new THashMap<String, Object>();\r
- Map<String, Object> sources = new THashMap<String, Object>();\r
- Map<String, Object> sheets = new THashMap<String, Object>();\r
- Map<String, Object> context = new THashMap<String, Object>();\r
- Map<String, Object> mode = new THashMap<String, Object>();\r
- Map<String, Object> states = new THashMap<String, Object>();\r
- \r
- sheetDimensions.put(DIMENSIONS_FIT_ROWS, false);\r
- sheetDimensions.put(DIMENSIONS_FIT_COLS, false);\r
- sheetDimensions.put(DIMENSIONS_COL_COUNT, 0);\r
- sheetDimensions.put(DIMENSIONS_ROW_COUNT, 0);\r
-\r
- excel.put(EXCEL_VISIBLE, false);\r
-\r
- headers.put(HEADERS_COL_WIDTHS, new int[] { });\r
- headers.put(HEADERS_ROW_HEIGHTS, new int[] { });\r
- headers.put(HEADERS_COL_LABELS, new String[] { });\r
- headers.put(HEADERS_ROW_LABELS, new String[] { });\r
- \r
- sources.put(SOURCES_AVAILABLE, new String[] { });\r
- sources.put(SOURCES_CURRENT, "");\r
- \r
- properties.put(DIMENSIONS, sheetDimensions);\r
- properties.put(HEADERS, headers);\r
- properties.put(EXCEL, excel);\r
- properties.put(SOURCES, sources);\r
- properties.put(SHEETS, sheets);\r
- properties.put(CONTEXT, context);\r
- properties.put(MODE, mode);\r
- properties.put(STATES, states);\r
- \r
- setProperty(EXCEL, EXCEL_VISIBLE, false);\r
-\r
- }\r
-\r
- CopyOnWriteArrayList<ClientModelListener> listeners = new CopyOnWriteArrayList<ClientModelListener>();\r
- \r
- @Override\r
- public void addListener(ClientModelListener listener) {\r
- listeners.add(listener);\r
- listener.rows(getRows());\r
- listener.columns(getColumns());\r
- listener.rowLabels((String[])getPropertyAt(HEADERS, HEADERS_ROW_LABELS));\r
- listener.columnWidths((int[])getPropertyAt(HEADERS, HEADERS_COL_WIDTHS));\r
- listener.sources((String[])getPropertyAt(SOURCES, SOURCES_AVAILABLE), (String)getPropertyAt(SOURCES, SOURCES_CURRENT));\r
- }\r
-\r
- @Override\r
- public void removeListener(ClientModelListener listener) {\r
- listeners.remove(listener);\r
- }\r
- \r
- private void fireFlush() {\r
- for(ClientModelListener listener : listeners)\r
- listener.flush();\r
- }\r
-\r
- private void fireRows() {\r
- for(ClientModelListener listener : listeners)\r
- listener.rows(getRows());\r
- }\r
-\r
- private void fireColumns() {\r
- for(ClientModelListener listener : listeners)\r
- listener.columns(getColumns());\r
- }\r
- \r
- private void fireColumnWidths() {\r
- for(ClientModelListener listener : listeners)\r
- listener.columnWidths((int[])getPropertyAt(HEADERS, HEADERS_COL_WIDTHS));\r
- }\r
- \r
- private void fireSources() {\r
- for(ClientModelListener listener : listeners)\r
- listener.sources((String[])getPropertyAt(SOURCES, SOURCES_AVAILABLE), (String)getPropertyAt(SOURCES, SOURCES_CURRENT));\r
- }\r
-\r
- private void fireProperty(String location, String property, Object value) {\r
- for(ClientModelListener listener : listeners)\r
- listener.propertyChange(location, property, value);\r
- }\r
-\r
- private void fireCleared(String location) {\r
- for(ClientModelListener listener : listeners)\r
- listener.cleared(location);\r
- }\r
- \r
- @Override\r
- public <T> T getPossiblePropertyAt(String location, String property) {\r
- try {\r
- T t = getPropertyAt(location, property);\r
- return t; \r
- } catch (Throwable e) {\r
- return null;\r
- }\r
- }\r
- \r
- @SuppressWarnings("unchecked")\r
- public synchronized <T> T getPropertyAt(String location, String property) {\r
-\r
- if(Spreadsheet.DEBUG) System.out.println("SimpleContainerTableModel.getPropertyAt " + location + " " + property);\r
- \r
- Map<String, Object> props = properties.get(location);\r
- if(props != null) {\r
- return (T)props.get(property);\r
- } else {\r
- Map<String, Object> cls = cells.get(location);\r
- if(cls != null) {\r
- return (T)cls.get(property);\r
- } else {\r
- return null;\r
- }\r
- }\r
-\r
- }\r
- \r
- private final Set<String> sizing = CollectionUtils.toSet(\r
- DIMENSIONS_COL_COUNT,\r
- DIMENSIONS_ROW_COUNT,\r
- DIMENSIONS_FIT_COLS,\r
- DIMENSIONS_FIT_ROWS);\r
- \r
- private boolean sizingProperty(String property) {\r
- return sizing.contains(property);\r
- }\r
- \r
- private boolean checkMaxRow(int row) {\r
- if((row+1) > maxRow) {\r
- maxRow = row+1;\r
- return true;\r
- } else {\r
- return false;\r
- }\r
- }\r
-\r
- private boolean checkMaxColumn(int column) {\r
- if((column+1) > maxColumn) {\r
- maxColumn = column+1;\r
- return true;\r
- } else {\r
- return false;\r
- }\r
- }\r
-\r
- @Override\r
- public synchronized void setProperty(final String location, final String property, final Object value) {\r
-\r
- assert(location != null);\r
- assert(property != null);\r
-\r
- modLocation.add(location);\r
- modProperty.add(property);\r
- modValue.add(value);\r
- \r
- }\r
- \r
- @Override\r
- public void clearAll() {\r
- clears.addAll(cells.keySet());\r
- }\r
-\r
- @Override\r
- public synchronized void clear(String location) {\r
- if (location.startsWith("Style"))\r
- // Nothing to do for now..\r
- return;\r
- clears.add(location);\r
- }\r
- \r
- @Override\r
- public synchronized void flush() {\r
- \r
- for(String location : clears) {\r
- \r
- Map<String, Object> cls = cells.remove(location);\r
- if(cls == null) return;\r
- \r
- long l = SpreadsheetUtils.decodeCellCoded(location);\r
- int row = (int)(l & 0xffffffff) - 1;\r
- int column = (int)((l>>32) & 0xffffffff);\r
- \r
- if(checkMaxRow(row)) fireRows();\r
- if(checkMaxColumn(column)) fireColumns();\r
-\r
- removeSpan(row, column);\r
- \r
- fireCleared(location);\r
- \r
- }\r
-\r
- for(int i=0;i<modLocation.size();i++) {\r
- \r
- String location = modLocation.get(i);\r
- String property = modProperty.get(i);\r
- Object value = modValue.get(i);\r
-\r
- if(Spreadsheet.DEBUG) System.out.println("ClientModelImpl.setProperty " + location + " " + property + " " + value);\r
-\r
- Map<String, Object> props = properties.get(location);\r
- if(props != null || location.startsWith("Style")) {\r
- if (location.startsWith("Style") && props == null) {\r
- props = new HashMap<>();\r
- properties.put(location, props);\r
- }\r
-\r
- if(sizingProperty(property)) {\r
-\r
- int currentRows = getRows();\r
- int currentCols = getColumns();\r
- props.put(property, value);\r
- if(getRows() != currentRows) fireRows();\r
- if(getColumns() != currentCols) fireColumns();\r
-\r
- } else {\r
-\r
- props.put(property, value);\r
- if(property.equals(HEADERS_COL_WIDTHS)) fireColumnWidths();\r
- if(property.equals(SOURCES_AVAILABLE) || property.equals(SOURCES_CURRENT)) fireSources();\r
-\r
- }\r
-\r
- } else {\r
-\r
- Map<String, Object> cls = cells.get(location);\r
- if(cls == null) {\r
- cls = new HashMap<String, Object>();\r
- cells.put(location, cls);\r
- }\r
-\r
- cls.put(property, value);\r
-\r
- long l = SpreadsheetUtils.decodeCellCoded(location);\r
- int row = (int)(l & 0xffffffff) - 1;\r
- int column = (int)((l>>32) & 0xffffffff);\r
-\r
- if(checkMaxRow(row)) fireRows();\r
- if(checkMaxColumn(column)) fireColumns();\r
-\r
- boolean rowSpanProperty = property.equals(ROW_SPAN);\r
- boolean columnSpanProperty = property.equals(COLUMN_SPAN);\r
- if (rowSpanProperty || columnSpanProperty) {\r
- Rectangle span = getRootSpan(row, column);\r
- int size = (Integer)value;\r
- \r
- if (span == null) {\r
- if (size > 1) {\r
- if (rowSpanProperty) {\r
- span = createSpan(row, column, size, 1);\r
- } else {\r
- span = createSpan(row, column, 1, size);\r
- }\r
- }\r
- } else {\r
- if (rowSpanProperty) {\r
- span.height = size;\r
- } else {\r
- span.width = size;\r
- }\r
- if ((span.width == 1) && (span.height == 1)) {\r
- removeSpan(row, column);\r
- }\r
- }\r
- }\r
- }\r
-\r
- fireProperty(location, property, value);\r
- \r
- }\r
- \r
- clears.clear();\r
- modLocation.clear();\r
- modProperty.clear();\r
- modValue.clear(); \r
- \r
- fireFlush();\r
- \r
- }\r
- \r
- @Override\r
- public int getRows() {\r
- boolean fitRows = getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_FIT_ROWS);\r
- if(fitRows) return maxRow;\r
- else return getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_ROW_COUNT);\r
- }\r
-\r
- @Override\r
- public int getColumns() {\r
- boolean fitCols = getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_FIT_COLS);\r
- if(fitCols) {\r
- return maxColumn;\r
- }\r
- else return getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_COL_COUNT);\r
- }\r
- \r
- @Override\r
- public int[] getColumnWidths() {\r
- int[] data = getPropertyAt(HEADERS, HEADERS_COL_WIDTHS);\r
- return data.clone();\r
- }\r
-\r
- @Override\r
- public int[] getRowHeights() {\r
- int[] data = getPropertyAt(HEADERS, HEADERS_ROW_HEIGHTS);\r
- return data.clone();\r
- }\r
-\r
- @Override\r
- public synchronized Collection<Pair<String, Object>> listAll(String property) {\r
-\r
- ArrayList<Pair<String, Object>> result = new ArrayList<Pair<String, Object>>(); \r
- \r
- for(Map.Entry<String, Map<String, Object>> entry : properties.entrySet()) {\r
- Object value = entry.getValue().get(property);\r
- if(value != null) result.add(Pair.make(entry.getKey(), value));\r
- }\r
- for(Map.Entry<String, Map<String, Object>> entry : cells.entrySet()) {\r
- Object value = entry.getValue().get(property);\r
- if(value != null) result.add(Pair.make(entry.getKey(), value));\r
- }\r
- \r
- return result;\r
- \r
- }\r
- \r
- private long spanKey(int row, int column) {\r
- return (row & 0xffffffff) | (((long)(column & 0xffffffff)) << 32);\r
- }\r
-\r
- @Override\r
- public synchronized Rectangle getSpan(int row, int column) {\r
- for (Rectangle span : spanMap.values()) {\r
- if (span.contains(column, row)) {\r
- return new Rectangle(span);\r
- }\r
- }\r
- return null;\r
- }\r
- \r
- @Override\r
- public synchronized List<Rectangle> getSpans() {\r
- List<Rectangle> spans = new ArrayList<Rectangle>(spanMap.size());\r
- for (Rectangle span : spanMap.values()) {\r
- spans.add(new Rectangle(span));\r
- }\r
- return spans; \r
- }\r
-\r
- private Rectangle getRootSpan(int row, int column) {\r
- return spanMap.get(spanKey(row, column));\r
- }\r
- \r
- private Rectangle createSpan(int row, int column, int rowSpan, int columnSpan) {\r
- Rectangle span = new Rectangle(column, row, columnSpan, rowSpan);\r
- spanMap.put(spanKey(row, column), span);\r
- return span;\r
- }\r
- \r
- private void removeSpan(int row, int column) {\r
- spanMap.remove(spanKey(row, column));\r
- }\r
- \r
-}\r
+/*******************************************************************************
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.spreadsheet.ui;
+
+import gnu.trove.map.hash.THashMap;
+
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.simantics.spreadsheet.ClientModel;
+import org.simantics.spreadsheet.util.SpreadsheetUtils;
+import org.simantics.utils.datastructures.Pair;
+import org.simantics.utils.datastructures.collections.CollectionUtils;
+
+public class ClientModelImpl implements ClientModel {
+
+ final private Map<String, Map<String, Object>> properties = new THashMap<String, Map<String, Object>>();
+ final private Map<String, Map<String, Object>> cells = new THashMap<String, Map<String, Object>>();
+
+ private int maxRow = 0;
+ private int maxColumn = 0;
+
+ private Set<String> clears = new HashSet<String>();
+// private ArrayList<Triple<String, String, Object>> modifications = new ArrayList<Triple<String, String, Object>>();
+
+ private ArrayList<String> modLocation = new ArrayList<String>();
+ private ArrayList<String> modProperty = new ArrayList<String>();
+ private ArrayList<Object> modValue = new ArrayList<Object>();
+ private Map<Long, Rectangle> spanMap = new HashMap<Long, Rectangle>();
+
+ public ClientModelImpl() {
+
+ if(Spreadsheet.DEBUG) System.out.println("SimpleContainerTableModel.init");
+
+ Map<String, Object> sheetDimensions = new THashMap<String, Object>();
+ Map<String, Object> headers = new THashMap<String, Object>();
+ Map<String, Object> excel = new THashMap<String, Object>();
+ Map<String, Object> sources = new THashMap<String, Object>();
+ Map<String, Object> sheets = new THashMap<String, Object>();
+ Map<String, Object> context = new THashMap<String, Object>();
+ Map<String, Object> mode = new THashMap<String, Object>();
+ Map<String, Object> states = new THashMap<String, Object>();
+
+ sheetDimensions.put(DIMENSIONS_FIT_ROWS, false);
+ sheetDimensions.put(DIMENSIONS_FIT_COLS, false);
+ sheetDimensions.put(DIMENSIONS_COL_COUNT, 0);
+ sheetDimensions.put(DIMENSIONS_ROW_COUNT, 0);
+
+ excel.put(EXCEL_VISIBLE, false);
+
+ headers.put(HEADERS_COL_WIDTHS, new int[] { });
+ headers.put(HEADERS_ROW_HEIGHTS, new int[] { });
+ headers.put(HEADERS_COL_LABELS, new String[] { });
+ headers.put(HEADERS_ROW_LABELS, new String[] { });
+
+ sources.put(SOURCES_AVAILABLE, new String[] { });
+ sources.put(SOURCES_CURRENT, "");
+
+ properties.put(DIMENSIONS, sheetDimensions);
+ properties.put(HEADERS, headers);
+ properties.put(EXCEL, excel);
+ properties.put(SOURCES, sources);
+ properties.put(SHEETS, sheets);
+ properties.put(CONTEXT, context);
+ properties.put(MODE, mode);
+ properties.put(STATES, states);
+
+ setProperty(EXCEL, EXCEL_VISIBLE, false);
+
+ }
+
+ CopyOnWriteArrayList<ClientModelListener> listeners = new CopyOnWriteArrayList<ClientModelListener>();
+
+ @Override
+ public void addListener(ClientModelListener listener) {
+ listeners.add(listener);
+ listener.rows(getRows());
+ listener.columns(getColumns());
+ listener.rowLabels((String[])getPropertyAt(HEADERS, HEADERS_ROW_LABELS));
+ listener.columnWidths((int[])getPropertyAt(HEADERS, HEADERS_COL_WIDTHS));
+ listener.sources((String[])getPropertyAt(SOURCES, SOURCES_AVAILABLE), (String)getPropertyAt(SOURCES, SOURCES_CURRENT));
+ }
+
+ @Override
+ public void removeListener(ClientModelListener listener) {
+ listeners.remove(listener);
+ }
+
+ private void fireFlush() {
+ for(ClientModelListener listener : listeners)
+ listener.flush();
+ }
+
+ private void fireRows() {
+ for(ClientModelListener listener : listeners)
+ listener.rows(getRows());
+ }
+
+ private void fireColumns() {
+ for(ClientModelListener listener : listeners)
+ listener.columns(getColumns());
+ }
+
+ private void fireColumnWidths() {
+ for(ClientModelListener listener : listeners)
+ listener.columnWidths((int[])getPropertyAt(HEADERS, HEADERS_COL_WIDTHS));
+ }
+
+ private void fireSources() {
+ for(ClientModelListener listener : listeners)
+ listener.sources((String[])getPropertyAt(SOURCES, SOURCES_AVAILABLE), (String)getPropertyAt(SOURCES, SOURCES_CURRENT));
+ }
+
+ private void fireProperty(String location, String property, Object value) {
+ for(ClientModelListener listener : listeners)
+ listener.propertyChange(location, property, value);
+ }
+
+ private void fireCleared(String location) {
+ for(ClientModelListener listener : listeners)
+ listener.cleared(location);
+ }
+
+ @Override
+ public <T> T getPossiblePropertyAt(String location, String property) {
+ try {
+ T t = getPropertyAt(location, property);
+ return t;
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized <T> T getPropertyAt(String location, String property) {
+
+ if(Spreadsheet.DEBUG) System.out.println("SimpleContainerTableModel.getPropertyAt " + location + " " + property);
+
+ Map<String, Object> props = properties.get(location);
+ if(props != null) {
+ return (T)props.get(property);
+ } else {
+ Map<String, Object> cls = cells.get(location);
+ if(cls != null) {
+ return (T)cls.get(property);
+ } else {
+ return null;
+ }
+ }
+
+ }
+
+ private final Set<String> sizing = CollectionUtils.toSet(
+ DIMENSIONS_COL_COUNT,
+ DIMENSIONS_ROW_COUNT,
+ DIMENSIONS_FIT_COLS,
+ DIMENSIONS_FIT_ROWS);
+
+ private boolean sizingProperty(String property) {
+ return sizing.contains(property);
+ }
+
+ private boolean checkMaxRow(int row) {
+ if((row+1) > maxRow) {
+ maxRow = row+1;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean checkMaxColumn(int column) {
+ if((column+1) > maxColumn) {
+ maxColumn = column+1;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public synchronized void setProperty(final String location, final String property, final Object value) {
+
+ assert(location != null);
+ assert(property != null);
+
+ modLocation.add(location);
+ modProperty.add(property);
+ modValue.add(value);
+
+ }
+
+ @Override
+ public void clearAll() {
+ clears.addAll(cells.keySet());
+ }
+
+ @Override
+ public synchronized void clear(String location) {
+ if (location.startsWith("Style"))
+ // Nothing to do for now..
+ return;
+ clears.add(location);
+ }
+
+ @Override
+ public synchronized void flush() {
+
+ for(String location : clears) {
+
+ Map<String, Object> cls = cells.remove(location);
+ if(cls == null) return;
+
+ long l = SpreadsheetUtils.decodeCellCoded(location);
+ int row = (int)(l & 0xffffffff) - 1;
+ int column = (int)((l>>32) & 0xffffffff);
+
+ if(checkMaxRow(row)) fireRows();
+ if(checkMaxColumn(column)) fireColumns();
+
+ removeSpan(row, column);
+
+ fireCleared(location);
+
+ }
+
+ for(int i=0;i<modLocation.size();i++) {
+
+ String location = modLocation.get(i);
+ String property = modProperty.get(i);
+ Object value = modValue.get(i);
+
+ if(Spreadsheet.DEBUG) System.out.println("ClientModelImpl.setProperty " + location + " " + property + " " + value);
+
+ Map<String, Object> props = properties.get(location);
+ if(props != null || location.startsWith("Style")) {
+ if (location.startsWith("Style") && props == null) {
+ props = new HashMap<>();
+ properties.put(location, props);
+ }
+
+ if(sizingProperty(property)) {
+
+ int currentRows = getRows();
+ int currentCols = getColumns();
+ props.put(property, value);
+ if(getRows() != currentRows) fireRows();
+ if(getColumns() != currentCols) fireColumns();
+
+ } else {
+
+ props.put(property, value);
+ if(property.equals(HEADERS_COL_WIDTHS)) fireColumnWidths();
+ if(property.equals(SOURCES_AVAILABLE) || property.equals(SOURCES_CURRENT)) fireSources();
+
+ }
+
+ } else {
+
+ Map<String, Object> cls = cells.get(location);
+ if(cls == null) {
+ cls = new HashMap<String, Object>();
+ cells.put(location, cls);
+ }
+
+ cls.put(property, value);
+
+ long l = SpreadsheetUtils.decodeCellCoded(location);
+ int row = (int)(l & 0xffffffff) - 1;
+ int column = (int)((l>>32) & 0xffffffff);
+
+ if(checkMaxRow(row)) fireRows();
+ if(checkMaxColumn(column)) fireColumns();
+
+ boolean rowSpanProperty = property.equals(ROW_SPAN);
+ boolean columnSpanProperty = property.equals(COLUMN_SPAN);
+ if (rowSpanProperty || columnSpanProperty) {
+ Rectangle span = getRootSpan(row, column);
+ int size = (Integer)value;
+
+ if (span == null) {
+ if (size > 1) {
+ if (rowSpanProperty) {
+ span = createSpan(row, column, size, 1);
+ } else {
+ span = createSpan(row, column, 1, size);
+ }
+ }
+ } else {
+ if (rowSpanProperty) {
+ span.height = size;
+ } else {
+ span.width = size;
+ }
+ if ((span.width == 1) && (span.height == 1)) {
+ removeSpan(row, column);
+ }
+ }
+ }
+ }
+
+ fireProperty(location, property, value);
+
+ }
+
+ clears.clear();
+ modLocation.clear();
+ modProperty.clear();
+ modValue.clear();
+
+ fireFlush();
+
+ }
+
+ @Override
+ public int getRows() {
+ boolean fitRows = getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_FIT_ROWS);
+ if(fitRows) return maxRow;
+ else return getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_ROW_COUNT);
+ }
+
+ @Override
+ public int getColumns() {
+ boolean fitCols = getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_FIT_COLS);
+ if(fitCols) {
+ return maxColumn;
+ }
+ else return getPropertyAt(ClientModel.DIMENSIONS, ClientModel.DIMENSIONS_COL_COUNT);
+ }
+
+ @Override
+ public int[] getColumnWidths() {
+ int[] data = getPropertyAt(HEADERS, HEADERS_COL_WIDTHS);
+ return data.clone();
+ }
+
+ @Override
+ public int[] getRowHeights() {
+ int[] data = getPropertyAt(HEADERS, HEADERS_ROW_HEIGHTS);
+ return data.clone();
+ }
+
+ @Override
+ public synchronized Collection<Pair<String, Object>> listAll(String property) {
+
+ ArrayList<Pair<String, Object>> result = new ArrayList<Pair<String, Object>>();
+
+ for(Map.Entry<String, Map<String, Object>> entry : properties.entrySet()) {
+ Object value = entry.getValue().get(property);
+ if(value != null) result.add(Pair.make(entry.getKey(), value));
+ }
+ for(Map.Entry<String, Map<String, Object>> entry : cells.entrySet()) {
+ Object value = entry.getValue().get(property);
+ if(value != null) result.add(Pair.make(entry.getKey(), value));
+ }
+
+ return result;
+
+ }
+
+ private long spanKey(int row, int column) {
+ return (row & 0xffffffff) | (((long)(column & 0xffffffff)) << 32);
+ }
+
+ @Override
+ public synchronized Rectangle getSpan(int row, int column) {
+ for (Rectangle span : spanMap.values()) {
+ if (span.contains(column, row)) {
+ return new Rectangle(span);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public synchronized List<Rectangle> getSpans() {
+ List<Rectangle> spans = new ArrayList<Rectangle>(spanMap.size());
+ for (Rectangle span : spanMap.values()) {
+ spans.add(new Rectangle(span));
+ }
+ return spans;
+ }
+
+ private Rectangle getRootSpan(int row, int column) {
+ return spanMap.get(spanKey(row, column));
+ }
+
+ private Rectangle createSpan(int row, int column, int rowSpan, int columnSpan) {
+ Rectangle span = new Rectangle(column, row, columnSpan, rowSpan);
+ spanMap.put(spanKey(row, column), span);
+ return span;
+ }
+
+ private void removeSpan(int row, int column) {
+ spanMap.remove(spanKey(row, column));
+ }
+
+}