001/** Default preferences definition for Vergil. */ 002 003/* 004 Copyright (c) 2006-2014 The Regents of the University of California. 005 All rights reserved. 006 007 Permission is hereby granted, without written agreement and without 008 license or royalty fees, to use, copy, modify, and distribute this 009 software and its documentation for any purpose, provided that the above 010 copyright notice and the following two paragraphs appear in all copies 011 of this software. 012 013 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 014 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 015 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 016 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 017 SUCH DAMAGE. 018 019 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 020 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 021 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 022 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 023 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 024 ENHANCEMENTS, OR MODIFICATIONS. 025 */ 026 027package ptolemy.actor.gui; 028 029import java.io.File; 030import java.io.FileWriter; 031import java.io.IOException; 032import java.net.MalformedURLException; 033import java.net.URL; 034import java.util.Iterator; 035 036import ptolemy.data.BooleanToken; 037import ptolemy.data.Token; 038import ptolemy.data.expr.Constants; 039import ptolemy.data.expr.ModelScope; 040import ptolemy.data.expr.Parameter; 041import ptolemy.data.expr.ScopeExtendingAttribute; 042import ptolemy.data.expr.SingletonParameter; 043import ptolemy.data.expr.StringParameter; 044import ptolemy.data.expr.Variable; 045import ptolemy.data.type.BaseType; 046import ptolemy.kernel.util.Attribute; 047import ptolemy.kernel.util.IllegalActionException; 048import ptolemy.kernel.util.NameDuplicationException; 049import ptolemy.kernel.util.NamedObj; 050import ptolemy.kernel.util.Settable; 051import ptolemy.moml.MoMLParser; 052import ptolemy.util.StringUtilities; 053 054/////////////////////////////////////////////////////////////////// 055//// PtolemyPreferences 056 057/** 058 * Default preferences definition for Vergil. This is defined as a class rather 059 * than in MoML so that the inheritance mechanism prevents exported MoML for 060 * every model from duplicating this information. 061 * 062 * @author Edward A. Lee, Contributor: Bert Rodiers 063 * @version $Id$ 064 @since Ptolemy II 5.2 065 * @Pt.ProposedRating Yellow (eal) 066 * @Pt.AcceptedRating Red (cxh) 067 */ 068public class PtolemyPreferences extends ScopeExtendingAttribute { 069 /** Construct an instance of the preferences attribute. 070 * @param container The container. 071 * @param name The name. 072 * @exception IllegalActionException If the attribute is not of an 073 * acceptable class for the container, or if the name contains a period. 074 * @exception NameDuplicationException If the name coincides with 075 * an attribute already in the container. 076 */ 077 public PtolemyPreferences(NamedObj container, String name) 078 throws IllegalActionException, NameDuplicationException { 079 super(container, name); 080 081 // Give the default values for all the preferences. 082 // Names start with underscores by convention to minimize 083 // the probability of conflict with model-specific parameters. 084 // Note that the default values here should conform with the 085 // defaults used in the code where these preferences are checked, 086 // if there are any. It's a good idea to provide them in 087 // case setAsDefault() is never called. 088 Parameter relationSize = new Parameter(this, "_relationSize"); 089 relationSize.setTypeEquals(BaseType.DOUBLE); 090 relationSize.setExpression("12.0"); 091 relationSize.setDisplayName("Relation size"); 092 093 Parameter portSize = new Parameter(this, "_portSize"); 094 portSize.setTypeEquals(BaseType.DOUBLE); 095 portSize.setExpression("4.0"); 096 portSize.setDisplayName("Port size"); 097 098 Parameter linkBendRadius = new Parameter(this, "_linkBendRadius"); 099 linkBendRadius.setTypeEquals(BaseType.DOUBLE); 100 linkBendRadius.setExpression("20.0"); 101 linkBendRadius.setDisplayName("Link bend radius"); 102 103 backgroundColor = new ColorAttribute(this, "backgroundColor"); 104 backgroundColor.setExpression("{0.9, 0.9, 0.9, 1.0}"); 105 backgroundColor.setDisplayName("Background Color"); 106 107 StringParameter showParameters = new StringParameter(this, 108 "_showParameters"); 109 showParameters.addChoice("None"); 110 showParameters.addChoice("Overridden parameters only"); 111 showParameters.addChoice("All"); 112 showParameters.setExpression("None"); 113 showParameters.setDisplayName("Show parameters"); 114 115 Parameter checkWidthConsistencyAtMultiports = new Parameter(this, 116 "_checkWidthConsistencyAtMultiports"); 117 checkWidthConsistencyAtMultiports.setTypeEquals(BaseType.BOOLEAN); 118 checkWidthConsistencyAtMultiports.setExpression("true"); 119 checkWidthConsistencyAtMultiports 120 .setDisplayName("Check width consistency at multiports"); 121 122 Parameter checkWidthConstraints = new Parameter(this, 123 "_checkWidthConstraints"); 124 checkWidthConstraints.setTypeEquals(BaseType.BOOLEAN); 125 checkWidthConstraints.setExpression("true"); 126 checkWidthConstraints.setDisplayName("Check width constraints"); 127 128 Parameter defaultInferredWidthTo1 = new Parameter(this, 129 "_defaultInferredWidthTo1"); 130 defaultInferredWidthTo1.setTypeEquals(BaseType.BOOLEAN); 131 defaultInferredWidthTo1.setExpression("false"); 132 defaultInferredWidthTo1.setDisplayName("Default inferred width to 1"); 133 134 // The icon. 135 _attachText("_iconDescription", "<svg>\n" + "<rect x=\"-60\" y=\"-10\" " 136 + "width=\"120\" height=\"20\" " + "style=\"fill:#00FFFF\"/>\n" 137 + "<text x=\"-55\" y=\"5\" " 138 + "style=\"font-size:14; font-family:SansSerif; fill:blue\">\n" 139 + "LocalPreferences\n" + "</text>\n" + "</svg>\n"); 140 // Hide the name. 141 SingletonParameter hideName = new SingletonParameter(this, "_hideName"); 142 hideName.setToken(BooleanToken.TRUE); 143 hideName.setVisibility(Settable.EXPERT); 144 } 145 146 /////////////////////////////////////////////////////////////////// 147 //// public parameters //// 148 149 /** The background color. */ 150 public ColorAttribute backgroundColor; 151 152 /////////////////////////////////////////////////////////////////// 153 //// public methods //// 154 155 /** Get the PtolemyPreferences within the specified configuration. 156 * @param configuration The configuration in which to search for 157 * {@link #PREFERENCES_WITHIN_CONFIGURATION} 158 * @return The associated PtolemyPreferences or null if not found. 159 * @exception IllegalActionException If there is a problem getting the 160 * {@link #PREFERENCES_WITHIN_CONFIGURATION} attribute. 161 */ 162 public static PtolemyPreferences getPtolemyPreferencesWithinConfiguration( 163 Configuration configuration) throws IllegalActionException { 164 PtolemyPreferences preferences = null; 165 166 try { 167 preferences = (PtolemyPreferences) configuration.getAttribute( 168 PtolemyPreferences.PREFERENCES_WITHIN_CONFIGURATION, 169 PtolemyPreferences.class); 170 } catch (IllegalActionException ex) { 171 return null; 172 } 173 return preferences; 174 } 175 176 /** Check to see whether a preference of the specified name is 177 * defined in the specified context, and if it is, return its value. 178 * Note that if there is an error in the expression for the preference, 179 * then this method will return null and report the error to standard out. 180 * This is done because we assume the error will normally be caught 181 * before this method is called. 182 * @param context The context for the preference. 183 * @param preferenceName The name of the preference. 184 * @return The value of the preference, or null if it is not set. 185 */ 186 public static Token preferenceValue(NamedObj context, 187 String preferenceName) { 188 return ModelScope.preferenceValue(context, preferenceName); 189 } 190 191 /** Check to see whether a preference of the specified name is 192 * defined in the container of the specified context, either directly 193 * or within an instance of PtolemyPreferences, or 194 * globally, and if it is, return it's value. Do not look any higher 195 * in the hierarchy. 196 * Note that if there is an error in the expression for the preference, 197 * then this method will return null and report the error to standard out. 198 * This is done because we assume the error will normally be caught 199 * before this method is called. 200 * @param context The context for the preference. 201 * @param preferenceName The name of the preference. 202 * @return The value of the preference, or null if it is not set. 203 */ 204 public static Token preferenceValueLocal(NamedObj context, 205 String preferenceName) { 206 try { 207 NamedObj container = context.getContainer(); 208 if (container != null) { 209 Attribute attribute = container.getAttribute(preferenceName); 210 if (attribute instanceof Variable) { 211 return ((Variable) attribute).getToken(); 212 } 213 Iterator<?> preferences = container 214 .attributeList(PtolemyPreferences.class).iterator(); 215 while (preferences.hasNext()) { 216 PtolemyPreferences preference = (PtolemyPreferences) preferences 217 .next(); 218 attribute = preference.getAttribute(preferenceName); 219 if (attribute instanceof Variable) { 220 return ((Variable) attribute).getToken(); 221 } 222 } 223 } 224 } catch (IllegalActionException ex) { 225 System.out.println("Warning: Invalid preference: " + ex); 226 } 227 // If no scoped variable is found, try for a defined constant. 228 return Constants.get(preferenceName); 229 } 230 231 /** Save the preference values in this instance to the user 232 * preferences file. 233 * @exception IOException If an error occurs writing the file. 234 */ 235 public void save() throws IOException { 236 String libraryName = StringUtilities.preferencesDirectory() 237 + PREFERENCES_FILE_NAME; 238 File file = new File(libraryName); 239 FileWriter writer = null; 240 try { 241 writer = new FileWriter(file); 242 exportMoML(writer); 243 } finally { 244 if (writer != null) { 245 try { 246 writer.close(); 247 } catch (IOException ex) { 248 System.out.println( 249 "Failed to close \"" + libraryName + "\": " + ex); 250 251 } 252 } 253 } 254 } 255 256 /** Set the values in this instance of PtolemyPreferences to be 257 * the default values by creating entries in the Constants class 258 * so that these values are accessible to any expression. 259 * @exception IllegalActionException If any expression for 260 * a preference cannot be evaluated. 261 */ 262 public void setAsDefault() throws IllegalActionException { 263 // Make the current global variables conform with any 264 // overridden preference values. 265 Iterator<?> parameters = attributeList(Variable.class).iterator(); 266 267 while (parameters.hasNext()) { 268 Variable parameter = (Variable) parameters.next(); 269 Token token = parameter.getToken(); 270 Constants.add(parameter.getName(), token); 271 } 272 } 273 274 /** Look for a default preferences object within the 275 * specified configuration, and set it as the default 276 * preferences. Then look for a user preferences file, 277 * and override the default preferences with the contents 278 * of that file. This method prints warning messages 279 * on standard out if there are problems with the 280 * preferences. 281 * @param configuration The specified configuration. 282 */ 283 public static void setDefaultPreferences(Configuration configuration) { 284 PtolemyPreferences preferences = null; 285 try { 286 preferences = getPtolemyPreferencesWithinConfiguration( 287 configuration); 288 } catch (IllegalActionException ex) { 289 System.out.println("Warning: Problem with preferences attribute " 290 + "in the configuration: " + ex.getMessage()); 291 292 // Can't do anything further. 293 return; 294 } 295 296 if (preferences == null) { 297 // No preferences found in the configuration at 298 // location "actor library.Utilities.LocalPreferences" 299 return; 300 } 301 302 // Now override with the user file, if present. 303 String libraryName = null; 304 305 try { 306 libraryName = StringUtilities.preferencesDirectory() 307 + PREFERENCES_FILE_NAME; 308 } catch (Exception ex) { 309 System.out.println("Warning: Failed to get the preferences " 310 + "directory (-sandbox always causes this): " 311 + ex.getMessage()); 312 313 // Can't do anything further. 314 return; 315 } 316 317 File file = new File(libraryName); 318 319 if (file.isFile() && file.canRead()) { 320 // If we have a jar URL, convert spaces to %20 321 URL fileURL; 322 323 try { 324 fileURL = JNLPUtilities 325 .canonicalizeJarURL(file.toURI().toURL()); 326 } catch (MalformedURLException ex) { 327 // This should not occur. 328 System.err.println("Malformed preferences URL: " + ex); 329 return; 330 } 331 332 MoMLParser parser = new MoMLParser(preferences.workspace()); 333 parser.setContext(preferences.getContainer()); 334 335 // Set the ErrorHandler so that if we have 336 // compatibility problems between devel and production 337 // versions, we can skip that element. 338 // MoMLParser.setErrorHandler(new VergilErrorHandler()); 339 340 try { 341 parser.parse(fileURL, fileURL); 342 } catch (Exception ex) { 343 System.out 344 .println("Failed to read user preferences file: " + ex); 345 } 346 } 347 348 try { 349 preferences.setAsDefault(); 350 } catch (IllegalActionException ex) { 351 System.out.println("Warning: Problem with preferences value: " 352 + ex.getMessage()); 353 } 354 } 355 356 /////////////////////////////////////////////////////////////////// 357 //// public variables //// 358 359 /** The file name where user-defined preferences are stored. */ 360 public static final String PREFERENCES_FILE_NAME = "PtolemyPreferences.xml"; 361 362 /** The location with the configuration of the preferences attribute. */ 363 public static final String PREFERENCES_WITHIN_CONFIGURATION = "actor library.Utilities.LocalPreferences"; 364}