X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.modeling.template2d.ui%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Ftemplate2d%2Fui%2Fdiagram%2Fadapter%2FDrawingFlagTableStyle.java;h=5c91160ebe33af7b52be93a845b471a713c940f2;hb=cb337ac8c87b7bdad11ffb8584f76610c51d3a75;hp=079017e8f8135e96e9125e8c28218c5f9f599ce8;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.modeling.template2d.ui/src/org/simantics/modeling/template2d/ui/diagram/adapter/DrawingFlagTableStyle.java b/bundles/org.simantics.modeling.template2d.ui/src/org/simantics/modeling/template2d/ui/diagram/adapter/DrawingFlagTableStyle.java index 079017e8f..5c91160eb 100644 --- a/bundles/org.simantics.modeling.template2d.ui/src/org/simantics/modeling/template2d/ui/diagram/adapter/DrawingFlagTableStyle.java +++ b/bundles/org.simantics.modeling.template2d.ui/src/org/simantics/modeling/template2d/ui/diagram/adapter/DrawingFlagTableStyle.java @@ -1,830 +1,830 @@ -/******************************************************************************* - * Copyright (c) 2012 Association for Decentralized Information Management 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.modeling.template2d.ui.diagram.adapter; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Shape; -import java.awt.Stroke; -import java.awt.geom.AffineTransform; -import java.awt.geom.Line2D; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map.Entry; -import java.util.TreeMap; -import java.util.concurrent.atomic.AtomicReference; - -import org.simantics.Simantics; -import org.simantics.databoard.Bindings; -import org.simantics.databoard.annotations.Optional; -import org.simantics.databoard.util.Bean; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.Session; -import org.simantics.db.common.procedure.adapter.TransientCacheListener; -import org.simantics.db.common.request.ResourceRead; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.layer0.variable.Variables; -import org.simantics.diagram.elements.TextNode; -import org.simantics.diagram.function.All; -import org.simantics.diagram.function.PredefinedVariables; -import org.simantics.diagram.profile.ProfileKeys; -import org.simantics.diagram.profile.StyleBase; -import org.simantics.diagram.stubs.DiagramResource; -import org.simantics.g2d.diagram.IDiagram; -import org.simantics.g2d.element.ElementClass; -import org.simantics.g2d.element.ElementHints; -import org.simantics.g2d.element.ElementUtils; -import org.simantics.g2d.element.IElement; -import org.simantics.g2d.element.SceneGraphNodeKey; -import org.simantics.g2d.element.handler.ElementAdapter; -import org.simantics.g2d.element.handler.FillColor; -import org.simantics.g2d.element.handler.InternalSize; -import org.simantics.g2d.element.handler.Outline; -import org.simantics.g2d.element.handler.OutlineColorSpec; -import org.simantics.g2d.element.handler.SceneGraph; -import org.simantics.g2d.element.handler.SelectionSpecification; -import org.simantics.g2d.element.handler.StrokeSpec; -import org.simantics.g2d.element.handler.Transform; -import org.simantics.g2d.element.handler.impl.StaticObjectAdapter; -import org.simantics.g2d.element.impl.Element; -import org.simantics.g2d.elementclass.NonCopyable; -import org.simantics.g2d.scenegraph.SceneGraphConstants; -import org.simantics.layer0.Layer0; -import org.simantics.modeling.template2d.ui.function.DrawingTemplateInfo; -import org.simantics.modeling.template2d.ui.function.FlagInfo; -import org.simantics.modeling.template2d.ui.function.FlagTableColumnInfo; -import org.simantics.modeling.template2d.ui.function.FlagTableInfo; -import org.simantics.modeling.template2d.ui.function.MonitorInfo; -import org.simantics.modeling.template2d.ui.function.TranslateFlag; -import org.simantics.scenegraph.INode; -import org.simantics.scenegraph.g2d.G2DParentNode; -import org.simantics.scenegraph.g2d.G2DSceneGraph; -import org.simantics.scenegraph.g2d.nodes.ShapeNode; -import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode; -import org.simantics.scenegraph.profile.DataNodeMap; -import org.simantics.scenegraph.profile.EvaluationContext; -import org.simantics.scenegraph.profile.common.ProfileVariables; -import org.simantics.scenegraph.utils.NodeUtil; -import org.simantics.ui.colors.Colors; -import org.simantics.ui.fonts.Fonts; -import org.simantics.utils.datastructures.hints.IHintContext.Key; - -public class DrawingFlagTableStyle extends StyleBase { - - private static final boolean DEBUG_PAINT_ELEMENTS = false; - - private static final String SLOT_TABLE_PREFIX = "slotTable<"; - private static final String SLOT_TABLE_SEPARATOR = ">"; - - private static final String SLOT_TABLE_ELEMENTS = "slotTableElements"; - - private ElementClass rowElementClass; - - public DrawingFlagTableStyle(ReadGraph graph) { - rowElementClass = ElementClass.compile( - RowElementHandler.INSTANCE, - RowElementSelectionHandler.INSTANCE, - NonCopyable.INSTANCE, - new StaticObjectAdapter(DiagramResource.getInstance(graph).Flag) - ).setId(RowElementHandler.class.getSimpleName()); - if (DEBUG_PAINT_ELEMENTS) - rowElementClass = rowElementClass.newClassWith(TestSceneGraph.INSTANCE); - } - - public static class StyleInfo extends Bean { - public TreeMap name2table; - public List flags; - @Optional - public Resource template = null; - //public String digest = ""; - }; - - - - public static class FlagInfos extends ResourceRead> { - public FlagInfos(Resource diagram) { - super(diagram); - } - - @Override - public ArrayList perform(ReadGraph g) throws DatabaseException { - ArrayList flagInfos = new ArrayList(); - try { - Layer0 L0 = Layer0.getInstance(g); - DiagramResource DIA = DiagramResource.getInstance(g); - - Collection children = g.getObjects(resource, L0.ConsistsOf); - for (Resource child:children){ - if (!g.isInstanceOf(child, DIA.Flag)) - continue; - - Resource flag = child; - String tableName = g.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableBinding, Bindings.STRING); - Integer rowIndex = g.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableRowIndex, Bindings.INTEGER); - FlagInfo flagInfo = new FlagInfo(); - flagInfo.flag = flag; - if (tableName != null && tableName.length() > 0) - flagInfo.flagTableName = tableName; - flagInfo.flagTableRowIndex = rowIndex; - flagInfos.add(flagInfo); - } - } catch (Throwable e){ - e.printStackTrace(System.err); - } - return flagInfos; - } - } - - @Override - public StyleInfo calculateStyle(ReadGraph graph, Resource runtimeDiagram, - Resource entry, Resource diagram, Variable activeComposite) - throws DatabaseException { - Resource template = All.getTemplate(graph, runtimeDiagram); - if (template == null) - return null; - DiagramResource DIA = DiagramResource.getInstance(graph); - Resource diagram2 = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration); - - StyleInfo info = new StyleInfo(); - DrawingTemplateInfo templateInfo = new DrawingTemplateInfo(template); - info.template = template; - info.name2table = graph.syncRequest(templateInfo, TransientCacheListener.> instance()); - if (info.name2table == null) - info.name2table = new TreeMap(); - //info.digest = templateInfo.getDigest(); - //System.err.println(templateInfo.getDigest()); - - info.flags = graph.syncRequest(new FlagInfos(diagram2), TransientCacheListener.> instance()); - if (info.flags == null) - info.flags = Collections.emptyList(); - return info; - } - - @Override - public void applyStyleForItem(EvaluationContext evaluationContext, DataNodeMap map, Object item, StyleInfo info) { - if (info == null || info.flags == null || info.name2table == null) - return; - - cleanupStyleForItem(evaluationContext, map, item); - - // render tables - Iterator> it = info.name2table.entrySet().iterator(); - while(it.hasNext()) { - Entry entry = it.next(); - String name = entry.getKey(); - FlagTableInfo table = entry.getValue(); - RenderTable com = new RenderTable(evaluationContext, table, name); - com.perform(); - - // render header texts - RenderHeaderTexts com3 = new RenderHeaderTexts(evaluationContext, table, name); - com3.perform(); - } - - // render texts of flags -// for (FlagInfo flagInfo : info.flags) { -// RenderFlagTexts com2 = new RenderFlagTexts(evaluationContext, flagInfo, info.name2table); -// com2.perform(); -// } - } - - - /** - * This is just for debugging where the invisible IO row elements are. - * Not intended to be enabled. - */ - private static class TestSceneGraph implements SceneGraph { - - private static final long serialVersionUID = 5749410674482131633L; - - public static final TestSceneGraph INSTANCE = new TestSceneGraph(); - private static final Key KEY_SG = new SceneGraphNodeKey(INode.class, "DEBUG_SG_NODE"); - - @Override - public void init(IElement e, G2DParentNode parent) { - ShapeNode node = parent.getOrCreateNode("debug", ShapeNode.class); - if (node != null) { - node.setTransform(new AffineTransform(ElementUtils.getTransform(e))); - node.setShape(ElementUtils.getElementBounds(e)); - node.setFill(true); - node.setColor(Color.CYAN); - e.setHint(KEY_SG, node); - } - } - - @Override - public void cleanup(IElement e) { - ElementUtils.removePossibleNode(e, KEY_SG); - } - - } - - - static class RowElementSelectionHandler implements SelectionSpecification { - - /** - * - */ - private static final long serialVersionUID = 2539536175525595035L; - - static final RowElementSelectionHandler INSTANCE = new RowElementSelectionHandler(); - - - private RowElementSelectionHandler() { - } - - @Override - public Object getAdapter(Class adapter) { - // outline color - if (adapter.equals(OutlineColorSpec.class)){ - return new OutlineColorSpec() { - /** - * - */ - private static final long serialVersionUID = 2372559366005877243L; - - @Override - public void setColor(IElement e, Color c) { - } - - @Override - public Color getColor(IElement e) { - return new Color(10,10,10,40); - } - }; - } - if (adapter.equals(FillColor.class)){ - return new FillColor() { - /** - * - */ - private static final long serialVersionUID = 558080965120741509L; - - @Override - public void setFillColor(IElement e, Color c) { - // TODO Auto-generated method stub - - } - - @Override - public Color getFillColor(IElement e) { - return new Color(10,10,10,40); - } - }; - } - if (adapter.equals(Outline.class)){ - return new Outline() { - /** - * - */ - private static final long serialVersionUID = 272200345438045483L; - - @Override - public Shape getElementShape(IElement e) { - return e.getHint(ElementHints.KEY_BOUNDS); - } - }; - } - if (adapter.equals(Transform.class)){ - return new Transform() { - /** - * - */ - private static final long serialVersionUID = 7653122570884609688L; - - @Override - public AffineTransform getTransform(IElement e) { - return e.getHint(ElementHints.KEY_TRANSFORM); - } - - @Override - public void setTransform(IElement e, AffineTransform at) { - } - }; - } - if (adapter.equals(StrokeSpec.class)){ - return new StrokeSpec() { - - /** - * - */ - private static final long serialVersionUID = 1074910311375484373L; - - @Override - public Stroke getStroke(IElement e) { - return new BasicStroke(0.15f, BasicStroke.CAP_SQUARE, - BasicStroke.CAP_SQUARE, 10.0f, - null, 0.0f); - } - - @Override - public void setStroke(IElement e, Stroke at) { - // TODO Auto-generated method stub - - } - - }; - } - // TODO Auto-generated method stub - return null; - } - - } - - - static class RowElementHandler implements InternalSize, Transform, ElementAdapter { - - static final RowElementHandler INSTANCE = new RowElementHandler(); - - private static final long serialVersionUID = 829379327756475944L; - - private RowElementHandler() { - } - - @Override - public Rectangle2D getBounds(IElement e, Rectangle2D size) { - if (size == null) - size = new Rectangle2D.Double(); - Rectangle2D r = e.getHint(ElementHints.KEY_BOUNDS); - size.setFrame(r); - return size; - } - - @Override - public AffineTransform getTransform(IElement e) { - AffineTransform at = e.getHint(ElementHints.KEY_TRANSFORM); - return at != null ? at : new AffineTransform(); - } - - @Override - public void setTransform(IElement e, AffineTransform at) { - e.setHint(ElementHints.KEY_TRANSFORM, at.clone()); - } - - @SuppressWarnings("unchecked") - @Override - public T adapt(IElement e, Class toClass) { - if (toClass == Resource.class) { - Wrapper ref = e.getHint(ElementHints.KEY_OBJECT); - if (ref != null) - return (T) ref.get(); - } - return null; - } - - } - - - public static class RenderHeaderTexts { - private FlagTableInfo table = null; - private String tableName = null; - private EvaluationContext evaluationContext = null; - - public RenderHeaderTexts(EvaluationContext evaluationContext, FlagTableInfo table, String tableName){ - this.table = table; - this.tableName = tableName; - this.evaluationContext = evaluationContext; - } - - public void perform(){ - if (table == null || evaluationContext == null || tableName == null) - return; - - Session session = Simantics.peekSession(); - if (session == null) - return; - - G2DSceneGraph sg = evaluationContext.getSceneGraph(); - if (sg == null) - return; - - for (int k=0;k monitorInfos = slotcolumn.columnHeaders; - if (monitorInfos == null) - continue; - - int cellInx = 0; - for (MonitorInfo slotColumnData:monitorInfos){ - String cellNodeName = null; - cellNodeName = cellLookupName(tableName, k, 0, cellInx); - cellInx++; - TextNode cellNode = (TextNode) NodeUtil.lookup(sg, cellNodeName); - if (cellNode == null) - continue; - String txtValue = ""; - if (slotColumnData != null && slotColumnData.getText() != null) - txtValue = slotColumnData.getText(); - final String text = txtValue; - - try { - String value = ""; - if (slotColumnData.getResource() != null) - value = Simantics.getSession().sync(new EvaluatePath(slotColumnData.getResource(), text)); // , TransientCacheListener. instance() - if (value != null) - cellNode.setText(value.toString()); - } catch (DatabaseException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - - - - } - } - } - -// public class RenderFlagTexts { -// private FlagInfo flagInfo = null; -// private TreeMap tables = null; -// private EvaluationContext evaluationContext = null; -// -// public RenderFlagTexts(EvaluationContext evaluationContext, FlagInfo flagInfo, TreeMap tables){ -// this.flagInfo = flagInfo; -// this.tables = tables; -// this.evaluationContext = evaluationContext; -// } -// -// public void perform(){ -// Session session = Simantics.peekSession(); -// if (session == null) -// return; -// -// FlagTableInfo table = tables.get(flagInfo.flagTableName); -// if (table == null) -// return; -// -// G2DSceneGraph sg = evaluationContext.getSceneGraph(); -// if (sg == null) -// return; -// -// INode tableNode = sg.lookupNode(tableLookupName(flagInfo.flagTableName)); -// if (tableNode == null) -// return; -// -// Rectangle2D rowBounds = new Rectangle2D.Double(0, table.getRowHeight()*flagInfo.flagTableRowIndex, table.getWidth(), table.getRowHeight()); -// rowBounds = GeometryUtils.transformShape(rowBounds, table.affineTransform).getBounds2D(); -// addFlagElement(evaluationContext, tableNode, rowBounds, flagInfo.flag); -// -// for (int k=0;k monitorInfos = slotcolumn.columnDatas; -// if (monitorInfos == null) -// continue; -// -// int cellInx = 0; -// for (MonitorInfo slotColumnData:monitorInfos){ -// String cellNodeName = cellLookupName(flagInfo.flagTableName, k, flagInfo.flagTableRowIndex, cellInx); -// cellInx++; -// TextNode cellNode = (TextNode) NodeUtil.lookup(sg, cellNodeName); -// if (cellNode == null) -// continue; -// -// String txtValue = ""; -// if (slotColumnData != null && slotColumnData.getText() != null) -// txtValue = slotColumnData.getText(); -// final String text = txtValue; -// -// try { -// String value = null; -// if (slotcolumn.getType() != FlagTableColumnInfo.TYPE_ROW_NUMBERING) -// value = Simantics.getSession().sync(new EvaluatePath(flagInfo.flag, text)); // , TransientCacheListener. instance() -// if (value != null) -// cellNode.setText(value.toString()); -// } catch (DatabaseException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// } -// } -// } -// } - - public static class EvaluatePath extends ResourceRead { - private String path = null; - - public EvaluatePath(Resource res, String path) { - super(res); - this.path = path; -// this.flagInfo = flagInfo; - } - - @Override - public String perform(ReadGraph g) throws DatabaseException { - PredefinedVariables vars = PredefinedVariables.getInstance(); - Variable resourceVariable = Variables.getVariable(g, resource); - //v = g.adapt(this.flag, Variable.class); - if (resourceVariable == null) - return ""; - Variable property = vars.getVariable(g, path, resource, resourceVariable); - Object value = null; - if (property == null) - return ""; - try { - value = property.getValue(g); - } catch (DatabaseException ex){ - } - if (value == null || !(value instanceof String)) - return ""; - return value.toString(); - } - } - - public static class RenderTable { - private FlagTableInfo table = null; - private String tableName = null; - private EvaluationContext evaluationContext = null; - - public RenderTable(EvaluationContext evaluationContext, FlagTableInfo table, String tableName){ - this.table = table; - this.evaluationContext = evaluationContext; - this.tableName = tableName; - } - - public void perform(){ - // render table - G2DSceneGraph sg = evaluationContext.getSceneGraph(); - if (sg == null) - return; - G2DParentNode nav = (G2DParentNode) sg.getNode(SceneGraphConstants.NAVIGATION_NODE_NAME); - if (nav == null) - return; - - String tableNodeName = tableLookupName(tableName); - RTreeNode tableNode = (RTreeNode) sg.getNode(tableNodeName); - if (tableNode == null){ - tableNode = ProfileVariables.claimChild(evaluationContext.getSceneGraph(), - SceneGraphConstants.NAVIGATION_NODE_NAME, tableNodeName, RTreeNode.class, //SingleElementNode.class, - evaluationContext); - } - if (tableNode == null) - return; - tableNode.setTransform(new AffineTransform(table.affineTransform)); - //tableNode.setVisible(false); - tableNode.setLookupId(tableNodeName); - - // Initialize row node book-keeping for this table - evaluationContext.setProperty(tableNode, SLOT_TABLE_ELEMENTS, new ArrayList()); - - Integer rowCount = table.getRowCount(); - if (rowCount <= 0) - return; - - // test if table is already generated - String colNodeName = SLOT_TABLE_PREFIX + tableName + SLOT_TABLE_SEPARATOR + "0"; - RTreeNode colNode = (RTreeNode) sg.getNode(colNodeName); - if (colNode != null) - return; - - tableNode.setZIndex(2); - - //if (table.columns.size()> 0){ - // draw horisontal lines - for (int k=-1;k 0) { - for (FlagTableColumnInfo column : table.columns) { - maxColumnHeaders = Math.max(maxColumnHeaders, column.columnHeaders.size()); - } - } - - // generate columns and cells - String cellNodeName = null; - TextNode cellNode = null; - for (int k = 0;k monitorInfos = slotcolumn.columnDatas; - if (lineInx < maxColumnHeaders) - monitorInfos = slotcolumn.columnHeaders; - - int cellInx = 0; - for (MonitorInfo slotColumnData:monitorInfos){ - cellNodeName = cellLookupName(tableName, k, lineInx, cellInx); - cellInx++; - cellNode = ProfileVariables.claimChild(evaluationContext.getSceneGraph(), - SceneGraphConstants.NAVIGATION_NODE_NAME+"."+tableNodeName+"."+colNodeName, cellNodeName, TextNode.class, - evaluationContext); - if (cellNode == null) - continue; - cellNode.setLookupId(cellNodeName); - - AffineTransform transform = new AffineTransform(); - if (slotColumnData != null){ - if (slotColumnData.getFont() != null) - cellNode.setFont(Fonts.awt(slotColumnData.getFont())); - if (slotColumnData.getColor() != null) - cellNode.setColor(Colors.awt(slotColumnData.getColor())); - if (slotColumnData.getTransform() != null) - transform = new AffineTransform(slotColumnData.getTransform()); - } - cellNode.setVerticalAlignment((byte) 3); - double cellY = table.getRowHeight()*lineInx+DrawingTemplateInfo.BASELINE_VERTICAL_OFFSET*table.getRowHeight(); - //cellNode.setText("yÅcolumn_" + k); - cellNode.setText(""); - if (lineInx >= maxColumnHeaders && slotcolumn.getType() == FlagTableColumnInfo.TYPE_ROW_NUMBERING){ - // set row number - cellNode.setText(new Integer(lineInx-maxColumnHeaders+slotcolumn.getStartOffset()).toString()); - cellNode.setHorizontalAlignment((byte) 0); - } - -// FontMetrics metrics = new FontMetrics(cellNode.getFont()); -// double dy = (metrics.getAscent() + metrics.getLeading())/2; - cellNode.setBorderWidth(0.f); - cellNode.setPadding(0.0, 0.0); - Rectangle2D bounds = cellNode.getBoundsInLocal(); - //double dy = bounds.getHeight()/2.0; - transform.translate(0.0, cellY); - cellNode.setTransform(transform); - cellNode.setFixedWidth(cellWidth); - } - - } - } - //tableNode.setVisible(true); - } - - void addLine(String nodeId, int x1, int y1, int x2, int y2, int cap, RTreeNode parent){ - Line2D line = new Line2D.Float(x1, y1, x2, y2); - BasicStroke stroke = new BasicStroke(TranslateFlag.lineWidth, cap, BasicStroke.JOIN_MITER); - ShapeNode shape = parent.addNode(nodeId, ShapeNode.class); // SingleElementNode - shape.setShape(line); - shape.setScaleStroke(false); - shape.setStroke(stroke); - shape.setFill(false); - shape.setColor(new Color(0, 0, 0)); - shape.setZIndex(10); - } - } - - protected void cleanupStyleForItem(EvaluationContext evaluationContext, DataNodeMap map, Object item) { - INode root = evaluationContext.getSceneGraph(); - if (root instanceof G2DSceneGraph) { - G2DSceneGraph sg = (G2DSceneGraph) root; - G2DParentNode nav = (G2DParentNode) sg.getNode(SceneGraphConstants.NAVIGATION_NODE_NAME); - -// ProfileVariables.denyChildren(nav, SLOT_TABLE_PREFIX); - - IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM); - for (String childId : NodeUtil.filterDirectChildIds(nav, SLOT_TABLE_PREFIX)) { - INode child = nav.getNode(childId); - List elements = evaluationContext.setProperty(child, SLOT_TABLE_ELEMENTS, null); - if (elements != null && diagram != null) - for (IElement e : elements) - cleanupElement(diagram, e); - nav.removeNode(childId); - } - } - } - - private void cleanupElement(IDiagram diagram, IElement e) { - diagram.removeElement(e); - } - - /** - * @param tableName slot table name - * @return lookup ID for the cell node - */ - private static String tableLookupName(String tableName) { - return new StringBuilder() - .append(SLOT_TABLE_PREFIX) - .append(tableName).toString(); - } - - /** - * @param tableName slot table name - * @param column 0..C-1, where C is the amount of columns - * @param row 0..N, where 0 is header - * @return lookup ID for the cell node - */ - private static String cellLookupName(String tableName, int column, int row, int index) { - return new StringBuilder() - .append(SLOT_TABLE_PREFIX) - .append(tableName) - .append(SLOT_TABLE_SEPARATOR) - .append(column) - .append(SLOT_TABLE_SEPARATOR) - .append(row) - .append(SLOT_TABLE_SEPARATOR) - .append(index).toString(); - } - - private IElement addFlagElement(EvaluationContext evaluationContext, INode tableNode, Rectangle2D bounds, Resource flag) { - IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM); - assert diagram != null; - List elements = evaluationContext.getProperty(tableNode, SLOT_TABLE_ELEMENTS); - assert elements != null; - IElement e = newFlagElement(evaluationContext, bounds, flag); - elements.add(e); - diagram.addElement(e); - return e; - } - - private IElement newFlagElement(EvaluationContext evaluationContext, Rectangle2D bounds, Resource flag) { - IElement e = Element.spawnNew(rowElementClass); - e.setHint(ElementHints.KEY_BOUNDS, bounds.clone()); - e.setHint(ElementHints.KEY_TRANSFORM, new AffineTransform()); - // Just incase there's problems with same objects in multiple diagram elements - //e.setHint(ElementHints.KEY_OBJECT, flag); - // Didn't seem to help though. - e.setHint(ElementHints.KEY_OBJECT, new Wrapper(flag)); - return e; - } - - @Override - public String toString() { - return "Flag table style"; - } - - /** - * IO table flag elements need a wrapper KEY_OBJECT whose toString() - * produces something else besides {@link Resource#toString()}. - */ - public static class Wrapper extends AtomicReference { - private static final long serialVersionUID = -4041629837352874410L; - public Wrapper(Resource r) { - super(r); - } - @Override - public String toString() { - return "IO-" + super.toString(); - } - } - -} +/******************************************************************************* + * Copyright (c) 2012 Association for Decentralized Information Management 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.modeling.template2d.ui.diagram.adapter; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; +import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicReference; + +import org.simantics.Simantics; +import org.simantics.databoard.Bindings; +import org.simantics.databoard.annotations.Optional; +import org.simantics.databoard.util.Bean; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.common.procedure.adapter.TransientCacheListener; +import org.simantics.db.common.request.ResourceRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.diagram.elements.TextNode; +import org.simantics.diagram.function.All; +import org.simantics.diagram.function.PredefinedVariables; +import org.simantics.diagram.profile.ProfileKeys; +import org.simantics.diagram.profile.StyleBase; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.element.ElementClass; +import org.simantics.g2d.element.ElementHints; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.SceneGraphNodeKey; +import org.simantics.g2d.element.handler.ElementAdapter; +import org.simantics.g2d.element.handler.FillColor; +import org.simantics.g2d.element.handler.InternalSize; +import org.simantics.g2d.element.handler.Outline; +import org.simantics.g2d.element.handler.OutlineColorSpec; +import org.simantics.g2d.element.handler.SceneGraph; +import org.simantics.g2d.element.handler.SelectionSpecification; +import org.simantics.g2d.element.handler.StrokeSpec; +import org.simantics.g2d.element.handler.Transform; +import org.simantics.g2d.element.handler.impl.StaticObjectAdapter; +import org.simantics.g2d.element.impl.Element; +import org.simantics.g2d.elementclass.NonCopyable; +import org.simantics.g2d.scenegraph.SceneGraphConstants; +import org.simantics.layer0.Layer0; +import org.simantics.modeling.template2d.ui.function.DrawingTemplateInfo; +import org.simantics.modeling.template2d.ui.function.FlagInfo; +import org.simantics.modeling.template2d.ui.function.FlagTableColumnInfo; +import org.simantics.modeling.template2d.ui.function.FlagTableInfo; +import org.simantics.modeling.template2d.ui.function.MonitorInfo; +import org.simantics.modeling.template2d.ui.function.TranslateFlag; +import org.simantics.scenegraph.INode; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.scenegraph.g2d.G2DSceneGraph; +import org.simantics.scenegraph.g2d.nodes.ShapeNode; +import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode; +import org.simantics.scenegraph.profile.DataNodeMap; +import org.simantics.scenegraph.profile.EvaluationContext; +import org.simantics.scenegraph.profile.common.ProfileVariables; +import org.simantics.scenegraph.utils.NodeUtil; +import org.simantics.ui.colors.Colors; +import org.simantics.ui.fonts.Fonts; +import org.simantics.utils.datastructures.hints.IHintContext.Key; + +public class DrawingFlagTableStyle extends StyleBase { + + private static final boolean DEBUG_PAINT_ELEMENTS = false; + + private static final String SLOT_TABLE_PREFIX = "slotTable<"; + private static final String SLOT_TABLE_SEPARATOR = ">"; + + private static final String SLOT_TABLE_ELEMENTS = "slotTableElements"; + + private ElementClass rowElementClass; + + public DrawingFlagTableStyle(ReadGraph graph) { + rowElementClass = ElementClass.compile( + RowElementHandler.INSTANCE, + RowElementSelectionHandler.INSTANCE, + NonCopyable.INSTANCE, + new StaticObjectAdapter(DiagramResource.getInstance(graph).Flag) + ).setId(RowElementHandler.class.getSimpleName()); + if (DEBUG_PAINT_ELEMENTS) + rowElementClass = rowElementClass.newClassWith(TestSceneGraph.INSTANCE); + } + + public static class StyleInfo extends Bean { + public TreeMap name2table; + public List flags; + @Optional + public Resource template = null; + //public String digest = ""; + }; + + + + public static class FlagInfos extends ResourceRead> { + public FlagInfos(Resource diagram) { + super(diagram); + } + + @Override + public ArrayList perform(ReadGraph g) throws DatabaseException { + ArrayList flagInfos = new ArrayList(); + try { + Layer0 L0 = Layer0.getInstance(g); + DiagramResource DIA = DiagramResource.getInstance(g); + + Collection children = g.getObjects(resource, L0.ConsistsOf); + for (Resource child:children){ + if (!g.isInstanceOf(child, DIA.Flag)) + continue; + + Resource flag = child; + String tableName = g.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableBinding, Bindings.STRING); + Integer rowIndex = g.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableRowIndex, Bindings.INTEGER); + FlagInfo flagInfo = new FlagInfo(); + flagInfo.flag = flag; + if (tableName != null && tableName.length() > 0) + flagInfo.flagTableName = tableName; + flagInfo.flagTableRowIndex = rowIndex; + flagInfos.add(flagInfo); + } + } catch (Throwable e){ + e.printStackTrace(System.err); + } + return flagInfos; + } + } + + @Override + public StyleInfo calculateStyle(ReadGraph graph, Resource runtimeDiagram, + Resource entry, Resource diagram, Variable activeComposite) + throws DatabaseException { + Resource template = All.getTemplate(graph, runtimeDiagram); + if (template == null) + return null; + DiagramResource DIA = DiagramResource.getInstance(graph); + Resource diagram2 = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration); + + StyleInfo info = new StyleInfo(); + DrawingTemplateInfo templateInfo = new DrawingTemplateInfo(template); + info.template = template; + info.name2table = graph.syncRequest(templateInfo, TransientCacheListener.> instance()); + if (info.name2table == null) + info.name2table = new TreeMap(); + //info.digest = templateInfo.getDigest(); + //System.err.println(templateInfo.getDigest()); + + info.flags = graph.syncRequest(new FlagInfos(diagram2), TransientCacheListener.> instance()); + if (info.flags == null) + info.flags = Collections.emptyList(); + return info; + } + + @Override + public void applyStyleForItem(EvaluationContext evaluationContext, DataNodeMap map, Object item, StyleInfo info) { + if (info == null || info.flags == null || info.name2table == null) + return; + + cleanupStyleForItem(evaluationContext, map, item); + + // render tables + Iterator> it = info.name2table.entrySet().iterator(); + while(it.hasNext()) { + Entry entry = it.next(); + String name = entry.getKey(); + FlagTableInfo table = entry.getValue(); + RenderTable com = new RenderTable(evaluationContext, table, name); + com.perform(); + + // render header texts + RenderHeaderTexts com3 = new RenderHeaderTexts(evaluationContext, table, name); + com3.perform(); + } + + // render texts of flags +// for (FlagInfo flagInfo : info.flags) { +// RenderFlagTexts com2 = new RenderFlagTexts(evaluationContext, flagInfo, info.name2table); +// com2.perform(); +// } + } + + + /** + * This is just for debugging where the invisible IO row elements are. + * Not intended to be enabled. + */ + private static class TestSceneGraph implements SceneGraph { + + private static final long serialVersionUID = 5749410674482131633L; + + public static final TestSceneGraph INSTANCE = new TestSceneGraph(); + private static final Key KEY_SG = new SceneGraphNodeKey(INode.class, "DEBUG_SG_NODE"); + + @Override + public void init(IElement e, G2DParentNode parent) { + ShapeNode node = parent.getOrCreateNode("debug", ShapeNode.class); + if (node != null) { + node.setTransform(new AffineTransform(ElementUtils.getTransform(e))); + node.setShape(ElementUtils.getElementBounds(e)); + node.setFill(true); + node.setColor(Color.CYAN); + e.setHint(KEY_SG, node); + } + } + + @Override + public void cleanup(IElement e) { + ElementUtils.removePossibleNode(e, KEY_SG); + } + + } + + + static class RowElementSelectionHandler implements SelectionSpecification { + + /** + * + */ + private static final long serialVersionUID = 2539536175525595035L; + + static final RowElementSelectionHandler INSTANCE = new RowElementSelectionHandler(); + + + private RowElementSelectionHandler() { + } + + @Override + public Object getAdapter(Class adapter) { + // outline color + if (adapter.equals(OutlineColorSpec.class)){ + return new OutlineColorSpec() { + /** + * + */ + private static final long serialVersionUID = 2372559366005877243L; + + @Override + public void setColor(IElement e, Color c) { + } + + @Override + public Color getColor(IElement e) { + return new Color(10,10,10,40); + } + }; + } + if (adapter.equals(FillColor.class)){ + return new FillColor() { + /** + * + */ + private static final long serialVersionUID = 558080965120741509L; + + @Override + public void setFillColor(IElement e, Color c) { + // TODO Auto-generated method stub + + } + + @Override + public Color getFillColor(IElement e) { + return new Color(10,10,10,40); + } + }; + } + if (adapter.equals(Outline.class)){ + return new Outline() { + /** + * + */ + private static final long serialVersionUID = 272200345438045483L; + + @Override + public Shape getElementShape(IElement e) { + return e.getHint(ElementHints.KEY_BOUNDS); + } + }; + } + if (adapter.equals(Transform.class)){ + return new Transform() { + /** + * + */ + private static final long serialVersionUID = 7653122570884609688L; + + @Override + public AffineTransform getTransform(IElement e) { + return e.getHint(ElementHints.KEY_TRANSFORM); + } + + @Override + public void setTransform(IElement e, AffineTransform at) { + } + }; + } + if (adapter.equals(StrokeSpec.class)){ + return new StrokeSpec() { + + /** + * + */ + private static final long serialVersionUID = 1074910311375484373L; + + @Override + public Stroke getStroke(IElement e) { + return new BasicStroke(0.15f, BasicStroke.CAP_SQUARE, + BasicStroke.CAP_SQUARE, 10.0f, + null, 0.0f); + } + + @Override + public void setStroke(IElement e, Stroke at) { + // TODO Auto-generated method stub + + } + + }; + } + // TODO Auto-generated method stub + return null; + } + + } + + + static class RowElementHandler implements InternalSize, Transform, ElementAdapter { + + static final RowElementHandler INSTANCE = new RowElementHandler(); + + private static final long serialVersionUID = 829379327756475944L; + + private RowElementHandler() { + } + + @Override + public Rectangle2D getBounds(IElement e, Rectangle2D size) { + if (size == null) + size = new Rectangle2D.Double(); + Rectangle2D r = e.getHint(ElementHints.KEY_BOUNDS); + size.setFrame(r); + return size; + } + + @Override + public AffineTransform getTransform(IElement e) { + AffineTransform at = e.getHint(ElementHints.KEY_TRANSFORM); + return at != null ? at : new AffineTransform(); + } + + @Override + public void setTransform(IElement e, AffineTransform at) { + e.setHint(ElementHints.KEY_TRANSFORM, at.clone()); + } + + @SuppressWarnings("unchecked") + @Override + public T adapt(IElement e, Class toClass) { + if (toClass == Resource.class) { + Wrapper ref = e.getHint(ElementHints.KEY_OBJECT); + if (ref != null) + return (T) ref.get(); + } + return null; + } + + } + + + public static class RenderHeaderTexts { + private FlagTableInfo table = null; + private String tableName = null; + private EvaluationContext evaluationContext = null; + + public RenderHeaderTexts(EvaluationContext evaluationContext, FlagTableInfo table, String tableName){ + this.table = table; + this.tableName = tableName; + this.evaluationContext = evaluationContext; + } + + public void perform(){ + if (table == null || evaluationContext == null || tableName == null) + return; + + Session session = Simantics.peekSession(); + if (session == null) + return; + + G2DSceneGraph sg = evaluationContext.getSceneGraph(); + if (sg == null) + return; + + for (int k=0;k monitorInfos = slotcolumn.columnHeaders; + if (monitorInfos == null) + continue; + + int cellInx = 0; + for (MonitorInfo slotColumnData:monitorInfos){ + String cellNodeName = null; + cellNodeName = cellLookupName(tableName, k, 0, cellInx); + cellInx++; + TextNode cellNode = (TextNode) NodeUtil.lookup(sg, cellNodeName); + if (cellNode == null) + continue; + String txtValue = ""; + if (slotColumnData != null && slotColumnData.getText() != null) + txtValue = slotColumnData.getText(); + final String text = txtValue; + + try { + String value = ""; + if (slotColumnData.getResource() != null) + value = Simantics.getSession().sync(new EvaluatePath(slotColumnData.getResource(), text)); // , TransientCacheListener. instance() + if (value != null) + cellNode.setText(value.toString()); + } catch (DatabaseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + + + } + } + } + +// public class RenderFlagTexts { +// private FlagInfo flagInfo = null; +// private TreeMap tables = null; +// private EvaluationContext evaluationContext = null; +// +// public RenderFlagTexts(EvaluationContext evaluationContext, FlagInfo flagInfo, TreeMap tables){ +// this.flagInfo = flagInfo; +// this.tables = tables; +// this.evaluationContext = evaluationContext; +// } +// +// public void perform(){ +// Session session = Simantics.peekSession(); +// if (session == null) +// return; +// +// FlagTableInfo table = tables.get(flagInfo.flagTableName); +// if (table == null) +// return; +// +// G2DSceneGraph sg = evaluationContext.getSceneGraph(); +// if (sg == null) +// return; +// +// INode tableNode = sg.lookupNode(tableLookupName(flagInfo.flagTableName)); +// if (tableNode == null) +// return; +// +// Rectangle2D rowBounds = new Rectangle2D.Double(0, table.getRowHeight()*flagInfo.flagTableRowIndex, table.getWidth(), table.getRowHeight()); +// rowBounds = GeometryUtils.transformShape(rowBounds, table.affineTransform).getBounds2D(); +// addFlagElement(evaluationContext, tableNode, rowBounds, flagInfo.flag); +// +// for (int k=0;k monitorInfos = slotcolumn.columnDatas; +// if (monitorInfos == null) +// continue; +// +// int cellInx = 0; +// for (MonitorInfo slotColumnData:monitorInfos){ +// String cellNodeName = cellLookupName(flagInfo.flagTableName, k, flagInfo.flagTableRowIndex, cellInx); +// cellInx++; +// TextNode cellNode = (TextNode) NodeUtil.lookup(sg, cellNodeName); +// if (cellNode == null) +// continue; +// +// String txtValue = ""; +// if (slotColumnData != null && slotColumnData.getText() != null) +// txtValue = slotColumnData.getText(); +// final String text = txtValue; +// +// try { +// String value = null; +// if (slotcolumn.getType() != FlagTableColumnInfo.TYPE_ROW_NUMBERING) +// value = Simantics.getSession().sync(new EvaluatePath(flagInfo.flag, text)); // , TransientCacheListener. instance() +// if (value != null) +// cellNode.setText(value.toString()); +// } catch (DatabaseException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// } +// } +// } +// } + + public static class EvaluatePath extends ResourceRead { + private String path = null; + + public EvaluatePath(Resource res, String path) { + super(res); + this.path = path; +// this.flagInfo = flagInfo; + } + + @Override + public String perform(ReadGraph g) throws DatabaseException { + PredefinedVariables vars = PredefinedVariables.getInstance(); + Variable resourceVariable = Variables.getVariable(g, resource); + //v = g.adapt(this.flag, Variable.class); + if (resourceVariable == null) + return ""; + Variable property = vars.getVariable(g, path, resource, resourceVariable); + Object value = null; + if (property == null) + return ""; + try { + value = property.getValue(g); + } catch (DatabaseException ex){ + } + if (value == null || !(value instanceof String)) + return ""; + return value.toString(); + } + } + + public static class RenderTable { + private FlagTableInfo table = null; + private String tableName = null; + private EvaluationContext evaluationContext = null; + + public RenderTable(EvaluationContext evaluationContext, FlagTableInfo table, String tableName){ + this.table = table; + this.evaluationContext = evaluationContext; + this.tableName = tableName; + } + + public void perform(){ + // render table + G2DSceneGraph sg = evaluationContext.getSceneGraph(); + if (sg == null) + return; + G2DParentNode nav = (G2DParentNode) sg.getNode(SceneGraphConstants.NAVIGATION_NODE_NAME); + if (nav == null) + return; + + String tableNodeName = tableLookupName(tableName); + RTreeNode tableNode = (RTreeNode) sg.getNode(tableNodeName); + if (tableNode == null){ + tableNode = ProfileVariables.claimChild(evaluationContext.getSceneGraph(), + SceneGraphConstants.NAVIGATION_NODE_NAME, tableNodeName, RTreeNode.class, //SingleElementNode.class, + evaluationContext); + } + if (tableNode == null) + return; + tableNode.setTransform(new AffineTransform(table.affineTransform)); + //tableNode.setVisible(false); + tableNode.setLookupId(tableNodeName); + + // Initialize row node book-keeping for this table + evaluationContext.setProperty(tableNode, SLOT_TABLE_ELEMENTS, new ArrayList()); + + Integer rowCount = table.getRowCount(); + if (rowCount <= 0) + return; + + // test if table is already generated + String colNodeName = SLOT_TABLE_PREFIX + tableName + SLOT_TABLE_SEPARATOR + "0"; + RTreeNode colNode = (RTreeNode) sg.getNode(colNodeName); + if (colNode != null) + return; + + tableNode.setZIndex(2); + + //if (table.columns.size()> 0){ + // draw horisontal lines + for (int k=-1;k 0) { + for (FlagTableColumnInfo column : table.columns) { + maxColumnHeaders = Math.max(maxColumnHeaders, column.columnHeaders.size()); + } + } + + // generate columns and cells + String cellNodeName = null; + TextNode cellNode = null; + for (int k = 0;k monitorInfos = slotcolumn.columnDatas; + if (lineInx < maxColumnHeaders) + monitorInfos = slotcolumn.columnHeaders; + + int cellInx = 0; + for (MonitorInfo slotColumnData:monitorInfos){ + cellNodeName = cellLookupName(tableName, k, lineInx, cellInx); + cellInx++; + cellNode = ProfileVariables.claimChild(evaluationContext.getSceneGraph(), + SceneGraphConstants.NAVIGATION_NODE_NAME+"."+tableNodeName+"."+colNodeName, cellNodeName, TextNode.class, + evaluationContext); + if (cellNode == null) + continue; + cellNode.setLookupId(cellNodeName); + + AffineTransform transform = new AffineTransform(); + if (slotColumnData != null){ + if (slotColumnData.getFont() != null) + cellNode.setFont(Fonts.awt(slotColumnData.getFont())); + if (slotColumnData.getColor() != null) + cellNode.setColor(Colors.awt(slotColumnData.getColor())); + if (slotColumnData.getTransform() != null) + transform = new AffineTransform(slotColumnData.getTransform()); + } + cellNode.setVerticalAlignment((byte) 3); + double cellY = table.getRowHeight()*lineInx+DrawingTemplateInfo.BASELINE_VERTICAL_OFFSET*table.getRowHeight(); + //cellNode.setText("yÅcolumn_" + k); + cellNode.setText(""); + if (lineInx >= maxColumnHeaders && slotcolumn.getType() == FlagTableColumnInfo.TYPE_ROW_NUMBERING){ + // set row number + cellNode.setText(new Integer(lineInx-maxColumnHeaders+slotcolumn.getStartOffset()).toString()); + cellNode.setHorizontalAlignment((byte) 0); + } + +// FontMetrics metrics = new FontMetrics(cellNode.getFont()); +// double dy = (metrics.getAscent() + metrics.getLeading())/2; + cellNode.setBorderWidth(0.f); + cellNode.setPadding(0.0, 0.0); + Rectangle2D bounds = cellNode.getBoundsInLocal(); + //double dy = bounds.getHeight()/2.0; + transform.translate(0.0, cellY); + cellNode.setTransform(transform); + cellNode.setFixedWidth(cellWidth); + } + + } + } + //tableNode.setVisible(true); + } + + void addLine(String nodeId, int x1, int y1, int x2, int y2, int cap, RTreeNode parent){ + Line2D line = new Line2D.Float(x1, y1, x2, y2); + BasicStroke stroke = new BasicStroke(TranslateFlag.lineWidth, cap, BasicStroke.JOIN_MITER); + ShapeNode shape = parent.addNode(nodeId, ShapeNode.class); // SingleElementNode + shape.setShape(line); + shape.setScaleStroke(false); + shape.setStroke(stroke); + shape.setFill(false); + shape.setColor(new Color(0, 0, 0)); + shape.setZIndex(10); + } + } + + protected void cleanupStyleForItem(EvaluationContext evaluationContext, DataNodeMap map, Object item) { + INode root = evaluationContext.getSceneGraph(); + if (root instanceof G2DSceneGraph) { + G2DSceneGraph sg = (G2DSceneGraph) root; + G2DParentNode nav = (G2DParentNode) sg.getNode(SceneGraphConstants.NAVIGATION_NODE_NAME); + +// ProfileVariables.denyChildren(nav, SLOT_TABLE_PREFIX); + + IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM); + for (String childId : NodeUtil.filterDirectChildIds(nav, SLOT_TABLE_PREFIX)) { + INode child = nav.getNode(childId); + List elements = evaluationContext.setProperty(child, SLOT_TABLE_ELEMENTS, null); + if (elements != null && diagram != null) + for (IElement e : elements) + cleanupElement(diagram, e); + nav.removeNode(childId); + } + } + } + + private void cleanupElement(IDiagram diagram, IElement e) { + diagram.removeElement(e); + } + + /** + * @param tableName slot table name + * @return lookup ID for the cell node + */ + private static String tableLookupName(String tableName) { + return new StringBuilder() + .append(SLOT_TABLE_PREFIX) + .append(tableName).toString(); + } + + /** + * @param tableName slot table name + * @param column 0..C-1, where C is the amount of columns + * @param row 0..N, where 0 is header + * @return lookup ID for the cell node + */ + private static String cellLookupName(String tableName, int column, int row, int index) { + return new StringBuilder() + .append(SLOT_TABLE_PREFIX) + .append(tableName) + .append(SLOT_TABLE_SEPARATOR) + .append(column) + .append(SLOT_TABLE_SEPARATOR) + .append(row) + .append(SLOT_TABLE_SEPARATOR) + .append(index).toString(); + } + + private IElement addFlagElement(EvaluationContext evaluationContext, INode tableNode, Rectangle2D bounds, Resource flag) { + IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM); + assert diagram != null; + List elements = evaluationContext.getProperty(tableNode, SLOT_TABLE_ELEMENTS); + assert elements != null; + IElement e = newFlagElement(evaluationContext, bounds, flag); + elements.add(e); + diagram.addElement(e); + return e; + } + + private IElement newFlagElement(EvaluationContext evaluationContext, Rectangle2D bounds, Resource flag) { + IElement e = Element.spawnNew(rowElementClass); + e.setHint(ElementHints.KEY_BOUNDS, bounds.clone()); + e.setHint(ElementHints.KEY_TRANSFORM, new AffineTransform()); + // Just incase there's problems with same objects in multiple diagram elements + //e.setHint(ElementHints.KEY_OBJECT, flag); + // Didn't seem to help though. + e.setHint(ElementHints.KEY_OBJECT, new Wrapper(flag)); + return e; + } + + @Override + public String toString() { + return "Flag table style"; + } + + /** + * IO table flag elements need a wrapper KEY_OBJECT whose toString() + * produces something else besides {@link Resource#toString()}. + */ + public static class Wrapper extends AtomicReference { + private static final long serialVersionUID = -4041629837352874410L; + public Wrapper(Resource r) { + super(r); + } + @Override + public String toString() { + return "IO-" + super.toString(); + } + } + +}