001/* Manhattan Geometry Link 002 003 Copyright (c) 2006-2016 The Regents of the University of California. 004 All rights reserved. 005 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the above 009 copyright notice and the following two paragraphs appear in all copies 010 of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 */ 025 026package ptolemy.vergil.actor; 027 028import java.util.ArrayList; 029 030import diva.canvas.Site; 031import diva.canvas.connector.BasicManhattanRouter; 032import diva.canvas.connector.ManhattanConnector; 033import ptolemy.actor.IOPort; 034import ptolemy.kernel.util.Location; 035import ptolemy.kernel.util.NamedObj; 036import ptolemy.vergil.kernel.Link; 037 038/////////////////////////////////////////////////////////////////// 039//// LinkManhattanConnector 040 041/** 042 An extension to BasicManhattanRouter supporting links to multiports. 043 044 @author Edward A. Lee 045 @version $Id$ 046 @since Ptolemy II 5.2 047 @Pt.ProposedRating Yellow (eal) 048 @Pt.AcceptedRating Red (eal) 049 */ 050public class LinkManhattanConnector extends ManhattanConnector { 051 /** Construct a new connector with the given tail and head 052 * for the specified link. The head and tail sites may be 053 * representative sites for multiport, in which case they are 054 * not necessarily the ones returned by getHeadSite() or 055 * getTailSite(). Those methods will return new sites 056 * as needed to ensure that each each connection is to its 057 * own site. 058 * @param tail The tail site. 059 * @param head The head site. 060 * @param link The link. 061 */ 062 public LinkManhattanConnector(Site tail, Site head, Link link) { 063 super(tail, head, _router); 064 065 Object headObject = link.getHead(); 066 067 if (headObject instanceof IOPort) { 068 _headPort = (IOPort) headObject; 069 } else if (headObject instanceof Location) { 070 // If this is an external port, the object might be an 071 // instance of Location contained by the port. 072 NamedObj container = ((Location) headObject).getContainer(); 073 074 if (container instanceof IOPort) { 075 _headPort = (IOPort) container; 076 } 077 } 078 079 Object tailObject = link.getTail(); 080 081 if (tailObject instanceof IOPort) { 082 _tailPort = (IOPort) tailObject; 083 } else if (tailObject instanceof Location) { 084 // If this is an external port, the object might be an 085 // instance of Location contained by the port. 086 NamedObj container = ((Location) tailObject).getContainer(); 087 088 if (container instanceof IOPort) { 089 _tailPort = (IOPort) container; 090 } 091 } 092 093 _link = link; 094 } 095 096 /////////////////////////////////////////////////////////////////// 097 //// public methods //// 098 099 /** Override the base class to return a different site for each 100 * connection to a multiport. 101 * @return The connection site. 102 */ 103 @Override 104 public Site getHeadSite() { 105 Site result = super.getHeadSite(); 106 if (_headPort == null || !_headPort.isMultiport()) { 107 return result; 108 } 109 if (result instanceof PortConnectSite) { 110 PortTerminal terminal = ((PortConnectSite) result).getTerminal(); 111 int orderIndex = terminal.getOrderIndex(this); 112 113 if (orderIndex >= 0) { 114 // This should not create a new site if it has already 115 // created one! Record the ones created and return them. 116 if (_headSites == null) { 117 _headSites = new ArrayList(); 118 } 119 if (_headSites.size() > orderIndex) { 120 if (_headSites.get(orderIndex) == null) { 121 result = new PortConnectSite(result.getFigure(), 122 terminal, orderIndex + 1, result.getNormal()); 123 } else { 124 result = (Site) _headSites.get(orderIndex); 125 } 126 _headSites.set(orderIndex, result); 127 } else { 128 result = new PortConnectSite(result.getFigure(), terminal, 129 orderIndex + 1, result.getNormal()); 130 while (_headSites.size() < orderIndex) { 131 _headSites.add(null); 132 } 133 _headSites.add(result); 134 } 135 } 136 } 137 return result; 138 } 139 140 /** Return the associated link. 141 * @return The associated link. 142 */ 143 public Link getLink() { 144 return _link; 145 } 146 147 /** Override the base class to return a different site for each 148 * connection to a multiport. 149 * @return The connection site. 150 */ 151 @Override 152 public Site getTailSite() { 153 Site result = super.getTailSite(); 154 if (_tailPort == null || !_tailPort.isMultiport()) { 155 return result; 156 } 157 if (result instanceof PortConnectSite) { 158 PortTerminal terminal = ((PortConnectSite) result).getTerminal(); 159 int orderIndex = terminal.getOrderIndex(this); 160 161 if (orderIndex >= 0) { 162 // This should not create a new site if it has already 163 // created one! Record the ones created and return them. 164 if (_tailSites == null) { 165 _tailSites = new ArrayList(); 166 } 167 if (_tailSites.size() > orderIndex) { 168 if (_tailSites.get(orderIndex) == null) { 169 result = new PortConnectSite(result.getFigure(), 170 terminal, orderIndex + 1, result.getNormal()); 171 } else { 172 result = (Site) _tailSites.get(orderIndex); 173 } 174 _tailSites.set(orderIndex, result); 175 } else { 176 result = new PortConnectSite(result.getFigure(), terminal, 177 orderIndex + 1, result.getNormal()); 178 while (_tailSites.size() < orderIndex) { 179 _tailSites.add(null); 180 } 181 _tailSites.add(result); 182 } 183 } 184 } 185 return result; 186 } 187 188 /////////////////////////////////////////////////////////////////// 189 //// private members //// 190 191 /** The port at the head, if there is one and it's an IOPort. */ 192 private IOPort _headPort = null; 193 194 /** Head sites, in case this is a multiport. */ 195 private ArrayList _headSites = null; 196 197 /** The link. */ 198 private Link _link; 199 200 /** Specialized router. */ 201 private static BasicManhattanRouter _router = new BasicManhattanRouter(); 202 203 /** The port at the tail, if there is one and it's an IOPort. */ 204 private IOPort _tailPort = null; 205 206 /** Tail sites, in case this is a multiport. */ 207 private ArrayList _tailSites = null; 208}