001/* An attribute that creates a text editor to edit a string attribute. 002 003 Copyright (c) 2003-2016 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.vergil.toolbox; 029 030import java.awt.Frame; 031import java.lang.reflect.Constructor; 032 033import javax.swing.text.Document; 034 035import ptolemy.actor.gui.EditorFactory; 036import ptolemy.data.IntToken; 037import ptolemy.data.expr.Parameter; 038import ptolemy.data.type.BaseType; 039import ptolemy.kernel.util.Attribute; 040import ptolemy.kernel.util.IllegalActionException; 041import ptolemy.kernel.util.NameDuplicationException; 042import ptolemy.kernel.util.NamedObj; 043import ptolemy.kernel.util.StringAttribute; 044import ptolemy.util.MessageHandler; 045 046/////////////////////////////////////////////////////////////////// 047//// TextEditorConfigureFactory 048 049/** 050 If this class is contained by a actor, then double clicking on that 051 actor will invoke a text editor that edits the value of a specified 052 string attribute. The string attribute must be contained by the 053 same container as this factory; its name is given by the 054 <i>attributeName</i> attribute of this factory. The number of 055 rows and columns displayed are given by the <i>rowsDisplayed</i> 056 and <i>columnsDisplayed</i> parameters. The default is 80 columns 057 and 40 rows. 058 <p> 059 This attribute is similar to TextEditorTableauFactory, except that 060 it opens the text editor when the containing actor is configured 061 (edit parameters), whereas TextEditorTableauFactory opens the text 062 editor when the user looks inside. 063 @see TextEditorTableauFactory 064 065 @author Edward A. Lee, contributor: Daniel Crawl 066 @version $Id$ 067 @since Ptolemy II 4.0 068 @Pt.ProposedRating Yellow (eal) 069 @Pt.AcceptedRating Red (ptolemy) 070 */ 071public class TextEditorConfigureFactory extends EditorFactory 072 implements TextEditorFactory { 073 /** Construct a factory with the specified container and name. 074 * @param container The container. 075 * @param name The name of the factory. 076 * @exception IllegalActionException If the factory is not of an 077 * acceptable attribute for the container. 078 * @exception NameDuplicationException If the name coincides with 079 * an attribute already in the container. 080 */ 081 public TextEditorConfigureFactory(NamedObj container, String name) 082 throws IllegalActionException, NameDuplicationException { 083 super(container, name); 084 085 attributeName = new StringAttribute(this, "attributeName"); 086 087 columnsDisplayed = new Parameter(this, "columnsDisplayed"); 088 columnsDisplayed.setTypeEquals(BaseType.INT); 089 columnsDisplayed.setExpression("80"); 090 091 rowsDisplayed = new Parameter(this, "rowsDisplayed"); 092 rowsDisplayed.setTypeEquals(BaseType.INT); 093 rowsDisplayed.setExpression("40"); 094 095 syntaxStyle = new StringAttribute(this, "syntaxStyle"); 096 097 } 098 099 /////////////////////////////////////////////////////////////////// 100 //// parameters //// 101 102 /** The name of the string attribute that is to be edited. */ 103 public StringAttribute attributeName; 104 105 /** The horizontal size of the display, in columns. This contains 106 * an integer, and defaults to 40. 107 */ 108 public Parameter columnsDisplayed; 109 110 /** The vertical size of the display, in rows. This contains an 111 * integer, and defaults to 10. 112 */ 113 public Parameter rowsDisplayed; 114 115 /** The style of the text to be edited. This may or may not be 116 * supported. If the package "org.fife.ui.rsyntaxtextarea" is found in 117 * the classpath, then the supported styles include 118 * "text/plain", "text/c", "text/clojure", "text/cpp", "text/cs", 119 * "text/css", "text/dtd", "text/fortran", 120 * "text/groovy", "text/html", "text/java", 121 * "text/javascript", "text/json", "text/jsp", 122 * "text/latex", "text/makefile", 123 * "text/perl", "text/php", 124 * "text/properties", "text/python", "text/ruby", "text/sas", 125 * "text/scala", "text/sql", "text/tcl", "text/unix", "text/vb", 126 * "text/bat", and "text/xml". 127 */ 128 public StringAttribute syntaxStyle; 129 130 /////////////////////////////////////////////////////////////////// 131 //// public methods //// 132 133 /** Remove any editor that may have been associated with this object 134 * by a previous call to createEditor(). 135 */ 136 @Override 137 public void clear() { 138 _editor = null; 139 } 140 141 /** Create an editor for editing the string attribute specified 142 * by the <i>attributeName</i> parameter. 143 * @param object The object to configure (which is expected to 144 * be the same as the container of this attribute). 145 * @param parent The frame with respect to which to define the 146 * editor. 147 */ 148 @Override 149 public void createEditor(NamedObj object, Frame parent) { 150 if (_editor == null) { 151 try { 152 StringAttribute attributeToEdit = (StringAttribute) getContainer() 153 .getAttribute(attributeName.getExpression(), 154 StringAttribute.class); 155 int numberOfRows = ((IntToken) rowsDisplayed.getToken()) 156 .intValue(); 157 int numberOfColumns = ((IntToken) columnsDisplayed.getToken()) 158 .intValue(); 159 160 String style = syntaxStyle.getExpression(); 161 if (style != null && !style.trim().equals("")) { 162 // Attempt to specify a syntax-aware text editor. 163 try { 164 165 Document doc = null; 166 try { 167 // Attempt to create a styled document. 168 // Use reflection here to avoid a hard dependency on an external package. 169 Class<?> docClass = Class.forName( 170 "org.fife.ui.rsyntaxtextarea.RSyntaxDocument"); 171 Constructor<?> docClassConstructor = docClass 172 .getConstructor(String.class); 173 doc = (Document) docClassConstructor 174 .newInstance(new Object[] { style }); 175 } catch (Throwable ex) { 176 // Ignore and use default text editor. 177 System.out.println( 178 "Note: failed to open syntax-directed editor: " 179 + ex.getMessage()); 180 } 181 182 if (doc != null) { 183 Class<?> editorClass = Class.forName( 184 "ptolemy.actor.gui.syntax.SyntaxTextEditorForStringAttributes"); 185 Constructor<?> constructor = editorClass 186 .getConstructor(new Class[] { 187 TextEditorFactory.class, 188 Attribute.class, Integer.TYPE, 189 Integer.TYPE, String.class, 190 Document.class }); 191 _editor = (TextEditorForStringAttributes) constructor 192 .newInstance(new Object[] { this, 193 attributeToEdit, numberOfRows, 194 numberOfColumns, 195 "Editor for " 196 + attributeName 197 .getExpression() 198 + " of " 199 + getContainer() 200 .getFullName(), 201 doc }); 202 203 _editor.text.append(TextEditorTableauFactory 204 .getTextToEdit(attributeToEdit)); 205 // The above will mark the text object modified. Reverse this. 206 _editor.setModified(false); 207 208 } 209 } catch (Throwable ex) { 210 // Ignore and use default text editor. 211 System.out.println( 212 "Note: failed to open syntax-directed editor: " 213 + ex.getMessage()); 214 } 215 } 216 if (_editor == null) { 217 _editor = new TextEditorForStringAttributes(this, 218 attributeToEdit, numberOfRows, numberOfColumns, 219 "Editor for " + attributeName.getExpression() 220 + " of " + getContainer().getFullName()); 221 } 222 } catch (IllegalActionException ex) { 223 MessageHandler.error( 224 "Cannot get specified string attribute to edit.", ex); 225 } 226 if (_editor == null) { 227 throw new NullPointerException("Could not create editor for " 228 + object.getFullName() + " in frame " + parent); 229 } else { 230 // Can't just call show() here because after calling pack() and 231 // before making visible we need to call adjustFileMenu(). 232 // Also, can't do this if the editor has already been created. 233 _editor.pack(); 234 _editor.adjustFileMenu(); 235 _editor.centerOnScreen(); 236 } 237 } 238 _editor.setVisible(true); 239 } 240 241 /** Return the current text of the text editor. 242 * @return The current text of the text editor, or null if there 243 * is none. 244 */ 245 @Override 246 public String getText() { 247 if (_editor != null) { 248 return _editor.text.getText(); 249 } 250 251 return null; 252 } 253 254 /////////////////////////////////////////////////////////////////// 255 //// private members //// 256 // Keep track of an open editor so that it isn't opened more than 257 // once. 258 private TextEditorForStringAttributes _editor; 259}