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=b18e10c8d63f50c8971ef2fd90150ae783b37e69;hb=85f9ed92b6332c3e539d9736d1536d5714444d69;hp=8ee627a57989c09a79732b4773281c1a1b493352;hpb=5c939c503e87edefa1f0d46447511dde003944e2;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 8ee627a5..b18e10c8 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 @@ -4,6 +4,9 @@ import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -13,9 +16,12 @@ 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.EditableRule; 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.edit.EditConfigAttributes; +import org.eclipse.nebula.widgets.nattable.edit.editor.CheckBoxCellEditor; import org.eclipse.nebula.widgets.nattable.freeze.CompositeFreezeLayer; import org.eclipse.nebula.widgets.nattable.freeze.FreezeLayer; import org.eclipse.nebula.widgets.nattable.grid.GridRegion; @@ -29,16 +35,16 @@ import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer; import org.eclipse.nebula.widgets.nattable.group.ColumnGroupHeaderLayer; import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel; import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer; -import org.eclipse.nebula.widgets.nattable.hover.HoverLayer; -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.painter.cell.CheckBoxPainter; import org.eclipse.nebula.widgets.nattable.reorder.RowReorderLayer; import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer; import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer; +import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration; import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes; import org.eclipse.nebula.widgets.nattable.style.DisplayMode; import org.eclipse.nebula.widgets.nattable.style.Style; @@ -51,23 +57,35 @@ 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.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.ResourceRead; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.PossibleActiveModel; +import org.simantics.db.procedure.Listener; +import org.simantics.district.network.ontology.DistrictNetworkResource; +import org.simantics.district.network.techtype.requests.EnableTechTypeItem; 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.simantics.utils.datastructures.Triple; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TechTypeTable extends Composite { - private static final String INVALID_LABEL = "INVALID"; + private static final CheckBoxCellEditor CHECK_BOX_CELL_EDITOR = new CheckBoxCellEditor(); + + private static final CheckBoxPainter CHECK_BOX_PAINTER = new CheckBoxPainter(); + + private static final String INVALID_LABEL = "INVALID"; + protected static final String CHECK_BOX_LABEL = "CHECK_BOX"; private final static Logger LOGGER = LoggerFactory.getLogger(TechTypeTable.class); + NatTable table; private TechTypeTableDataProvider bodyDataProvider; DataLayer bodyDataLayer; @@ -86,18 +104,19 @@ public class TechTypeTable extends Composite { private Resource componentType; private Resource tableResource; + private String keyName; protected Set validationResult; - public TechTypeTable(Composite parent, int style, Resource componentType, Resource tableResource, String data) { + public TechTypeTable(Composite parent, int style, Resource componentType) { super(parent, style); + this.tableResource = null; this.componentType = componentType; - this.tableResource = tableResource; - defaultInitializeUI(data); + defaultInitializeUI(); } - private void defaultInitializeUI(String data) { + private void defaultInitializeUI() { GridDataFactory.fillDefaults().grab(true, true).applyTo(this); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(this); @@ -111,7 +130,7 @@ public class TechTypeTable extends Composite { GridDataFactory.fillDefaults().grab(true, true).applyTo(tableComposite); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(tableComposite); - createTable(tableComposite, data); + createTable(tableComposite); } private void createFilterBar(Composite filterComposite) { @@ -130,26 +149,76 @@ public class TechTypeTable extends Composite { } - private void createTable(Composite parent, String data) { + private void createTable(Composite parent) { + Triple> tableData; + String data = null; + int[] enabled = null; + if (componentType != null) { + try { + tableData = Simantics.getSession().syncRequest(new TableDataRequest(componentType), new TableDataListener(componentType)); + if (tableData != null) { + this.tableResource = tableData.first; + data = tableData.second; + enabled = tableData.third.stream().mapToInt(Integer::intValue).toArray(); + } else { + this.tableResource = null; + } + } catch (DatabaseException e) { + LOGGER.error("Failed to read tech type table data for {}", componentType, e); + } + } + // 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(data); + bodyDataProvider = new TechTypeTableDataProvider(data, enabled); bodyDataLayer = new DataLayer(bodyDataProvider); + bodyDataLayer.setConfigLabelAccumulator(new IConfigLabelAccumulator() { + @Override + public void accumulateConfigLabels(LabelStack configLabels, int columnPosition, int rowPosition) { + if (columnPosition == 0) { + configLabels.addLabel(CHECK_BOX_LABEL); + } else if (validationResult != null && 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); + } + } + } + } + }); + + bodyDataProvider.addEnableListener((rowIndex, enable) -> { + if (this.tableResource != null) { + try { + Simantics.getSession().syncRequest( + new EnableTechTypeItem(this.tableResource, rowIndex, enable) + ); + } catch (DatabaseException e) { + LOGGER.error("Failed to update enable state for {}", tableResource, e); + } + } + }); + 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 - // cursor moves out of the cell area - hoverLayer.addConfiguration(new BodyHoverStylingBindings(hoverLayer)); - - selectionLayer = new SelectionLayer(hoverLayer); +// HoverLayer hoverLayer = new HoverLayer(rowReorderLayer, false); +// // we need to ensure that the hover styling is removed when the mouse +// // cursor moves out of the cell area +// hoverLayer.addConfiguration(new BodyHoverStylingBindings(hoverLayer)); +// +// selectionLayer = new SelectionLayer(hoverLayer); + selectionLayer = new SelectionLayer(rowReorderLayer); viewportLayer = new ViewportLayer(selectionLayer); viewportLayer.setRegionName(GridRegion.BODY); @@ -188,18 +257,43 @@ public class TechTypeTable extends Composite { table = new NatTable(parent, NatTable.DEFAULT_STYLE_OPTIONS | SWT.BORDER, gridLayer, false); GridDataFactory.fillDefaults().grab(true, true).applyTo(table); + table.addConfiguration(new SingleClickSortConfiguration()); + // 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(EditConfigAttributes.CELL_EDITABLE_RULE, + new EditableRule() { + @Override + public boolean isEditable(int columnIndex, int rowIndex) { + return columnIndex == 0; + } + }); + configRegistry.registerConfigAttribute( CellConfigAttributes.CELL_STYLE, cellStyle, DisplayMode.NORMAL, INVALID_LABEL ); + + configRegistry.registerConfigAttribute( + EditConfigAttributes.CELL_EDITOR, + CHECK_BOX_CELL_EDITOR, + DisplayMode.EDIT, + CHECK_BOX_LABEL + ); + + configRegistry.registerConfigAttribute( + CellConfigAttributes.CELL_PAINTER, + CHECK_BOX_PAINTER, + DisplayMode.NORMAL, + CHECK_BOX_LABEL + ); } }); @@ -231,7 +325,7 @@ public class TechTypeTable extends Composite { LOGGER.error("Failed to read possible tech type key name for {}", componentType, e); } } - return keyName.startsWith("_") ? keyName.substring(1) : keyName; + return keyName != null && keyName.startsWith("_") ? keyName.substring(1) : keyName; } @Override @@ -239,6 +333,73 @@ public class TechTypeTable extends Composite { cpb.dispose(); super.dispose(); } + + public void setComponentType(Resource componentType) { + if (Objects.equals(this.componentType, componentType)) + return; + + this.componentType = componentType; + this.keyName = getKeyColumnName(componentType); + + if (componentType != null) { + Simantics.getSession().asyncRequest(new TableDataRequest(componentType), new TableDataListener(componentType)); + } + } + + private final class TableDataListener implements Listener>> { + private final Resource componentType; + + private TableDataListener(Resource componentType) { + this.componentType = componentType; + } + + @Override + public void execute(Triple> result) { + TechTypeTable.this.getDisplay().asyncExec(() -> { + if (isDisposed() || result == null) + return; + + TechTypeTable.this.tableResource = result.first; + String data = result.second; + int[] enabled = result.third.stream().mapToInt(Integer::intValue).toArray(); + + setTechTypeData(data, enabled); + setValidationResult(null); + }); + } + + @Override + public void exception(Throwable t) { + LOGGER.error("Error updating tech type table data for {}", componentType, t); + } + + @Override + public boolean isDisposed() { + return TechTypeTable.this.table != null && TechTypeTable.this.table.isDisposed() || + !Objects.equals(TechTypeTable.this.componentType, componentType); + } + } + + private final class TableDataRequest extends ResourceRead>> { + private TableDataRequest(Resource componentType) { + super(componentType); + } + + @Override + public Triple> perform(ReadGraph graph) throws DatabaseException { + Resource model = graph.syncRequest(new PossibleActiveModel(Simantics.getProjectResource())); + if (model == null) + return null; + Resource tableResource = graph.syncRequest(new PossibleTechTypeTable(model, this.resource)); + if (tableResource == null) + return null; + + String data = graph.getRelatedValue2(tableResource, DistrictNetworkResource.getInstance(graph).TechType_TechTypeTable_HasData); + int[] enabled = graph.getRelatedValue2(tableResource, DistrictNetworkResource.getInstance(graph).TechType_TechTypeTable_HasEnabledItems); + List list = Arrays.stream(enabled).mapToObj(Integer::valueOf).collect(Collectors.toList()); + return Triple.make(tableResource, data, list); + } + } public void setTechTypePath(String path) { String data; @@ -254,29 +415,21 @@ public class TechTypeTable extends Composite { @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); + setComponentType(componentType); } - public void setTechTypeData(String data) { + public void setTechTypeData(String data, int[] enabled) { bodyDataProvider.setData(data); + bodyDataProvider.setEnabledFlags(enabled); table.refresh(true); } - public void setComponentType(Resource componentType) { - this.componentType = componentType; - } - /** * Set results of a validation operation * @@ -292,26 +445,7 @@ public class TechTypeTable extends Composite { 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); + keyName = getKeyColumnName(componentType); } table.refresh();