| PortCreateEdgeModeDemo.java |
1 /****************************************************************************
2 * This demo file is part of yFiles for Java 2.14.
3 * Copyright (c) 2000-2017 by yWorks GmbH, Vor dem Kreuzberg 28,
4 * 72070 Tuebingen, Germany. All rights reserved.
5 *
6 * yFiles demo files exhibit yFiles for Java functionalities. Any redistribution
7 * of demo files in source code or binary form, with or without
8 * modification, is not permitted.
9 *
10 * Owners of a valid software license for a yFiles for Java version that this
11 * demo is shipped with are allowed to use the demo source code as basis
12 * for their own yFiles for Java powered applications. Use of such programs is
13 * governed by the rights and conditions as set out in the yFiles for Java
14 * license agreement.
15 *
16 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19 * NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 ***************************************************************************/
28 package demo.view.viewmode;
29
30
31 import demo.view.DemoBase;
32 import demo.view.DemoDefaults;
33 import y.base.Edge;
34 import y.base.Node;
35 import y.base.YCursor;
36 import y.base.YList;
37 import y.view.CreateEdgeMode;
38 import y.view.EdgeRealizer;
39 import y.view.EditMode;
40 import y.view.Graph2D;
41 import y.view.NodeRealizer;
42 import y.view.Port;
43
44 import java.awt.EventQueue;
45 import java.util.Locale;
46
47 /**
48 * Demonstrates how {@link CreateEdgeMode} can be customized in order to
49 * control automatic assignments of ports for edges.
50 * Edges are created in such a way, that the source port is always on
51 * the top side of the source node and the target port is always on the bottom
52 * side of the target node.
53 * <p>
54 * Usage: Create some nodes and edges. Select an edge to check its source
55 * and target ports.
56 * </p>
57 * @see <a href="http://docs.yworks.com/yfiles/doc/api/index.html#/dguide/mvc_controller#custom_edit_mode" target="_blank">Section User Interaction</a> in the yFiles for Java Developer's Guide
58 */
59 public class PortCreateEdgeModeDemo extends DemoBase
60 {
61 protected void initialize() {
62 super.initialize();
63 loadGraph("resource/PortCreateEdgeModeDemo.graphml");
64 DemoDefaults.applyRealizerDefaults(view.getGraph2D());
65 }
66
67 protected void registerViewModes() {
68 EditMode editMode = new EditMode();
69 view.addViewMode( editMode );
70 //set a custom CreateEdgeMode for the edge mode
71 editMode.setCreateEdgeMode( new PortCreateEdgeMode() );
72 }
73
74 public static class PortCreateEdgeMode extends CreateEdgeMode
75 {
76 private Edge edge; // need this for the hook
77
78 /**
79 * If a node was hit at the given coordinates, that node
80 * will be used as target node for the newly created edge.
81 *
82 */
83 public void mouseReleasedLeft(double x, double y)
84 {
85 // simulate a pressed shift...
86 // this will trigger CreateEdgeMode, to preassign offset
87 // to source and target ports
88 super.mouseShiftReleasedLeft(x, y);
89
90 if (edge != null){ // the edge has just been created
91 Graph2D graph = (Graph2D) edge.getGraph();
92 EdgeRealizer er = graph.getRealizer(edge);
93
94 // get a list of port candidates
95 YList ports = getPorts(edge.source(), edge);
96 Port p = er.getSourcePort();
97 // snap to one of them
98 snap(er, true, p.getOffsetX(), p.getOffsetY(), ports);
99
100 // get a list of port candidates
101 ports = getPorts(edge.target(), edge);
102 p = er.getTargetPort();
103 // snap to one of them
104 snap(er, false, p.getOffsetX(), p.getOffsetY(), ports);
105
106 // do some clean up
107 edge = null;
108 graph.updateViews();
109 }
110
111 }
112
113 /**
114 * Initiates the creation of an edge.
115 *
116 */
117 public void mousePressedLeft(double x, double y)
118 {
119 // simulate a pressed shift...
120 // this will trigger CreateEdgeMode, to preassign offset
121 // to source and target ports
122 super.mouseShiftPressedLeft(x, y);
123 }
124
125
126 public void edgeCreated(Edge e){
127 //remember the edge...
128 this.edge = e;
129 }
130
131 /**
132 * This method finds a list of Port objects for a specific edge/node pair
133 *
134 * @param onNode the node
135 * @param forEdge the edge
136 * @return a list of Port objects
137 */
138 public YList getPorts(Node onNode, Edge forEdge) {
139 YList list = new YList();
140 Graph2D graph = (Graph2D) onNode.getGraph();
141 NodeRealizer nr = graph.getRealizer(onNode);
142 EdgeRealizer er = graph.getRealizer(forEdge);
143
144 if (onNode == forEdge.source()) {
145 // source ports are centered on bottom of the node
146 list.add(new Port(0, nr.getHeight() / 2));
147 } else {
148 // target ports are centered at the top of the node
149 list.add(new Port(0, -nr.getHeight() / 2));
150 }
151 return list;
152 }
153
154 /**
155 * This method calculates a metric for ports and points
156 *
157 * @param x the initial x offset
158 * @param y the initial y offset
159 * @param port the port
160 * @return the distance between the point (x,y) and the port
161 */
162 public static double getDistance(double x, double y, Port port) {
163 return Math.sqrt((x - port.getOffsetX()) * (x - port.getOffsetX())
164 + (y - port.getOffsetY()) * (y - port.getOffsetY()));
165 }
166
167 /**
168 * This method chooses from a list of given ports for an edge
169 * a suitable port, given an initial placement.
170 *
171 * @param edge the affected edge
172 * @param source whether we look at the source node
173 * @param x the initial x offset
174 * @param y the initial y offset
175 * @param ports a list of Port objects (candidates)
176 */
177 public void snap(EdgeRealizer edge, boolean source, double x, double y, YList ports) {
178 if (ports == null || ports.size() < 1) {
179 return; // do nothing
180 }
181
182 // find the closest port with regards to the getDistance function
183 Port closest = (Port) ports.first();
184 double dist = getDistance(x, y, closest);
185
186 for (YCursor cursor = ports.cursor(); cursor.ok(); cursor.next()) {
187 Port p = (Port) cursor.current();
188 double d2 = getDistance(x, y, p);
189 if (d2 < dist) {
190 dist = d2;
191 closest = p;
192 }
193 }
194
195 // assign the port
196 if (source) {
197 edge.setSourcePort(closest);
198 } else {
199 edge.setTargetPort(closest);
200 }
201 }
202
203 }
204
205 public static void main(String[] args) {
206 EventQueue.invokeLater(new Runnable() {
207 public void run() {
208 Locale.setDefault(Locale.ENGLISH);
209 initLnF();
210 (new PortCreateEdgeModeDemo()).start();
211 }
212 });
213 }
214 }
215
216
217
218