1   /****************************************************************************
2    * This demo file is part of yFiles for Java 2.14.
3    * Copyright (c) 2000-2017 by yWorks GmbH, Vor dem Kreuzberg 28,
4    * 72070 Tuebingen, Germany. All rights reserved.
5    * 
6    * yFiles demo files exhibit yFiles for Java functionalities. Any redistribution
7    * of demo files in source code or binary form, with or without
8    * modification, is not permitted.
9    * 
10   * Owners of a valid software license for a yFiles for Java version that this
11   * demo is shipped with are allowed to use the demo source code as basis
12   * for their own yFiles for Java powered applications. Use of such programs is
13   * governed by the rights and conditions as set out in the yFiles for Java
14   * license agreement.
15   * 
16   * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
17   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19   * NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21   * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   *
27   ***************************************************************************/
28  package demo.view.realizer;
29  
30  import demo.view.DemoBase;
31  import y.base.Node;
32  import y.geom.OrientedRectangle;
33  import y.view.ArcEdgeRealizer;
34  import y.view.Arrow;
35  import y.view.Bend;
36  import y.view.BevelNodePainter;
37  import y.view.BridgeCalculator;
38  import y.view.DefaultGraph2DRenderer;
39  import y.view.Drawable;
40  import y.view.EdgeLabel;
41  import y.view.GenericNodeRealizer;
42  import y.view.Graph2D;
43  import y.view.ImageNodeRealizer;
44  import y.view.InterfacePort;
45  import y.view.LineType;
46  import y.view.NodeLabel;
47  import y.view.PolyLineEdgeRealizer;
48  import y.view.QuadCurveEdgeRealizer;
49  import y.view.ShapeNodeRealizer;
50  import y.view.ShinyPlateNodePainter;
51  import y.view.SmartEdgeLabelModel;
52  import y.view.SmartNodeLabelModel;
53  import y.view.YLabel;
54  
55  import java.awt.BasicStroke;
56  import java.awt.Color;
57  import java.awt.EventQueue;
58  import java.awt.Graphics2D;
59  import java.awt.Rectangle;
60  import java.awt.Stroke;
61  import java.awt.geom.Ellipse2D;
62  import java.awt.geom.GeneralPath;
63  import java.util.Locale;
64  import java.util.Map;
65  import java.util.Set;
66  
67  /**
68   * Demonstrates visual features and editor behavior.
69   * <p/>
70   * The following features are demonstrated:
71   * <ol>
72   * <li>EdgeLabels that display icons and text</li>
73   * <li>Rotated Labels</li>
74   * <li>Auto rotating EdgeLabels</li>
75   * <li>Transparent colors</li>
76   * <li>Gradients</li>
77   * <li>Bridges for crossing PolyLine Edges</li>
78   * <li>InterfacePorts that display icons. (A port defines the logical and visual endpoint of and edge path)</li>
79   * <li>In edit mode you can reposition an edge label by pressing on it with the left mouse button and then by dragging
80   * the label around. For better orientation some edges provide snap lines with suitable label positions. The snap lines
81   * disappear, if the shift key is pressed down. Then the placement of labels at arbitrary positions is possible.</li>
82   * <li>In edit mode you can interactively change the offsets of edge ports. Select the edge that should have different
83   * ports. A little black dot will appear at the point where the port has its logical location. You can drag the black
84   * dot around. If you release the mouse again the offset of the port will be changed.</li>
85   * <li>In edit mode you can create an edge that has non-zero port offsets by starting edge creation with the shift key
86   * pressed down. The point where you press will become the source port location of the edge. If you have the shift key
87   * down when you finish edge creation (by releasing the mouse over a node) that the release point will become the offset
88   * of the target port of the edge.</li>
89   * </ol>
90   */
91  public class VisualFeatureDemo extends DemoBase {
92    private static final String SHINY_NODE_CONFIGURATION = "ShinyNodeConfig";
93    private static final String BEVEL_NODE_CONFIGURATION = "BevelNodeConfig";
94  
95    public VisualFeatureDemo() {
96  
97      final Graph2D graph = view.getGraph2D();
98  
99  
100     // show bridges
101     ((DefaultGraph2DRenderer) view.getGraph2DRenderer()).setBridgeCalculator(new BridgeCalculator());
102 
103     ShapeNodeRealizer defaultNodeRealizer = new ShapeNodeRealizer();
104     // configure a drop shadow
105     defaultNodeRealizer.setDropShadowColor(new Color(0, 0, 0, 64));
106     defaultNodeRealizer.setDropShadowOffsetX((byte) 5);
107     defaultNodeRealizer.setDropShadowOffsetY((byte) 5);
108     defaultNodeRealizer.setSize(50, 50);
109     configureNodeLabel(defaultNodeRealizer.getLabel(), SmartNodeLabelModel.POSITION_CENTER);
110     //set to graph as default
111     graph.setDefaultNodeRealizer(defaultNodeRealizer);
112 
113 
114 
115     //Node 1 to show the line type of the node
116     ShapeNodeRealizer node1Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
117     node1Realizer.setCenter(50, 50);
118     node1Realizer.setLineColor(Color.BLUE);
119     node1Realizer.setLineType(LineType.DASHED_1);
120     node1Realizer.setFillColor(Color.ORANGE);
121     node1Realizer.setShapeType(ShapeNodeRealizer.DIAMOND);
122     final Node node1 = graph.createNode(node1Realizer);
123 
124 
125     //Node 2
126     ShapeNodeRealizer node2Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
127     node2Realizer.setCenter(250, 50);
128     node2Realizer.setLineColor(Color.GRAY);
129     node2Realizer.setLineType(LineType.LINE_1);
130     node2Realizer.setFillColor2(Color.CYAN);
131     node2Realizer.setFillColor(Color.WHITE);
132     node2Realizer.setShapeType(ShapeNodeRealizer.DIAMOND);
133     final Node node2 = graph.createNode(node2Realizer);
134 
135 
136     //Node 3 to show the line type of the node
137     ShapeNodeRealizer node3Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
138     node3Realizer.setCenter(400, 50);
139     node3Realizer.setLineColor(Color.BLACK);
140     node3Realizer.setLineType(LineType.LINE_1);
141     node3Realizer.setFillColor(new Color(192, 192, 192, 255));
142     node3Realizer.setFillColor2(null);
143     node3Realizer.setShapeType(ShapeNodeRealizer.ROUND_RECT);
144     final Node node3 = graph.createNode(node3Realizer);
145 
146     //Node 4
147     ShapeNodeRealizer node4Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
148     node4Realizer.setCenter(600, 50);
149     node4Realizer.setLineColor(Color.GRAY);
150     node4Realizer.setLineType(LineType.LINE_1);
151     node4Realizer.setFillColor(new Color(255, 102, 0, 255));
152     node4Realizer.setFillColor2(Color.ORANGE);
153     node4Realizer.setShapeType(ShapeNodeRealizer.TRAPEZOID_2);
154     final Node node4 = graph.createNode(node4Realizer);
155 
156     //Instance of edge realizer that will be default
157     PolyLineEdgeRealizer defaultEdgeRealizer = new PolyLineEdgeRealizer();
158     defaultEdgeRealizer.setTargetArrow(Arrow.STANDARD);
159     graph.setDefaultEdgeRealizer(defaultEdgeRealizer);
160 
161     //add an edge between 1 und 2
162     PolyLineEdgeRealizer edge1_2Realizer = new PolyLineEdgeRealizer();
163     edge1_2Realizer.setLineType(LineType.DASHED_1);
164     edge1_2Realizer.setSourceArrow(Arrow.STANDARD);
165     edge1_2Realizer.setTargetArrow(Arrow.WHITE_DIAMOND);
166     graph.createEdge(node1, node2, edge1_2Realizer);
167 
168     //add an edge between 2 und 3
169     PolyLineEdgeRealizer edge2_3Realizer = new PolyLineEdgeRealizer();
170     edge2_3Realizer.setLineType(LineType.DASHED_DOTTED_2);
171     edge2_3Realizer.setSourceArrow(Arrow.NONE);
172     edge2_3Realizer.setTargetArrow(Arrow.NONE);
173     graph.createEdge(node2, node3,edge2_3Realizer);
174 
175     //add an edge between 3 und 4
176     //setup source arrow drawable
177     Drawable drawable = new Drawable() {
178       public void paint(Graphics2D g) {
179         Color color = g.getColor();
180         Stroke stroke = g.getStroke();
181         g.setStroke(new BasicStroke(2));
182         g.setColor(Color.yellow);
183         Ellipse2D.Double ellipse = new Ellipse2D.Double(-19, -9, 18, 18);
184         g.fill(ellipse);
185         g.setColor(Color.orange);
186         g.draw(ellipse);
187         g.setColor(Color.black);
188         GeneralPath path = new GeneralPath();
189         path.moveTo(-14, -4);
190         path.lineTo(-5, 0);
191         path.lineTo(-14, 4);
192         g.draw(path);
193         g.setStroke(stroke);
194         g.setColor(color);
195       }
196 
197       public Rectangle getBounds() {
198         return new Rectangle(-20, -20, 20, 20);
199       }
200     };
201 
202     PolyLineEdgeRealizer edge3_4Realizer = new PolyLineEdgeRealizer();
203     edge3_4Realizer.setLineType(LineType.LINE_1);
204     edge3_4Realizer.setSourceArrow(Arrow.addCustomArrow("coolArrow", drawable));
205     edge3_4Realizer.setTargetArrow(Arrow.DIAMOND);
206     Bend bend1 = edge3_4Realizer.createBend(470.0, 70.0, null, Graph2D.AFTER);
207     Bend bend2 = edge3_4Realizer.createBend(530.0, 30.0, bend1, Graph2D.AFTER);
208     graph.createEdge(node3, node4,edge3_4Realizer);
209 
210     //Node 5
211     ShapeNodeRealizer node5Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
212     node5Realizer.setCenter(50, 150);
213     node5Realizer.setLineColor(Color.BLACK);
214     node5Realizer.setLineType(LineType.LINE_1);
215     node5Realizer.setFillColor(Color.ORANGE);
216     node5Realizer.setFillColor2(null);
217     node5Realizer.setShapeType(ShapeNodeRealizer.TRIANGLE);
218     final Node node5 = graph.createNode(node5Realizer);
219 
220     //Node 6
221     ShapeNodeRealizer node6Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
222     node6Realizer.setCenter(250, 150);
223     node6Realizer.setLineColor(Color.BLACK);
224     node6Realizer.setLineType(LineType.LINE_1);
225     node6Realizer.setFillColor(new Color(255, 204, 0, 255));
226     node6Realizer.setShapeType(ShapeNodeRealizer.HEXAGON);
227     final Node node6 = graph.createNode(node6Realizer);
228 
229 
230     //Configure  new node realizers with specific painters
231     GenericNodeRealizer.Factory factory = GenericNodeRealizer.getFactory();
232     Map configurationMap = factory.createDefaultConfigurationMap();
233 
234     // ShinyPlateNodePainter has an option to draw a drop shadow that is more efficient
235     // than wrapping it in a ShadowNodePainter.
236     ShinyPlateNodePainter shinyPlateNodePainter = new ShinyPlateNodePainter();
237     shinyPlateNodePainter.setRadius(10);
238     shinyPlateNodePainter.setDrawShadow(true);
239     configurationMap.put(GenericNodeRealizer.Painter.class, shinyPlateNodePainter);
240     configurationMap.put(GenericNodeRealizer.ContainsTest.class, shinyPlateNodePainter);
241     factory.addConfiguration(SHINY_NODE_CONFIGURATION, configurationMap);
242 
243     BevelNodePainter bevelNodePainter = new BevelNodePainter();
244     bevelNodePainter.setDrawShadow(true);
245     configurationMap.put(GenericNodeRealizer.Painter.class, bevelNodePainter);
246     configurationMap.put(GenericNodeRealizer.ContainsTest.class, bevelNodePainter);
247     factory.addConfiguration(BEVEL_NODE_CONFIGURATION, configurationMap);
248 
249 
250     //Node 7
251     GenericNodeRealizer gnr_shiny = new GenericNodeRealizer(SHINY_NODE_CONFIGURATION);
252     gnr_shiny.setLineColor(new Color(255, 153, 0, 255));
253     gnr_shiny.setFillColor(new Color(255, 153, 0, 255));
254     gnr_shiny.setSize(50, 50);
255     gnr_shiny.setCenter(400, 150);
256     configureNodeLabel(gnr_shiny.getLabel(), SmartNodeLabelModel.POSITION_CENTER);
257     Node node7 = graph.createNode(gnr_shiny);
258 
259     //Node 8
260     GenericNodeRealizer gnr_bevel = new GenericNodeRealizer(BEVEL_NODE_CONFIGURATION);
261     gnr_bevel.setLineColor(new Color(255, 153, 0, 255));
262     gnr_bevel.setFillColor(new Color(255, 153, 0, 255));
263     gnr_bevel.setSize(50, 50);
264     gnr_bevel.setCenter(600, 150);
265     configureNodeLabel(gnr_bevel.getLabel(), SmartNodeLabelModel.POSITION_CENTER);
266     Node node8 = graph.createNode(gnr_bevel);
267 
268 
269     //add an edge between 1 und 5
270     PolyLineEdgeRealizer edge1_5Realizer = new PolyLineEdgeRealizer();
271     edge1_5Realizer.setSourceArrow(Arrow.NONE);
272     edge1_5Realizer.setTargetArrow(Arrow.SKEWED_DASH);
273     graph.createEdge(node1, node5, edge1_5Realizer);
274 
275     //add an edge between 5 und 6
276     PolyLineEdgeRealizer edge5_6Realizer = new PolyLineEdgeRealizer();
277     edge5_6Realizer.setSourceArrow(Arrow.WHITE_DELTA);
278     edge5_6Realizer.setTargetArrow(Arrow.STANDARD);
279     graph.createEdge(node5, node6, edge5_6Realizer);
280 
281     //add an edge between 6 und 6 (itself)
282     PolyLineEdgeRealizer edge6_6Realizer = new PolyLineEdgeRealizer();
283     edge6_6Realizer.setTargetArrow(Arrow.STANDARD);
284     graph.createEdge(node6, node6, edge6_6Realizer);
285 
286     //add an edge between 6 und 7
287     PolyLineEdgeRealizer edge6_7Realizer = new PolyLineEdgeRealizer();
288     edge6_7Realizer.setSourceArrow(Arrow.NONE);
289     edge6_7Realizer.setTargetArrow(Arrow.NONE);
290     graph.createEdge(node6, node7, edge6_7Realizer);
291 
292     //add an edge between 7 und 8
293     PolyLineEdgeRealizer edge7_8Realizer = new PolyLineEdgeRealizer();
294     edge7_8Realizer.setSourceArrow(Arrow.WHITE_DELTA);
295     edge7_8Realizer.setTargetArrow(Arrow.WHITE_DIAMOND);
296     EdgeLabel labelFor7_8_Edge = edge7_8Realizer.getLabel();
297     labelFor7_8_Edge.setText("EDGE LABEL");
298     configureEdgeLabel(labelFor7_8_Edge, SmartEdgeLabelModel.POSITION_RIGHT);
299     graph.createEdge(node7, node8,edge7_8Realizer);
300 
301     //Node 9
302     ShapeNodeRealizer node9Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
303     node9Realizer.setCenter(50, 250);
304     node9Realizer.setLineColor(Color.BLACK);
305     node9Realizer.setLineType(LineType.LINE_1);
306     node9Realizer.setFillColor(new Color(153, 204, 255, 255));
307     node9Realizer.setFillColor2(null);
308     node9Realizer.setShapeType(ShapeNodeRealizer.OCTAGON);
309     final Node node9 = graph.createNode(node9Realizer);
310 
311     //Node 10 (image node realizer)
312     // display an ImageNodeRealizer
313     ImageNodeRealizer imageNodeRealizer = new ImageNodeRealizer();
314     imageNodeRealizer.setImageURL(getSharedResource("resource/yicon.png"));
315     imageNodeRealizer.setAlphaImageUsed(true);
316     imageNodeRealizer.setCenter(250, 250);
317     imageNodeRealizer.setToImageSize();
318     imageNodeRealizer.setSize(40,50);
319     configureNodeLabel(imageNodeRealizer.getLabel(), SmartNodeLabelModel.POSITION_CENTER);
320     final Node node10 = graph.createNode(imageNodeRealizer);
321 
322 
323     // Edge between 9 and 10
324     PolyLineEdgeRealizer edge9_10Realizer = new PolyLineEdgeRealizer();
325     edge9_10Realizer.setSourceArrow(Arrow.STANDARD);
326     // choose smooth bends
327     edge9_10Realizer.setSmoothedBends(true);
328     // choose a thicker line
329     edge9_10Realizer.setLineType(LineType.LINE_2);
330 
331     //setup edge label
332     EdgeLabel labelForEdge9_10 = edge9_10Realizer.getLabel();
333     labelForEdge9_10.setText("rotated edge label");
334     configureEdgeLabel(labelForEdge9_10, SmartEdgeLabelModel.POSITION_RIGHT);
335     labelForEdge9_10.setRotationAngle(15);
336     labelForEdge9_10.setIcon(getIconResource("resource/Start24.png"));
337 
338     //setup visual source port
339     InterfacePort p = new InterfacePort();
340     p.setIcon(getIconResource("resource/Delete24.png"));
341     edge9_10Realizer.setSourcePort(p);
342 
343     //setup visual target port
344     p = new InterfacePort();
345     p.setIcon(getIconResource("resource/Properties24.png"));
346     edge9_10Realizer.setTargetPort(p);
347 
348     //add an edge between 9 und 10
349     graph.createEdge(node9, node10, edge9_10Realizer);
350 
351 
352     //Node 11
353     GenericNodeRealizer gnr_shiny2 = new GenericNodeRealizer(SHINY_NODE_CONFIGURATION);
354     gnr_shiny2.setLineColor(new Color(255, 153, 0, 255));
355     gnr_shiny2.setFillColor(new Color(255, 153, 0, 255));
356     gnr_shiny2.setSize(15, 50);
357     gnr_shiny2.setCenter(400, 250);
358     configureNodeLabel(gnr_shiny2.getLabel(), SmartNodeLabelModel.POSITION_CENTER);
359     Node node11 = graph.createNode(gnr_shiny2);
360 
361     //Edge 10 11
362     PolyLineEdgeRealizer edge10_11Realizer = new PolyLineEdgeRealizer();
363     edge10_11Realizer.setTargetArrow(Arrow.CONVEX);
364     graph.createEdge(node10, node11, edge10_11Realizer);
365 
366     //Node 12
367     ShapeNodeRealizer node12Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
368     node12Realizer.setCenter(600, 250);
369     node12Realizer.setLineColor(Color.BLACK);
370     node12Realizer.setLineType(LineType.LINE_1);
371     node12Realizer.setFillColor(new Color(255, 102, 0, 255));
372     node12Realizer.setFillColor2(new Color(255, 153, 0, 255));
373     node12Realizer.setShapeType(ShapeNodeRealizer.PARALLELOGRAM);
374     final Node node12 = graph.createNode(600, 250);
375 
376     //Quadratic curve edge for nodes 11 und 12
377     QuadCurveEdgeRealizer quadCurveEdgeRealizer = new QuadCurveEdgeRealizer();
378     quadCurveEdgeRealizer.setTargetArrow(Arrow.STANDARD);
379     graph.createEdge(node11, node12, quadCurveEdgeRealizer);
380     //add symmetrical bends on the edge
381     double bendStartX = quadCurveEdgeRealizer.getSourceIntersection().getX();
382     double bendEndX = quadCurveEdgeRealizer.getTargetIntersection().getX();
383     //calculate the y - middle between source and target to alternate the position of the bends
384     double bendStartEndY = (quadCurveEdgeRealizer.getSourceIntersection().getY() + quadCurveEdgeRealizer.getTargetIntersection().getY())/2;
385     Bend lastBend = null;
386     int numberOfBends = 10;
387     double deltaX = (bendEndX - bendStartX) / numberOfBends;
388     double x = bendStartX;
389     double y = 0;
390     for (int i = 0; i < numberOfBends; i++) {
391       x = x + deltaX;
392       if (i % 2 == 0) {
393         y = bendStartEndY - 25;
394       } else {
395         y = bendStartEndY + 25;
396       }
397       lastBend = quadCurveEdgeRealizer.createBend(x, y, lastBend, Graph2D.AFTER);
398     }
399 
400     //Node 13
401     // reconfigure the default NodeRealizer
402     ShapeNodeRealizer node13Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
403     node13Realizer.setShapeType(ShapeNodeRealizer.ELLIPSE);
404     node13Realizer.setCenter(50, 350);
405     node13Realizer.setFillColor(Color.YELLOW);
406     final NodeLabel nodeLabel = node13Realizer.getLabel();
407     nodeLabel.setText("<html><b><font color=\"red\">HTML</b><br/>labels!</html>");
408     configureNodeLabel(nodeLabel, SmartNodeLabelModel.POSITION_SOUTH);
409     Node node13 = graph.createNode(node13Realizer);
410 
411     //Node 14
412     ShapeNodeRealizer node14Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
413     node14Realizer.setShapeType(ShapeNodeRealizer.ELLIPSE);
414     node14Realizer.setSize(50, 50);
415     node14Realizer.setCenter(250,350);
416     node14Realizer.setFillColor(Color.red);
417     node14Realizer.setFillColor2(Color.yellow);
418     final NodeLabel node14Label = node14Realizer.getLabel();
419     node14Label.setFontSize(8);
420     node14Label.setText("Transparency! and automatically cropped text for custom label size!.");
421     Set configurations = NodeLabel.getFactory().getAvailableConfigurations();
422     // set a custom configuration for the label
423     if (configurations.contains("CroppingLabel")) {
424       node14Label.setConfiguration("CroppingLabel");
425       node14Label.setAutoSizePolicy(YLabel.AUTOSIZE_NONE);
426       node14Label.setContentSize(40, 40);
427     }
428     node14Label.setRotationAngle(45);
429     node14Label.setBackgroundColor(new Color(255, 255, 255, 128));
430     node14Label.setLineColor(Color.GRAY);
431     Node node14 = graph.createNode(node14Realizer);
432 
433     // add an edge from node 13 to 14
434     final ArcEdgeRealizer arcEdgeRealizer = new ArcEdgeRealizer();
435     arcEdgeRealizer.setTargetArrow(Arrow.STANDARD);
436     arcEdgeRealizer.setLineType(LineType.DOTTED_2);
437     EdgeLabel edge13_14Label = arcEdgeRealizer.getLabel();
438     edge13_14Label.setText("Arc edge");
439     edge13_14Label.setModel(EdgeLabel.FREE);
440     graph.createEdge(node14, node13, arcEdgeRealizer);
441     final OrientedRectangle labelBounds = edge13_14Label.getOrientedBox();
442     final Object newParam = edge13_14Label.getBestModelParameterForBounds(labelBounds.getMovedInstance(-80, 40));
443     edge13_14Label.setModelParameter(newParam);
444 
445 
446      //Node 15
447     ShapeNodeRealizer node15Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
448     node15Realizer.setShapeType(ShapeNodeRealizer.RECT_3D);
449     node15Realizer.setSize(50, 50);
450     node15Realizer.setCenter(400,350);
451     node15Realizer.setFillColor(Color.red);
452     node15Realizer.setFillColor2(Color.yellow);
453     final NodeLabel node15Label = node15Realizer.getLabel();
454     node15Label.setFontSize(8);
455     node15Label.setText("Transparency! and automatically cropped text for custom label size!.");
456     
457     // set a custom configuration for the label
458     if (configurations.contains("CroppingLabel")) {
459       node15Label.setConfiguration("CroppingLabel");
460       node15Label.setAutoSizePolicy(YLabel.AUTOSIZE_NONE);
461       node15Label.setContentSize(50, 50);
462     }
463     node15Label.setRotationAngle(45);
464     node15Label.setBackgroundColor(new Color(255, 255, 255, 128));
465     node15Label.setLineColor(Color.GRAY);
466     Node node15 = graph.createNode(node15Realizer);
467 
468     //Node 16
469     // reconfigure the default NodeRealizer
470     ShapeNodeRealizer node16Realizer = new ShapeNodeRealizer(graph.getDefaultNodeRealizer());
471     node16Realizer.setCenter(600, 350);
472     node16Realizer.setShapeType(ShapeNodeRealizer.ELLIPSE);
473     node16Realizer.setFillColor(Color.WHITE);
474     node16Realizer.setLineColor(new Color(255,80,0,255));
475     node16Realizer.setLineType(LineType.LINE_4);
476     final NodeLabel node16Label = node16Realizer.getLabel();
477     node16Label.setText("<html><b>1,2,3...</b></html>");
478     Node node16 = graph.createNode(node16Realizer);
479 
480     //Edge 14 15
481     PolyLineEdgeRealizer edge14_15Realizer = new PolyLineEdgeRealizer();
482     edge14_15Realizer.setTargetArrow(Arrow.addCustomArrow("offsetArrow", Arrow.T_SHAPE, 20));
483     graph.createEdge(node14, node15, edge14_15Realizer);
484 
485     //Edge 15 16
486     PolyLineEdgeRealizer edge15_16Realizer = new PolyLineEdgeRealizer();
487     edge15_16Realizer.setTargetArrow(Arrow.STANDARD);
488     graph.createEdge(node15, node16, edge15_16Realizer);
489 
490     //Edge 4 8
491     PolyLineEdgeRealizer edge4_8Realizer = new PolyLineEdgeRealizer();
492     edge4_8Realizer.setLineType(LineType.DOTTED_2);
493     EdgeLabel edge4_8Label = edge4_8Realizer.getLabel();
494     edge4_8Label.setText("Dotted");
495     configureEdgeLabel(edge4_8Label, SmartEdgeLabelModel.POSITION_LEFT);
496     graph.createEdge(node4, node8, edge4_8Realizer);
497 
498     // add an edge from node 16 to 12
499     final ArcEdgeRealizer arcEdge16_12Realizer = new ArcEdgeRealizer();
500     arcEdge16_12Realizer.setTargetArrow(Arrow.STANDARD);
501     arcEdge16_12Realizer.setLineType(LineType.DOTTED_1);
502     graph.createEdge(node16, node12, arcEdge16_12Realizer);
503   }
504 
505   private void configureEdgeLabel(EdgeLabel label, int position) {
506     final SmartEdgeLabelModel model = new SmartEdgeLabelModel();
507     label.setLabelModel(model, model.createDiscreteModelParameter(position));
508   }
509 
510   private void configureNodeLabel(NodeLabel label, int position) {
511     SmartNodeLabelModel model = new SmartNodeLabelModel();
512     label.setLabelModel(model, model.createDiscreteModelParameter(position));
513   }
514 
515 
516   public static void main(String[] args) {
517     EventQueue.invokeLater(new Runnable() {
518       public void run() {
519         Locale.setDefault(Locale.ENGLISH);
520         initLnF();
521         (new VisualFeatureDemo()).start("Visual Feature Demo");
522       }
523     });
524   }
525 }
526