001/* A GUI widget for renaming an object. 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 javax.swing.BoxLayout; 031 032import ptolemy.data.BooleanToken; 033import ptolemy.data.Token; 034import ptolemy.data.expr.Parameter; 035import ptolemy.gui.Query; 036import ptolemy.gui.QueryListener; 037import ptolemy.kernel.Port; 038import ptolemy.kernel.util.AbstractSettableAttribute; 039import ptolemy.kernel.util.Attribute; 040import ptolemy.kernel.util.ChangeListener; 041import ptolemy.kernel.util.ChangeRequest; 042import ptolemy.kernel.util.IllegalActionException; 043import ptolemy.kernel.util.NamedObj; 044import ptolemy.moml.MoMLChangeRequest; 045import ptolemy.util.MessageHandler; 046import ptolemy.util.StringUtilities; 047 048/////////////////////////////////////////////////////////////////// 049//// RenameConfigurer 050 051/** 052 This class is an editor widget to rename an object. 053 054 @see Configurer 055 @author Edward A. Lee 056 @version $Id$ 057 @since Ptolemy II 1.0 058 @Pt.ProposedRating Yellow (eal) 059 @Pt.AcceptedRating Red (neuendor) 060 */ 061@SuppressWarnings("serial") 062public class RenameConfigurer extends Query 063 implements ChangeListener, QueryListener { 064 /** Construct a rename configurer for the specified entity. 065 * @param object The entity to configure. 066 */ 067 public RenameConfigurer(NamedObj object) { 068 super(); 069 this.addQueryListener(this); 070 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 071 setTextWidth(25); 072 _object = object; 073 addLine(_NAME_LABEL, _NAME_LABEL, object.getName()); 074 addTextArea(_DISPLAY_NAME_LABEL, _DISPLAY_NAME_LABEL, 075 object.getDisplayName()); 076 077 // By default, names are not shown for ports, and are shown 078 // for everything else. Note that ports are a little confusing, 079 // because names are _always_ shown for external ports inside 080 // a composite actor. This dialog determines whether they will 081 // be shown on the outside of the composite actor. 082 boolean nameShowing = false; 083 084 if (object instanceof Port) { 085 nameShowing = _isPropertySet(_object, "_showName"); 086 } else { 087 nameShowing = !_isPropertySet(_object, "_hideName"); 088 } 089 090 // Don't include the Show name check box for 091 // AbstractSettableAttributes We choose 092 // AbstractSettableAttribute because we don't want the 093 // "Show name" check box for RequireVersion, which eventually 094 // extends AbstractSettableAttribute, but we do want the 095 // "Show name" check box for Director, which extends Attribute. 096 // See 097 // http://bugzilla.ecoinformatics.org/show_bug.cgi?id=3363 098 if (!(object instanceof AbstractSettableAttribute)) { 099 addCheckBox("Show name", "Show name", nameShowing); 100 } 101 } 102 103 /////////////////////////////////////////////////////////////////// 104 //// public methods //// 105 106 /** Apply the changes by renaming the object. 107 */ 108 public void apply() { 109 if (_changed) { 110 String newName = StringUtilities 111 .escapeForXML(getStringValue(_NAME_LABEL)); 112 String displayName = StringUtilities 113 .escapeForXML(getStringValue(_DISPLAY_NAME_LABEL)); 114 115 NamedObj parent = _object.getContainer(); 116 if (parent == null) { 117 // Hitting F2 in an empty model and renaming the canvas can result in a NPE. 118 // See https://chess.eecs.berkeley.edu/bugzilla/show_bug.cgi?id=355 119 MessageHandler.message( 120 "Please save the model before changing the name."); 121 return; 122 } 123 String oldName = StringUtilities.escapeForXML(_object.getName()); 124 String oldDisplayName = StringUtilities 125 .escapeForXML(_object.getDisplayName()); 126 127 StringBuffer moml = new StringBuffer("<"); 128 String elementName = _object.getElementName(); 129 moml.append(elementName); 130 moml.append(" name=\""); 131 moml.append(oldName); 132 moml.append("\">"); 133 if (!oldName.equals(newName)) { 134 moml.append("<rename name=\""); 135 moml.append(newName); 136 moml.append("\"/>"); 137 } 138 if (!oldDisplayName.equals(displayName)) { 139 moml.append("<display name=\""); 140 moml.append(displayName); 141 moml.append("\"/>"); 142 } 143 144 // Don't include the Show name check box for AbstractSettableAttributes 145 // http://bugzilla.ecoinformatics.org/show_bug.cgi?id=3363 146 if (!(_object instanceof AbstractSettableAttribute)) { 147 // Remove or show name. 148 boolean showName = getBooleanValue("Show name"); 149 150 if (_object instanceof Port) { 151 boolean previousShowName = _isPropertySet(_object, 152 "_showName"); 153 154 if (showName != previousShowName) { 155 if (showName) { 156 moml.append("<property name=\"_showName\" " 157 + "class=\"ptolemy.data.expr.SingletonParameter\"" 158 + " value=\"true\"/>"); 159 } else { 160 if (!(_object.getAttribute( 161 "_showName") instanceof Parameter)) { 162 moml.append( 163 "<deleteProperty name=\"_showName\"/>"); 164 } else { 165 moml.append("<property name=\"_showName\" " 166 + "class=\"ptolemy.data.expr.SingletonParameter\"" 167 + " value=\"false\"/>"); 168 } 169 } 170 } 171 } else { 172 boolean previousShowName = !_isPropertySet(_object, 173 "_hideName"); 174 175 if (showName != previousShowName) { 176 if (showName) { 177 if (!(_object.getAttribute( 178 "_hideName") instanceof Parameter)) { 179 moml.append( 180 "<deleteProperty name=\"_hideName\"/>"); 181 } else { 182 moml.append("<property name=\"_hideName\" " 183 + "class=\"ptolemy.data.expr.SingletonParameter\"" 184 + " value=\"false\"/>"); 185 } 186 } else { 187 moml.append("<property name=\"_hideName\" " 188 + "class=\"ptolemy.data.expr.SingletonParameter\"" 189 + " value=\"true\"/>"); 190 } 191 } 192 } 193 } 194 195 moml.append("</"); 196 moml.append(elementName); 197 moml.append(">"); 198 199 MoMLChangeRequest request = new MoMLChangeRequest(this, // originator 200 parent, // context 201 moml.toString(), // MoML code 202 null); // base 203 204 request.addChangeListener(this); 205 request.setUndoable(true); 206 parent.requestChange(request); 207 } 208 } 209 210 /** React to the fact that the change has been successfully executed 211 * by doing nothing. 212 * @param change The change that has been executed. 213 */ 214 @Override 215 public void changeExecuted(ChangeRequest change) { 216 // Nothing to do. 217 } 218 219 /** React to the fact that the change has failed by reporting it. 220 * @param change The change that was attempted. 221 * @param exception The exception that resulted. 222 */ 223 @Override 224 public void changeFailed(ChangeRequest change, Exception exception) { 225 // Ignore if this is not the originator. 226 if (change != null && change.getSource() != this) { 227 return; 228 } 229 230 if (change != null && !change.isErrorReported()) { 231 change.setErrorReported(true); 232 MessageHandler.error("Rename failed: ", exception); 233 } 234 } 235 236 /** Called to notify that one of the entries has changed. 237 * This simply sets a flag that enables application of the change 238 * when the apply() method is called. 239 * @param name The name of the entry that changed. 240 */ 241 @Override 242 public void changed(String name) { 243 _changed = true; 244 } 245 246 /** 247 * Get the object upon which this RenameConfigurer is operating. 248 * @return The object. 249 */ 250 public NamedObj getObject() { 251 // This method makes it possible to determine which object is being 252 // renamed. This is especially useful when dealing with the 253 // MoMLChangeRequest generated by this class from other classes. 254 return _object; 255 } 256 257 /////////////////////////////////////////////////////////////////// 258 //// private methods //// 259 260 /** Return true if the property of the specified name is set for 261 * the specified object. A property is specified if the specified 262 * object contains an attribute with the specified name and that 263 * attribute is either not a boolean-valued parameter, or it is 264 * a boolean-valued parameter with value true. 265 * @param object The object. 266 * @param name The property name. 267 * @return True if the property is set. 268 */ 269 private boolean _isPropertySet(NamedObj object, String name) { 270 Attribute attribute = object.getAttribute(name); 271 272 if (attribute == null) { 273 return false; 274 } 275 276 if (attribute instanceof Parameter) { 277 try { 278 Token token = ((Parameter) attribute).getToken(); 279 280 if (token instanceof BooleanToken) { 281 if (!((BooleanToken) token).booleanValue()) { 282 return false; 283 } 284 } 285 } catch (IllegalActionException e) { 286 // Ignore, using default of true. 287 } 288 } 289 290 return true; 291 } 292 293 /////////////////////////////////////////////////////////////////// 294 //// private variables //// 295 // Indicator that the name has changed. 296 private boolean _changed = false; 297 298 // The object that this configurer configures. 299 private NamedObj _object; 300 301 private static String _NAME_LABEL = "Name"; 302 private static String _DISPLAY_NAME_LABEL = "Display name"; 303}