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.layout.DefaultLayoutGraph;
32  import y.layout.tree.DefaultNodePlacer;
33  import y.layout.tree.DefaultPortAssignment;
34  import y.layout.tree.GenericTreeLayouter;
35  import y.layout.tree.NodePlacer;
36  import y.layout.tree.PortAssignment;
37  import y.util.DataProviders;
38  
39  import javax.swing.BorderFactory;
40  import javax.swing.JCheckBox;
41  import javax.swing.JLabel;
42  import javax.swing.JPanel;
43  import javax.swing.border.Border;
44  import javax.swing.border.EtchedBorder;
45  import javax.swing.event.ChangeEvent;
46  import java.awt.Dimension;
47  import java.awt.GridBagLayout;
48  import java.awt.event.ActionEvent;
49  import java.awt.event.ActionListener;
50  import java.awt.event.ItemEvent;
51  import java.util.Hashtable;
52  
53  /**
54   * Property editor panel used by
55   * {@link demo.layout.tree.IncrementalTreeLayouterDemo} 
56   * to provide means for configuring the generic tree layouter.
57   * 
58   */
59  class DefaultNodePlacerConfigPanel extends javax.swing.JPanel
60  {
61    
62    private DefaultNodePlacer placer;
63    private GenericTreeLayouter treeLayouter;
64  
65    /** Creates new form DefaultNodePlacerConfigPanel */
66    public DefaultNodePlacerConfigPanel()
67    {
68      initComponents();
69      DefaultLayoutGraph graph = new DefaultLayoutGraph();
70      Node root = graph.createNode();
71      graph.getNodeLayout(root).setSize(30,30);
72      for (int i = 0; i < 3; i++){
73        Node child = graph.createNode();
74        graph.getNodeLayout(child).setSize(50 - i * 10 ,30);
75        graph.createEdge(root, child);
76      }
77      this.placer = new DefaultNodePlacer(DefaultNodePlacer.PLACEMENT_HORIZONTAL_DOWNWARD, 40, 40);
78      this.treeLayouter = new GenericTreeLayouter();
79      layoutPreviewPanel.setGraph(graph);
80      layoutPreviewPanel.setPreferredSize(new Dimension(160,160));
81      graph.addDataProvider(GenericTreeLayouter.NODE_PLACER_DPKEY, DataProviders.createConstantDataProvider(placer));
82  //    layoutPreviewPanel.setLayouter(new GenericTreeLayouter());
83      layoutPreviewPanel.setLayouter(this.treeLayouter);
84      updateFromPlacer();
85      updateFromPort();
86      layoutPreviewPanel.update();
87    }
88  
89    /** This method is called from within the constructor to
90     * initialize the form.
91     * WARNING: Do NOT modify this code. The content of this method is
92     * always regenerated by the Form Editor.
93     */
94    private void initComponents()//GEN-BEGIN:initComponents
95    {
96      java.awt.GridBagConstraints gridBagConstraints;
97  
98      childPlacementLabel = new javax.swing.JLabel();
99      rootAlignmentLabel = new javax.swing.JLabel();
100     alignmentSlider = new javax.swing.JSlider();
101     horizontalSlider = new javax.swing.JSlider();
102     hSpacingLabel = new javax.swing.JLabel();
103     placementComboBox = new javax.swing.JComboBox();
104     verticalSlider = new javax.swing.JSlider();
105     vSpacingLabel = new javax.swing.JLabel();
106     previewPanel = new javax.swing.JPanel();
107     layoutPreviewPanel = new demo.layout.withoutview.LayoutPreviewPanel();
108     routingStyleLabel = new javax.swing.JLabel();
109     routingStyleComboBox = new javax.swing.JComboBox();
110     ratioLabel = new javax.swing.JLabel();
111     ratioSlider = new javax.swing.JSlider( javax.swing.JSlider.HORIZONTAL, 0, 200, 100);
112     minFirstSegmentLabel = new javax.swing.JLabel();
113     minLastSegmentLabel = new javax.swing.JLabel();
114     minFirstSegmentSlider = new javax.swing.JSlider();
115     minLastSegmentSlider = new javax.swing.JSlider();
116     slopeLabel = new javax.swing.JLabel();
117     slopeSlider = new javax.swing.JSlider( javax.swing.JSlider.HORIZONTAL, 0, 200, 0);
118     slopeHeightLabel = new javax.swing.JLabel();
119     slopeHeightSlider = new javax.swing.JSlider();
120     distributedCheckBox = new JCheckBox("Distributed Port Assignment Style");
121 
122     setLayout(new java.awt.GridBagLayout());
123 
124     setBorder(new javax.swing.border.EmptyBorder(new java.awt.Insets(6, 6, 6, 6)));
125 
126     //////////////////
127     // Drop down box for the alignment of children in respect to their parents
128     //////////////////
129 
130     childPlacementLabel.setText("Child Placement");
131     gridBagConstraints = new java.awt.GridBagConstraints();
132     gridBagConstraints.gridx = 0;
133     gridBagConstraints.gridy = 0;
134     gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
135     add(childPlacementLabel, gridBagConstraints);
136 
137     placementComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Horizontally Downwards", "Horizontally Upwards", "Vertically to Left", "Vertically to Right" }));
138     placementComboBox.addItemListener(new java.awt.event.ItemListener()
139     {
140       public void itemStateChanged(java.awt.event.ItemEvent evt)
141       {
142         placementComboBoxItemStateChanged(evt);
143       }
144     });
145 
146     gridBagConstraints = new java.awt.GridBagConstraints();
147     gridBagConstraints.gridx = 0;
148     gridBagConstraints.gridy = 1;
149     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
150     gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 4);
151     add(placementComboBox, gridBagConstraints);
152 
153     //////////////////
154     // Drop down box for the selection of the routing style between nodes
155     //////////////////
156 
157     routingStyleLabel.setText("Routing Style");
158     gridBagConstraints = new java.awt.GridBagConstraints();
159     gridBagConstraints.gridx = 0;
160     gridBagConstraints.gridy = 2;
161     gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
162     gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
163     add(routingStyleLabel, gridBagConstraints);
164 
165     routingStyleComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Fork", "Fork at Root", "Poly Line Connect" }));
166     routingStyleComboBox.addItemListener(new java.awt.event.ItemListener()
167     {
168       public void itemStateChanged(java.awt.event.ItemEvent evt)
169       {
170         routingStyleComboBoxItemStateChanged(evt);
171       }
172     });
173 
174     gridBagConstraints = new java.awt.GridBagConstraints();
175     gridBagConstraints.gridx = 0;
176     gridBagConstraints.gridy = 3;
177     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
178     gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 5);
179     add(routingStyleComboBox, gridBagConstraints);
180 
181     //////////////////
182     // Slider for the horizontal spacing between nodes
183     //////////////////
184 
185     hSpacingLabel.setText("Horizontal Spacing");
186     gridBagConstraints = new java.awt.GridBagConstraints();
187     gridBagConstraints.gridx = 0;
188     gridBagConstraints.gridy = 5;
189     gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
190     gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
191     add(hSpacingLabel, gridBagConstraints);
192 
193     horizontalSlider.setMinorTickSpacing(5);
194     horizontalSlider.setPaintTicks(true);
195     horizontalSlider.addChangeListener(new javax.swing.event.ChangeListener()
196     {
197       public void stateChanged(javax.swing.event.ChangeEvent evt)
198       {
199         horizontalSliderStateChanged(evt);
200       }
201     });
202 
203     gridBagConstraints = new java.awt.GridBagConstraints();
204     gridBagConstraints.gridx = 0;
205     gridBagConstraints.gridy = 6;
206     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
207     add(horizontalSlider, gridBagConstraints);
208 
209     //////////////////
210     // Slider for the vertical spacing between nodes
211     //////////////////
212 
213     vSpacingLabel.setText("Vertical Spacing");
214     gridBagConstraints = new java.awt.GridBagConstraints();
215     gridBagConstraints.gridx = 0;
216     gridBagConstraints.gridy = 7;
217     gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
218     gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
219     add(vSpacingLabel, gridBagConstraints);
220 
221     verticalSlider.setMinorTickSpacing(5);
222     verticalSlider.setPaintTicks(true);
223     verticalSlider.addChangeListener(new javax.swing.event.ChangeListener()
224     {
225       public void stateChanged(javax.swing.event.ChangeEvent evt)
226       {
227         verticalSliderStateChanged(evt);
228       }
229     });
230 
231     gridBagConstraints = new java.awt.GridBagConstraints();
232     gridBagConstraints.gridx = 0;
233     gridBagConstraints.gridy = 8;
234     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
235     add(verticalSlider, gridBagConstraints);
236 
237     //////////////////
238     // Slope related items here. Slopes are only available for ROUTE_FORK routing style for now.
239     //////////////////
240     // Slider for the minimum length of the segment from the port of the parent node to the first bend of the outgoing edge
241     //////////////////
242     Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
243     JPanel slopeItems = new JPanel(new GridBagLayout());
244     slopeItems.setBorder(BorderFactory.createTitledBorder(border, "Slopes"));
245 
246     minFirstSegmentLabel.setText("Min First Segment Length");
247     gridBagConstraints = new java.awt.GridBagConstraints();
248     gridBagConstraints.gridx = 0;
249     gridBagConstraints.gridy = 0;
250     gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
251     gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
252     slopeItems.add(minFirstSegmentLabel, gridBagConstraints);
253 
254     minFirstSegmentSlider.setMinorTickSpacing(5);
255     minFirstSegmentSlider.setPaintTicks(true);
256     minFirstSegmentSlider.addChangeListener(new javax.swing.event.ChangeListener() {
257       public void stateChanged(javax.swing.event.ChangeEvent evt) {
258         minFirstSegSliderStateChanged(evt);
259       }
260     });
261 
262     gridBagConstraints = new java.awt.GridBagConstraints();
263     gridBagConstraints.gridx = 0;
264     gridBagConstraints.gridy = 1;
265     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
266     slopeItems.add(minFirstSegmentSlider, gridBagConstraints);
267 
268     //////////////////
269     // Slider for the minimum length of the segment from the last bend of an edge to the port of the child node
270     //////////////////
271 
272     minLastSegmentLabel.setText("Min Last Segment Length");
273     gridBagConstraints = new java.awt.GridBagConstraints();
274     gridBagConstraints.gridx = 0;
275     gridBagConstraints.gridy = 2;
276     gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
277     gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
278     slopeItems.add(minLastSegmentLabel, gridBagConstraints);
279 
280     minLastSegmentSlider.setMinorTickSpacing(5);
281     minLastSegmentSlider.setPaintTicks(true);
282     minLastSegmentSlider.addChangeListener(new javax.swing.event.ChangeListener() {
283       public void stateChanged(javax.swing.event.ChangeEvent evt) {
284         minLastSegSliderStateChanged(evt);
285       }
286     });
287 
288     gridBagConstraints = new java.awt.GridBagConstraints();
289     gridBagConstraints.gridx = 0;
290     gridBagConstraints.gridy = 3;
291     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
292     slopeItems.add(minLastSegmentSlider, gridBagConstraints);
293 
294     //////////////////
295     // Slider for the minimum slope
296     //////////////////
297 
298     slopeLabel.setText("Min Slope");
299     gridBagConstraints = new java.awt.GridBagConstraints();
300     gridBagConstraints.gridx = 0;
301     gridBagConstraints.gridy = 4;
302     gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
303     gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
304     slopeItems.add(slopeLabel, gridBagConstraints);
305 
306     slopeSlider.setMinorTickSpacing(5);
307     slopeSlider.setPaintTicks(true);
308     slopeSlider.setPaintLabels(true);
309     Hashtable slopeLabelTable = new Hashtable();
310     slopeLabelTable.put(new Integer(0), new JLabel("0"));
311     slopeLabelTable.put(new Integer(100), new JLabel("1.0"));
312     slopeLabelTable.put(new Integer(200), new JLabel("2.0"));
313     slopeSlider.setLabelTable(slopeLabelTable);
314     slopeSlider.addChangeListener(new javax.swing.event.ChangeListener() {
315       public void stateChanged(javax.swing.event.ChangeEvent evt) {
316         slopeSliderStateChanged(evt);
317       }
318     });
319 
320     gridBagConstraints = new java.awt.GridBagConstraints();
321     gridBagConstraints.gridx = 0;
322     gridBagConstraints.gridy = 5;
323     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
324     slopeItems.add(slopeSlider, gridBagConstraints);
325 
326     //////////////////
327     // Slider for the minimum slope height
328     //////////////////
329 
330     slopeHeightLabel.setText("Min Slope Height");
331     gridBagConstraints = new java.awt.GridBagConstraints();
332     gridBagConstraints.gridx = 0;
333     gridBagConstraints.gridy = 6;
334     gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
335     gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
336     slopeItems.add(slopeHeightLabel, gridBagConstraints);
337 
338     slopeHeightSlider.setMinorTickSpacing(5);
339     slopeHeightSlider.setPaintTicks(true);
340     slopeHeightSlider.addChangeListener(new javax.swing.event.ChangeListener() {
341       public void stateChanged(javax.swing.event.ChangeEvent evt) {
342         slopeHeightSliderStateChanged(evt);
343       }
344     });
345 
346     gridBagConstraints = new java.awt.GridBagConstraints();
347     gridBagConstraints.gridx = 0;
348     gridBagConstraints.gridy = 7;
349     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
350     slopeItems.add(slopeHeightSlider, gridBagConstraints);
351 
352     gridBagConstraints = new java.awt.GridBagConstraints();
353     gridBagConstraints.gridx = 0;
354     gridBagConstraints.gridy = 9;
355     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
356     gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
357     add(slopeItems, gridBagConstraints);
358 
359     // END Slope related items.
360 
361     //////////////////
362     //  Port assignment related items
363     //////////////////
364     //  Slider for the ratio of the port's border gap to port gap
365     //////////////////
366 
367     JPanel portItems = new JPanel(new GridBagLayout());
368     portItems.setBorder(BorderFactory.createTitledBorder(border, "Port Assignment"));
369 
370     //////////////////
371     // A check box that indicates whether or not the ports of a node should be distributed (true) or on the same point
372     //////////////////
373 
374     distributedCheckBox.addActionListener(new ActionListener() {
375       public void actionPerformed(final ActionEvent e) {
376         boolean selected = ((JCheckBox) e.getSource()).isSelected();
377         DefaultNodePlacerConfigPanel.this.ratioLabel.setEnabled(selected);
378         DefaultNodePlacerConfigPanel.this.ratioSlider.setEnabled(selected);
379         assignPortAssignment(selected);
380         layoutPreviewPanel.update();
381         fireChangeListenerStateChanged(new ChangeEvent(DefaultNodePlacerConfigPanel.this));
382       }
383     });
384     gridBagConstraints = new java.awt.GridBagConstraints();
385     gridBagConstraints.gridx = 0;
386     gridBagConstraints.gridy = 0;
387     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
388     gridBagConstraints.insets = new java.awt.Insets(5, 4, 0, 5);
389     portItems.add(distributedCheckBox, gridBagConstraints);
390 
391     ratioLabel.setText("Port Border Gap Ratio");
392     gridBagConstraints = new java.awt.GridBagConstraints();
393     gridBagConstraints.gridx = 0;
394     gridBagConstraints.gridy = 1;
395     gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
396     gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
397     portItems.add(ratioLabel, gridBagConstraints);
398 
399     ratioSlider.setMinorTickSpacing(5);
400     ratioSlider.setPaintTicks(true);
401     ratioSlider.setPaintLabels(true);
402     Hashtable ratioLabelTable = new Hashtable();
403     ratioLabelTable.put(new Integer(0), new JLabel("0"));
404     ratioLabelTable.put(new Integer(50), new JLabel("1:2"));
405     ratioLabelTable.put(new Integer(100), new JLabel("1:1"));
406     ratioLabelTable.put(new Integer(150), new JLabel("3:2"));
407     ratioLabelTable.put(new Integer(200), new JLabel("2:1"));
408     ratioSlider.setLabelTable(ratioLabelTable);
409     ratioSlider.addChangeListener(new javax.swing.event.ChangeListener()
410     {
411       public void stateChanged(javax.swing.event.ChangeEvent evt)
412       {
413         ratioSliderStateChanged(evt);
414       }
415     });
416 
417     gridBagConstraints = new java.awt.GridBagConstraints();
418     gridBagConstraints.gridx = 0;
419     gridBagConstraints.gridy = 2;
420     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
421     portItems.add(ratioSlider, gridBagConstraints);
422 
423     // END port assignment related items
424 
425     gridBagConstraints = new java.awt.GridBagConstraints();
426     gridBagConstraints.gridx = 0;
427     gridBagConstraints.gridy = 10 ;
428     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
429     add(portItems, gridBagConstraints);
430 
431 
432     //////////////////
433     // Root Alignment Slider - Leading, Center, Median, Trailing etc.
434     //////////////////
435 
436     rootAlignmentLabel.setText("Root Alignment");
437     gridBagConstraints = new java.awt.GridBagConstraints();
438     gridBagConstraints.gridx = 0;
439     gridBagConstraints.gridy = 11;
440     gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
441     gridBagConstraints.insets = new java.awt.Insets(7, 0, 0, 0);
442     add(rootAlignmentLabel, gridBagConstraints);
443 
444     alignmentSlider.setMaximum(5);
445     alignmentSlider.setMinorTickSpacing(1);
446     alignmentSlider.setPaintLabels(true);
447     alignmentSlider.setPaintTicks(true);
448     alignmentSlider.setSnapToTicks(true);
449 
450     Hashtable labelTable = new Hashtable();
451     labelTable.put( new Integer( 0 ), new JLabel("Leading") );
452     labelTable.put( new Integer( 3 ), new JLabel("Median") );
453     labelTable.put( new Integer( 5 ), new JLabel("Trailing") );
454     alignmentSlider.setLabelTable( labelTable );
455     alignmentSlider.addChangeListener(new javax.swing.event.ChangeListener()
456     {
457       public void stateChanged(javax.swing.event.ChangeEvent evt)
458       {
459         alignmentSliderStateChanged(evt);
460       }
461     });
462 
463     gridBagConstraints = new java.awt.GridBagConstraints();
464     gridBagConstraints.gridx = 0;
465     gridBagConstraints.gridy = 12;
466     gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
467     add(alignmentSlider, gridBagConstraints);
468 
469     //////////////////
470     // Preview Window
471     //////////////////
472 
473     previewPanel.setLayout(new java.awt.BorderLayout());
474     previewPanel.setBorder(new javax.swing.border.TitledBorder("Preview"));
475     layoutPreviewPanel.setBackground(new java.awt.Color(255, 255, 255));
476     previewPanel.add(layoutPreviewPanel, java.awt.BorderLayout.CENTER);
477 
478     gridBagConstraints = new java.awt.GridBagConstraints();
479     gridBagConstraints.gridx = 0;
480     gridBagConstraints.gridy = 13;
481     gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
482     gridBagConstraints.weightx = 1.0;
483     gridBagConstraints.weighty = 1.0;
484     add(previewPanel, gridBagConstraints);
485 
486   }//GEN-END:initComponents
487 
488   /**
489    * Calculates settings for the placement of children and enables the distribution of the ports.
490    */
491   private void assignPortAssignment(boolean selected){
492     final DefaultPortAssignment dpa = (DefaultPortAssignment) treeLayouter.getDefaultPortAssignment();
493     if (!selected){
494       // center port assignment, no reversion needed.
495       dpa.setMode(DefaultPortAssignment.MODE_NONE);
496       dpa.setReversedPortOrder(false);
497     }
498     else {
499       final int placementSelection = this.placementComboBox.getSelectedIndex();
500       final boolean  leading = this.alignmentSlider.getValue() < 2 || this.alignmentSlider.getValue() == 7; //  center and median are excluded
501       final boolean  trailing = this.alignmentSlider.getValue() > 3 && this.alignmentSlider.getValue() != 7;
502       final boolean rootForking = this.routingStyleComboBox.getSelectedIndex() == 1;
503       if (placementSelection == 0 ){
504         // placement is horizontally downwards. For proper distribution, the relative position of the root to it's children must be checked.
505         if (rootForking){
506           if (leading){
507             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_EAST);
508             dpa.setReversedPortOrder(true);
509           }
510           else if (trailing){
511             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_WEST);
512             dpa.setReversedPortOrder(false);
513           }
514           else { // center or median
515             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_SOUTH);
516             dpa.setReversedPortOrder(false);
517           }
518         }
519         else {
520           dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_SOUTH);
521           dpa.setReversedPortOrder(false);
522         }
523       }
524       else if (placementSelection == 1) {
525         // placement is horizontally upwards. For proper distribution, the relative position of the root to it's children must be checked.
526         if (rootForking) {
527           if (leading) {
528             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_EAST);
529             dpa.setReversedPortOrder(false);
530           } else if (trailing) {
531             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_WEST);
532             dpa.setReversedPortOrder(true);
533           } else { // center or median
534             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_NORTH);
535             dpa.setReversedPortOrder(false);
536           }
537         } else {
538           dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_NORTH);
539           dpa.setReversedPortOrder(false);
540         }
541       } else if (placementSelection == 2) {
542         // placement is vertically left. For proper distribution, the relative position of the root to it's children must be checked.
543         if (rootForking) {
544           if (leading) {
545             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_SOUTH);
546             dpa.setReversedPortOrder(false);
547           } else if (trailing) {
548             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_NORTH);
549             dpa.setReversedPortOrder(true);
550           } else { // center or median
551             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_WEST);
552             dpa.setReversedPortOrder(false);
553           }
554         } else {
555           dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_WEST);
556           dpa.setReversedPortOrder(false);
557         }
558       } else if (placementSelection == 3) {
559         // placement is vertically right. For proper distribution, the relative position of the root to it's children must be checked.
560         if (rootForking) {
561           if (leading) {
562             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_SOUTH);
563             dpa.setReversedPortOrder(true);
564           } else if (trailing) {
565             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_NORTH);
566             dpa.setReversedPortOrder(false);
567           } else { // center or median
568             dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_EAST);
569             dpa.setReversedPortOrder(false);
570           }
571         } else {
572           dpa.setMode(DefaultPortAssignment.MODE_PORT_DISTRIBUTED_EAST);
573           dpa.setReversedPortOrder(false);
574         }
575       }
576     }
577   }
578 
579   private void ratioSliderStateChanged(ChangeEvent evt) //GEN-FIRST:event_ratioSliderStateChanged
580   {//GEN-HEADEREND:event_ratioSliderStateChanged
581     ((DefaultPortAssignment)treeLayouter.getDefaultPortAssignment()).setBorderGapToPortGapRatio(ratioSlider.getValue() * 0.01d);
582     layoutPreviewPanel.update();
583     fireChangeListenerStateChanged(new ChangeEvent(this));
584   }//GEN-LAST:event_ratioSliderStateChanged
585 
586   private void routingStyleComboBoxItemStateChanged(java.awt.event.ItemEvent evt)//GEN-FIRST:event_routingStyleComboBoxItemStateChanged
587   {//GEN-HEADEREND:event_routingStyleComboBoxItemStateChanged
588     if (evt.getStateChange() == ItemEvent.SELECTED){
589       switch (routingStyleComboBox.getSelectedIndex()){
590         case 0:
591           placer.setRoutingStyle(DefaultNodePlacer.ROUTING_FORK);
592           enableSlopePanel(true);
593           break;
594         case 1:
595           placer.setRoutingStyle(DefaultNodePlacer.ROUTING_FORK_AT_ROOT);
596           enableSlopePanel(false);
597           break;
598         case 2:
599           placer.setRoutingStyle(DefaultNodePlacer.ROUTING_POLY_LINE);
600           enableSlopePanel(false);
601           break;
602       }
603       assignPortAssignment(this.distributedCheckBox.isSelected());
604       layoutPreviewPanel.update();
605       fireChangeListenerStateChanged(new ChangeEvent(this));
606     }
607   }//GEN-LAST:event_routingStyleComboBoxItemStateChanged
608 
609   private void verticalSliderStateChanged(javax.swing.event.ChangeEvent evt)//GEN-FIRST:event_verticalSliderStateChanged
610   {//GEN-HEADEREND:event_verticalSliderStateChanged
611     placer.setVerticalDistance(verticalSlider.getValue());
612     layoutPreviewPanel.update();
613     fireChangeListenerStateChanged(new ChangeEvent(this));
614   }//GEN-LAST:event_verticalSliderStateChanged
615 
616   private void horizontalSliderStateChanged(javax.swing.event.ChangeEvent evt)//GEN-FIRST:event_horizontalSliderStateChanged
617   {//GEN-HEADEREND:event_horizontalSliderStateChanged
618     placer.setHorizontalDistance(horizontalSlider.getValue());
619     layoutPreviewPanel.update();
620     fireChangeListenerStateChanged(new ChangeEvent(this));
621   }//GEN-LAST:event_horizontalSliderStateChanged
622 
623   private void minFirstSegSliderStateChanged(javax.swing.event.ChangeEvent evt)//GEN-FIRST:event_minFirstSegSliderStateChanged
624   {//GEN-HEADEREND:minFirstSegSliderStateChanged
625     placer.setMinFirstSegmentLength(minFirstSegmentSlider.getValue());
626     layoutPreviewPanel.update();
627     fireChangeListenerStateChanged(new ChangeEvent(this));
628   }//GEN-LAST:event_minFirstSegSliderStateChanged
629 
630   private void minLastSegSliderStateChanged(javax.swing.event.ChangeEvent evt)//GEN-FIRST:event_minLastSegSliderStateChanged
631   {//GEN-HEADEREND:minLastSegSliderStateChanged
632     placer.setMinLastSegmentLength(minLastSegmentSlider.getValue());
633     layoutPreviewPanel.update();
634     fireChangeListenerStateChanged(new ChangeEvent(this));
635   }//GEN-LAST:event_minlastSegSliderStateChanged
636 
637   private void slopeSliderStateChanged(javax.swing.event.ChangeEvent evt)//GEN-FIRST:event_slopeSliderStateChanged
638   {//GEN-HEADEREND:event_slopeSliderStateChanged
639     placer.setMinSlope(slopeSlider.getValue()*0.01d);
640     layoutPreviewPanel.update();
641     fireChangeListenerStateChanged(new ChangeEvent(this));
642   }//GEN-LAST:event_slopeSliderStateChanged
643 
644   private void slopeHeightSliderStateChanged(javax.swing.event.ChangeEvent evt)//GEN-FIRST:event_slopeHeightSliderStateChanged
645   {//GEN-HEADEREND:event_slopeHeightSliderStateChanged
646     placer.setMinSlopeHeight(slopeHeightSlider.getValue());
647     layoutPreviewPanel.update();
648     fireChangeListenerStateChanged(new ChangeEvent(this));
649   }//GEN-LAST:event_slopeHeightSliderStateChanged
650 
651   private void alignmentSliderStateChanged(javax.swing.event.ChangeEvent evt)//GEN-FIRST:event_alignmentSliderStateChanged
652   {//GEN-HEADEREND:event_alignmentSliderStateChanged
653     placer.setRootAlignment( (byte) alignmentSlider.getValue());
654     assignPortAssignment(this.distributedCheckBox.isSelected());
655     layoutPreviewPanel.update();
656     fireChangeListenerStateChanged(new ChangeEvent(this));
657   }//GEN-LAST:event_alignmentSliderStateChanged
658 
659   private void placementComboBoxItemStateChanged(java.awt.event.ItemEvent evt)//GEN-FIRST:event_placementComboBoxItemStateChanged
660   {//GEN-HEADEREND:event_placementComboBoxItemStateChanged
661     if (evt.getStateChange() == ItemEvent.SELECTED){
662       switch (placementComboBox.getSelectedIndex()){
663         case 0:
664           placer.setChildPlacement(DefaultNodePlacer.PLACEMENT_HORIZONTAL_DOWNWARD);
665           break;
666         case 1:
667           placer.setChildPlacement(DefaultNodePlacer.PLACEMENT_HORIZONTAL_UPWARD);
668           break;
669         case 2:
670           placer.setChildPlacement(DefaultNodePlacer.PLACEMENT_VERTICAL_TO_LEFT);
671           break;
672         case 3:
673           placer.setChildPlacement(DefaultNodePlacer.PLACEMENT_VERTICAL_TO_RIGHT);
674           break;
675       }
676       assignPortAssignment(this.distributedCheckBox.isSelected());
677       layoutPreviewPanel.update();
678       fireChangeListenerStateChanged(new ChangeEvent(this));
679     }
680   }//GEN-LAST:event_placementComboBoxItemStateChanged
681 
682   /**
683    * Enables or disables all slope related items.
684    * @param enabled whether the slope related items should be enabled or not.
685    */
686   private void enableSlopePanel(boolean enabled){
687     this.minFirstSegmentLabel.setEnabled(enabled);
688     this.minFirstSegmentSlider.setEnabled(enabled);
689     this.minLastSegmentLabel.setEnabled(enabled);
690     this.minLastSegmentSlider.setEnabled(enabled);
691     this.slopeLabel.setEnabled(enabled);
692     this.slopeSlider.setEnabled(enabled);
693     this.slopeHeightLabel.setEnabled(enabled);
694     this.slopeHeightSlider.setEnabled(enabled);
695   }
696 
697   /**
698    * Updates the current model to the values of the current {@link NodePlacer}.
699    */
700   public void updateFromPlacer(){
701     switch (placer.getChildPlacement()){
702       case DefaultNodePlacer.PLACEMENT_HORIZONTAL_DOWNWARD:
703         placementComboBox.setSelectedIndex(0);
704         break;
705       case DefaultNodePlacer.PLACEMENT_HORIZONTAL_UPWARD:
706         placementComboBox.setSelectedIndex(1);
707         break;
708       case DefaultNodePlacer.PLACEMENT_VERTICAL_TO_LEFT:
709         placementComboBox.setSelectedIndex(2);
710         break;
711       case DefaultNodePlacer.PLACEMENT_VERTICAL_TO_RIGHT:
712         placementComboBox.setSelectedIndex(3);
713         break;
714     }
715     switch (placer.getRoutingStyle()){
716       case DefaultNodePlacer.ROUTING_FORK:
717         routingStyleComboBox.setSelectedIndex(0);
718         break;
719       case DefaultNodePlacer.ROUTING_FORK_AT_ROOT:
720         routingStyleComboBox.setSelectedIndex(1);
721         break;
722       case DefaultNodePlacer.ROUTING_POLY_LINE:
723         routingStyleComboBox.setSelectedIndex(2);
724         break;
725     }
726     alignmentSlider.setValue(placer.getRootAlignment());
727     horizontalSlider.setValue((int)placer.getHorizontalDistance());
728     verticalSlider.setValue((int)placer.getVerticalDistance());
729     minFirstSegmentSlider.setValue((int) placer.getMinFirstSegmentLength());
730     minLastSegmentSlider.setValue((int) placer.getMinLastSegmentLength());
731     slopeSlider.setValue((int) (placer.getMinSlope() * 100));
732     slopeHeightSlider.setValue((int) (placer.getMinSlopeHeight()));
733   }
734 
735   /**
736    * Updates the current model to the values of the current {@link DefaultPortAssignment}.
737    */
738   public void updateFromPort(){
739     DefaultPortAssignment dpa = (DefaultPortAssignment) treeLayouter.getDefaultPortAssignment();
740     boolean distributed = dpa.getMode() != DefaultPortAssignment.MODE_NONE;
741     distributedCheckBox.setSelected(distributed);
742     ratioLabel.setEnabled(distributed);
743     ratioSlider.setEnabled(distributed);
744     ratioSlider.setValue((int) (dpa.getBorderGapToPortGapRatio()*100));
745   }
746 
747   /**
748    * Updates the current node placer with the values of the given node placer.
749    * Also invokes <code>updateFromPlacer()</code>.
750    * @param fromPlacer the {@link NodePlacer} to get the new values from.
751    */
752   public void adoptPlacerValues(NodePlacer fromPlacer){
753     if (fromPlacer instanceof DefaultNodePlacer){
754       DefaultNodePlacer p = (DefaultNodePlacer) fromPlacer;
755       this.placer.setRoutingStyle(p.getRoutingStyle());
756       this.placer.setChildPlacement(p.getChildPlacement());
757       this.placer.setVerticalDistance(p.getVerticalDistance());
758       this.placer.setHorizontalDistance(p.getHorizontalDistance());
759       this.placer.setRootAlignment(p.getRootAlignment());
760       this.placer.setMinFirstSegmentLength(p.getMinFirstSegmentLength());
761       this.placer.setMinLastSegmentLength(p.getMinLastSegmentLength());
762       this.placer.setMinSlope(p.getMinSlope());
763       this.placer.setMinSlopeHeight(p.getMinSlopeHeight());
764       updateFromPlacer();
765     }
766   }
767 
768   /**
769    * Updates the current port assignment with the values of the given port assignment.
770    * Also invokes <code>updateFromPort()</code>.
771    * @param fromPort the {@link DefaultPortAssignment} to get the new values from.
772    */
773   public void adoptPortValues(PortAssignment fromPort){
774     if (fromPort instanceof DefaultPortAssignment){
775       DefaultPortAssignment p = (DefaultPortAssignment) fromPort;
776       DefaultPortAssignment to = (DefaultPortAssignment) this.treeLayouter.getDefaultPortAssignment();
777       to.setMode(p.getMode());
778       to.setBorderGapToPortGapRatio(p.getBorderGapToPortGapRatio());
779       to.setReversedPortOrder(p.isReversedPortOrder());
780       updateFromPort();
781     }
782   }
783 
784   /**
785    * Creates a new clone of the placer.
786    * @return a new instance of the <code>NodePlacer</code> with the same settings.
787    */
788   public NodePlacer createPlacerCopy(){
789     return (NodePlacer) placer.clone();
790   }
791 
792   /**
793    * Creates a new clone of the DefaultPortAssignment.
794    * @return a new instance of the <code>DefaultPortAssignment</code> with the same settings.
795    */
796   public DefaultPortAssignment createPortAssignmentCopy(){
797     DefaultPortAssignment dpa = (DefaultPortAssignment)this.treeLayouter.getDefaultPortAssignment();
798     DefaultPortAssignment copy = new DefaultPortAssignment (dpa.getMode(), dpa.getBorderGapToPortGapRatio());
799     copy.setReversedPortOrder(dpa.isReversedPortOrder());
800     return copy;
801   }
802   
803   /**
804    * Registers ChangeListener to receive events.
805    * @param listener The listener to register.
806    */
807   public synchronized void addChangeListener(javax.swing.event.ChangeListener listener)
808   {
809     if (changeListenerList == null )
810     {
811       changeListenerList = new java.util.ArrayList();
812     }
813     changeListenerList.add(listener);
814   }
815   
816   /**
817    * Removes ChangeListener from the list of listeners.
818    * @param listener The listener to remove.
819    */
820   public synchronized void removeChangeListener(javax.swing.event.ChangeListener listener)
821   {
822     if (changeListenerList != null )
823     {
824       changeListenerList.remove(listener);
825     }
826   }
827   
828   /**
829    * Notifies all registered listeners about the event.
830    *
831    * @param event The event to be fired
832    */
833   private void fireChangeListenerStateChanged(javax.swing.event.ChangeEvent event)
834   {
835     java.util.ArrayList list;
836     synchronized (this)
837     {
838       if (changeListenerList == null) return;
839       list = (java.util.ArrayList)changeListenerList.clone();
840     }
841     for (int i = 0; i < list.size(); i++)
842     {
843       ((javax.swing.event.ChangeListener)list.get(i)).stateChanged(event);
844     }
845   }
846   
847   // Variables declaration - do not modify//GEN-BEGIN:variables
848   private javax.swing.JSlider alignmentSlider;
849   private javax.swing.JLabel childPlacementLabel;
850   private javax.swing.JLabel hSpacingLabel;
851   private javax.swing.JSlider horizontalSlider;
852   private demo.layout.withoutview.LayoutPreviewPanel layoutPreviewPanel;
853   private javax.swing.JComboBox placementComboBox;
854   private javax.swing.JPanel previewPanel;
855   private javax.swing.JLabel rootAlignmentLabel;
856   private javax.swing.JComboBox routingStyleComboBox;
857   private javax.swing.JLabel routingStyleLabel;
858   private javax.swing.JLabel vSpacingLabel;
859   private javax.swing.JSlider verticalSlider;
860   private javax.swing.JSlider ratioSlider;
861   private javax.swing.JLabel ratioLabel;
862   private javax.swing.JSlider minFirstSegmentSlider;
863   private javax.swing.JSlider minLastSegmentSlider;
864   private javax.swing.JLabel minFirstSegmentLabel;
865   private javax.swing.JLabel minLastSegmentLabel;
866   private javax.swing.JSlider slopeSlider;
867   private javax.swing.JLabel slopeLabel;
868   private javax.swing.JSlider slopeHeightSlider;
869   private javax.swing.JLabel slopeHeightLabel;
870   private JCheckBox distributedCheckBox;
871   // End of variables declaration//GEN-END:variables
872   /**
873    * Utility field holding list of ChangeListeners.
874    */
875   private transient java.util.ArrayList changeListenerList;  
876    
877 }
878