]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling.template2d.ui/src/org/simantics/modeling/template2d/ui/diagram/adapter/DrawingFlagTableStyle.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.modeling.template2d.ui / src / org / simantics / modeling / template2d / ui / diagram / adapter / DrawingFlagTableStyle.java
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
new file mode 100644 (file)
index 0000000..079017e
--- /dev/null
@@ -0,0 +1,830 @@
+/*******************************************************************************\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