package org.simantics.district.network.ui.techtype.table; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; 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.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.freeze.CompositeFreezeLayer; import org.eclipse.nebula.widgets.nattable.freeze.FreezeLayer; import org.eclipse.nebula.widgets.nattable.grid.GridRegion; import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider; import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer; import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer; import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer; import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer; import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer; 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.reorder.RowReorderLayer; import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer; import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer; import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; 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.exception.DatabaseException; import org.simantics.district.network.techtype.requests.WriteTechTypeTable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TechTypeTable extends Composite { private final static Logger LOGGER = LoggerFactory.getLogger(TechTypeTable.class); NatTable table; private TechTypeTableDataProvider bodyDataProvider; DataLayer bodyDataLayer; private IConfigRegistry summaryConfigRegistry; private IUniqueIndexLayer summaryRowLayer; private ViewportLayer viewportLayer; private CompositeFreezeLayer compositeFreezeLayer; private FreezeLayer freezeLayer; // private TableDataSortModel sortModel; private ColumnHideShowLayer columnHideShowLayer; private ColumnGroupModel columnGroupModel = new ColumnGroupModel(); private TechTypeColumnHeaderTableDataProvider columnHeaderDataProvider; Clipboard cpb; public SelectionLayer selectionLayer; private TechTypeTableSortModel sortModel; private Resource componentType; public TechTypeTable(Composite parent, int style, Resource componentType, String data) { super(parent, style); this.componentType = componentType; defaultInitializeUI(data); } 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); createFilterBar(filterComposite); Composite tableComposite = new Composite(this, SWT.NONE); GridDataFactory.fillDefaults().grab(true, true).applyTo(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, 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(data); bodyDataLayer = new DataLayer(bodyDataProvider); 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); viewportLayer = new ViewportLayer(selectionLayer); viewportLayer.setRegionName(GridRegion.BODY); freezeLayer = new FreezeLayer(selectionLayer); compositeFreezeLayer = new CompositeFreezeLayer(freezeLayer, viewportLayer, selectionLayer); // build the column header layer columnHeaderDataProvider = new TechTypeColumnHeaderTableDataProvider(bodyDataProvider); 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); columnGroupHeaderLayer.setCalculateHeight(true); SortHeaderLayer columnSortHeaderLayer = new SortHeaderLayer<>(columnGroupHeaderLayer, sortModel = new TechTypeTableSortModel(bodyDataProvider)); // build the row header layer IDataProvider rowHeaderDataProvider = new TechTypeRowHeaderTableDataProvider(bodyDataProvider); DataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider); rowHeaderDataLayer.setRowsResizableByDefault(false); rowHeaderDataLayer.setColumnsResizableByDefault(false); RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, compositeFreezeLayer, selectionLayer); // build the corner layer 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); // Register a CopyDataCommandHandler that also copies the headers and // uses the configured IDisplayConverters 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); table.addConfiguration(new DefaultNatTableStyleConfiguration()); // table.addConfiguration(new EditingSupportConfiguration(bodyDataProvider)); table.configure(); } @Override public void dispose() { cpb.dispose(); super.dispose(); } 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 WriteTechTypeTable(componentType, data)); } catch (DatabaseException e) { LOGGER.error("Failed to write tech type table data to model", e); } setTechTypeData(data); } public void setTechTypeData(String data) { bodyDataProvider.setData(data); table.refresh(true); } public void setComponentType(Resource componentType) { this.componentType = componentType; } }