1 /*******************************************************************************
2 * Copyright (c) 2012 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.modeling.template2d.ui.diagram.adapter;
14 import java.awt.BasicStroke;
15 import java.awt.Color;
16 import java.awt.Shape;
17 import java.awt.Stroke;
18 import java.awt.geom.AffineTransform;
19 import java.awt.geom.Line2D;
20 import java.awt.geom.Rectangle2D;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map.Entry;
27 import java.util.TreeMap;
28 import java.util.concurrent.atomic.AtomicReference;
30 import org.simantics.Simantics;
31 import org.simantics.databoard.Bindings;
32 import org.simantics.databoard.annotations.Optional;
33 import org.simantics.databoard.util.Bean;
34 import org.simantics.db.ReadGraph;
35 import org.simantics.db.Resource;
36 import org.simantics.db.Session;
37 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
38 import org.simantics.db.common.request.ResourceRead;
39 import org.simantics.db.exception.DatabaseException;
40 import org.simantics.db.layer0.variable.Variable;
41 import org.simantics.db.layer0.variable.Variables;
42 import org.simantics.diagram.elements.TextNode;
43 import org.simantics.diagram.function.All;
44 import org.simantics.diagram.function.PredefinedVariables;
45 import org.simantics.diagram.profile.ProfileKeys;
46 import org.simantics.diagram.profile.StyleBase;
47 import org.simantics.diagram.stubs.DiagramResource;
48 import org.simantics.g2d.diagram.IDiagram;
49 import org.simantics.g2d.element.ElementClass;
50 import org.simantics.g2d.element.ElementHints;
51 import org.simantics.g2d.element.ElementUtils;
52 import org.simantics.g2d.element.IElement;
53 import org.simantics.g2d.element.SceneGraphNodeKey;
54 import org.simantics.g2d.element.handler.ElementAdapter;
55 import org.simantics.g2d.element.handler.FillColor;
56 import org.simantics.g2d.element.handler.InternalSize;
57 import org.simantics.g2d.element.handler.Outline;
58 import org.simantics.g2d.element.handler.OutlineColorSpec;
59 import org.simantics.g2d.element.handler.SceneGraph;
60 import org.simantics.g2d.element.handler.SelectionSpecification;
61 import org.simantics.g2d.element.handler.StrokeSpec;
62 import org.simantics.g2d.element.handler.Transform;
63 import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;
64 import org.simantics.g2d.element.impl.Element;
65 import org.simantics.g2d.elementclass.NonCopyable;
66 import org.simantics.g2d.scenegraph.SceneGraphConstants;
67 import org.simantics.layer0.Layer0;
68 import org.simantics.modeling.template2d.ui.function.DrawingTemplateInfo;
69 import org.simantics.modeling.template2d.ui.function.FlagInfo;
70 import org.simantics.modeling.template2d.ui.function.FlagTableColumnInfo;
71 import org.simantics.modeling.template2d.ui.function.FlagTableInfo;
72 import org.simantics.modeling.template2d.ui.function.MonitorInfo;
73 import org.simantics.modeling.template2d.ui.function.TranslateFlag;
74 import org.simantics.scenegraph.INode;
75 import org.simantics.scenegraph.g2d.G2DParentNode;
76 import org.simantics.scenegraph.g2d.G2DSceneGraph;
77 import org.simantics.scenegraph.g2d.nodes.ShapeNode;
78 import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode;
79 import org.simantics.scenegraph.profile.DataNodeMap;
80 import org.simantics.scenegraph.profile.EvaluationContext;
81 import org.simantics.scenegraph.profile.common.ProfileVariables;
82 import org.simantics.scenegraph.utils.NodeUtil;
83 import org.simantics.ui.colors.Colors;
84 import org.simantics.ui.fonts.Fonts;
85 import org.simantics.utils.datastructures.hints.IHintContext.Key;
87 public class DrawingFlagTableStyle extends StyleBase<DrawingFlagTableStyle.StyleInfo> {
89 private static final boolean DEBUG_PAINT_ELEMENTS = false;
91 private static final String SLOT_TABLE_PREFIX = "slotTable<";
92 private static final String SLOT_TABLE_SEPARATOR = ">";
94 private static final String SLOT_TABLE_ELEMENTS = "slotTableElements";
96 private ElementClass rowElementClass;
98 public DrawingFlagTableStyle(ReadGraph graph) {
99 rowElementClass = ElementClass.compile(
100 RowElementHandler.INSTANCE,
101 RowElementSelectionHandler.INSTANCE,
102 NonCopyable.INSTANCE,
103 new StaticObjectAdapter(DiagramResource.getInstance(graph).Flag)
104 ).setId(RowElementHandler.class.getSimpleName());
105 if (DEBUG_PAINT_ELEMENTS)
106 rowElementClass = rowElementClass.newClassWith(TestSceneGraph.INSTANCE);
109 public static class StyleInfo extends Bean {
110 public TreeMap<String, FlagTableInfo> name2table;
111 public List<FlagInfo> flags;
113 public Resource template = null;
114 //public String digest = "";
119 public static class FlagInfos extends ResourceRead<ArrayList<FlagInfo>> {
120 public FlagInfos(Resource diagram) {
125 public ArrayList<FlagInfo> perform(ReadGraph g) throws DatabaseException {
126 ArrayList<FlagInfo> flagInfos = new ArrayList<FlagInfo>();
128 Layer0 L0 = Layer0.getInstance(g);
129 DiagramResource DIA = DiagramResource.getInstance(g);
131 Collection<Resource> children = g.getObjects(resource, L0.ConsistsOf);
132 for (Resource child:children){
133 if (!g.isInstanceOf(child, DIA.Flag))
136 Resource flag = child;
137 String tableName = g.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableBinding, Bindings.STRING);
138 Integer rowIndex = g.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableRowIndex, Bindings.INTEGER);
139 FlagInfo flagInfo = new FlagInfo();
140 flagInfo.flag = flag;
141 if (tableName != null && tableName.length() > 0)
142 flagInfo.flagTableName = tableName;
143 flagInfo.flagTableRowIndex = rowIndex;
144 flagInfos.add(flagInfo);
146 } catch (Throwable e){
147 e.printStackTrace(System.err);
154 public StyleInfo calculateStyle(ReadGraph graph, Resource runtimeDiagram,
155 Resource entry, Resource diagram, Variable activeComposite)
156 throws DatabaseException {
157 Resource template = All.getTemplate(graph, runtimeDiagram);
158 if (template == null)
160 DiagramResource DIA = DiagramResource.getInstance(graph);
161 Resource diagram2 = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration);
163 StyleInfo info = new StyleInfo();
164 DrawingTemplateInfo templateInfo = new DrawingTemplateInfo(template);
165 info.template = template;
166 info.name2table = graph.syncRequest(templateInfo, TransientCacheListener.<TreeMap<String, FlagTableInfo>> instance());
167 if (info.name2table == null)
168 info.name2table = new TreeMap<String,FlagTableInfo>();
169 //info.digest = templateInfo.getDigest();
170 //System.err.println(templateInfo.getDigest());
172 info.flags = graph.syncRequest(new FlagInfos(diagram2), TransientCacheListener.<ArrayList<FlagInfo>> instance());
173 if (info.flags == null)
174 info.flags = Collections.emptyList();
179 public void applyStyleForItem(EvaluationContext evaluationContext, DataNodeMap map, Object item, StyleInfo info) {
180 if (info == null || info.flags == null || info.name2table == null)
183 cleanupStyleForItem(evaluationContext, map, item);
186 Iterator<Entry<String,FlagTableInfo>> it = info.name2table.entrySet().iterator();
187 while(it.hasNext()) {
188 Entry<String,FlagTableInfo> entry = it.next();
189 String name = entry.getKey();
190 FlagTableInfo table = entry.getValue();
191 RenderTable com = new RenderTable(evaluationContext, table, name);
194 // render header texts
195 RenderHeaderTexts com3 = new RenderHeaderTexts(evaluationContext, table, name);
199 // render texts of flags
200 // for (FlagInfo flagInfo : info.flags) {
201 // RenderFlagTexts com2 = new RenderFlagTexts(evaluationContext, flagInfo, info.name2table);
208 * This is just for debugging where the invisible IO row elements are.
209 * Not intended to be enabled.
211 private static class TestSceneGraph implements SceneGraph {
213 private static final long serialVersionUID = 5749410674482131633L;
215 public static final TestSceneGraph INSTANCE = new TestSceneGraph();
216 private static final Key KEY_SG = new SceneGraphNodeKey(INode.class, "DEBUG_SG_NODE");
219 public void init(IElement e, G2DParentNode parent) {
220 ShapeNode node = parent.getOrCreateNode("debug", ShapeNode.class);
222 node.setTransform(new AffineTransform(ElementUtils.getTransform(e)));
223 node.setShape(ElementUtils.getElementBounds(e));
225 node.setColor(Color.CYAN);
226 e.setHint(KEY_SG, node);
231 public void cleanup(IElement e) {
232 ElementUtils.removePossibleNode(e, KEY_SG);
238 static class RowElementSelectionHandler implements SelectionSpecification {
243 private static final long serialVersionUID = 2539536175525595035L;
245 static final RowElementSelectionHandler INSTANCE = new RowElementSelectionHandler();
248 private RowElementSelectionHandler() {
252 public Object getAdapter(Class adapter) {
254 if (adapter.equals(OutlineColorSpec.class)){
255 return new OutlineColorSpec() {
259 private static final long serialVersionUID = 2372559366005877243L;
262 public void setColor(IElement e, Color c) {
266 public Color getColor(IElement e) {
267 return new Color(10,10,10,40);
271 if (adapter.equals(FillColor.class)){
272 return new FillColor() {
276 private static final long serialVersionUID = 558080965120741509L;
279 public void setFillColor(IElement e, Color c) {
280 // TODO Auto-generated method stub
285 public Color getFillColor(IElement e) {
286 return new Color(10,10,10,40);
290 if (adapter.equals(Outline.class)){
291 return new Outline() {
295 private static final long serialVersionUID = 272200345438045483L;
298 public Shape getElementShape(IElement e) {
299 return e.getHint(ElementHints.KEY_BOUNDS);
303 if (adapter.equals(Transform.class)){
304 return new Transform() {
308 private static final long serialVersionUID = 7653122570884609688L;
311 public AffineTransform getTransform(IElement e) {
312 return e.getHint(ElementHints.KEY_TRANSFORM);
316 public void setTransform(IElement e, AffineTransform at) {
320 if (adapter.equals(StrokeSpec.class)){
321 return new StrokeSpec() {
326 private static final long serialVersionUID = 1074910311375484373L;
329 public Stroke getStroke(IElement e) {
330 return new BasicStroke(0.15f, BasicStroke.CAP_SQUARE,
331 BasicStroke.CAP_SQUARE, 10.0f,
336 public void setStroke(IElement e, Stroke at) {
337 // TODO Auto-generated method stub
343 // TODO Auto-generated method stub
350 static class RowElementHandler implements InternalSize, Transform, ElementAdapter {
352 static final RowElementHandler INSTANCE = new RowElementHandler();
354 private static final long serialVersionUID = 829379327756475944L;
356 private RowElementHandler() {
360 public Rectangle2D getBounds(IElement e, Rectangle2D size) {
362 size = new Rectangle2D.Double();
363 Rectangle2D r = e.getHint(ElementHints.KEY_BOUNDS);
369 public AffineTransform getTransform(IElement e) {
370 AffineTransform at = e.getHint(ElementHints.KEY_TRANSFORM);
371 return at != null ? at : new AffineTransform();
375 public void setTransform(IElement e, AffineTransform at) {
376 e.setHint(ElementHints.KEY_TRANSFORM, at.clone());
379 @SuppressWarnings("unchecked")
381 public <T> T adapt(IElement e, Class<T> toClass) {
382 if (toClass == Resource.class) {
383 Wrapper ref = e.getHint(ElementHints.KEY_OBJECT);
385 return (T) ref.get();
393 public static class RenderHeaderTexts {
394 private FlagTableInfo table = null;
395 private String tableName = null;
396 private EvaluationContext evaluationContext = null;
398 public RenderHeaderTexts(EvaluationContext evaluationContext, FlagTableInfo table, String tableName){
400 this.tableName = tableName;
401 this.evaluationContext = evaluationContext;
404 public void perform(){
405 if (table == null || evaluationContext == null || tableName == null)
408 Session session = Simantics.peekSession();
412 G2DSceneGraph sg = evaluationContext.getSceneGraph();
416 for (int k=0;k<table.columns.size();k++){
417 FlagTableColumnInfo slotcolumn = table.columns.get(k);
418 if (slotcolumn == null)
421 List<MonitorInfo> monitorInfos = slotcolumn.columnHeaders;
422 if (monitorInfos == null)
426 for (MonitorInfo slotColumnData:monitorInfos){
427 String cellNodeName = null;
428 cellNodeName = cellLookupName(tableName, k, 0, cellInx);
430 TextNode cellNode = (TextNode) NodeUtil.lookup(sg, cellNodeName);
431 if (cellNode == null)
433 String txtValue = "";
434 if (slotColumnData != null && slotColumnData.getText() != null)
435 txtValue = slotColumnData.getText();
436 final String text = txtValue;
440 if (slotColumnData.getResource() != null)
441 value = Simantics.getSession().sync(new EvaluatePath(slotColumnData.getResource(), text)); // , TransientCacheListener.<String> instance()
443 cellNode.setText(value.toString());
444 } catch (DatabaseException e) {
445 // TODO Auto-generated catch block
457 // public class RenderFlagTexts {
458 // private FlagInfo flagInfo = null;
459 // private TreeMap<String, FlagTableInfo> tables = null;
460 // private EvaluationContext evaluationContext = null;
462 // public RenderFlagTexts(EvaluationContext evaluationContext, FlagInfo flagInfo, TreeMap<String, FlagTableInfo> tables){
463 // this.flagInfo = flagInfo;
464 // this.tables = tables;
465 // this.evaluationContext = evaluationContext;
468 // public void perform(){
469 // Session session = Simantics.peekSession();
470 // if (session == null)
473 // FlagTableInfo table = tables.get(flagInfo.flagTableName);
474 // if (table == null)
477 // G2DSceneGraph sg = evaluationContext.getSceneGraph();
481 // INode tableNode = sg.lookupNode(tableLookupName(flagInfo.flagTableName));
482 // if (tableNode == null)
485 // Rectangle2D rowBounds = new Rectangle2D.Double(0, table.getRowHeight()*flagInfo.flagTableRowIndex, table.getWidth(), table.getRowHeight());
486 // rowBounds = GeometryUtils.transformShape(rowBounds, table.affineTransform).getBounds2D();
487 // addFlagElement(evaluationContext, tableNode, rowBounds, flagInfo.flag);
489 // for (int k=0;k<table.columns.size();k++){
490 // FlagTableColumnInfo slotcolumn = table.columns.get(k);
491 // if (slotcolumn == null)
494 // List<MonitorInfo> monitorInfos = slotcolumn.columnDatas;
495 // if (monitorInfos == null)
499 // for (MonitorInfo slotColumnData:monitorInfos){
500 // String cellNodeName = cellLookupName(flagInfo.flagTableName, k, flagInfo.flagTableRowIndex, cellInx);
502 // TextNode cellNode = (TextNode) NodeUtil.lookup(sg, cellNodeName);
503 // if (cellNode == null)
506 // String txtValue = "";
507 // if (slotColumnData != null && slotColumnData.getText() != null)
508 // txtValue = slotColumnData.getText();
509 // final String text = txtValue;
512 // String value = null;
513 // if (slotcolumn.getType() != FlagTableColumnInfo.TYPE_ROW_NUMBERING)
514 // value = Simantics.getSession().sync(new EvaluatePath(flagInfo.flag, text)); // , TransientCacheListener.<String> instance()
515 // if (value != null)
516 // cellNode.setText(value.toString());
517 // } catch (DatabaseException e) {
518 // // TODO Auto-generated catch block
519 // e.printStackTrace();
526 public static class EvaluatePath extends ResourceRead<String> {
527 private String path = null;
529 public EvaluatePath(Resource res, String path) {
532 // this.flagInfo = flagInfo;
536 public String perform(ReadGraph g) throws DatabaseException {
537 PredefinedVariables vars = PredefinedVariables.getInstance();
538 Variable resourceVariable = Variables.getVariable(g, resource);
539 //v = g.adapt(this.flag, Variable.class);
540 if (resourceVariable == null)
542 Variable property = vars.getVariable(g, path, resource, resourceVariable);
544 if (property == null)
547 value = property.getValue(g);
548 } catch (DatabaseException ex){
550 if (value == null || !(value instanceof String))
552 return value.toString();
556 public static class RenderTable {
557 private FlagTableInfo table = null;
558 private String tableName = null;
559 private EvaluationContext evaluationContext = null;
561 public RenderTable(EvaluationContext evaluationContext, FlagTableInfo table, String tableName){
563 this.evaluationContext = evaluationContext;
564 this.tableName = tableName;
567 public void perform(){
569 G2DSceneGraph sg = evaluationContext.getSceneGraph();
572 G2DParentNode nav = (G2DParentNode) sg.getNode(SceneGraphConstants.NAVIGATION_NODE_NAME);
576 String tableNodeName = tableLookupName(tableName);
577 RTreeNode tableNode = (RTreeNode) sg.getNode(tableNodeName);
578 if (tableNode == null){
579 tableNode = ProfileVariables.claimChild(evaluationContext.getSceneGraph(),
580 SceneGraphConstants.NAVIGATION_NODE_NAME, tableNodeName, RTreeNode.class, //SingleElementNode.class,
583 if (tableNode == null)
585 tableNode.setTransform(new AffineTransform(table.affineTransform));
586 //tableNode.setVisible(false);
587 tableNode.setLookupId(tableNodeName);
589 // Initialize row node book-keeping for this table
590 evaluationContext.setProperty(tableNode, SLOT_TABLE_ELEMENTS, new ArrayList<IElement>());
592 Integer rowCount = table.getRowCount();
596 // test if table is already generated
597 String colNodeName = SLOT_TABLE_PREFIX + tableName + SLOT_TABLE_SEPARATOR + "0";
598 RTreeNode colNode = (RTreeNode) sg.getNode(colNodeName);
602 tableNode.setZIndex(2);
604 //if (table.columns.size()> 0){
605 // draw horisontal lines
606 for (int k=-1;k<rowCount;k++){
607 int lineY = (int)(table.getRowHeight()*k+table.getRowHeight());
608 if (k==-1 || k+1 == rowCount){
609 this.addLine("line_" + k, 0, lineY, table.getWidth().intValue(), lineY, BasicStroke.CAP_BUTT, tableNode);
612 this.addLine("lineEnd_" + k, table.getWidth().intValue()-3, lineY, table.getWidth().intValue(), lineY, BasicStroke.CAP_BUTT, tableNode);
613 this.addLine("lineStart_" + k, 0, lineY, 3, lineY, BasicStroke.CAP_BUTT, tableNode);
616 // draw the first vertical line
617 int lineY = (int)(table.getRowHeight()*(rowCount));
618 this.addLine("bar_0", 0, 0, 0, lineY, BasicStroke.CAP_SQUARE, tableNode);
619 // draw the last vertical line
620 this.addLine("bar_last", (int)((double)table.getWidth()), 0, (int)((double)table.getWidth()), lineY, BasicStroke.CAP_SQUARE, tableNode);
624 // Support header row hiding when there are no header columns
626 int maxColumnHeaders = 0;
627 if (table.columns.size() > 0) {
628 for (FlagTableColumnInfo column : table.columns) {
629 maxColumnHeaders = Math.max(maxColumnHeaders, column.columnHeaders.size());
633 // generate columns and cells
634 String cellNodeName = null;
635 TextNode cellNode = null;
636 for (int k = 0;k<table.columns.size();k++){
637 colNodeName = SLOT_TABLE_PREFIX + tableName + SLOT_TABLE_SEPARATOR + k;
638 colNode = ProfileVariables.claimChild(evaluationContext.getSceneGraph(),
639 SceneGraphConstants.NAVIGATION_NODE_NAME+"."+tableNodeName, colNodeName, RTreeNode.class,
644 double colXAfter = 0.0;
645 if (table.getWeightTotal() != 0.0){
646 double weightBefore = 0.0;
647 for (int m=0;m<k;m++){
648 FlagTableColumnInfo slotcolumn = table.columns.get(m);
649 if (slotcolumn == null || slotcolumn.getWeight() == Float.NaN)
651 weightBefore = weightBefore + slotcolumn.getWeight();
653 FlagTableColumnInfo slotcolumn = table.columns.get(k);
654 colXAfter = ((weightBefore+slotcolumn.getWeight())/table.getWeightTotal())*table.getWidth();
655 double procent = weightBefore/table.getWeightTotal();
656 colX = procent*table.getWidth();
657 colNode.setTransform(AffineTransform.getTranslateInstance(colX, 0.0));
660 // draw intermediate vertical lines
661 // int lineY = (int)(table.getRowHeight()*(rowCount));
662 // this.addLine("bar_" + (k+1), (int)colXAfter, 0, (int)colXAfter, lineY, BasicStroke.CAP_SQUARE, tableNode);
664 FlagTableColumnInfo slotcolumn = table.columns.get(k);
665 double cellProcent = slotcolumn.getWeight()/table.getWeightTotal();
666 float cellWidth = (float)cellProcent*table.getWidth();
669 if (cellWidth == 0.0F)
672 for (int lineInx=0;lineInx<rowCount;lineInx++){
673 List<MonitorInfo> monitorInfos = slotcolumn.columnDatas;
674 if (lineInx < maxColumnHeaders)
675 monitorInfos = slotcolumn.columnHeaders;
678 for (MonitorInfo slotColumnData:monitorInfos){
679 cellNodeName = cellLookupName(tableName, k, lineInx, cellInx);
681 cellNode = ProfileVariables.claimChild(evaluationContext.getSceneGraph(),
682 SceneGraphConstants.NAVIGATION_NODE_NAME+"."+tableNodeName+"."+colNodeName, cellNodeName, TextNode.class,
684 if (cellNode == null)
686 cellNode.setLookupId(cellNodeName);
688 AffineTransform transform = new AffineTransform();
689 if (slotColumnData != null){
690 if (slotColumnData.getFont() != null)
691 cellNode.setFont(Fonts.awt(slotColumnData.getFont()));
692 if (slotColumnData.getColor() != null)
693 cellNode.setColor(Colors.awt(slotColumnData.getColor()));
694 if (slotColumnData.getTransform() != null)
695 transform = new AffineTransform(slotColumnData.getTransform());
697 cellNode.setVerticalAlignment((byte) 3);
698 double cellY = table.getRowHeight()*lineInx+DrawingTemplateInfo.BASELINE_VERTICAL_OFFSET*table.getRowHeight();
699 //cellNode.setText("yĆ
column_" + k);
700 cellNode.setText("");
701 if (lineInx >= maxColumnHeaders && slotcolumn.getType() == FlagTableColumnInfo.TYPE_ROW_NUMBERING){
703 cellNode.setText(new Integer(lineInx-maxColumnHeaders+slotcolumn.getStartOffset()).toString());
704 cellNode.setHorizontalAlignment((byte) 0);
707 // FontMetrics metrics = new FontMetrics(cellNode.getFont());
708 // double dy = (metrics.getAscent() + metrics.getLeading())/2;
709 cellNode.setBorderWidth(0.f);
710 cellNode.setPadding(0.0, 0.0);
711 Rectangle2D bounds = cellNode.getBoundsInLocal();
712 //double dy = bounds.getHeight()/2.0;
713 transform.translate(0.0, cellY);
714 cellNode.setTransform(transform);
715 cellNode.setFixedWidth(cellWidth);
720 //tableNode.setVisible(true);
723 void addLine(String nodeId, int x1, int y1, int x2, int y2, int cap, RTreeNode parent){
724 Line2D line = new Line2D.Float(x1, y1, x2, y2);
725 BasicStroke stroke = new BasicStroke(TranslateFlag.lineWidth, cap, BasicStroke.JOIN_MITER);
726 ShapeNode shape = parent.addNode(nodeId, ShapeNode.class); // SingleElementNode
727 shape.setShape(line);
728 shape.setScaleStroke(false);
729 shape.setStroke(stroke);
730 shape.setFill(false);
731 shape.setColor(new Color(0, 0, 0));
736 protected void cleanupStyleForItem(EvaluationContext evaluationContext, DataNodeMap map, Object item) {
737 INode root = evaluationContext.getSceneGraph();
738 if (root instanceof G2DSceneGraph) {
739 G2DSceneGraph sg = (G2DSceneGraph) root;
740 G2DParentNode nav = (G2DParentNode) sg.getNode(SceneGraphConstants.NAVIGATION_NODE_NAME);
742 // ProfileVariables.denyChildren(nav, SLOT_TABLE_PREFIX);
744 IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM);
745 for (String childId : NodeUtil.filterDirectChildIds(nav, SLOT_TABLE_PREFIX)) {
746 INode child = nav.getNode(childId);
747 List<IElement> elements = evaluationContext.setProperty(child, SLOT_TABLE_ELEMENTS, null);
748 if (elements != null && diagram != null)
749 for (IElement e : elements)
750 cleanupElement(diagram, e);
751 nav.removeNode(childId);
756 private void cleanupElement(IDiagram diagram, IElement e) {
757 diagram.removeElement(e);
761 * @param tableName slot table name
762 * @return lookup ID for the cell node
764 private static String tableLookupName(String tableName) {
765 return new StringBuilder()
766 .append(SLOT_TABLE_PREFIX)
767 .append(tableName).toString();
771 * @param tableName slot table name
772 * @param column 0..C-1, where C is the amount of columns
773 * @param row 0..N, where 0 is header
774 * @return lookup ID for the cell node
776 private static String cellLookupName(String tableName, int column, int row, int index) {
777 return new StringBuilder()
778 .append(SLOT_TABLE_PREFIX)
780 .append(SLOT_TABLE_SEPARATOR)
782 .append(SLOT_TABLE_SEPARATOR)
784 .append(SLOT_TABLE_SEPARATOR)
785 .append(index).toString();
788 private IElement addFlagElement(EvaluationContext evaluationContext, INode tableNode, Rectangle2D bounds, Resource flag) {
789 IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM);
790 assert diagram != null;
791 List<IElement> elements = evaluationContext.getProperty(tableNode, SLOT_TABLE_ELEMENTS);
792 assert elements != null;
793 IElement e = newFlagElement(evaluationContext, bounds, flag);
795 diagram.addElement(e);
799 private IElement newFlagElement(EvaluationContext evaluationContext, Rectangle2D bounds, Resource flag) {
800 IElement e = Element.spawnNew(rowElementClass);
801 e.setHint(ElementHints.KEY_BOUNDS, bounds.clone());
802 e.setHint(ElementHints.KEY_TRANSFORM, new AffineTransform());
803 // Just incase there's problems with same objects in multiple diagram elements
804 //e.setHint(ElementHints.KEY_OBJECT, flag);
805 // Didn't seem to help though.
806 e.setHint(ElementHints.KEY_OBJECT, new Wrapper(flag));
811 public String toString() {
812 return "Flag table style";
816 * IO table flag elements need a wrapper KEY_OBJECT whose toString()
817 * produces something else besides {@link Resource#toString()}.
819 public static class Wrapper extends AtomicReference<Resource> {
820 private static final long serialVersionUID = -4041629837352874410L;
821 public Wrapper(Resource r) {
825 public String toString() {
826 return "IO-" + super.toString();