1
14 package demo.layout;
15
16 import demo.view.DemoBase;
17 import demo.view.DemoDefaults;
18 import y.base.Node;
19 import y.layout.BufferedLayouter;
20 import y.layout.Layouter;
21 import y.layout.organic.SmartOrganicLayouter;
22 import y.layout.hierarchic.IncrementalHierarchicLayouter;
23 import y.layout.orthogonal.OrthogonalLayouter;
24 import y.layout.random.RandomLayouter;
25 import y.view.Graph2D;
26 import y.view.Graph2DLayoutExecutor;
27
28 import javax.swing.AbstractAction;
29 import javax.swing.Action;
30 import javax.swing.JToolBar;
31 import javax.swing.Box;
32 import javax.swing.JLabel;
33 import javax.swing.JButton;
34 import javax.swing.JDialog;
35 import javax.swing.JOptionPane;
36 import javax.swing.BorderFactory;
37 import javax.swing.SwingUtilities;
38 import javax.swing.JRootPane;
39 import javax.swing.JPanel;
40 import javax.swing.JProgressBar;
41 import javax.swing.JComboBox;
42 import java.awt.event.ActionEvent;
43 import java.awt.BorderLayout;
44 import java.awt.Dimension;
45 import java.awt.EventQueue;
46 import java.util.Locale;
47 import java.util.Random;
48
49
55 public class Graph2DLayoutExecutorDemo extends DemoBase
56 {
57 private JLabel statusLabel;
59 private JProgressBar progressBar = new JProgressBar();
61
62 private JComboBox layoutExecutionTypeBox;
64
65 private JComboBox layouterBox;
67
68 public Graph2DLayoutExecutorDemo() {
69 buildGraph( view.getGraph2D() );
71
72 view.setViewPoint2D(-200.0, -200.0);
73 }
74
75 protected void configureDefaultRealizers() {
76 DemoDefaults.registerDefaultNodeConfiguration(false);
79 DemoDefaults.configureDefaultRealizers(view);
80 }
81
82
85 public void addContentTo(JRootPane rootPane) {
86 this.statusLabel = new JLabel("Status");
87 final Dimension minimumSize = this.statusLabel.getMinimumSize();
88 this.statusLabel.setMinimumSize(new Dimension(Math.max(200, minimumSize.width), minimumSize.height));
89 final JPanel panel = new JPanel();
90 panel.add(this.statusLabel, BorderLayout.LINE_START);
91 this.progressBar.setMaximum(100);
92 this.progressBar.setMinimum(0);
93 this.progressBar.setValue(0);
94 panel.add(progressBar, BorderLayout.CENTER);
95 getContentPane().add(panel, BorderLayout.SOUTH);
96 super.addContentTo(rootPane);
97 }
98
99
100 void buildGraph(Graph2D graph) {
101 graph.clear();
102 Node[] nodes = new Node[400];
103 for(int i = 0; i < nodes.length; i++)
104 {
105 nodes[i] = graph.createNode();
106 graph.getRealizer(nodes[i]).setLabelText(String.valueOf(i));
107 }
108 Random random = new Random(0L);
109 for ( int i = 0; i < nodes.length; i++ ) {
110
111 int edgeCount;
112
113 if (random.nextInt(10) == 0) {
114 edgeCount = 4 + random.nextInt(5);
115 } else {
116 edgeCount = random.nextInt(3);
117 }
118
119 for ( int j = 0; j < edgeCount; j++ ) {
120 graph.createEdge( nodes[ i ], nodes[ random.nextInt(nodes.length) ] );
121 }
122 }
123
124 (new BufferedLayouter(new RandomLayouter())).doLayout(graph);
125 }
126
127
130 protected JToolBar createToolBar() {
131 final Action layoutAction = new AbstractAction(
132 "Layout", SHARED_LAYOUT_ICON) {
133 public void actionPerformed(ActionEvent e) {
134 applyLayout();
135 }
136 };
137
138 layouterBox = new JComboBox(new Object[]{"Hierarchic", "Organic", "Orthogonal"});
140 layouterBox.setMaximumSize(layouterBox.getPreferredSize());
141 layouterBox.setSelectedIndex(0);
142
143 layoutExecutionTypeBox = new JComboBox(
145 new Object[]{"Animated", "AnimatedThreaded", "Buffered", "Threaded", "Unbuffered", "AnimatedInOwnThread"});
146 layoutExecutionTypeBox.setMaximumSize(layoutExecutionTypeBox.getPreferredSize());
147 layoutExecutionTypeBox.setSelectedIndex(1);
148
149 final JToolBar toolBar = super.createToolBar();
150 toolBar.addSeparator();
151 toolBar.add(createActionControl(layoutAction));
152 toolBar.addSeparator(TOOLBAR_SMALL_SEPARATOR);
153 toolBar.add(layouterBox);
154 toolBar.addSeparator(TOOLBAR_SMALL_SEPARATOR);
155 toolBar.add(layoutExecutionTypeBox);
156
157 return toolBar;
158 }
159
160
163 void applyLayout() {
164 Layouter layouter = createLayouter();
165 switch (layoutExecutionTypeBox.getSelectedIndex()) {
166 case 0:
167 applyLayoutAnimated(layouter);
168 break;
169 case 1:
170 applyLayoutAnimatedThreaded(layouter);
171 break;
172 case 2:
173 applyLayoutBuffered(layouter);
174 break;
175 case 3:
176 applyLayoutThreaded(layouter);
177 break;
178 case 4:
179 applyLayoutUnbuffered(layouter);
180 break;
181 case 5:
182 applyLayoutAnimatedInOwnThread(layouter);
183 break;
184 }
185 }
186
187
190 Layouter createLayouter() {
191 switch (layouterBox.getSelectedIndex()) {
192 default:
193 case 0:
194 return new IncrementalHierarchicLayouter();
195 case 1:
196 final SmartOrganicLayouter organicLayouter = new SmartOrganicLayouter();
197 organicLayouter.setQualityTimeRatio(1.0);
198 organicLayouter.setMaximumDuration(2L * 60L * 1000L);
199 return organicLayouter;
200 case 2:
201 return new OrthogonalLayouter();
202 }
203 }
204
205
211 void applyLayoutAnimatedThreaded(final Layouter layouter) {
212 this.progressBar.setIndeterminate(true);
213 final Graph2DLayoutExecutor layoutExecutor = new Graph2DLayoutExecutor(Graph2DLayoutExecutor.ANIMATED_THREADED);
214 layoutExecutor.getLayoutMorpher().setPreferredDuration(3000L);
216 layoutExecutor.getLayoutMorpher().setEasedExecution(true);
217 layoutExecutor.getLayoutMorpher().setSmoothViewTransform(true);
218 layoutExecutor.setLockingView(true);
220
221 final JDialog dialog = new JDialog(JOptionPane.getRootFrame(), "");
222
223 final Graph2DLayoutExecutor.LayoutThreadHandle handle = layoutExecutor.doLayout(view, layouter, new Runnable() {
226 public void run() {
227 dialog.dispose();
228 progressBar.setIndeterminate(false);
229 statusLabel.setText("Layout Done");
230 }
231 }, new Graph2DLayoutExecutor.ExceptionListener() {
232 public void exceptionHappened(Throwable t) {
233 t.printStackTrace(System.err);
235 statusLabel.setText("Exception Happened.");
236 }
237 });
238
239 this.statusLabel.setText("Layout is running");
241
242 final Box box = Box.createVerticalBox();
243 box.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
244 final JLabel label = new JLabel("Layout Running [" + layouter.getClass().getName() + "].");
245 box.add(label);
246 box.add(Box.createVerticalStrut(12));
247 box.add(new JButton(new AbstractAction("Cancel") {
248 private boolean canceled;
249 public void actionPerformed(ActionEvent e) {
250 if (!canceled) {
252 handle.cancel();
253 statusLabel.setText("Cancelling");
254 label.setText("Canceled Thread.[" + layouter.getClass().getName() + "].");
255 ((JButton)e.getSource()).setText("Kill");
256 canceled = true;
257 } else {
258 handle.getThread().stop();
261 setEnabled(false);
262 statusLabel.setText("Killed");
263 }
264 }
265 }));
266 dialog.getContentPane().add(box);
267 dialog.setLocationRelativeTo(view);
268 dialog.pack();
269
270 if (handle.isRunning()) {
271 dialog.setVisible(true);
272 }
273 }
274
275
279 void applyLayoutBuffered(final Layouter layouter){
280 final Graph2DLayoutExecutor layoutExecutor = new Graph2DLayoutExecutor(Graph2DLayoutExecutor.BUFFERED);
281 layoutExecutor.doLayout(view, layouter);
282 }
283
284
289 void applyLayoutAnimated(final Layouter layouter){
290 statusLabel.setText("Starting Animated Blocking Layout");
292 progressBar.setIndeterminate(true);
293 try {
294 final Graph2DLayoutExecutor layoutExecutor = new Graph2DLayoutExecutor(Graph2DLayoutExecutor.ANIMATED);
295 layoutExecutor.doLayout(view, layouter);
296 } finally {
297 progressBar.setIndeterminate(false);
298 statusLabel.setText("Animated Blocking Layout Done.");
299 }
300 }
301
302
307 void applyLayoutAnimatedInOwnThread(final Layouter layouter){
308 statusLabel.setText("Starting own layout thread.");
309 progressBar.setIndeterminate(true);
310 final Graph2DLayoutExecutor layoutExecutor = new Graph2DLayoutExecutor(Graph2DLayoutExecutor.ANIMATED);
311 new Thread(new Runnable() {
312 public void run() {
313 try {
314 layoutExecutor.doLayout(view, layouter);
315 } finally {
316 SwingUtilities.invokeLater(new Runnable() {
317 public void run() {
318 statusLabel.setText("Layout Thread Finished.");
319 progressBar.setIndeterminate(false);
320 }
321 });
322 }
323 }
324 }).start();
325 }
326
327
332 void applyLayoutThreaded(final Layouter layouter){
333 statusLabel.setText("Starting threaded layout");
334 progressBar.setIndeterminate(true);
335 final Graph2DLayoutExecutor layoutExecutor = new Graph2DLayoutExecutor(Graph2DLayoutExecutor.THREADED);
336 layoutExecutor.doLayout(view, layouter, new Runnable() {
337 public void run() {
338 statusLabel.setText("Layout Returned");
339 progressBar.setIndeterminate(false);
340 }
341 }, null);
342 statusLabel.setText("Return from doLayout()");
343 }
344
345 void applyLayoutUnbuffered(final Layouter layouter) {
346 final Graph2DLayoutExecutor layoutExecutor = new Graph2DLayoutExecutor(Graph2DLayoutExecutor.UNBUFFERED);
347 layoutExecutor.doLayout(view, layouter);
348 }
349
350 public static void main(String[] args) {
351 EventQueue.invokeLater(new Runnable() {
352 public void run() {
353 Locale.setDefault(Locale.ENGLISH);
354 initLnF();
355 (new Graph2DLayoutExecutorDemo()).start();
356 }
357 });
358 }
359 }