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