--- /dev/null
+/*******************************************************************************\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