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