X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.district.network.ui%2Fsrc%2Forg%2Fsimantics%2Fdistrict%2Fnetwork%2Fui%2Ftechtype%2Ftable%2FTechTypeTable.java;h=8ee627a57989c09a79732b4773281c1a1b493352;hb=34ba99ecdb35c06c6769b43dca81c88b45f20295;hp=725700f89c50b1c660d9b95418e65e479e91c223;hpb=97fca8781af176c8e0dfdb624f634e4a799704fe;p=simantics%2Fdistrict.git diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/techtype/table/TechTypeTable.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/techtype/table/TechTypeTable.java index 725700f8..8ee627a5 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/techtype/table/TechTypeTable.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/techtype/table/TechTypeTable.java @@ -1,15 +1,21 @@ package org.simantics.district.network.ui.techtype.table; -import java.io.Serializable; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Set; +import java.util.stream.Collectors; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.nebula.widgets.nattable.NatTable; +import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration; +import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes; import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration; import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry; import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataCommandHandler; import org.eclipse.nebula.widgets.nattable.data.IDataProvider; -import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor; import org.eclipse.nebula.widgets.nattable.freeze.CompositeFreezeLayer; import org.eclipse.nebula.widgets.nattable.freeze.FreezeLayer; import org.eclipse.nebula.widgets.nattable.grid.GridRegion; @@ -28,10 +34,15 @@ import org.eclipse.nebula.widgets.nattable.hover.config.BodyHoverStylingBindings import org.eclipse.nebula.widgets.nattable.layer.DataLayer; import org.eclipse.nebula.widgets.nattable.layer.ILayer; import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer; +import org.eclipse.nebula.widgets.nattable.layer.LabelStack; +import org.eclipse.nebula.widgets.nattable.layer.cell.IConfigLabelAccumulator; import org.eclipse.nebula.widgets.nattable.reorder.RowReorderLayer; -import org.eclipse.nebula.widgets.nattable.selection.RowSelectionModel; import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer; import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer; +import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes; +import org.eclipse.nebula.widgets.nattable.style.DisplayMode; +import org.eclipse.nebula.widgets.nattable.style.Style; +import org.eclipse.nebula.widgets.nattable.util.GUIHelper; import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; @@ -39,9 +50,24 @@ import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; +import org.simantics.Simantics; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.request.PossibleActiveModel; +import org.simantics.district.network.techtype.requests.PossibleTechTypeKeyName; +import org.simantics.district.network.techtype.requests.PossibleTechTypeTable; +import org.simantics.district.network.techtype.requests.WriteTechTypeTable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class TechTypeTable extends Composite { + private static final String INVALID_LABEL = "INVALID"; + + private final static Logger LOGGER = LoggerFactory.getLogger(TechTypeTable.class); + NatTable table; private TechTypeTableDataProvider bodyDataProvider; DataLayer bodyDataLayer; @@ -50,63 +76,73 @@ public class TechTypeTable extends Composite { private ViewportLayer viewportLayer; private CompositeFreezeLayer compositeFreezeLayer; private FreezeLayer freezeLayer; - //private TableDataSortModel sortModel; + // private TableDataSortModel sortModel; private ColumnHideShowLayer columnHideShowLayer; private ColumnGroupModel columnGroupModel = new ColumnGroupModel(); private TechTypeColumnHeaderTableDataProvider columnHeaderDataProvider; Clipboard cpb; public SelectionLayer selectionLayer; - private TechTypeTableSortModel sortModel; + private TechTypeTableSortModel sortModel; + + private Resource componentType; + private Resource tableResource; - public TechTypeTable(Composite parent, int style) { + protected Set validationResult; + + public TechTypeTable(Composite parent, int style, Resource componentType, Resource tableResource, String data) { super(parent, style); - defaultInitializeUI(); + this.componentType = componentType; + this.tableResource = tableResource; + + defaultInitializeUI(data); } - private void defaultInitializeUI() { + private void defaultInitializeUI(String data) { GridDataFactory.fillDefaults().grab(true, true).applyTo(this); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(this); - + Composite filterComposite = new Composite(this, SWT.NONE); GridDataFactory.fillDefaults().grab(true, false).applyTo(filterComposite); - GridLayoutFactory.fillDefaults().numColumns(1).applyTo(filterComposite); - + GridLayoutFactory.fillDefaults().numColumns(1).applyTo(filterComposite); + + createFilterBar(filterComposite); - createFilterBar(filterComposite); - Composite tableComposite = new Composite(this, SWT.NONE); GridDataFactory.fillDefaults().grab(true, true).applyTo(tableComposite); - GridLayoutFactory.fillDefaults().numColumns(1).applyTo(tableComposite); - createTable(tableComposite); + GridLayoutFactory.fillDefaults().numColumns(1).applyTo(tableComposite); + + createTable(tableComposite, data); } private void createFilterBar(Composite filterComposite) { - - Text filterText = new Text(filterComposite, SWT.BORDER); - GridDataFactory.fillDefaults().grab(true, true).applyTo(filterText); - filterText.addModifyListener(new ModifyListener() { - - @Override - public void modifyText(ModifyEvent e) { - System.out.println("text modified"); - bodyDataProvider.setFilter(filterText.getText()); - table.refresh(true); - } - }); - - } - - private void createTable(Composite parent) { - - // build the body layer stack - // Usually you would create a new layer stack by extending AbstractIndexLayerTransform and - // setting the ViewportLayer as underlying layer. But in this case using the ViewportLayer + + Text filterText = new Text(filterComposite, SWT.BORDER); + GridDataFactory.fillDefaults().grab(true, true).applyTo(filterText); + filterText.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + System.out.println("text modified"); + bodyDataProvider.setFilter(filterText.getText()); + table.refresh(true); + } + }); + + } + + private void createTable(Composite parent, String data) { + + // build the body layer stack + // Usually you would create a new layer stack by extending + // AbstractIndexLayerTransform and + // setting the ViewportLayer as underlying layer. But in this case using the + // ViewportLayer // directly as body layer is also working. - bodyDataProvider = new TechTypeTableDataProvider(); + bodyDataProvider = new TechTypeTableDataProvider(data); bodyDataLayer = new DataLayer(bodyDataProvider); - - RowReorderLayer rowReorderLayer = - new RowReorderLayer(columnHideShowLayer = new ColumnHideShowLayer(bodyDataLayer)); + + RowReorderLayer rowReorderLayer = new RowReorderLayer( + columnHideShowLayer = new ColumnHideShowLayer(bodyDataLayer)); HoverLayer hoverLayer = new HoverLayer(rowReorderLayer, false); // we need to ensure that the hover styling is removed when the mouse @@ -114,7 +150,7 @@ public class TechTypeTable extends Composite { hoverLayer.addConfiguration(new BodyHoverStylingBindings(hoverLayer)); selectionLayer = new SelectionLayer(hoverLayer); - + viewportLayer = new ViewportLayer(selectionLayer); viewportLayer.setRegionName(GridRegion.BODY); freezeLayer = new FreezeLayer(selectionLayer); @@ -125,10 +161,13 @@ public class TechTypeTable extends Composite { DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(columnHeaderDataProvider); columnHeaderDataLayer.setRowsResizableByDefault(false); columnHeaderDataLayer.setColumnsResizableByDefault(true); - ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, compositeFreezeLayer, selectionLayer); - ColumnGroupHeaderLayer columnGroupHeaderLayer = new ColumnGroupHeaderLayer(columnHeaderLayer, selectionLayer, columnGroupModel); + ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, compositeFreezeLayer, + selectionLayer); + ColumnGroupHeaderLayer columnGroupHeaderLayer = new ColumnGroupHeaderLayer(columnHeaderLayer, selectionLayer, + columnGroupModel); columnGroupHeaderLayer.setCalculateHeight(true); - SortHeaderLayer columnSortHeaderLayer = new SortHeaderLayer<>(columnGroupHeaderLayer, sortModel = new TechTypeTableSortModel(bodyDataProvider)); + SortHeaderLayer columnSortHeaderLayer = new SortHeaderLayer<>(columnGroupHeaderLayer, + sortModel = new TechTypeTableSortModel(bodyDataProvider)); // build the row header layer IDataProvider rowHeaderDataProvider = new TechTypeRowHeaderTableDataProvider(bodyDataProvider); @@ -138,44 +177,151 @@ public class TechTypeTable extends Composite { RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, compositeFreezeLayer, selectionLayer); // build the corner layer - IDataProvider cornerDataProvider = new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider); + IDataProvider cornerDataProvider = new DefaultCornerDataProvider(columnHeaderDataProvider, + rowHeaderDataProvider); DataLayer cornerDataLayer = new DataLayer(cornerDataProvider); ILayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, columnSortHeaderLayer); // build the grid layer GridLayer gridLayer = new GridLayer(compositeFreezeLayer, columnSortHeaderLayer, rowHeaderLayer, cornerLayer); - + table = new NatTable(parent, NatTable.DEFAULT_STYLE_OPTIONS | SWT.BORDER, gridLayer, false); GridDataFactory.fillDefaults().grab(true, true).applyTo(table); + // Show entries labeled "INVALID" with red text + table.addConfiguration(new AbstractRegistryConfiguration() { + @Override + public void configureRegistry(IConfigRegistry configRegistry) { + Style cellStyle = new Style(); + cellStyle.setAttributeValue(CellStyleAttributes.BACKGROUND_COLOR, GUIHelper.COLOR_RED); + configRegistry.registerConfigAttribute( + CellConfigAttributes.CELL_STYLE, + cellStyle, + DisplayMode.NORMAL, + INVALID_LABEL + ); + } + }); + // Register a CopyDataCommandHandler that also copies the headers and // uses the configured IDisplayConverters - CopyDataCommandHandler copyHandler = new CopyDataCommandHandler( - selectionLayer, - columnHeaderDataLayer, + CopyDataCommandHandler copyHandler = new CopyDataCommandHandler(selectionLayer, columnHeaderDataLayer, rowHeaderDataLayer); copyHandler.setCopyFormattedText(true); gridLayer.registerCommandHandler(copyHandler); - + // initialize paste handler with SWT clipboard cpb = new Clipboard(getDisplay()); - //PasteDataCommandHandler pasteHandler = new PasteDataCommandHandler(bodyDataProvider, bodyDataLayer, selectionLayer, cpb); - //bodyDataLayer.registerCommandHandler(pasteHandler); - + // PasteDataCommandHandler pasteHandler = new + // PasteDataCommandHandler(bodyDataProvider, bodyDataLayer, selectionLayer, + // cpb); + // bodyDataLayer.registerCommandHandler(pasteHandler); + table.addConfiguration(new DefaultNatTableStyleConfiguration()); - //table.addConfiguration(new EditingSupportConfiguration(bodyDataProvider)); + // table.addConfiguration(new EditingSupportConfiguration(bodyDataProvider)); table.configure(); } - + + private static String getKeyColumnName(Resource componentType) { + String keyName = null; + if (componentType != null) { + try { + keyName = Simantics.getSession().syncRequest(new PossibleTechTypeKeyName(componentType)); + } catch (DatabaseException e) { + LOGGER.error("Failed to read possible tech type key name for {}", componentType, e); + } + } + return keyName.startsWith("_") ? keyName.substring(1) : keyName; + } + @Override public void dispose() { cpb.dispose(); super.dispose(); } - public void setTechTypePath(String path) { - bodyDataProvider.setPath(path); - table.refresh(true); - } + public void setTechTypePath(String path) { + String data; + try { + data = Files.lines(Paths.get(path), Charset.defaultCharset()).collect(Collectors.joining("\n")); + } catch (IOException e) { + LOGGER.error("Failed to read contents of file '{}' as {}", path, Charset.defaultCharset(), e); + return; + } + + try { + Simantics.getSession().syncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + graph.syncRequest(new WriteTechTypeTable(componentType, data)); + Resource model = graph.syncRequest(new PossibleActiveModel(Simantics.getProjectResource())); + if (model != null) { + tableResource = graph.syncRequest(new PossibleTechTypeTable(model, componentType)); + } + } + }); + } catch (DatabaseException e) { + LOGGER.error("Failed to write tech type table data to model", e); + } + + setTechTypeData(data); + setValidationResult(null); + } + + public void setTechTypeData(String data) { + bodyDataProvider.setData(data); + table.refresh(true); + } + + public void setComponentType(Resource componentType) { + this.componentType = componentType; + } + + /** + * Set results of a validation operation + * + * Invalid entries are designated by a string of the form "/". + * + * This method must be called in the SWT thread. + * + * @param result A set of strings representing invalid entries + */ + public void setValidationResult(Set result) { + if (result != null && result.isEmpty()) + result = null; + + this.validationResult = result; + if (result != null) { + String keyName = getKeyColumnName(componentType); + + bodyDataLayer.setConfigLabelAccumulator(new IConfigLabelAccumulator() { + @Override + public void accumulateConfigLabels(LabelStack configLabels, int columnPosition, int rowPosition) { + if (keyName != null) { + int keyColumn = bodyDataProvider.getVariableIndex(keyName); + if (keyColumn >= 0) { + String key = (String) bodyDataProvider.getDataValue(keyColumn, rowPosition); + String columnName = bodyDataProvider.getVariableName(columnPosition); + + if (validationResult.contains(key + "/" + columnName)) { + configLabels.addLabel(INVALID_LABEL); + } + } + } + } + }); + } else { + bodyDataLayer.setConfigLabelAccumulator(null); + } + + table.refresh(); + } + /** + * Get a resource representation of the currently open table, or null if + * table is not stored in the model. + */ + public Resource getCurrentTable() { + return tableResource; + } }