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