]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientModelImpl.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.spreadsheet.ui / src / org / simantics / spreadsheet / ui / ClientModelImpl.java
diff --git a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientModelImpl.java b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientModelImpl.java
new file mode 100644 (file)
index 0000000..93bd742
--- /dev/null
@@ -0,0 +1,413 @@
+/*******************************************************************************\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