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