1
28 package demo.layout.hierarchic;
29
30 import demo.view.DemoBase;
31 import demo.view.DemoDefaults;
32
33 import y.base.DataMap;
34 import y.base.Node;
35 import y.base.NodeCursor;
36 import y.base.NodeList;
37 import y.base.NodeMap;
38 import y.layout.Layouter;
39 import y.layout.hierarchic.IncrementalHierarchicLayouter;
40 import y.layout.hierarchic.incremental.IncrementalHintsFactory;
41 import y.layout.hierarchic.incremental.NodeLayoutDescriptor;
42 import y.layout.hierarchic.incremental.RoutingStyle;
43 import y.layout.hierarchic.incremental.SimplexNodePlacer;
44 import y.layout.hierarchic.incremental.SwimLaneDescriptor;
45 import y.util.Maps;
46 import y.view.Arrow;
47 import y.view.EdgeRealizer;
48 import y.view.EditMode;
49 import y.view.Graph2D;
50 import y.view.PopupMode;
51
52 import javax.swing.AbstractAction;
53 import javax.swing.JMenu;
54 import javax.swing.JPopupMenu;
55 import javax.swing.JToolBar;
56 import java.awt.Cursor;
57 import java.awt.EventQueue;
58 import java.awt.event.ActionEvent;
59 import java.util.Locale;
60
61
85 public class SimpleSwimlaneLayouterDemo extends DemoBase {
86
87 private DataMap hintMap;
88
89
90 private NodeMap swimLaneMap;
91
92
93 private IncrementalHierarchicLayouter hierarchicLayouter;
94 private IncrementalHintsFactory hintsFactory;
95
96
97 private SwimlaneDrawable swimLaneDrawable;
98
99 public SimpleSwimlaneLayouterDemo() {
100 this (null);
101 }
102
103 public SimpleSwimlaneLayouterDemo(String helpFilePath) {
104 final Graph2D graph = view.getGraph2D();
105 EdgeRealizer defaultER = graph.getDefaultEdgeRealizer();
106 defaultER.setArrow(Arrow.STANDARD);
107
108 hintMap = Maps.createHashedDataMap();
110 swimLaneMap = graph.createNodeMap();
111 graph.addDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY, hintMap);
112 graph.addDataProvider(IncrementalHierarchicLayouter.SWIMLANE_DESCRIPTOR_DPKEY, swimLaneMap);
113
114 hierarchicLayouter = new IncrementalHierarchicLayouter();
116
117 hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumFirstSegmentLength(15);
119 hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumLastSegmentLength(20);
120 hierarchicLayouter.getEdgeLayoutDescriptor().setRoutingStyle(new RoutingStyle(RoutingStyle.EDGE_STYLE_OCTILINEAR));
121 hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumDistance(10.0d);
122
123 hierarchicLayouter.getNodeLayoutDescriptor().setLayerAlignment(0.5d);
124 hierarchicLayouter.setMinimumLayerDistance(30.0d);
125 hierarchicLayouter.getNodeLayoutDescriptor().setNodeLabelMode(
126 NodeLayoutDescriptor.NODE_LABEL_MODE_CONSIDER_FOR_DRAWING);
127 hierarchicLayouter.setConsiderNodeLabelsEnabled(true);
128 hierarchicLayouter.setBackloopRoutingEnabled(true);
129
130 ((SimplexNodePlacer) hierarchicLayouter.getNodePlacer()).setBaryCenterModeEnabled(false);
133
134 hintsFactory = hierarchicLayouter.createIncrementalHintsFactory();
136
137 hierarchicLayouter.setComponentLayouterEnabled(false);
139
140 view.addBackgroundDrawable(swimLaneDrawable = new SwimlaneDrawable(view.getGraph2D(), swimLaneMap));
142
143 loadGraph("resource/swimlane.graphml");
144 DemoDefaults.applyRealizerDefaults(graph);
145
146 addHelpPane(helpFilePath);
147
148 calcLayout(hierarchicLayouter);
149 }
150
151 protected void configureDefaultRealizers() {
152 super.configureDefaultRealizers();
153 view.getGraph2D().getDefaultNodeRealizer().setSize(30, 30);
154 }
155
156 class LayoutFromSketchAction extends AbstractAction {
157 LayoutFromSketchAction() {
158 super("Layout From Sketch", SHARED_LAYOUT_ICON);
159 }
160
161 public void actionPerformed(ActionEvent ev) {
162 calcIncrementalLayout(new NodeList().nodes());
163 }
164 }
165
166 class LayoutIncrementallyAction extends AbstractAction {
167 LayoutIncrementallyAction() {
168 super("Layout Incrementally", SHARED_LAYOUT_ICON);
169 }
170
171 public void actionPerformed(ActionEvent ev) {
172 calcIncrementalLayout(view.getGraph2D().selectedNodes());
173 }
174 }
175
176 class LayoutAction extends AbstractAction {
177 LayoutAction() {
178 super("Layout", SHARED_LAYOUT_ICON);
179 }
180
181 public void actionPerformed(ActionEvent ev) {
182 calcFreshLayout();
183 }
184 }
185
186 protected JToolBar createToolBar() {
187 JToolBar tb = super.createToolBar();
188 tb.addSeparator();
189 tb.add(createActionControl(new LayoutAction()));
190 tb.add(createActionControl(new LayoutFromSketchAction()));
191 tb.add(createActionControl(new LayoutIncrementallyAction()));
192 return tb;
193 }
194
195 public void calcFreshLayout() {
196 hierarchicLayouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH);
197 calcLayout(hierarchicLayouter);
198 }
199
200 public void updateSwimLanes() {
201 for (NodeCursor nc = view.getGraph2D().nodes(); nc.ok(); nc.next()) {
202 SwimLaneDescriptor sld = new SwimLaneDescriptor(view.getGraph2D().getLabelText(nc.node()));
203 sld.setLeftLaneInset(5);
204 sld.setRightLaneInset(5);
205 sld.setMinimumLaneWidth(100);
206 swimLaneMap.set(nc.node(), sld);
207 }
208 }
209
210 public void calcIncrementalLayout(NodeCursor incrementalNodes) {
211 try {
212 for (incrementalNodes.toFirst(); incrementalNodes.ok(); incrementalNodes.next()) {
214 hintMap.set(incrementalNodes.node(), hintsFactory.createLayerIncrementallyHint(incrementalNodes.node()));
215 }
216 hierarchicLayouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_INCREMENTAL);
218 calcLayout(hierarchicLayouter);
220 } finally {
221 for (incrementalNodes.toFirst(); incrementalNodes.ok(); incrementalNodes.next()) {
223 hintMap.set(incrementalNodes.node(), null);
224 }
225 }
226 }
227
228 protected void calcLayout(Layouter layouter) {
229 Graph2D graph = view.getGraph2D();
230 if (!graph.isEmpty()) {
231 Cursor oldCursor = view.getViewCursor();
232 try {
233 updateSwimLanes();
235 view.applyLayoutAnimated(layouter);
236 } finally {
237 view.setViewCursor(oldCursor);
238 }
239 }
240 swimLaneDrawable.updateLanes();
241 view.fitContent();
242 view.updateView();
243 }
244
245 protected EditMode createEditMode() {
246 EditMode editMode = super.createEditMode();
247 editMode.setPopupMode(new PopupMode() {
248 public JPopupMenu getNodePopup(Node v) {
249 return createPopup();
250 }
251
252 private JPopupMenu createPopup() {
253 JPopupMenu menu = new JPopupMenu();
254 JMenu laneMenu = new JMenu("Move to lane");
255 menu.add(laneMenu);
256 laneMenu.add(new MoveSelectedNodesToLayerAction(1));
257 laneMenu.add(new MoveSelectedNodesToLayerAction(2));
258 laneMenu.add(new MoveSelectedNodesToLayerAction(3));
259 laneMenu.add(new MoveSelectedNodesToLayerAction(4));
260 laneMenu.add(new MoveSelectedNodesToLayerAction(5));
261 laneMenu.add(new MoveSelectedNodesToLayerAction(6));
262 return menu;
263 }
264
265 public JPopupMenu getSelectionPopup(double x, double y) {
266 return createPopup();
267 }
268 });
269 return editMode;
270 }
271
272
273
276 public static void main(String[] args) {
277 EventQueue.invokeLater(new Runnable() {
278 public void run() {
279 Locale.setDefault(Locale.ENGLISH);
280 initLnF();
281 (new SimpleSwimlaneLayouterDemo("resource/simpleswimlanelayouterdemohelp.html")).start("Simple Swimlane Layout Demo");
282 }
283 });
284 }
285
286 private class MoveSelectedNodesToLayerAction extends AbstractAction {
287 private int layer;
288
289 MoveSelectedNodesToLayerAction(int layer) {
290 super(String.valueOf(layer));
291 this.layer = layer;
292 }
293
294 public void actionPerformed(ActionEvent e) {
295 for (NodeCursor nodeCursor = view.getGraph2D().selectedNodes(); nodeCursor.ok(); nodeCursor.next()) {
296 Node node = nodeCursor.node();
297 view.getGraph2D().setLabelText(node, String.valueOf(layer));
298 }
299 calcIncrementalLayout(view.getGraph2D().selectedNodes());
300 }
301 }
302 }