| PortCreateEdgeModeDemo.java |
1 /****************************************************************************
2 **
3 ** This file is part of yFiles-2.9.
4 **
5 ** yWorks proprietary/confidential. Use is subject to license terms.
6 **
7 ** Redistribution of this file or of an unauthorized byte-code version
8 ** of this file is strictly forbidden.
9 **
10 ** Copyright (c) 2000-2011 by yWorks GmbH, Vor dem Kreuzberg 28,
11 ** 72070 Tuebingen, Germany. All rights reserved.
12 **
13 ***************************************************************************/
14 package demo.view.viewmode;
15
16
17 import demo.view.DemoBase;
18 import demo.view.DemoDefaults;
19 import y.base.Edge;
20 import y.base.Node;
21 import y.base.YCursor;
22 import y.base.YList;
23 import y.view.CreateEdgeMode;
24 import y.view.EdgeRealizer;
25 import y.view.EditMode;
26 import y.view.Graph2D;
27 import y.view.NodeRealizer;
28 import y.view.Port;
29
30 import java.awt.EventQueue;
31 import java.util.Locale;
32
33 /**
34 * Demonstrates how {@link CreateEdgeMode} can be customized in order to
35 * control automatic assignments of ports for edges.
36 * Edges are created in such a way, that the source port is always on
37 * the top side of the source node and the target port is always on the bottom
38 * side of the target node.
39 * <p>
40 * Usage: Create some nodes and edges. Select an edge to check its source
41 * and target ports.
42 * </p>
43 * @see <a href="http://docs.yworks.com/yfiles/doc/developers-guide/mvc_controller.html#custom_edit_mode">Section User Interaction</a> in the yFiles for Java Developer's Guide
44 */
45 public class PortCreateEdgeModeDemo extends DemoBase
46 {
47 protected void initialize() {
48 super.initialize();
49 loadGraph("resource/PortCreateEdgeModeDemo.graphml");
50 DemoDefaults.applyRealizerDefaults(view.getGraph2D());
51 }
52
53 protected void registerViewModes() {
54 EditMode editMode = new EditMode();
55 view.addViewMode( editMode );
56 //set a custom CreateEdgeMode for the edge mode
57 editMode.setCreateEdgeMode( new PortCreateEdgeMode() );
58 }
59
60 public static class PortCreateEdgeMode extends CreateEdgeMode
61 {
62 private Edge edge; // need this for the hook
63
64 /**
65 * If a node was hit at the given coordinates, that node
66 * will be used as target node for the newly created edge.
67 *
68 */
69 public void mouseReleasedLeft(double x, double y)
70 {
71 // simulate a pressed shift...
72 // this will trigger CreateEdgeMode, to preassign offset
73 // to source and target ports
74 super.mouseShiftReleasedLeft(x, y);
75
76 if (edge != null){ // the edge has just been created
77 Graph2D graph = (Graph2D) edge.getGraph();
78 EdgeRealizer er = graph.getRealizer(edge);
79
80 // get a list of port candidates
81 YList ports = getPorts(edge.source(), edge);
82 Port p = er.getSourcePort();
83 // snap to one of them
84 snap(er, true, p.getOffsetX(), p.getOffsetY(), ports);
85
86 // get a list of port candidates
87 ports = getPorts(edge.target(), edge);
88 p = er.getTargetPort();
89 // snap to one of them
90 snap(er, false, p.getOffsetX(), p.getOffsetY(), ports);
91
92 // do some clean up
93 edge = null;
94 graph.updateViews();
95 }
96
97 }
98
99 /**
100 * Initiates the creation of an edge.
101 *
102 */
103 public void mousePressedLeft(double x, double y)
104 {
105 // simulate a pressed shift...
106 // this will trigger CreateEdgeMode, to preassign offset
107 // to source and target ports
108 super.mouseShiftPressedLeft(x, y);
109 }
110
111
112 public void edgeCreated(Edge e){
113 //remember the edge...
114 this.edge = e;
115 }
116
117 /**
118 * This method finds a list of Port objects for a specific edge/node pair
119 *
120 * @param onNode the node
121 * @param forEdge the edge
122 * @return a list of Port objects
123 */
124 public YList getPorts(Node onNode, Edge forEdge) {
125 YList list = new YList();
126 Graph2D graph = (Graph2D) onNode.getGraph();
127 NodeRealizer nr = graph.getRealizer(onNode);
128 EdgeRealizer er = graph.getRealizer(forEdge);
129
130 if (onNode == forEdge.source()) {
131 // source ports are centered on bottom of the node
132 list.add(new Port(0, nr.getHeight() / 2));
133 } else {
134 // target ports are centered at the top of the node
135 list.add(new Port(0, -nr.getHeight() / 2));
136 }
137 return list;
138 }
139
140 /**
141 * This method calculates a metric for ports and points
142 *
143 * @param x the initial x offset
144 * @param y the initial y offset
145 * @param port the port
146 * @return the distance between the point (x,y) and the port
147 */
148 public static double getDistance(double x, double y, Port port) {
149 return Math.sqrt((x - port.getOffsetX()) * (x - port.getOffsetX())
150 + (y - port.getOffsetY()) * (y - port.getOffsetY()));
151 }
152
153 /**
154 * This method chooses from a list of given ports for an edge
155 * a suitable port, given an initial placement.
156 *
157 * @param edge the affected edge
158 * @param source whether we look at the source node
159 * @param x the initial x offset
160 * @param y the initial y offset
161 * @param ports a list of Port objects (candidates)
162 */
163 public void snap(EdgeRealizer edge, boolean source, double x, double y, YList ports) {
164 if (ports == null || ports.size() < 1) {
165 return; // do nothing
166 }
167
168 // find the closest port with regards to the getDistance function
169 Port closest = (Port) ports.first();
170 double dist = getDistance(x, y, closest);
171
172 for (YCursor cursor = ports.cursor(); cursor.ok(); cursor.next()) {
173 Port p = (Port) cursor.current();
174 double d2 = getDistance(x, y, p);
175 if (d2 < dist) {
176 dist = d2;
177 closest = p;
178 }
179 }
180
181 // assign the port
182 if (source) {
183 edge.setSourcePort(closest);
184 } else {
185 edge.setTargetPort(closest);
186 }
187 }
188
189 }
190
191 public static void main(String[] args) {
192 EventQueue.invokeLater(new Runnable() {
193 public void run() {
194 Locale.setDefault(Locale.ENGLISH);
195 initLnF();
196 (new PortCreateEdgeModeDemo()).start();
197 }
198 });
199 }
200 }
201
202
203
204