1
14 package demo.view.layout.hierarchic;
15
16 import demo.view.DemoBase;
17 import y.base.DataMap;
18 import y.base.Node;
19 import y.base.NodeCursor;
20 import y.base.NodeList;
21 import y.base.NodeMap;
22 import y.layout.BufferedLayouter;
23 import y.layout.GraphLayout;
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.LayoutMorpher;
36 import y.view.PopupMode;
37
38 import javax.swing.AbstractAction;
39 import javax.swing.JMenu;
40 import javax.swing.JPopupMenu;
41 import javax.swing.JToolBar;
42 import java.awt.Cursor;
43 import java.awt.event.ActionEvent;
44
45
69 public class SimpleSwimLaneLayouterDemo extends DemoBase
70 {
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 {
86 final Graph2D graph = view.getGraph2D();
87 EdgeRealizer defaultER = graph.getDefaultEdgeRealizer();
88 defaultER.setArrow(Arrow.STANDARD);
89
90 hintMap = Maps.createHashedDataMap();
92 swimLaneMap = graph.createNodeMap();
93 graph.addDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY, hintMap);
94 graph.addDataProvider(IncrementalHierarchicLayouter.SWIMLANE_DESCRIPTOR_DPKEY, swimLaneMap);
95
96 hierarchicLayouter = new IncrementalHierarchicLayouter();
98
99 hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumFirstSegmentLength(15);
101 hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumLastSegmentLength(20);
102 hierarchicLayouter.getEdgeLayoutDescriptor().setOrthogonallyRouted(true);
103 hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumDistance(10.0d);
104
105 hierarchicLayouter.getNodeLayoutDescriptor().setLayerAlignment(0.5d);
106 hierarchicLayouter.setMinimumLayerDistance(30.0d);
107 hierarchicLayouter.getNodeLayoutDescriptor().setNodeLabelMode(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.gml" );
124 calcLayout( hierarchicLayouter );
125 }
126
127 class LayoutFromSketchAction extends AbstractAction
128 {
129 LayoutFromSketchAction()
130 {
131 super("Layout From Sketch");
132 }
133
134 public void actionPerformed(ActionEvent ev)
135 {
136 calcIncrementalLayout(new NodeList().nodes());
137 }
138 }
139
140 class LayoutIncrementallyAction extends AbstractAction
141 {
142 LayoutIncrementallyAction()
143 {
144 super("Layout Incrementally");
145 }
146
147 public void actionPerformed(ActionEvent ev)
148 {
149 calcIncrementalLayout(view.getGraph2D().selectedNodes());
150 }
151 }
152
153 class LayoutAction extends AbstractAction
154 {
155 LayoutAction()
156 {
157 super("Layout");
158 }
159
160 public void actionPerformed(ActionEvent ev)
161 {
162 calcFreshLayout();
163 }
164 }
165
166 protected JToolBar createToolBar()
167 {
168 JToolBar tb = super.createToolBar();
169 tb.add(new LayoutAction());
170 tb.add(new LayoutFromSketchAction());
171 tb.add(new LayoutIncrementallyAction());
172 return tb;
173 }
174
175 public void calcFreshLayout(){
176 hierarchicLayouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH);
177 calcLayout(hierarchicLayouter);
178 }
179
180 public void updateSwimLanes(){
181 for (NodeCursor nc = view.getGraph2D().nodes(); nc.ok(); nc.next()){
182 SwimLaneDescriptor sld = new SwimLaneDescriptor(view.getGraph2D().getLabelText(nc.node()));
183 sld.setLeftLaneInset(5);
184 sld.setRightLaneInset(5);
185 sld.setMinimumLaneWidth(100);
186 swimLaneMap.set(nc.node(), sld);
187 }
188 }
189
190 public void calcIncrementalLayout(NodeCursor incrementalNodes){
191 try {
192 for (incrementalNodes.toFirst(); incrementalNodes.ok(); incrementalNodes.next()){
194 hintMap.set(incrementalNodes.node(), hintsFactory.createLayerIncrementallyHint(incrementalNodes.node()));
195 }
196 hierarchicLayouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_INCREMENTAL);
198 calcLayout(hierarchicLayouter);
200 } finally {
201 for (incrementalNodes.toFirst(); incrementalNodes.ok(); incrementalNodes.next()){
203 hintMap.set(incrementalNodes.node(), null);
204 }
205 }
206 }
207
208 protected void calcLayout(Layouter layouter){
209 Graph2D graph = view.getGraph2D();
210 if (!graph.isEmpty()){
211 Cursor oldCursor = view.getCanvasComponent().getCursor();
212 try {
213 updateSwimLanes();
215 GraphLayout result = new BufferedLayouter(layouter).calcLayout(view.getGraph2D());
216 LayoutMorpher morpher = new LayoutMorpher(view, result);
217 morpher.setSmoothViewTransform(true);
218 morpher.setPreferredDuration(300);
219 morpher.execute();
220 } finally {
221 view.getCanvasComponent().setCursor(oldCursor);
222 }
223 }
224 swimLaneDrawable.updateLanes();
225 view.fitContent();
226 view.updateView();
227 }
228
229 protected EditMode createEditMode() {
230 EditMode editMode = super.createEditMode();
231 editMode.setPopupMode( new PopupMode( ){
232 public JPopupMenu getNodePopup( Node v ) {
233 return createPopup();
234 }
235
236 private JPopupMenu createPopup() {
237 JPopupMenu menu = new JPopupMenu();
238 JMenu laneMenu = new JMenu( "Move to lane" );
239 menu.add( laneMenu );
240 laneMenu.add( new MoveSelectedNodesToLayerAction(1) );
241 laneMenu.add( new MoveSelectedNodesToLayerAction(2) );
242 laneMenu.add( new MoveSelectedNodesToLayerAction(3) );
243 laneMenu.add( new MoveSelectedNodesToLayerAction(4) );
244 laneMenu.add( new MoveSelectedNodesToLayerAction(5) );
245 laneMenu.add( new MoveSelectedNodesToLayerAction(6) );
246 return menu;
247 }
248
249 public JPopupMenu getSelectionPopup( double x, double y ) {
250 return createPopup();
251 }
252 });
253 return editMode;
254 }
255
256
257
260 public static void main(String args[])
261 {
262 initLnF();
263 SimpleSwimLaneLayouterDemo demo = new SimpleSwimLaneLayouterDemo();
264 demo.start("Simple Swimlane Layout Demo");
265 }
266
267 private class MoveSelectedNodesToLayerAction extends AbstractAction {
268 private int layer;
269
270 MoveSelectedNodesToLayerAction( int layer ) {
271 super( String.valueOf( layer ) );
272 this.layer = layer;
273 }
274
275 public void actionPerformed( ActionEvent e ) {
276 for ( NodeCursor nodeCursor = view.getGraph2D().selectedNodes(); nodeCursor.ok(); nodeCursor.next() ) {
277 Node node = nodeCursor.node();
278 view.getGraph2D().setLabelText( node, String.valueOf( layer ) );
279 }
280 calcIncrementalLayout( view.getGraph2D().selectedNodes() );
281 }
282 }
283 }