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.layout.organic;
15  
16  import demo.module.OrganicLayoutModule;
17  import demo.view.DemoBase;
18  import y.base.Edge;
19  import y.base.EdgeCursor;
20  import y.base.EdgeMap;
21  import y.layout.organic.OrganicLayouter;
22  import y.module.GRIPModule;
23  import y.module.OrganicEdgeRouterModule;
24  import y.module.SmartOrganicLayoutModule;
25  import y.module.YModule;
26  import y.option.OptionHandler;
27  import y.view.EdgeRealizer;
28  import y.view.EditMode;
29  import y.view.Graph2D;
30  import y.view.NodeRealizer;
31  import y.view.PopupMode;
32  import y.view.YLabel;
33  
34  import javax.swing.AbstractAction;
35  import javax.swing.ButtonGroup;
36  import javax.swing.JMenu;
37  import javax.swing.JMenuBar;
38  import javax.swing.JPopupMenu;
39  import javax.swing.JRadioButtonMenuItem;
40  import javax.swing.JToolBar;
41  import java.awt.event.ActionEvent;
42  import java.awt.event.ActionListener;
43  
44  /** 
45   * Demonstrates different organic layout algorithms and 
46   * how to specify individual preferred edge lengths 
47   * for OrganicLayouter.  
48   * <br>
49   * In this demo the edge lengths can be specified by right clicking 
50   * on an edge or applying the current node distances using the button from the 
51   * toolbar. 
52   * Choose the item "Edit Preferred Edge Length" from the context menu to open up 
53   * a label editor that allows for entering a value for the edge length in pixels.
54   * Note that the entered value must be numeric. Otherwise 
55   * a default length will be chosen.
56   */
57  public class OrganicLayouterDemo extends DemoBase
58  {
59    EdgeMap preferredEdgeLengthMap;
60    YModule module;
61    
62    public OrganicLayouterDemo()
63    {
64      preferredEdgeLengthMap = view.getGraph2D().createEdgeMap();
65      view.getGraph2D().addDataProvider( OrganicLayouter.PREFERRED_EDGE_LENGTH_DATA, preferredEdgeLengthMap);
66      module = new SmartOrganicLayoutModule();
67      loadGraph( "resource/organic.gml" );
68    }
69  
70    protected void registerViewModes() {
71      EditMode editMode = new EditMode();
72      view.addViewMode( editMode );
73  
74      editMode.setPopupMode( new PopupMode() {
75        public JPopupMenu getEdgePopup( Edge e ) {
76          JPopupMenu pm = new JPopupMenu();
77          pm.add( new EditLabel( e ) );
78          return pm;
79        }
80      } );
81    }
82  
83    /** 
84     * Returns ViewActionDemo toolbar plus actions to trigger some layout algorithms 
85     */
86    protected JToolBar createToolBar()
87    {
88      JToolBar bar = super.createToolBar();
89      
90      bar.addSeparator();
91      bar.add(new LayoutAction());
92      bar.add(new OptionAction());
93      bar.add(new AssignLengthsAction("Assign Lengths"));
94      return bar;
95    }
96    
97    protected JMenuBar createMenuBar(){
98      JMenuBar mb = super.createMenuBar();
99      JMenu layoutMenu = new JMenu("Style");
100     ButtonGroup bg = new ButtonGroup();
101     ActionListener listener = new ActionListener(){
102       public void actionPerformed(ActionEvent ae){
103         module = new OrganicLayoutModule();
104       }
105     };
106     JRadioButtonMenuItem item = new JRadioButtonMenuItem("Classic");
107     item.addActionListener(listener);
108     bg.add(item);
109     layoutMenu.add(item);
110     listener = new ActionListener(){
111       public void actionPerformed(ActionEvent ae){
112         module = new SmartOrganicLayoutModule();
113       }
114     };
115     item = new JRadioButtonMenuItem("Smart");
116     item.addActionListener(listener);
117     item.setSelected(true);
118     bg.add(item);
119     layoutMenu.add(item);
120     
121     listener = new ActionListener(){
122       public void actionPerformed(ActionEvent ae){
123         module = new GRIPModule();
124       }
125     };
126     item = new JRadioButtonMenuItem("GRIP");
127     item.addActionListener(listener);
128     bg.add(item);
129     layoutMenu.add(item);
130     listener = new ActionListener(){
131       public void actionPerformed(ActionEvent ae){
132         module = new OrganicEdgeRouterModule();
133       }
134     };
135     item = new JRadioButtonMenuItem("EdgeRouting");
136     item.addActionListener(listener);
137     bg.add(item);
138     layoutMenu.add(item);
139     mb.add(layoutMenu);
140     return mb;
141   }
142   
143   /** 
144    *  Displays the layout options for organic layouter
145    */
146   class OptionAction extends AbstractAction
147   {
148     OptionAction() 
149     {
150       super("Options...");
151     }
152     
153     public void actionPerformed(ActionEvent e)
154     {
155       //display the option handler
156       OptionHandler op = module.getOptionHandler();
157       if( op != null) {
158         if( !op.showEditor() )
159           return;
160       }
161     }
162   }
163   
164   /** 
165    *  Launches the OrganicLayouter.
166    */
167   class LayoutAction extends AbstractAction
168   {
169     LayoutAction()
170     {
171       super("Layout");
172     }
173     
174     public void actionPerformed(ActionEvent e)
175     {
176       //update preferredEdgeLengthData before launching the module
177       Graph2D graph = view.getGraph2D();
178       for(EdgeCursor ec = graph.edges();ec.ok(); ec.next())
179       {
180         Edge edge = ec.edge();
181         String eLabel = graph.getLabelText(edge);
182         preferredEdgeLengthMap.set(edge,null);
183         try{
184           preferredEdgeLengthMap.setInt(edge,(int)Double.parseDouble(eLabel));
185         }
186         catch(Exception ex) {}
187       }
188       
189       //start the module
190       module.start(view.getGraph2D());
191     }
192   }
193 
194   /**
195    * Action that opens a text editor for the label of an edge
196    * <p>
197    * The inlined label editor allows to enter a single line of
198    * label text for an edge. To terminate the label editor 
199    * press "Enter".
200    */
201   class EditLabel extends AbstractAction
202   {
203     Edge e;
204     
205     EditLabel(Edge e)
206     {
207       super("Edit Preferred Edge Length");
208       this.e = e;
209     }
210     
211     public void actionPerformed(ActionEvent ev)
212     {
213       
214       final EdgeRealizer r = view.getGraph2D().getRealizer(e);
215       final YLabel label = r.getLabel();
216             
217       view.openLabelEditor(label, 
218                            label.getBox().getX(),
219                            label.getBox().getY(),
220                            null,true); 
221     }
222   }
223   
224   class AssignLengthsAction extends AbstractAction
225   {
226     public AssignLengthsAction(String name){
227       super(name);
228     }
229     
230     public void actionPerformed(ActionEvent e)
231     {
232       Graph2D g = view.getGraph2D();
233       for (EdgeCursor ec = g.edges(); ec.ok(); ec.next()){
234         NodeRealizer snr = g.getRealizer(ec.edge().source());
235         NodeRealizer tnr = g.getRealizer(ec.edge().target());
236         double deltaX = snr.getCenterX() - tnr.getCenterX();
237         double deltaY = snr.getCenterY() - tnr.getCenterY();
238         double dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
239         EdgeRealizer er = g.getRealizer(ec.edge());
240         er.getLabel().setText(Integer.toString((int)dist));
241       }
242       g.updateViews();
243     }
244   }
245   
246   public static void main(String args[])
247   {
248     initLnF();
249     
250     OrganicLayouterDemo demo = new OrganicLayouterDemo();
251     
252     demo.start("Organic Layouter Demo");
253   }
254 }
255 
256 
257       
258