001/* A GUI widget for configuring ports. 002 003 Copyright (c) 1998-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.actor.gui; 029 030import java.util.HashSet; 031import java.util.Iterator; 032import java.util.Locale; 033import java.util.Set; 034import java.util.StringTokenizer; 035 036import javax.swing.BoxLayout; 037 038import ptolemy.actor.TypedIOPort; 039import ptolemy.gui.Query; 040import ptolemy.gui.QueryListener; 041import ptolemy.kernel.Entity; 042import ptolemy.kernel.util.NamedObj; 043import ptolemy.kernel.util.StringAttribute; 044import ptolemy.moml.MoMLChangeRequest; 045import ptolemy.util.StringUtilities; 046 047/////////////////////////////////////////////////////////////////// 048//// PortConfigurer 049 050/** 051 This class is an editor to configure the ports of an object. 052 It supports setting their input, output, and multiport properties, 053 and adding and removing ports. Only ports that extend the TypedIOPort 054 class are listed, since more primitive ports cannot be configured 055 in this way. 056 057 @see Configurer 058 @author Steve Neuendorffer and Edward A. Lee 059 @version $Id$ 060 @since Ptolemy II 1.0 061 @Pt.ProposedRating Yellow (eal) 062 @Pt.AcceptedRating Red (neuendor) 063 @deprecated This class is no longer used. Use PortConfigurerDialog. 064 */ 065@Deprecated 066@SuppressWarnings("serial") 067public class PortConfigurer extends Query implements QueryListener { 068 /** Construct a port configurer for the specified entity. 069 * @param object The entity to configure. 070 */ 071 public PortConfigurer(Entity object) { 072 super(); 073 this.addQueryListener(this); 074 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 075 076 setTextWidth(15); 077 078 // The second column is for type designators. 079 setColumns(3); 080 081 _object = object; 082 083 Iterator ports = _object.portList().iterator(); 084 085 while (ports.hasNext()) { 086 Object candidate = ports.next(); 087 088 if (candidate instanceof TypedIOPort) { 089 TypedIOPort port = (TypedIOPort) candidate; 090 Set optionsDefault = new HashSet(); 091 092 if (port.isInput()) { 093 optionsDefault.add("input"); 094 } 095 096 if (port.isOutput()) { 097 optionsDefault.add("output"); 098 } 099 100 if (port.isMultiport()) { 101 optionsDefault.add("multiport"); 102 } 103 104 addSelectButtons(port.getName(), port.getName(), _optionsArray, 105 optionsDefault); 106 107 String typeEntryName = port.getName() + " type"; 108 addLine(typeEntryName, typeEntryName, 109 port.getType().toString()); 110 111 // Add a column that controls on which side 112 // of the icon the port lies. 113 StringAttribute cardinal = (StringAttribute) port 114 .getAttribute("_cardinal"); 115 String cardinalValue = "SOUTH"; 116 117 if (cardinal != null) { 118 cardinalValue = cardinal.getExpression() 119 .toUpperCase(Locale.getDefault()); 120 } else if (port.isInput() && !port.isOutput()) { 121 cardinalValue = "WEST"; 122 } else if (port.isOutput() && !port.isInput()) { 123 cardinalValue = "EAST"; 124 } 125 126 addChoice(port.getName() + " cardinal", 127 port.getName() + ": cardinal direction", _cardinals, 128 cardinalValue); 129 } 130 } 131 } 132 133 /////////////////////////////////////////////////////////////////// 134 //// public methods //// 135 136 /** Apply the changes by configuring the ports that have changed. 137 */ 138 public void apply() { 139 StringBuffer moml = new StringBuffer("<group>"); 140 boolean foundOne = false; 141 Iterator ports = _object.portList().iterator(); 142 NamedObj parent = null; 143 144 while (ports.hasNext()) { 145 Object candidate = ports.next(); 146 147 if (candidate instanceof TypedIOPort) { 148 TypedIOPort port = (TypedIOPort) candidate; 149 String name = port.getName(); 150 151 // Check whether the positioning information has changed. 152 String nameCardinal = name + " cardinal"; 153 154 if (_changed.contains(nameCardinal)) { 155 // The context for the MoML should be the first container 156 // above this port in the hierarchy that defers its 157 // MoML definition, or the immediate parent 158 // if there is none. 159 parent = port.getContainer(); 160 foundOne = true; 161 moml.append("<port name=\""); 162 moml.append(port.getName()); 163 moml.append("\">"); 164 165 String cardinalVal = getStringValue(nameCardinal); 166 moml.append("<property name=\"_cardinal\" " 167 + "class = \"ptolemy.kernel.util.StringAttribute\" " 168 + "value = \"" + cardinalVal + "\"/>"); 169 moml.append("</port>"); 170 } 171 172 // If either the I/O designation or the type changed, 173 // then generate additional MoML. 174 String typeEntryName = name + " type"; 175 176 if (_changed.contains(name) 177 || _changed.contains(typeEntryName)) { 178 // Change to the type or I/O status. Create a MoML command. 179 String value = getStringValue(name); 180 181 // First, parse the value, which may be a 182 // comma-separated list. 183 Set selectedValues = new HashSet(); 184 StringTokenizer tokenizer = new StringTokenizer(value, ","); 185 186 while (tokenizer.hasMoreTokens()) { 187 selectedValues.add(tokenizer.nextToken().trim()); 188 } 189 190 // The context for the MoML should be the first container 191 // above this port in the hierarchy that defers its 192 // MoML definition, or the immediate parent 193 // if there is none. 194 parent = port.getContainer(); 195 foundOne = true; 196 moml.append("<port name=\""); 197 moml.append(port.getName()); 198 moml.append("\">"); 199 200 if (selectedValues.contains("input")) { 201 moml.append("<property name=\"input\"/>"); 202 } else { 203 moml.append( 204 "<property name=\"input\" value=\"false\"/>"); 205 } 206 207 if (selectedValues.contains("output")) { 208 moml.append("<property name=\"output\"/>"); 209 } else { 210 moml.append( 211 "<property name=\"output\" value=\"false\"/>"); 212 } 213 214 if (selectedValues.contains("multiport")) { 215 moml.append("<property name=\"multiport\"/>"); 216 } else { 217 moml.append( 218 "<property name=\"multiport\" value=\"false\"/>"); 219 } 220 221 if (_changed.contains(typeEntryName)) { 222 // Type designation has changed. 223 String type = getStringValue(typeEntryName); 224 moml.append("<property name=\"_type\" " 225 + "class = \"ptolemy.actor.TypeAttribute\" " 226 + "value = \"" 227 + StringUtilities.escapeForXML(type) + "\"/>"); 228 } 229 230 moml.append("</port>"); 231 } 232 } 233 } 234 235 if (foundOne) { 236 moml.append("</group>"); 237 238 MoMLChangeRequest request = new MoMLChangeRequest(this, // originator 239 parent, // context 240 moml.toString(), // MoML code 241 null); // base 242 243 request.setUndoable(true); 244 245 // NOTE: There is no need to listen for completion 246 // or errors in this change request, since, in theory, 247 // it will just work. Will someone report the error 248 // if one occurs? I hope so... 249 parent.requestChange(request); 250 } 251 } 252 253 /** Called to notify that one of the entries has changed. 254 * This simply sets a flag that enables application of the change 255 * when the apply() method is called. 256 * @param name The name of the entry that changed. 257 */ 258 @Override 259 public void changed(String name) { 260 _changed.add(name); 261 } 262 263 /////////////////////////////////////////////////////////////////// 264 //// private variables //// 265 // Possible placements of ports. 266 private String[] _cardinals = { "NORTH", "SOUTH", "EAST", "WEST" }; 267 268 // The set of names of ports that have changed. 269 private Set _changed = new HashSet(); 270 271 // The object that this configurer configures. 272 private Entity _object; 273 274 // The possible configurations for a port. 275 private String[] _optionsArray = { "input", "output", "multiport" }; 276}