1
28 package demo.layout.tree;
29
30 import demo.view.DemoBase;
31 import y.anim.AnimationPlayer;
32 import y.base.Edge;
33 import y.base.EdgeMap;
34 import y.base.Node;
35 import y.base.NodeCursor;
36 import y.base.NodeMap;
37 import y.geom.YPoint;
38 import y.layout.PortConstraint;
39 import y.layout.PortConstraintKeys;
40 import y.layout.tree.AbstractRotatableNodePlacer.RootAlignment;
41 import y.layout.tree.FromSketchNodePlacer;
42 import y.layout.tree.GenericTreeLayouter;
43 import y.layout.tree.NodePlacer;
44 import y.layout.tree.SimpleNodePlacer;
45 import y.util.DataProviderAdapter;
46 import y.view.CreateChildEdgeMode;
47 import y.view.EdgeRealizer;
48 import y.view.EditMode;
49 import y.view.Graph2D;
50 import y.view.HotSpotMode;
51 import y.view.NodeRealizer;
52 import y.view.PopupMode;
53 import y.view.PortAssignmentMoveSelectionMode;
54
55 import javax.swing.AbstractAction;
56 import java.awt.Color;
57 import java.awt.Cursor;
58 import java.awt.event.ActionEvent;
59 import java.lang.reflect.Method;
60
61
65 public abstract class AbstractTreeDemo extends DemoBase {
66 protected GenericTreeLayouter treeLayouter = new GenericTreeLayouter();
67
68 protected EdgeMap sourcePortMap;
69 protected EdgeMap targetPortMap;
70 protected NodeMap portAssignmentMap;
71 protected NodeMap nodePlacerMap;
72 protected PortAssignmentMoveSelectionMode portAssignmentMoveMode = new TreePortAssignmentMode();
73 protected Color[] layerColors = {Color.red, Color.orange, Color.yellow, Color.blue, Color.cyan,
74 Color.green};
75
76
79 protected AbstractTreeDemo() {
80 view.addViewMode(new TreeCreateEditMode());
81
82 AnimationPlayer animationPlayer = new AnimationPlayer();
83 animationPlayer.addAnimationListener(view);
84
85 Graph2D graph = view.getGraph2D();
86
87 sourcePortMap = graph.createEdgeMap();
88 targetPortMap = graph.createEdgeMap();
89 portAssignmentMap = graph.createNodeMap();
90 nodePlacerMap = graph.createNodeMap();
91 graph.addDataProvider(GenericTreeLayouter.NODE_PLACER_DPKEY, new DataProviderAdapter() {
92 public Object get( final Object dataHolder ) {
93 if (((Node) dataHolder).outDegree() == 0) {
94 return null;
95 } else {
96 return nodePlacerMap.get(dataHolder);
97 }
98 }
99 });
100 graph.addDataProvider(GenericTreeLayouter.PORT_ASSIGNMENT_DPKEY, portAssignmentMap);
101 graph.addDataProvider(GenericTreeLayouter.CHILD_COMPARATOR_DPKEY, new ChildEdgeComparatorProvider());
102 graph.addDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY, sourcePortMap);
103 graph.addDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY, targetPortMap);
104
105 portAssignmentMoveMode.setSpc(sourcePortMap);
106 portAssignmentMoveMode.setTpc(targetPortMap);
107 }
108
109
112 public void setNodePlacer(Node node, NodePlacer placer) {
113 nodePlacerMap.set(node, placer);
114 }
115
116
119 public void calcLayout() {
120 if (!view.getGraph2D().isEmpty()) {
121 Cursor oldCursor = view.getViewCursor();
122 try {
123 view.setViewCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
124 view.applyLayoutAnimated(treeLayouter);
125 } finally {
126 view.setViewCursor(oldCursor);
127 }
128 }
129 }
130
131
134 protected PopupMode createTreePopupMode() {
135 return null;
136 }
137
138
141 protected void registerViewModes() {
142 }
143
144 protected NodePlacer createDefaultNodePlacer() {
145 return new SimpleNodePlacer();
146 }
147
148 protected final class ChildEdgeComparatorProvider extends DataProviderAdapter {
149 public Object get(Object dataHolder) {
150 NodePlacer placer = (NodePlacer) nodePlacerMap.get(dataHolder);
151 if (placer instanceof FromSketchNodePlacer){
152 return ((FromSketchNodePlacer) placer).createFromSketchComparator();
153 }
154 return null;
155 }
156 }
157
158 private final class TreeHotSpotMode extends HotSpotMode {
159 public void mouseReleasedLeft(double x, double y) {
160 super.mouseReleasedLeft(x, y);
161 calcLayout();
162 }
163 }
164
165 protected class TreeCreateEditMode extends EditMode {
166 TreeCreateEditMode() {
167 if (portAssignmentMoveMode == null) {
168 throw new IllegalStateException("portAssignmentMoveMode is null");
169 }
170 setMoveSelectionMode(portAssignmentMoveMode);
171 setCreateEdgeMode(new TreeCreateChildEdgeMode());
172 setHotSpotMode(new TreeHotSpotMode());
173 setPopupMode(AbstractTreeDemo.this.createTreePopupMode());
174 }
175
176 public boolean doAllowNodeCreation() {
177 return getGraph2D().N() == 0;
178 }
179
180 protected void nodeCreated(Node v) {
181 super.nodeCreated(v);
182 setNodePlacer(v, createDefaultNodePlacer());
183 }
184 }
185
186 private final class TreeCreateChildEdgeMode extends CreateChildEdgeMode {
187
188 public void mouseReleasedLeft(double x, double y) {
189 getGraph2D().firePreEvent();
191 super.mouseReleasedLeft(x, y);
192 }
193
194 protected void edgeCreated(Edge edge) {
195 int depth = 1;
196 for (Node node = edge.source(); node.inDegree() > 0; node = node.firstInEdge().source()) {
197 depth++;
198 }
199 Graph2D g = getGraph2D();
200 g.getRealizer(edge.target()).setFillColor(layerColors[depth % layerColors.length]);
201 EdgeRealizer er = g.getRealizer(edge);
202 if (nodePlacerMap.get(edge.source()) == null) {
203 parseNodePlacement(g, edge, er);
204 }
205
206 setNodePlacer(edge.target(), createDefaultNodePlacer());
207 parseTargetPort(g, edge, er);
208 g.unselectAll();
209 calcLayout();
210
211 getGraph2D().firePostEvent();
213 }
214
215 protected NodeRealizer activeDummyTargetRealizer;
216
217 protected boolean acceptSourceNode(Node source, double x, double y) {
218 final boolean accept = super.acceptSourceNode(source, x, y);
219 activeDummyTargetRealizer = createChildNodeRealizer();
220 int depth = 1;
221 for (Node n = source; n.inDegree() > 0; n = n.firstInEdge().source()){
222 depth++;
223 }
224 activeDummyTargetRealizer.setFillColor(layerColors[depth % layerColors.length]);
225 return accept;
226 }
227
228 protected NodeRealizer createDummyTargetNodeRealizer(double x, double y) {
229 return activeDummyTargetRealizer;
230 }
231
232 private void parseNodePlacement(Graph2D g, Edge e, EdgeRealizer er) {
233 nodePlacerMap.set(e.source(), new SimpleNodePlacer());
234 }
235
236 private void parseTargetPort(Graph2D g, Edge e, EdgeRealizer er) {
237 if (er.bendCount() > 0) {
238 YPoint lastPoint = new YPoint(er.lastBend().getX(), er.lastBend().getY());
239 NodeRealizer target = g.getRealizer(e.target());
240 double dx = lastPoint.x - target.getCenterX();
241 double dy = lastPoint.y - target.getCenterY();
242 byte side;
243 if (Math.abs(dx) > Math.abs(dy)) {
244 if (dx > 0.0) {
245 side = PortConstraint.EAST;
246 } else {
247 side = PortConstraint.WEST;
248 }
249 } else {
250 if (dy > 0.0) {
251 side = PortConstraint.SOUTH;
252 } else {
253 side = PortConstraint.NORTH;
254 }
255 }
256 targetPortMap.set(e, PortConstraint.create(side));
257 }
258 }
259
260 protected NodeRealizer createChildNodeRealizer() {
261 NodeRealizer retValue = super.createChildNodeRealizer();
262 retValue.setLabelText("");
263 return retValue;
264 }
265
266 }
267
268 protected class SetHorizontalAlignmentAction extends AbstractAction {
269 private RootAlignment alignment;
270
271 protected SetHorizontalAlignmentAction(String name, RootAlignment alignment) {
272 super(name);
273 this.alignment = alignment;
274 }
275
276 public void actionPerformed(ActionEvent e) {
277 for (NodeCursor nodeCursor = view.getGraph2D().selectedNodes(); nodeCursor.ok(); nodeCursor.next()) {
278 Node node = nodeCursor.node();
279 NodePlacer nodePlacer = (NodePlacer) nodePlacerMap.get(node);
280
281 try {
282 Method method = nodePlacer.getClass().getMethod("setRootAlignment", new Class[]{RootAlignment.class});
283 method.invoke(nodePlacer, new Object[]{alignment});
284 } catch (Exception ex) {
285 }
286 }
287 calcLayout();
288 }
289 }
290
291 abstract class SetNodePlacerAction extends AbstractAction {
292 protected SetNodePlacerAction(String name) {
293 super(name);
294 }
295
296 public void actionPerformed(ActionEvent e) {
297 for (NodeCursor nodeCursor = view.getGraph2D().selectedNodes(); nodeCursor.ok(); nodeCursor.next()) {
298 Node node = nodeCursor.node();
299 nodePlacerMap.set(node, createNodePlacer());
300 }
301 calcLayout();
302 }
303
304 protected abstract NodePlacer createNodePlacer();
305 }
306
307 private final class TreePortAssignmentMode extends PortAssignmentMoveSelectionMode {
308 TreePortAssignmentMode() {
309 super(null, null);
310 }
311
312 protected boolean isPortReassignmentAllowed(Edge edge, boolean source) {
313 return !source;
314 }
315
316 protected void selectionMovedAction(double dx, double dy, double x, double y) {
317 super.selectionMovedAction(dx, dy, x, y);
318 calcLayout();
319 }
320
321 }
322 }
323