]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 /*******************************************************************************\r
2  * Copyright (c) 2012 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.modeling.template2d.ui.diagram.adapter;\r
13 \r
14 import java.awt.BasicStroke;\r
15 import java.awt.Color;\r
16 import java.awt.Shape;\r
17 import java.awt.Stroke;\r
18 import java.awt.geom.AffineTransform;\r
19 import java.awt.geom.Line2D;\r
20 import java.awt.geom.Rectangle2D;\r
21 import java.util.ArrayList;\r
22 import java.util.Collection;\r
23 import java.util.Collections;\r
24 import java.util.Iterator;\r
25 import java.util.List;\r
26 import java.util.Map.Entry;\r
27 import java.util.TreeMap;\r
28 import java.util.concurrent.atomic.AtomicReference;\r
29 \r
30 import org.simantics.Simantics;\r
31 import org.simantics.databoard.Bindings;\r
32 import org.simantics.databoard.annotations.Optional;\r
33 import org.simantics.databoard.util.Bean;\r
34 import org.simantics.db.ReadGraph;\r
35 import org.simantics.db.Resource;\r
36 import org.simantics.db.Session;\r
37 import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
38 import org.simantics.db.common.request.ResourceRead;\r
39 import org.simantics.db.exception.DatabaseException;\r
40 import org.simantics.db.layer0.variable.Variable;\r
41 import org.simantics.db.layer0.variable.Variables;\r
42 import org.simantics.diagram.elements.TextNode;\r
43 import org.simantics.diagram.function.All;\r
44 import org.simantics.diagram.function.PredefinedVariables;\r
45 import org.simantics.diagram.profile.ProfileKeys;\r
46 import org.simantics.diagram.profile.StyleBase;\r
47 import org.simantics.diagram.stubs.DiagramResource;\r
48 import org.simantics.g2d.diagram.IDiagram;\r
49 import org.simantics.g2d.element.ElementClass;\r
50 import org.simantics.g2d.element.ElementHints;\r
51 import org.simantics.g2d.element.ElementUtils;\r
52 import org.simantics.g2d.element.IElement;\r
53 import org.simantics.g2d.element.SceneGraphNodeKey;\r
54 import org.simantics.g2d.element.handler.ElementAdapter;\r
55 import org.simantics.g2d.element.handler.FillColor;\r
56 import org.simantics.g2d.element.handler.InternalSize;\r
57 import org.simantics.g2d.element.handler.Outline;\r
58 import org.simantics.g2d.element.handler.OutlineColorSpec;\r
59 import org.simantics.g2d.element.handler.SceneGraph;\r
60 import org.simantics.g2d.element.handler.SelectionSpecification;\r
61 import org.simantics.g2d.element.handler.StrokeSpec;\r
62 import org.simantics.g2d.element.handler.Transform;\r
63 import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
64 import org.simantics.g2d.element.impl.Element;\r
65 import org.simantics.g2d.elementclass.NonCopyable;\r
66 import org.simantics.g2d.scenegraph.SceneGraphConstants;\r
67 import org.simantics.layer0.Layer0;\r
68 import org.simantics.modeling.template2d.ui.function.DrawingTemplateInfo;\r
69 import org.simantics.modeling.template2d.ui.function.FlagInfo;\r
70 import org.simantics.modeling.template2d.ui.function.FlagTableColumnInfo;\r
71 import org.simantics.modeling.template2d.ui.function.FlagTableInfo;\r
72 import org.simantics.modeling.template2d.ui.function.MonitorInfo;\r
73 import org.simantics.modeling.template2d.ui.function.TranslateFlag;\r
74 import org.simantics.scenegraph.INode;\r
75 import org.simantics.scenegraph.g2d.G2DParentNode;\r
76 import org.simantics.scenegraph.g2d.G2DSceneGraph;\r
77 import org.simantics.scenegraph.g2d.nodes.ShapeNode;\r
78 import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode;\r
79 import org.simantics.scenegraph.profile.DataNodeMap;\r
80 import org.simantics.scenegraph.profile.EvaluationContext;\r
81 import org.simantics.scenegraph.profile.common.ProfileVariables;\r
82 import org.simantics.scenegraph.utils.NodeUtil;\r
83 import org.simantics.ui.colors.Colors;\r
84 import org.simantics.ui.fonts.Fonts;\r
85 import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
86 \r
87 public class DrawingFlagTableStyle extends StyleBase<DrawingFlagTableStyle.StyleInfo> {\r
88 \r
89         private static final boolean DEBUG_PAINT_ELEMENTS = false;\r
90 \r
91         private static final String SLOT_TABLE_PREFIX    = "slotTable<";\r
92         private static final String SLOT_TABLE_SEPARATOR = ">";\r
93 \r
94         private static final String SLOT_TABLE_ELEMENTS  = "slotTableElements";\r
95 \r
96         private ElementClass rowElementClass;\r
97 \r
98         public DrawingFlagTableStyle(ReadGraph graph) {\r
99                 rowElementClass = ElementClass.compile(\r
100                                 RowElementHandler.INSTANCE,\r
101                                 RowElementSelectionHandler.INSTANCE,\r
102                                 NonCopyable.INSTANCE,\r
103                                 new StaticObjectAdapter(DiagramResource.getInstance(graph).Flag)\r
104                 ).setId(RowElementHandler.class.getSimpleName());\r
105                 if (DEBUG_PAINT_ELEMENTS)\r
106                         rowElementClass = rowElementClass.newClassWith(TestSceneGraph.INSTANCE);\r
107         }\r
108 \r
109         public static class StyleInfo extends Bean {\r
110                 public TreeMap<String, FlagTableInfo> name2table;\r
111                 public List<FlagInfo> flags;\r
112                 @Optional\r
113                 public Resource template = null;\r
114                 //public String digest = "";\r
115         };\r
116         \r
117         \r
118         \r
119         public static class FlagInfos extends ResourceRead<ArrayList<FlagInfo>> {\r
120             public FlagInfos(Resource diagram) {\r
121                 super(diagram);\r
122             }\r
123 \r
124             @Override\r
125             public ArrayList<FlagInfo> perform(ReadGraph g) throws DatabaseException {\r
126                 ArrayList<FlagInfo> flagInfos = new ArrayList<FlagInfo>();\r
127                 try {\r
128                         Layer0 L0 = Layer0.getInstance(g);\r
129                         DiagramResource DIA = DiagramResource.getInstance(g);\r
130 \r
131                         Collection<Resource> children = g.getObjects(resource, L0.ConsistsOf);\r
132                         for (Resource child:children){\r
133                                 if (!g.isInstanceOf(child, DIA.Flag))\r
134                                         continue;\r
135 \r
136                                 Resource flag = child;\r
137                                 String tableName = g.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableBinding, Bindings.STRING);\r
138                                 Integer rowIndex = g.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableRowIndex, Bindings.INTEGER);\r
139                                 FlagInfo flagInfo = new FlagInfo();\r
140                                 flagInfo.flag = flag;\r
141                                 if (tableName != null && tableName.length() > 0)\r
142                                         flagInfo.flagTableName = tableName;\r
143                                 flagInfo.flagTableRowIndex = rowIndex;\r
144                                 flagInfos.add(flagInfo);\r
145                         }\r
146                 } catch (Throwable e){\r
147                         e.printStackTrace(System.err);\r
148                 }\r
149                 return flagInfos;\r
150             }\r
151         }\r
152 \r
153         @Override\r
154         public StyleInfo calculateStyle(ReadGraph graph, Resource runtimeDiagram,\r
155                         Resource entry, Resource diagram, Variable activeComposite)\r
156                         throws DatabaseException {\r
157                 Resource template = All.getTemplate(graph, runtimeDiagram);\r
158                 if (template == null)\r
159                         return null;\r
160                 DiagramResource DIA = DiagramResource.getInstance(graph);\r
161                 Resource diagram2 = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration);\r
162 \r
163                 StyleInfo info = new StyleInfo();\r
164                 DrawingTemplateInfo templateInfo = new DrawingTemplateInfo(template);\r
165                 info.template = template;\r
166                 info.name2table = graph.syncRequest(templateInfo, TransientCacheListener.<TreeMap<String, FlagTableInfo>> instance());\r
167                 if (info.name2table == null)\r
168                     info.name2table = new TreeMap<String,FlagTableInfo>();\r
169                 //info.digest = templateInfo.getDigest();\r
170                 //System.err.println(templateInfo.getDigest());\r
171 \r
172                 info.flags = graph.syncRequest(new FlagInfos(diagram2), TransientCacheListener.<ArrayList<FlagInfo>> instance());\r
173                 if (info.flags == null)\r
174                     info.flags = Collections.emptyList();\r
175                 return info;\r
176         }\r
177         \r
178         @Override\r
179         public void applyStyleForItem(EvaluationContext evaluationContext, DataNodeMap map, Object item, StyleInfo info) {\r
180                 if (info == null || info.flags == null || info.name2table == null)\r
181                         return;\r
182 \r
183                 cleanupStyleForItem(evaluationContext, map, item);\r
184 \r
185                 // render tables\r
186                 Iterator<Entry<String,FlagTableInfo>> it = info.name2table.entrySet().iterator();\r
187                 while(it.hasNext()) {\r
188                         Entry<String,FlagTableInfo> entry = it.next();\r
189                         String name = entry.getKey();\r
190                         FlagTableInfo table = entry.getValue();\r
191                         RenderTable com = new RenderTable(evaluationContext, table, name);\r
192                         com.perform();\r
193 \r
194                         // render header texts\r
195                         RenderHeaderTexts com3 = new RenderHeaderTexts(evaluationContext, table, name);\r
196                         com3.perform();\r
197                 }\r
198 \r
199                 // render texts of flags\r
200 //              for (FlagInfo flagInfo : info.flags) {\r
201 //                      RenderFlagTexts com2 = new RenderFlagTexts(evaluationContext, flagInfo, info.name2table);\r
202 //                      com2.perform();\r
203 //              }\r
204         }\r
205         \r
206 \r
207         /**\r
208          * This is just for debugging where the invisible IO row elements are.\r
209          * Not intended to be enabled.\r
210          */\r
211         private static class TestSceneGraph implements SceneGraph {\r
212 \r
213             private static final long serialVersionUID = 5749410674482131633L;\r
214 \r
215             public static final TestSceneGraph INSTANCE = new TestSceneGraph();\r
216             private static final Key KEY_SG = new SceneGraphNodeKey(INode.class, "DEBUG_SG_NODE");\r
217 \r
218             @Override\r
219             public void init(IElement e, G2DParentNode parent) {\r
220                 ShapeNode node = parent.getOrCreateNode("debug", ShapeNode.class);\r
221                 if (node != null) {\r
222                     node.setTransform(new AffineTransform(ElementUtils.getTransform(e)));\r
223                     node.setShape(ElementUtils.getElementBounds(e));\r
224                     node.setFill(true);\r
225                     node.setColor(Color.CYAN);\r
226                     e.setHint(KEY_SG, node);\r
227                 }\r
228             }\r
229 \r
230             @Override\r
231             public void cleanup(IElement e) {\r
232                 ElementUtils.removePossibleNode(e, KEY_SG);\r
233             }\r
234 \r
235         }\r
236         \r
237         \r
238     static class RowElementSelectionHandler implements SelectionSpecification {\r
239 \r
240         /**\r
241                  * \r
242                  */\r
243                 private static final long serialVersionUID = 2539536175525595035L;\r
244                 \r
245                 static final RowElementSelectionHandler INSTANCE = new RowElementSelectionHandler();\r
246 \r
247 \r
248         private RowElementSelectionHandler() {\r
249         }\r
250 \r
251                 @Override\r
252                 public Object getAdapter(Class adapter) {\r
253                         // outline color\r
254                         if (adapter.equals(OutlineColorSpec.class)){\r
255                                 return new OutlineColorSpec() {\r
256                                         /**\r
257                                          * \r
258                                          */\r
259                                         private static final long serialVersionUID = 2372559366005877243L;\r
260 \r
261                                         @Override\r
262                                         public void setColor(IElement e, Color c) {\r
263                                         }\r
264 \r
265                                         @Override\r
266                                         public Color getColor(IElement e) {\r
267                                                 return new Color(10,10,10,40);\r
268                                         }\r
269                                 };\r
270                         }\r
271                         if (adapter.equals(FillColor.class)){\r
272                                 return new FillColor() {\r
273                                         /**\r
274                                          * \r
275                                          */\r
276                                         private static final long serialVersionUID = 558080965120741509L;\r
277 \r
278                                         @Override\r
279                                         public void setFillColor(IElement e, Color c) {\r
280                                                 // TODO Auto-generated method stub\r
281                                                 \r
282                                         }\r
283 \r
284                                         @Override\r
285                                         public Color getFillColor(IElement e) {\r
286                                                 return new Color(10,10,10,40);\r
287                                         }\r
288                                 };\r
289                         }\r
290                         if (adapter.equals(Outline.class)){\r
291                                 return new Outline() {\r
292                                         /**\r
293                                          * \r
294                                          */\r
295                                         private static final long serialVersionUID = 272200345438045483L;\r
296 \r
297                                         @Override\r
298                                         public Shape getElementShape(IElement e) {\r
299                                                 return e.getHint(ElementHints.KEY_BOUNDS);\r
300                                         }\r
301                                 };\r
302                         }\r
303                         if (adapter.equals(Transform.class)){\r
304                                 return new Transform() {\r
305                                         /**\r
306                                          * \r
307                                          */\r
308                                         private static final long serialVersionUID = 7653122570884609688L;\r
309 \r
310                                         @Override\r
311                                         public AffineTransform getTransform(IElement e) {\r
312                                                 return e.getHint(ElementHints.KEY_TRANSFORM);\r
313                                         }\r
314 \r
315                                         @Override\r
316                                         public void setTransform(IElement e, AffineTransform at) {\r
317                                         }\r
318                                 };\r
319                         }\r
320                         if (adapter.equals(StrokeSpec.class)){\r
321                                 return new StrokeSpec() {\r
322 \r
323                                         /**\r
324                                          * \r
325                                          */\r
326                                         private static final long serialVersionUID = 1074910311375484373L;\r
327 \r
328                                         @Override\r
329                                         public Stroke getStroke(IElement e) {\r
330                                                 return new BasicStroke(0.15f, BasicStroke.CAP_SQUARE,\r
331                                                     BasicStroke.CAP_SQUARE, 10.0f,\r
332                                                     null, 0.0f);\r
333                                         }\r
334 \r
335                                         @Override\r
336                                         public void setStroke(IElement e, Stroke at) {\r
337                                                 // TODO Auto-generated method stub\r
338                                                 \r
339                                         }\r
340                                         \r
341                                 };\r
342                         }\r
343                         // TODO Auto-generated method stub\r
344                         return null;\r
345                 }\r
346 \r
347     }\r
348 \r
349     \r
350     static class RowElementHandler implements InternalSize, Transform, ElementAdapter {\r
351 \r
352         static final RowElementHandler INSTANCE = new RowElementHandler();\r
353 \r
354         private static final long serialVersionUID = 829379327756475944L;\r
355 \r
356         private RowElementHandler() {\r
357         }\r
358 \r
359         @Override\r
360         public Rectangle2D getBounds(IElement e, Rectangle2D size) {\r
361             if (size == null)\r
362                 size = new Rectangle2D.Double();\r
363             Rectangle2D r = e.getHint(ElementHints.KEY_BOUNDS);\r
364             size.setFrame(r);\r
365             return size;\r
366         }\r
367 \r
368         @Override\r
369         public AffineTransform getTransform(IElement e) {\r
370             AffineTransform at = e.getHint(ElementHints.KEY_TRANSFORM);\r
371             return at != null ? at : new AffineTransform();\r
372         }\r
373 \r
374         @Override\r
375         public void setTransform(IElement e, AffineTransform at) {\r
376             e.setHint(ElementHints.KEY_TRANSFORM, at.clone());\r
377         }\r
378 \r
379         @SuppressWarnings("unchecked")\r
380         @Override\r
381         public <T> T adapt(IElement e, Class<T> toClass) {\r
382             if (toClass == Resource.class) {\r
383                 Wrapper ref = e.getHint(ElementHints.KEY_OBJECT);\r
384                 if (ref != null)\r
385                     return (T) ref.get();\r
386             }\r
387             return null;\r
388         }\r
389 \r
390     }\r
391 \r
392 \r
393         public static class RenderHeaderTexts {\r
394                 private FlagTableInfo table = null;\r
395                 private String tableName = null;\r
396                 private EvaluationContext evaluationContext = null;\r
397                 \r
398                 public RenderHeaderTexts(EvaluationContext evaluationContext, FlagTableInfo table, String tableName){\r
399                         this.table = table;\r
400                         this.tableName = tableName;\r
401                         this.evaluationContext = evaluationContext;\r
402                 }\r
403                 \r
404                 public void perform(){\r
405                         if (table == null || evaluationContext == null || tableName == null)\r
406                                 return;\r
407 \r
408                         Session session = Simantics.peekSession();\r
409                         if (session == null)\r
410                                 return;\r
411 \r
412                         G2DSceneGraph sg = evaluationContext.getSceneGraph();\r
413                         if (sg == null)\r
414                                 return;\r
415 \r
416                         for (int k=0;k<table.columns.size();k++){\r
417                                 FlagTableColumnInfo slotcolumn = table.columns.get(k);\r
418                                 if (slotcolumn == null)\r
419                                         continue;\r
420 \r
421                                 List<MonitorInfo> monitorInfos = slotcolumn.columnHeaders;\r
422                                 if (monitorInfos == null)\r
423                                         continue;\r
424 \r
425                                 int cellInx = 0;\r
426                                 for (MonitorInfo slotColumnData:monitorInfos){\r
427                                         String cellNodeName = null;\r
428                                         cellNodeName = cellLookupName(tableName, k, 0, cellInx);\r
429                                         cellInx++;\r
430                                         TextNode cellNode = (TextNode) NodeUtil.lookup(sg, cellNodeName);\r
431                                         if (cellNode == null)\r
432                                                 continue;\r
433                                         String txtValue = "";\r
434                                         if (slotColumnData != null && slotColumnData.getText() != null)\r
435                                                 txtValue = slotColumnData.getText();\r
436                                         final String text = txtValue;\r
437 \r
438                                         try {\r
439                                                 String value = "";\r
440                                                 if (slotColumnData.getResource() != null)\r
441                                                         value = Simantics.getSession().sync(new EvaluatePath(slotColumnData.getResource(), text)); // , TransientCacheListener.<String> instance()\r
442                                                 if (value != null)\r
443                                                         cellNode.setText(value.toString());\r
444                                         } catch (DatabaseException e) {\r
445                                                 // TODO Auto-generated catch block\r
446                                                 e.printStackTrace();\r
447                                         }\r
448                                         \r
449                                 }\r
450                                         \r
451 \r
452                                 \r
453                         }\r
454                 }\r
455         }\r
456 \r
457 //      public class RenderFlagTexts {\r
458 //              private FlagInfo flagInfo = null;\r
459 //              private TreeMap<String, FlagTableInfo> tables = null;\r
460 //              private EvaluationContext evaluationContext = null;\r
461 //              \r
462 //              public RenderFlagTexts(EvaluationContext evaluationContext, FlagInfo flagInfo, TreeMap<String, FlagTableInfo> tables){\r
463 //                      this.flagInfo = flagInfo;\r
464 //                      this.tables = tables;\r
465 //                      this.evaluationContext = evaluationContext;\r
466 //              }\r
467 //              \r
468 //              public void perform(){\r
469 //                      Session session = Simantics.peekSession();\r
470 //                      if (session == null)\r
471 //                              return;\r
472 //\r
473 //                      FlagTableInfo table = tables.get(flagInfo.flagTableName);\r
474 //                      if (table == null)\r
475 //                              return;\r
476 //\r
477 //                      G2DSceneGraph sg = evaluationContext.getSceneGraph();\r
478 //                      if (sg == null)\r
479 //                              return;\r
480 //\r
481 //                      INode tableNode = sg.lookupNode(tableLookupName(flagInfo.flagTableName));\r
482 //                      if (tableNode == null)\r
483 //                              return;\r
484 //\r
485 //                      Rectangle2D rowBounds = new Rectangle2D.Double(0, table.getRowHeight()*flagInfo.flagTableRowIndex, table.getWidth(), table.getRowHeight());\r
486 //                      rowBounds = GeometryUtils.transformShape(rowBounds, table.affineTransform).getBounds2D();\r
487 //                      addFlagElement(evaluationContext, tableNode, rowBounds, flagInfo.flag);\r
488 //\r
489 //                      for (int k=0;k<table.columns.size();k++){\r
490 //                              FlagTableColumnInfo slotcolumn = table.columns.get(k);\r
491 //                              if (slotcolumn == null)\r
492 //                                      continue;\r
493 //                              \r
494 //                              List<MonitorInfo> monitorInfos = slotcolumn.columnDatas;\r
495 //                              if (monitorInfos == null)\r
496 //                                      continue;\r
497 //\r
498 //                              int cellInx = 0;\r
499 //                              for (MonitorInfo slotColumnData:monitorInfos){\r
500 //                                      String cellNodeName = cellLookupName(flagInfo.flagTableName, k, flagInfo.flagTableRowIndex, cellInx);\r
501 //                                      cellInx++;\r
502 //                                      TextNode cellNode = (TextNode) NodeUtil.lookup(sg, cellNodeName);\r
503 //                                      if (cellNode == null)\r
504 //                                              continue;\r
505 //\r
506 //                                      String txtValue = "";\r
507 //                                      if (slotColumnData != null && slotColumnData.getText() != null)\r
508 //                                              txtValue = slotColumnData.getText();\r
509 //                                      final String text = txtValue;\r
510 //\r
511 //                                      try {\r
512 //                                              String value = null;\r
513 //                                              if (slotcolumn.getType() != FlagTableColumnInfo.TYPE_ROW_NUMBERING)\r
514 //                                                      value = Simantics.getSession().sync(new EvaluatePath(flagInfo.flag, text)); // , TransientCacheListener.<String> instance()\r
515 //                                              if (value != null)\r
516 //                                                      cellNode.setText(value.toString());\r
517 //                                      } catch (DatabaseException e) {\r
518 //                                              // TODO Auto-generated catch block\r
519 //                                              e.printStackTrace();\r
520 //                                      }\r
521 //                              }\r
522 //                      }\r
523 //              }\r
524 //      }\r
525         \r
526         public static class EvaluatePath extends ResourceRead<String> {\r
527                 private String path = null;\r
528                 \r
529             public EvaluatePath(Resource res, String path) {\r
530                 super(res);\r
531                 this.path = path;\r
532 //              this.flagInfo = flagInfo;\r
533             }\r
534 \r
535             @Override\r
536             public String perform(ReadGraph g) throws DatabaseException {\r
537                 PredefinedVariables vars = PredefinedVariables.getInstance();\r
538                 Variable resourceVariable = Variables.getVariable(g, resource);\r
539                 //v = g.adapt(this.flag, Variable.class);\r
540                 if (resourceVariable == null)\r
541                         return "";\r
542                 Variable property = vars.getVariable(g, path, resource, resourceVariable);\r
543                 Object value = null;\r
544                 if (property == null)\r
545                         return "";\r
546                 try {\r
547                         value = property.getValue(g);\r
548                 } catch (DatabaseException ex){\r
549                 }\r
550                 if (value == null || !(value instanceof String))\r
551                         return "";\r
552                 return value.toString();\r
553             }\r
554         }\r
555 \r
556         public static class RenderTable {\r
557                 private FlagTableInfo table = null;\r
558                 private String tableName = null;\r
559                 private EvaluationContext evaluationContext = null;\r
560 \r
561                 public  RenderTable(EvaluationContext evaluationContext, FlagTableInfo table, String tableName){\r
562                         this.table = table;\r
563                         this.evaluationContext = evaluationContext;\r
564                         this.tableName = tableName;\r
565                 }\r
566 \r
567                 public void perform(){\r
568                         // render table \r
569                         G2DSceneGraph sg = evaluationContext.getSceneGraph();\r
570                         if (sg == null)\r
571                                 return;\r
572                         G2DParentNode nav = (G2DParentNode) sg.getNode(SceneGraphConstants.NAVIGATION_NODE_NAME);\r
573                         if (nav == null)\r
574                                 return;\r
575 \r
576                         String tableNodeName = tableLookupName(tableName);\r
577                         RTreeNode tableNode = (RTreeNode) sg.getNode(tableNodeName);\r
578                         if (tableNode == null){\r
579                                 tableNode = ProfileVariables.claimChild(evaluationContext.getSceneGraph(),\r
580                                                 SceneGraphConstants.NAVIGATION_NODE_NAME, tableNodeName, RTreeNode.class, //SingleElementNode.class,\r
581                                                 evaluationContext);\r
582                         }\r
583                         if (tableNode == null)\r
584                                 return;\r
585                         tableNode.setTransform(new AffineTransform(table.affineTransform));\r
586                         //tableNode.setVisible(false);\r
587                         tableNode.setLookupId(tableNodeName);\r
588 \r
589                         // Initialize row node book-keeping for this table\r
590                         evaluationContext.setProperty(tableNode, SLOT_TABLE_ELEMENTS, new ArrayList<IElement>());\r
591 \r
592                         Integer rowCount = table.getRowCount();\r
593                         if (rowCount <= 0)\r
594                                 return;\r
595 \r
596                         // test if table is already generated\r
597                         String colNodeName = SLOT_TABLE_PREFIX + tableName + SLOT_TABLE_SEPARATOR + "0";\r
598                         RTreeNode colNode = (RTreeNode) sg.getNode(colNodeName);\r
599                         if (colNode != null) \r
600                                 return;\r
601                         \r
602                         tableNode.setZIndex(2);\r
603 \r
604                         //if (table.columns.size()> 0){\r
605                                 // draw horisontal lines\r
606                                 for (int k=-1;k<rowCount;k++){\r
607                                         int lineY = (int)(table.getRowHeight()*k+table.getRowHeight());\r
608                                         if (k==-1 || k+1 == rowCount){\r
609                                                 this.addLine("line_" + k, 0, lineY, table.getWidth().intValue(), lineY, BasicStroke.CAP_BUTT, tableNode);\r
610                                                 continue;\r
611                                         }\r
612                                         this.addLine("lineEnd_" + k, table.getWidth().intValue()-3, lineY, table.getWidth().intValue(), lineY, BasicStroke.CAP_BUTT, tableNode);\r
613                                         this.addLine("lineStart_" + k, 0, lineY, 3, lineY, BasicStroke.CAP_BUTT, tableNode);\r
614                                 }\r
615                                 {\r
616                                         // draw the first vertical line\r
617                                         int lineY = (int)(table.getRowHeight()*(rowCount));\r
618                                         this.addLine("bar_0", 0, 0, 0, lineY, BasicStroke.CAP_SQUARE, tableNode);\r
619                                         // draw the last vertical line\r
620                                         this.addLine("bar_last", (int)((double)table.getWidth()), 0, (int)((double)table.getWidth()), lineY, BasicStroke.CAP_SQUARE, tableNode);\r
621                                 }\r
622                         //}\r
623 \r
624                         // Support header row hiding when there are no header columns\r
625                         // defined\r
626                         int maxColumnHeaders = 0;\r
627                         if (table.columns.size() > 0) {\r
628                                 for (FlagTableColumnInfo column : table.columns) {\r
629                                         maxColumnHeaders = Math.max(maxColumnHeaders, column.columnHeaders.size());\r
630                                 }\r
631                         }\r
632 \r
633                         // generate columns and cells\r
634                         String cellNodeName = null;\r
635                         TextNode cellNode = null;\r
636                         for (int k = 0;k<table.columns.size();k++){\r
637                                 colNodeName = SLOT_TABLE_PREFIX + tableName + SLOT_TABLE_SEPARATOR + k;\r
638                                 colNode = ProfileVariables.claimChild(evaluationContext.getSceneGraph(),\r
639                                                 SceneGraphConstants.NAVIGATION_NODE_NAME+"."+tableNodeName, colNodeName, RTreeNode.class,\r
640                                                 evaluationContext);\r
641                                 if (colNode == null)\r
642                                         continue;\r
643                                 double colX = 0.0;\r
644                                 double colXAfter = 0.0;\r
645                                 if (table.getWeightTotal() != 0.0){\r
646                                         double weightBefore = 0.0; \r
647                                         for (int m=0;m<k;m++){\r
648                                                 FlagTableColumnInfo slotcolumn = table.columns.get(m);\r
649                                                 if (slotcolumn == null || slotcolumn.getWeight() == Float.NaN)\r
650                                                         continue;\r
651                                                 weightBefore = weightBefore + slotcolumn.getWeight();\r
652                                         }\r
653                                         FlagTableColumnInfo slotcolumn = table.columns.get(k);\r
654                                         colXAfter = ((weightBefore+slotcolumn.getWeight())/table.getWeightTotal())*table.getWidth(); \r
655                                         double procent = weightBefore/table.getWeightTotal();\r
656                                         colX = procent*table.getWidth();\r
657                                         colNode.setTransform(AffineTransform.getTranslateInstance(colX, 0.0));\r
658                                 }\r
659                                 \r
660                                 // draw intermediate vertical lines\r
661 //                              int lineY = (int)(table.getRowHeight()*(rowCount));\r
662 //                              this.addLine("bar_" + (k+1), (int)colXAfter, 0, (int)colXAfter, lineY, BasicStroke.CAP_SQUARE, tableNode);\r
663                                 \r
664                                 FlagTableColumnInfo slotcolumn = table.columns.get(k);\r
665                                 double cellProcent = slotcolumn.getWeight()/table.getWeightTotal();\r
666                                 float cellWidth = (float)cellProcent*table.getWidth();\r
667                                 if (cellWidth < 0.0)\r
668                                         cellWidth = 0.0F;\r
669                                 if (cellWidth == 0.0F)\r
670                                         continue;\r
671                                 \r
672                                 for (int lineInx=0;lineInx<rowCount;lineInx++){\r
673                                         List<MonitorInfo> monitorInfos = slotcolumn.columnDatas;\r
674                                         if (lineInx < maxColumnHeaders)\r
675                                                 monitorInfos = slotcolumn.columnHeaders;\r
676 \r
677                                         int cellInx = 0;\r
678                                         for (MonitorInfo slotColumnData:monitorInfos){\r
679                                                 cellNodeName = cellLookupName(tableName, k, lineInx, cellInx);\r
680                                                 cellInx++;\r
681                                                 cellNode = ProfileVariables.claimChild(evaluationContext.getSceneGraph(),\r
682                                                                 SceneGraphConstants.NAVIGATION_NODE_NAME+"."+tableNodeName+"."+colNodeName, cellNodeName, TextNode.class,\r
683                                                                 evaluationContext);\r
684                                                 if (cellNode == null)\r
685                                                         continue;\r
686                                                 cellNode.setLookupId(cellNodeName);\r
687 \r
688                                                 AffineTransform transform = new AffineTransform();\r
689                                                 if (slotColumnData != null){\r
690                                                         if (slotColumnData.getFont() != null)\r
691                                                                 cellNode.setFont(Fonts.awt(slotColumnData.getFont()));\r
692                                                         if (slotColumnData.getColor() != null)\r
693                                                                 cellNode.setColor(Colors.awt(slotColumnData.getColor()));\r
694                                                         if (slotColumnData.getTransform() != null)\r
695                                                                 transform = new AffineTransform(slotColumnData.getTransform());\r
696                                                 }\r
697                                                 cellNode.setVerticalAlignment((byte) 3);\r
698                                                 double cellY = table.getRowHeight()*lineInx+DrawingTemplateInfo.BASELINE_VERTICAL_OFFSET*table.getRowHeight();\r
699                                                 //cellNode.setText("yÃ…column_" + k);\r
700                                                 cellNode.setText("");\r
701                                                 if (lineInx >= maxColumnHeaders && slotcolumn.getType() == FlagTableColumnInfo.TYPE_ROW_NUMBERING){\r
702                                                         // set row number\r
703                                                         cellNode.setText(new Integer(lineInx-maxColumnHeaders+slotcolumn.getStartOffset()).toString());\r
704                                                         cellNode.setHorizontalAlignment((byte) 0);\r
705                                                 }\r
706 \r
707 //                                              FontMetrics metrics = new FontMetrics(cellNode.getFont());\r
708 //                                              double dy = (metrics.getAscent() + metrics.getLeading())/2;\r
709                                                 cellNode.setBorderWidth(0.f);\r
710                                                 cellNode.setPadding(0.0, 0.0);\r
711                                                 Rectangle2D bounds = cellNode.getBoundsInLocal();\r
712                                                 //double dy = bounds.getHeight()/2.0;\r
713                                                 transform.translate(0.0, cellY);\r
714                                                 cellNode.setTransform(transform);\r
715                                                 cellNode.setFixedWidth(cellWidth);\r
716                                         }\r
717                                         \r
718                                 }\r
719                         }\r
720                         //tableNode.setVisible(true);\r
721                 }\r
722                 \r
723                 void addLine(String nodeId, int x1, int y1, int x2, int y2, int cap, RTreeNode parent){\r
724                         Line2D line = new Line2D.Float(x1, y1, x2, y2);\r
725                         BasicStroke stroke = new BasicStroke(TranslateFlag.lineWidth, cap, BasicStroke.JOIN_MITER);\r
726                         ShapeNode shape = parent.addNode(nodeId, ShapeNode.class); // SingleElementNode\r
727                         shape.setShape(line);\r
728                         shape.setScaleStroke(false);\r
729                         shape.setStroke(stroke);\r
730                         shape.setFill(false);\r
731                         shape.setColor(new Color(0, 0, 0));\r
732                         shape.setZIndex(10);\r
733                 }\r
734         }\r
735 \r
736         protected void cleanupStyleForItem(EvaluationContext evaluationContext, DataNodeMap map, Object item) {\r
737                 INode root = evaluationContext.getSceneGraph();\r
738                 if (root instanceof G2DSceneGraph) {\r
739                         G2DSceneGraph sg = (G2DSceneGraph) root;\r
740                         G2DParentNode nav = (G2DParentNode) sg.getNode(SceneGraphConstants.NAVIGATION_NODE_NAME);\r
741 \r
742 //                      ProfileVariables.denyChildren(nav, SLOT_TABLE_PREFIX);\r
743 \r
744                         IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM);\r
745                         for (String childId : NodeUtil.filterDirectChildIds(nav, SLOT_TABLE_PREFIX)) {\r
746                             INode child = nav.getNode(childId);\r
747                             List<IElement> elements = evaluationContext.setProperty(child, SLOT_TABLE_ELEMENTS, null);\r
748                             if (elements != null && diagram != null)\r
749                                 for (IElement e : elements)\r
750                                     cleanupElement(diagram, e);\r
751                             nav.removeNode(childId);\r
752                         }\r
753                 }\r
754         }\r
755 \r
756         private void cleanupElement(IDiagram diagram, IElement e) {\r
757                 diagram.removeElement(e);\r
758         }\r
759 \r
760     /**\r
761          * @param tableName slot table name\r
762          * @return lookup ID for the cell node\r
763          */\r
764         private static String tableLookupName(String tableName) {\r
765             return new StringBuilder()\r
766             .append(SLOT_TABLE_PREFIX)\r
767             .append(tableName).toString();\r
768         }\r
769 \r
770         /**\r
771          * @param tableName slot table name\r
772          * @param column 0..C-1, where C is the amount of columns\r
773          * @param row 0..N, where 0 is header\r
774          * @return lookup ID for the cell node\r
775          */\r
776         private static String cellLookupName(String tableName, int column, int row, int index) {\r
777             return new StringBuilder()\r
778             .append(SLOT_TABLE_PREFIX)\r
779             .append(tableName)\r
780             .append(SLOT_TABLE_SEPARATOR)\r
781             .append(column)\r
782             .append(SLOT_TABLE_SEPARATOR)\r
783             .append(row)\r
784             .append(SLOT_TABLE_SEPARATOR)\r
785             .append(index).toString();\r
786         }\r
787 \r
788     private IElement addFlagElement(EvaluationContext evaluationContext, INode tableNode, Rectangle2D bounds, Resource flag) {\r
789         IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM);\r
790         assert diagram != null;\r
791         List<IElement> elements = evaluationContext.getProperty(tableNode, SLOT_TABLE_ELEMENTS);\r
792         assert elements != null;\r
793         IElement e = newFlagElement(evaluationContext, bounds, flag);\r
794         elements.add(e);\r
795         diagram.addElement(e);\r
796         return e;\r
797     }\r
798 \r
799     private IElement newFlagElement(EvaluationContext evaluationContext, Rectangle2D bounds, Resource flag) {\r
800         IElement e = Element.spawnNew(rowElementClass);\r
801         e.setHint(ElementHints.KEY_BOUNDS, bounds.clone());\r
802         e.setHint(ElementHints.KEY_TRANSFORM, new AffineTransform());\r
803         // Just incase there's problems with same objects in multiple diagram elements\r
804         //e.setHint(ElementHints.KEY_OBJECT, flag);\r
805         // Didn't seem to help though.\r
806         e.setHint(ElementHints.KEY_OBJECT, new Wrapper(flag));\r
807         return e;\r
808     }\r
809 \r
810     @Override\r
811     public String toString() {\r
812         return "Flag table style";\r
813     }\r
814 \r
815     /**\r
816      * IO table flag elements need a wrapper KEY_OBJECT whose toString()\r
817      * produces something else besides {@link Resource#toString()}.\r
818      */\r
819     public static class Wrapper extends AtomicReference<Resource> {\r
820         private static final long serialVersionUID = -4041629837352874410L;\r
821         public Wrapper(Resource r) {\r
822             super(r);\r
823         }\r
824         @Override\r
825         public String toString() {\r
826             return "IO-" + super.toString();\r
827         }\r
828     }\r
829 \r
830 }\r