X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.spreadsheet.ui%2Fsrc%2Forg%2Fsimantics%2Fspreadsheet%2Fui%2FClientModelImpl.java;h=86fda3d5a7634933efff640a2690ba99de19773b;hb=5915c1bbd6d0c6125aa3c815c7843339190f28e4;hp=93bd742b5d591468b471b30213482fcc35600282;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git 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 index 93bd742b5..86fda3d5a 100644 --- 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 @@ -1,413 +1,413 @@ -/******************************************************************************* - * 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> properties = new THashMap>(); - final private Map> cells = new THashMap>(); - - private int maxRow = 0; - private int maxColumn = 0; - - private Set clears = new HashSet(); -// private ArrayList> modifications = new ArrayList>(); - - private ArrayList modLocation = new ArrayList(); - private ArrayList modProperty = new ArrayList(); - private ArrayList modValue = new ArrayList(); - private Map spanMap = new HashMap(); - - public ClientModelImpl() { - - if(Spreadsheet.DEBUG) System.out.println("SimpleContainerTableModel.init"); - - Map sheetDimensions = new THashMap(); - Map headers = new THashMap(); - Map excel = new THashMap(); - Map sources = new THashMap(); - Map sheets = new THashMap(); - Map context = new THashMap(); - Map mode = new THashMap(); - Map states = new THashMap(); - - 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 listeners = new CopyOnWriteArrayList(); - - @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 getPossiblePropertyAt(String location, String property) { - try { - T t = getPropertyAt(location, property); - return t; - } catch (Throwable e) { - return null; - } - } - - @SuppressWarnings("unchecked") - public synchronized T getPropertyAt(String location, String property) { - - if(Spreadsheet.DEBUG) System.out.println("SimpleContainerTableModel.getPropertyAt " + location + " " + property); - - Map props = properties.get(location); - if(props != null) { - return (T)props.get(property); - } else { - Map cls = cells.get(location); - if(cls != null) { - return (T)cls.get(property); - } else { - return null; - } - } - - } - - private final Set 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 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 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 cls = cells.get(location); - if(cls == null) { - cls = new HashMap(); - 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> listAll(String property) { - - ArrayList> result = new ArrayList>(); - - for(Map.Entry> entry : properties.entrySet()) { - Object value = entry.getValue().get(property); - if(value != null) result.add(Pair.make(entry.getKey(), value)); - } - for(Map.Entry> 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 getSpans() { - List spans = new ArrayList(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)); - } - -} +/******************************************************************************* + * 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> properties = new THashMap>(); + final private Map> cells = new THashMap>(); + + private int maxRow = 0; + private int maxColumn = 0; + + private Set clears = new HashSet(); +// private ArrayList> modifications = new ArrayList>(); + + private ArrayList modLocation = new ArrayList(); + private ArrayList modProperty = new ArrayList(); + private ArrayList modValue = new ArrayList(); + private Map spanMap = new HashMap(); + + public ClientModelImpl() { + + if(Spreadsheet.DEBUG) System.out.println("SimpleContainerTableModel.init"); + + Map sheetDimensions = new THashMap(); + Map headers = new THashMap(); + Map excel = new THashMap(); + Map sources = new THashMap(); + Map sheets = new THashMap(); + Map context = new THashMap(); + Map mode = new THashMap(); + Map states = new THashMap(); + + 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 listeners = new CopyOnWriteArrayList(); + + @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 getPossiblePropertyAt(String location, String property) { + try { + T t = getPropertyAt(location, property); + return t; + } catch (Throwable e) { + return null; + } + } + + @SuppressWarnings("unchecked") + public synchronized T getPropertyAt(String location, String property) { + + if(Spreadsheet.DEBUG) System.out.println("SimpleContainerTableModel.getPropertyAt " + location + " " + property); + + Map props = properties.get(location); + if(props != null) { + return (T)props.get(property); + } else { + Map cls = cells.get(location); + if(cls != null) { + return (T)cls.get(property); + } else { + return null; + } + } + + } + + private final Set 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 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 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 cls = cells.get(location); + if(cls == null) { + cls = new HashMap(); + 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> listAll(String property) { + + ArrayList> result = new ArrayList>(); + + for(Map.Entry> entry : properties.entrySet()) { + Object value = entry.getValue().get(property); + if(value != null) result.add(Pair.make(entry.getKey(), value)); + } + for(Map.Entry> 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 getSpans() { + List spans = new ArrayList(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)); + } + +}