1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.9. 
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-2011 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.layout.tree;
15  
16  import y.base.Node;
17  import y.base.NodeCursor;
18  import y.base.NodeMap;
19  import y.layout.tree.AbstractRotatableNodePlacer.Matrix;
20  import y.layout.tree.AbstractRotatableNodePlacer.RootAlignment;
21  import y.layout.tree.AssistantPlacer;
22  import y.layout.tree.DoubleLinePlacer;
23  import y.layout.tree.NodePlacer;
24  import y.layout.tree.SimpleNodePlacer;
25  import y.view.Arrow;
26  import y.view.EdgeRealizer;
27  import y.view.Graph2D;
28  import y.view.LineType;
29  import y.view.PolyLineEdgeRealizer;
30  import y.view.PopupMode;
31  
32  import javax.swing.JCheckBoxMenuItem;
33  import javax.swing.JMenu;
34  import javax.swing.JPopupMenu;
35  import java.awt.event.ActionEvent;
36  import java.awt.event.ActionListener;
37  import java.awt.EventQueue;
38  import java.util.Locale;
39  
40  /**
41   * This demo shows how to use {@link y.layout.tree.GenericTreeLayouter}
42   * in conjunction with {@link y.layout.tree.AssistantPlacer}.
43   * <br>
44   * AssistantPlacer is a special NodePlacer that uses two layout strategies.
45   * Depending on the boolean provided through the special DataProvider found at
46   * the key {@link y.layout.tree.AssistantPlacer#ASSISTANT_DPKEY},
47   * the AssistantPlacer decides how to layout its children.<br>
48   * If the boolean is set to true for a specific node, it is interpreted as "assistant."
49   * All assistants are placed using the {@link y.layout.tree.LeftRightPlacer}.
50   * <br>
51   * The other children are placed below the assistants, using the child node
52   *  placer of the AssistantPlacer. The child node placer can be set using the
53   * method
54   * {@link y.layout.tree.AssistantPlacer#setChildNodePlacer(y.layout.tree.NodePlacer)}.
55   * <br>
56   * This demo offers its functionality via context menus. The actual selected
57   * nodes can be marked as assistants or "non-assistants," and the child node
58   * placer can be be set this way, too.
59   *
60   * @see <a href="http://docs.yworks.com/yfiles/doc/developers-guide/cls_GenericTreeLayouter.html">Section Generic Tree Layout</a> in the yFiles for Java Developer's Guide
61   */
62  public class AssistantPlacerDemo extends AbstractTreeDemo {
63    public static void main(String[] args) {
64      EventQueue.invokeLater(new Runnable() {
65        public void run() {
66          Locale.setDefault(Locale.ENGLISH);
67          initLnF();
68          (new AssistantPlacerDemo()).start("Assistant Placer Demo");
69        }
70      });
71    }
72  
73    private NodeMap isAssistantNodeMap;
74  
75    public AssistantPlacerDemo() {
76      Graph2D graph = view.getGraph2D();
77  
78      isAssistantNodeMap = graph.createNodeMap();
79      graph.addDataProvider( AssistantPlacer.ASSISTANT_DPKEY, isAssistantNodeMap );
80  
81      //Realizers
82      EdgeRealizer defaultER = graph.getDefaultEdgeRealizer();
83      defaultER.setArrow( Arrow.STANDARD );
84      ( ( PolyLineEdgeRealizer ) defaultER ).setSmoothedBends( true );
85      defaultER.setLineType( LineType.LINE_2 );
86  
87      createSampleGraph( view.getGraph2D() );
88      calcLayout();
89    }
90  
91    protected NodePlacer createDefaultNodePlacer() {
92      return new AssistantPlacer();
93    }
94  
95    protected boolean isDeletionEnabled() {
96      return false;
97    }
98  
99    private void createSampleGraph( Graph2D graph ) {
100     graph.clear();
101     Node root = graph.createNode();
102     graph.getRealizer( root ).setFillColor( layerColors[ 0 ] );
103     nodePlacerMap.set( root, new AssistantPlacer() );
104     createChildren( graph, root, 6, 1, 1 );
105     calcLayout();
106     view.fitContent();
107   }
108 
109   private void createChildren( Graph2D graph, Node root, int children, int layer, int layers ) {
110     for ( int i = 0; i < children; i++ ) {
111       Node child = graph.createNode();
112       graph.createEdge( root, child );
113       graph.getRealizer( child ).setFillColor( layerColors[ layer % layerColors.length ] );
114 
115       if ( i % 3 == 0 ) {
116         isAssistantNodeMap.setBool(child, true);
117       }
118       NodePlacer nodePlacer = new AssistantPlacer();
119       nodePlacerMap.set( child, nodePlacer );
120       if ( layers > 0 ) {
121         createChildren( graph, child, children, layer + 1, layers - 1 );
122       }
123     }
124   }
125 
126   protected PopupMode createTreePopupMode() {
127     return new TreeLayouterPopupMode();
128   }
129 
130   private final class TreeLayouterPopupMode extends PopupMode {
131     private JPopupMenu nodePlacementMenu;
132     private JCheckBoxMenuItem checkbox;
133 
134     TreeLayouterPopupMode() {
135       nodePlacementMenu = new JPopupMenu();
136 
137       checkbox = new JCheckBoxMenuItem( "Assistant" );
138       nodePlacementMenu.add( checkbox );
139 
140       checkbox.addActionListener( new ActionListener() {
141         public void actionPerformed( ActionEvent e ) {
142           for ( NodeCursor nodeCursor = getGraph2D().selectedNodes(); nodeCursor.ok(); nodeCursor.next() ) {
143             Node node = nodeCursor.node();
144             isAssistantNodeMap.setBool( node, checkbox.isSelected() );
145           }
146           calcLayout();
147         }
148       } );
149 
150       nodePlacementMenu.addSeparator();
151 
152       JMenu childPlacer = new JMenu( "Child NodePlacers" );
153       nodePlacementMenu.add( childPlacer );
154 
155       childPlacer.add( new SetNodePlacerAction( "Default" ) {
156         protected NodePlacer createNodePlacer() {
157           AssistantPlacer assistantPlacer = new AssistantPlacer();
158           assistantPlacer.setChildNodePlacer( new SimpleNodePlacer( Matrix.DEFAULT, RootAlignment.CENTER ) );
159           return assistantPlacer;
160         }
161       } );
162 
163       childPlacer.add( new SetNodePlacerAction( "Double Line" ) {
164         protected NodePlacer createNodePlacer() {
165           AssistantPlacer assistantPlacer = new AssistantPlacer();
166           assistantPlacer.setChildNodePlacer( new DoubleLinePlacer( Matrix.DEFAULT ) );
167           return assistantPlacer;
168         }
169       } );
170     }
171 
172     public JPopupMenu getNodePopup( final Node v ) {
173       checkbox.setSelected( isAssistantNodeMap.getBool( v ) );
174       return nodePlacementMenu;
175     }
176 
177     private void updateSelectionState() {
178       //Set selection state
179       checkbox.setSelected( false );
180       for ( NodeCursor nodeCursor = getGraph2D().selectedNodes(); nodeCursor.ok(); nodeCursor.next() ) {
181         Node node = nodeCursor.node();
182         if ( isAssistantNodeMap.getBool( node ) ) {
183           checkbox.setSelected( true );
184           break;
185         }
186       }
187     }
188 
189     public JPopupMenu getSelectionPopup( double x, double y ) {
190       if ( getGraph2D().selectedNodes().ok() ) {
191         updateSelectionState();
192         return nodePlacementMenu;
193       } else {
194         return null;
195       }
196     }
197   }
198 }
199