1
14 package demo.layout.hierarchic;
15
16 import demo.view.DemoBase;
17 import demo.view.DemoDefaults;
18
19 import y.base.DataMap;
20 import y.base.Node;
21 import y.base.NodeCursor;
22 import y.base.NodeList;
23 import y.base.NodeMap;
24 import y.layout.Layouter;
25 import y.layout.hierarchic.IncrementalHierarchicLayouter;
26 import y.layout.hierarchic.incremental.IncrementalHintsFactory;
27 import y.layout.hierarchic.incremental.NodeLayoutDescriptor;
28 import y.layout.hierarchic.incremental.SimplexNodePlacer;
29 import y.layout.hierarchic.incremental.SwimLaneDescriptor;
30 import y.util.Maps;
31 import y.view.Arrow;
32 import y.view.EdgeRealizer;
33 import y.view.EditMode;
34 import y.view.Graph2D;
35 import y.view.PopupMode;
36
37 import javax.swing.AbstractAction;
38 import javax.swing.JMenu;
39 import javax.swing.JPopupMenu;
40 import javax.swing.JToolBar;
41 import java.awt.Cursor;
42 import java.awt.EventQueue;
43 import java.awt.event.ActionEvent;
44 import java.util.Locale;
45
46
70 public class SimpleSwimlaneLayouterDemo extends DemoBase {
71
72 private DataMap hintMap;
73
74
75 private NodeMap swimLaneMap;
76
77
78 private IncrementalHierarchicLayouter hierarchicLayouter;
79 private IncrementalHintsFactory hintsFactory;
80
81
82 private SwimlaneDrawable swimLaneDrawable;
83
84 public SimpleSwimlaneLayouterDemo() {
85 final Graph2D graph = view.getGraph2D();
86 EdgeRealizer defaultER = graph.getDefaultEdgeRealizer();
87 defaultER.setArrow(Arrow.STANDARD);
88
89 hintMap = Maps.createHashedDataMap();
91 swimLaneMap = graph.createNodeMap();
92 graph.addDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY, hintMap);
93 graph.addDataProvider(IncrementalHierarchicLayouter.SWIMLANE_DESCRIPTOR_DPKEY, swimLaneMap);
94
95 hierarchicLayouter = new IncrementalHierarchicLayouter();
97
98 hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumFirstSegmentLength(15);
100 hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumLastSegmentLength(20);
101 hierarchicLayouter.getEdgeLayoutDescriptor().setOrthogonallyRouted(true);
102 hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumDistance(10.0d);
103
104 hierarchicLayouter.getNodeLayoutDescriptor().setLayerAlignment(0.5d);
105 hierarchicLayouter.setMinimumLayerDistance(30.0d);
106 hierarchicLayouter.getNodeLayoutDescriptor().setNodeLabelMode(
107 NodeLayoutDescriptor.NODE_LABEL_MODE_CONSIDER_FOR_DRAWING);
108 hierarchicLayouter.setConsiderNodeLabelsEnabled(true);
109
110 ((SimplexNodePlacer) hierarchicLayouter.getNodePlacer()).setBaryCenterModeEnabled(true);
113
114 hintsFactory = hierarchicLayouter.createIncrementalHintsFactory();
116
117 hierarchicLayouter.setComponentLayouterEnabled(false);
119
120 view.addBackgroundDrawable(swimLaneDrawable = new SwimlaneDrawable(view.getGraph2D(), swimLaneMap));
122
123 loadGraph("resource/swimlane.graphml");
124 DemoDefaults.applyRealizerDefaults(graph);
125
126 calcLayout(hierarchicLayouter);
127 }
128
129 protected void configureDefaultRealizers() {
130 super.configureDefaultRealizers();
131 view.getGraph2D().getDefaultNodeRealizer().setSize(30, 30);
132 }
133
134 class LayoutFromSketchAction extends AbstractAction {
135 LayoutFromSketchAction() {
136 super("Layout From Sketch", SHARED_LAYOUT_ICON);
137 }
138
139 public void actionPerformed(ActionEvent ev) {
140 calcIncrementalLayout(new NodeList().nodes());
141 }
142 }
143
144 class LayoutIncrementallyAction extends AbstractAction {
145 LayoutIncrementallyAction() {
146 super("Layout Incrementally", SHARED_LAYOUT_ICON);
147 }
148
149 public void actionPerformed(ActionEvent ev) {
150 calcIncrementalLayout(view.getGraph2D().selectedNodes());
151 }
152 }
153
154 class LayoutAction extends AbstractAction {
155 LayoutAction() {
156 super("Layout", SHARED_LAYOUT_ICON);
157 }
158
159 public void actionPerformed(ActionEvent ev) {
160 calcFreshLayout();
161 }
162 }
163
164 protected JToolBar createToolBar() {
165 JToolBar tb = super.createToolBar();
166 tb.addSeparator();
167 tb.add(createActionControl(new LayoutAction()));
168 tb.add(createActionControl(new LayoutFromSketchAction()));
169 tb.add(createActionControl(new LayoutIncrementallyAction()));
170 return tb;
171 }
172
173 public void calcFreshLayout() {
174 hierarchicLayouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH);
175 calcLayout(hierarchicLayouter);
176 }
177
178 public void updateSwimLanes() {
179 for (NodeCursor nc = view.getGraph2D().nodes(); nc.ok(); nc.next()) {
180 SwimLaneDescriptor sld = new SwimLaneDescriptor(view.getGraph2D().getLabelText(nc.node()));
181 sld.setLeftLaneInset(5);
182 sld.setRightLaneInset(5);
183 sld.setMinimumLaneWidth(100);
184 swimLaneMap.set(nc.node(), sld);
185 }
186 }
187
188 public void calcIncrementalLayout(NodeCursor incrementalNodes) {
189 try {
190 for (incrementalNodes.toFirst(); incrementalNodes.ok(); incrementalNodes.next()) {
192 hintMap.set(incrementalNodes.node(), hintsFactory.createLayerIncrementallyHint(incrementalNodes.node()));
193 }
194 hierarchicLayouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_INCREMENTAL);
196 calcLayout(hierarchicLayouter);
198 } finally {
199 for (incrementalNodes.toFirst(); incrementalNodes.ok(); incrementalNodes.next()) {
201 hintMap.set(incrementalNodes.node(), null);
202 }
203 }
204 }
205
206 protected void calcLayout(Layouter layouter) {
207 Graph2D graph = view.getGraph2D();
208 if (!graph.isEmpty()) {
209 Cursor oldCursor = view.getCanvasComponent().getCursor();
210 try {
211 updateSwimLanes();
213 view.applyLayoutAnimated(layouter);
214 } finally {
215 view.getCanvasComponent().setCursor(oldCursor);
216 }
217 }
218 swimLaneDrawable.updateLanes();
219 view.fitContent();
220 view.updateView();
221 }
222
223 protected EditMode createEditMode() {
224 EditMode editMode = super.createEditMode();
225 editMode.setPopupMode(new PopupMode() {
226 public JPopupMenu getNodePopup(Node v) {
227 return createPopup();
228 }
229
230 private JPopupMenu createPopup() {
231 JPopupMenu menu = new JPopupMenu();
232 JMenu laneMenu = new JMenu("Move to lane");
233 menu.add(laneMenu);
234 laneMenu.add(new MoveSelectedNodesToLayerAction(1));
235 laneMenu.add(new MoveSelectedNodesToLayerAction(2));
236 laneMenu.add(new MoveSelectedNodesToLayerAction(3));
237 laneMenu.add(new MoveSelectedNodesToLayerAction(4));
238 laneMenu.add(new MoveSelectedNodesToLayerAction(5));
239 laneMenu.add(new MoveSelectedNodesToLayerAction(6));
240 return menu;
241 }
242
243 public JPopupMenu getSelectionPopup(double x, double y) {
244 return createPopup();
245 }
246 });
247 return editMode;
248 }
249
250
251
254 public static void main(String[] args) {
255 EventQueue.invokeLater(new Runnable() {
256 public void run() {
257 Locale.setDefault(Locale.ENGLISH);
258 initLnF();
259 (new SimpleSwimlaneLayouterDemo()).start("Simple Swimlane Layout Demo");
260 }
261 });
262 }
263
264 private class MoveSelectedNodesToLayerAction extends AbstractAction {
265 private int layer;
266
267 MoveSelectedNodesToLayerAction(int layer) {
268 super(String.valueOf(layer));
269 this.layer = layer;
270 }
271
272 public void actionPerformed(ActionEvent e) {
273 for (NodeCursor nodeCursor = view.getGraph2D().selectedNodes(); nodeCursor.ok(); nodeCursor.next()) {
274 Node node = nodeCursor.node();
275 view.getGraph2D().setLabelText(node, String.valueOf(layer));
276 }
277 calcIncrementalLayout(view.getGraph2D().selectedNodes());
278 }
279 }
280 }