1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.6. 
4    ** 
5    ** yWorks proprietary/confidential. Use is subject to license terms.
6    **
7    ** Redistribution of this file or of an unauthorized byte-code version
8    ** of this file is strictly forbidden.
9    **
10   ** Copyright (c) 2000-2008 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.view.realizer;
15  
16  import demo.view.DemoBase;
17  import y.base.EdgeCursor;
18  import y.view.Arrow;
19  import y.view.BendList;
20  import y.view.BridgeCalculator;
21  import y.view.DefaultGraph2DRenderer;
22  import y.view.EdgeRealizer;
23  import y.view.GenericEdgePainter;
24  import y.view.GenericEdgeRealizer;
25  import y.view.Graph2D;
26  
27  import javax.swing.AbstractAction;
28  import javax.swing.JToolBar;
29  import java.awt.Graphics2D;
30  import java.awt.event.ActionEvent;
31  import java.awt.geom.GeneralPath;
32  import java.awt.geom.PathIterator;
33  import java.util.Map;
34  
35  /**
36   * This class demonstrates how to utilize {@link y.view.BridgeCalculator} to draw bridges/gaps for crossing edges with
37   * custom {@link EdgeRealizer}s.
38   * It demonstrates how to wrap a {@link GenericEdgeRealizer.Painter} implementation of a customized
39   * {@link y.view.GenericEdgeRealizer} and use the current {@link BridgeCalculator} instance
40   * from the {@link DefaultGraph2DRenderer}
41   * to incorporate the calculation of bridges into the rendering.
42   *
43   */
44  public class BridgeEdgeRealizerDemo extends DemoBase {
45    BridgeCalculator bridgeCalculator;
46  
47    public BridgeEdgeRealizerDemo() {
48      super();
49      // get the factory to register our own styles
50      GenericEdgeRealizer.Factory factory = GenericEdgeRealizer.getFactory();
51  
52      // Retrieve a map that holds the default GenericEdgeRealizer configuration.
53      // The implementations contained therein can be replaced one by one in order 
54      // to create custom configurations... 
55      Map implementationsMap = factory.createDefaultConfigurationMap();
56  
57      // notice that the painter instance is wrapped using BridgedEdgePainter
58      // which modifies the GeneralPath instance and provides the necessary BridgeCalculatorHandler
59      // if the BridgeCalculator's mode should be set to two pass rendering (modes other than
60      // CROSSING_MODE_ORDER_INDUCED)
61      final BridgedEdgePainter painter = new BridgedEdgePainter(
62          new GenericEdgePainter(), BridgeCalculator.CROSSING_STYLE_GAP);
63      implementationsMap.put(GenericEdgeRealizer.Painter.class, painter);
64      // used only when the bridgeCalculator is set to two pass rendering - otherwise not needed
65      implementationsMap.put(GenericEdgeRealizer.BridgeCalculatorHandler.class, painter);
66  
67      // finally add the configuration to the factory
68      factory.addConfiguration("bridgetype1", implementationsMap);
69  
70      // and another style
71      final BridgedEdgePainter painter2 = new BridgedEdgePainter(
72          new GenericEdgePainter(), BridgeCalculator.CROSSING_STYLE_ARC);
73      implementationsMap.put(GenericEdgeRealizer.Painter.class, painter2);
74      // used only when the bridgeCalculator is set to two pass rendering - otherwise not needed
75      implementationsMap.put(GenericEdgeRealizer.BridgeCalculatorHandler.class, painter2);
76  
77      // finally add the configuration to the factory
78      factory.addConfiguration("bridgetype2", implementationsMap);
79  
80      // Create a default EdgeRealizer
81      GenericEdgeRealizer ger = new GenericEdgeRealizer();
82  
83      // initialize the default edgerealizer to the type we just registered...
84      ger.setConfiguration("bridgetype1");
85      ger.setTargetArrow(Arrow.STANDARD);
86  
87      // set the realizer...
88      final Graph2D graph = view.getGraph2D();
89      graph.setDefaultEdgeRealizer(ger);
90  
91      // set an appropriate graph2drenderer that resets the bridgecalculator initially for each painting
92      bridgeCalculator = new BridgeCalculator();
93      // optionally set a different crossing mode
94      // (triggers usage of BridgeCalculatorHandler implementation)
95      // bridgeCalculator.setCrossingMode(BridgeCalculator.CROSSING_MODE_HORIZONTAL_CROSSES_VERTICAL);
96      ((DefaultGraph2DRenderer) view.getGraph2DRenderer()).setBridgeCalculator(bridgeCalculator);
97  
98      loadGraph( "resource/bridgeEdgeRealizer.gml" );
99    }
100 
101   protected JToolBar createToolBar() {
102     JToolBar toolBar = super.createToolBar();
103     toolBar.add(new AbstractAction("Default Type 1") {
104       public void actionPerformed(ActionEvent e) {
105         Graph2D graph = view.getGraph2D();
106 
107         EdgeCursor ec = graph.selectedEdges();
108         if(ec.size() == 0){
109           ec = graph.edges();
110         }
111         for (; ec.ok(); ec.next()) {
112           ((GenericEdgeRealizer)graph.getRealizer(ec.edge())).setConfiguration("bridgetype1");
113         }
114         view.getGraph2D().setDefaultEdgeRealizer(new GenericEdgeRealizer("bridgetype1"));
115         graph.updateViews();
116       }
117     });
118     toolBar.add(new AbstractAction("Default Type 2") {
119       public void actionPerformed(ActionEvent e) {
120         Graph2D graph = view.getGraph2D();
121         EdgeCursor ec = graph.selectedEdges();
122         if(ec.size() == 0){
123           ec = graph.edges();
124         }
125         for (; ec.ok(); ec.next()) {
126           ((GenericEdgeRealizer)graph.getRealizer(ec.edge())).setConfiguration("bridgetype2");
127         }
128         view.getGraph2D().setDefaultEdgeRealizer(new GenericEdgeRealizer("bridgetype2"));
129         graph.updateViews();
130       }
131     });
132     return toolBar;
133   }
134 
135   /**
136    * Wrapping GenericEdgeRealizer.Painter implemenation that modifies the given
137    * GeneralPath to incorporate bridges. Then delegates the actual painting to
138    * the given instance.
139    */
140   static final class BridgedEdgePainter implements GenericEdgeRealizer.Painter, GenericEdgeRealizer.BridgeCalculatorHandler {
141     private final GenericEdgeRealizer.Painter painter;
142     private final short bridgeStyle;
143 
144     public BridgedEdgePainter(GenericEdgeRealizer.Painter painter, short bridgeStyle) {
145       this.painter = painter;
146       this.bridgeStyle = bridgeStyle;
147     }
148 
149     public void paint(EdgeRealizer context, BendList bends, GeneralPath path, Graphics2D gfx, boolean selected) {
150       // modify the GeneralPath
151       BridgeCalculator bridgeCalculator = DefaultGraph2DRenderer.getBridgeCalculator(context, gfx);
152       if (bridgeCalculator != null) {
153         GeneralPath p = new GeneralPath();
154         // remember old style
155         final short crossingStyle = bridgeCalculator.getCrossingStyle();
156         try {
157           bridgeCalculator.setCrossingStyle(bridgeStyle);
158           PathIterator pathIterator = bridgeCalculator.insertBridges(path.getPathIterator(null, 1.0d));
159           p.append(pathIterator, true);
160           // and delegate the painting
161           painter.paint(context, bends, p, gfx, selected);
162         } finally {
163           bridgeCalculator.setCrossingStyle(crossingStyle);
164         }
165       } else {
166         painter.paint(context, bends, path, gfx, selected);
167       }
168     }
169 
170     public void paintSloppy(EdgeRealizer context, BendList bends, GeneralPath path, Graphics2D gfx, boolean selected) {
171       painter.paintSloppy(context, bends, path, gfx, selected);
172     }
173 
174     // necessary for two-pass rendering only - the obstacles produced by this realizer have to be
175     // registered with the BridgeCalculator
176     public void registerObstacles(EdgeRealizer context, BendList bends, GeneralPath path, BridgeCalculator calculator) {
177       calculator.registerObstacles(path.getPathIterator(null));
178     }
179   }
180 
181 
182   public static void main(String[] args) {
183     initLnF();
184     new BridgeEdgeRealizerDemo().start("Bridge EdgeRealizer Demo");
185   }
186 }
187