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.component;
29  
30  import demo.view.DemoBase;
31  import y.layout.ComponentLayouter;
32  import y.view.Graph2DLayoutExecutor;
33  import y.view.ShapeNodeRealizer;
34  
35  import javax.swing.AbstractAction;
36  import javax.swing.JComboBox;
37  import javax.swing.JComponent;
38  import javax.swing.JLabel;
39  import javax.swing.JMenu;
40  import javax.swing.JMenuBar;
41  import javax.swing.JSlider;
42  import javax.swing.JToolBar;
43  import javax.swing.SwingConstants;
44  import javax.swing.event.ChangeEvent;
45  import javax.swing.event.ChangeListener;
46  import java.awt.Color;
47  import java.awt.Component;
48  import java.awt.Dimension;
49  import java.awt.EventQueue;
50  import java.awt.event.ActionEvent;
51  import java.awt.event.ActionListener;
52  import java.awt.event.ComponentAdapter;
53  import java.awt.event.ComponentEvent;
54  import java.net.URL;
55  import java.util.Locale;
56  
57  /**
58   * The {@link y.layout.ComponentLayouter} arranges the connected components of a graph. This demo shows how the
59   * components can be arranged using different arrangement styles provided by the <code>ComponentLayouter</code>.
60   */
61  public class ComponentLayouterDemo extends DemoBase {
62    private byte style;
63    private int spacing;
64  
65    /**
66     * Initializes a new instance of the demo and loads a sample graph.
67     */
68    public ComponentLayouterDemo() {
69      this(null);
70    }
71  
72    /**
73     * Initializes a new instance of the demo, adds a help pane for the specified file and loads a sample graph.
74     */
75    public ComponentLayouterDemo(final String helpFilePath) {
76      addHelpPane(helpFilePath);
77      loadGraph("resource/graphs_sample.graphml");
78    }
79  
80    /**
81     * Registers view actions and adds a component resize handler.
82     */
83    protected void registerViewActions() {
84      super.registerViewActions();
85      view.addComponentListener(new ComponentAdapter() {
86        public void componentResized(ComponentEvent e) {
87          layout();
88        }
89      });
90    }
91  
92    /**
93     * Creates and adds a pane with help text.
94     */
95    protected JComponent createHelpPane(URL helpURL) {
96      final JComponent helpPane = super.createHelpPane(helpURL);
97      helpPane.setPreferredSize(new Dimension(300, 250));
98      return helpPane;
99    }
100 
101   /**
102    * Sets the default node realizer to <code>ShapeNodeRealizer</code>.
103    */
104   protected void configureDefaultRealizers() {
105     final ShapeNodeRealizer nr = new ShapeNodeRealizer(ShapeNodeRealizer.RECT);
106     nr.setFillColor(Color.ORANGE);
107     nr.removeLabel(0);
108     view.getGraph2D().setDefaultNodeRealizer(nr);
109   }
110 
111   /**
112    * Creates a toolbar for configuring and running the <code>ComponentLayouter</code>.
113    */
114   protected JToolBar createToolBar() {
115     final JToolBar bar = super.createToolBar();
116     bar.addSeparator();
117     bar.add(createActionControl(new AbstractAction("Layout", SHARED_LAYOUT_ICON) {
118       public void actionPerformed(ActionEvent e) {
119         layout();
120       }
121     }));
122     bar.addSeparator();
123     bar.add(new JLabel(" Style: "));
124     bar.add(createStyleComboBox());
125     bar.add(new JLabel(" Spacing: "));
126     bar.add(createSpacingSlider());
127     return bar;
128   }
129 
130   /**
131    * Creates a combo box for choosing the component arrangement strategy.
132    */
133   private Component createStyleComboBox() {
134     final JComboBox comboBox = new JComboBox(new Object[]{
135         "Multiple Rows",
136         "Single Row",
137         "Single Column",
138         "Packed Rectangle",
139         "Compact Rectangle",
140         "Packed Circle",
141         "Compact Circle",
142         "Nested Rows",
143         "Compact Nested Rows",
144         "Width Constrained Nested Rows",
145         "Height Constrained Nested Rows",
146         "Width Constrained Compact Nested Rows",
147         "Height Constrained Compact Nested Rows"});
148     final byte[] styles = new byte[]{
149         ComponentLayouter.STYLE_ROWS,
150         ComponentLayouter.STYLE_SINGLE_ROW,
151         ComponentLayouter.STYLE_SINGLE_COLUMN,
152         ComponentLayouter.STYLE_PACKED_RECTANGLE,
153         ComponentLayouter.STYLE_PACKED_COMPACT_RECTANGLE,
154         ComponentLayouter.STYLE_PACKED_CIRCLE,
155         ComponentLayouter.STYLE_PACKED_COMPACT_CIRCLE,
156         ComponentLayouter.STYLE_MULTI_ROWS,
157         ComponentLayouter.STYLE_MULTI_ROWS_COMPACT,
158         ComponentLayouter.STYLE_MULTI_ROWS_WIDTH_CONSTRAINED,
159         ComponentLayouter.STYLE_MULTI_ROWS_HEIGHT_CONSTRAINED,
160         ComponentLayouter.STYLE_MULTI_ROWS_WIDTH_CONSTRAINED_COMPACT,
161         ComponentLayouter.STYLE_MULTI_ROWS_HEIGHT_CONSTRAINED_COMPACT};
162     comboBox.setMaximumSize(comboBox.getPreferredSize());
163     comboBox.addActionListener(new ActionListener() {
164       public void actionPerformed(ActionEvent e) {
165         style = styles[comboBox.getSelectedIndex()];
166         layout();
167       }
168     });
169     style = styles[0];
170     return comboBox;
171   }
172 
173   /**
174    * Creates a slider for choosing the spacing between the components.
175    */
176   private Component createSpacingSlider() {
177     spacing = 10;
178     final JSlider slider = new JSlider(SwingConstants.HORIZONTAL, 10, 100, spacing);
179     slider.setMaximumSize(new Dimension(200, 100));
180     slider.addChangeListener(new ChangeListener() {
181       public void stateChanged(ChangeEvent e) {
182         if (!slider.getValueIsAdjusting()) {
183           spacing = slider.getValue();
184           layout();
185         }
186       }
187     });
188     return slider;
189   }
190 
191   /**
192    * Creates the default menu bar and adds an additional menu of examples graphs.
193    */
194   protected JMenuBar createMenuBar() {
195     final JMenuBar menuBar = super.createMenuBar();
196     JMenu menu = new JMenu("Sample Graphs");
197     menuBar.add(menu);
198     menu.add(new AbstractAction("Nodes") {
199       public void actionPerformed(ActionEvent e) {
200         loadGraph("resource/nodes_sample.graphml");
201         layout();
202       }
203     });
204     menu.add(new AbstractAction("Graphs") {
205       public void actionPerformed(ActionEvent e) {
206         loadGraph("resource/graphs_sample.graphml");
207         layout();
208       }
209     });
210     return menuBar;
211   }
212 
213   /**
214    * Runs the <code>ComponentLayouter</code>.
215    */
216   private void layout() {
217     final ComponentLayouter layouter = new ComponentLayouter();
218     layouter.setStyle(style);
219     layouter.setComponentSpacing(spacing);
220     layouter.setPreferredLayoutSize(view.getWidth(), view.getHeight());
221     new Graph2DLayoutExecutor().doLayout(view, layouter);
222   }
223 
224   public static void main(String[] args) {
225     EventQueue.invokeLater(new Runnable() {
226       public void run() {
227         Locale.setDefault(Locale.ENGLISH);
228         initLnF();
229         new ComponentLayouterDemo("resource/componentlayouterhelp.html").start("Component Layouter Demo");
230       }
231     });
232   }
233 }
234