001/* An attribute that creates an editor pane to edit the icon description. 002 003 Copyright (c) 1998-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.Component; 031import java.awt.Dimension; 032import java.awt.Frame; 033import java.awt.GraphicsEnvironment; 034import java.io.Reader; 035import java.io.StringReader; 036import java.net.URL; 037import java.util.Iterator; 038import java.util.StringTokenizer; 039 040import javax.swing.JPanel; 041import javax.swing.JScrollPane; 042import javax.swing.JTextArea; 043 044import diva.canvas.toolbox.SVGParser; 045import diva.util.xml.XmlDocument; 046import diva.util.xml.XmlElement; 047import diva.util.xml.XmlReader; 048import ptolemy.actor.gui.EditorFactory; 049import ptolemy.gui.ComponentDialog; 050import ptolemy.gui.Query; 051import ptolemy.kernel.util.ConfigurableAttribute; 052import ptolemy.kernel.util.IllegalActionException; 053import ptolemy.kernel.util.InternalErrorException; 054import ptolemy.kernel.util.KernelException; 055import ptolemy.kernel.util.NameDuplicationException; 056import ptolemy.kernel.util.NamedObj; 057import ptolemy.kernel.util.SingletonConfigurableAttribute; 058import ptolemy.moml.MoMLChangeRequest; 059 060/////////////////////////////////////////////////////////////////// 061//// AnnotationEditorFactory 062 063/** 064 If this class is contained by a visible attribute (one that has 065 an attribute called "_iconDescription"), then double clicking on that 066 attribute will invoke an editor for a textual annotation. 067 This class is contained by visible attribute in the Vergil 068 utilities library, which provides a facility for adding visual 069 annotations to diagrams. 070 071 @author Edward A. Lee 072 @version $Id$ 073 @since Ptolemy II 2.0 074 @Pt.ProposedRating Red (eal) 075 @Pt.AcceptedRating Red (johnr) 076 @deprecated Use ptolemy.vergil.kernel.attributes.TextAttribute. 077 */ 078@Deprecated 079public class AnnotationEditorFactory extends EditorFactory { 080 /** Construct a factory with the specified container and name. 081 * @param container The container. 082 * @param name The name of the factory. 083 * @exception IllegalActionException If the factory is not of an 084 * acceptable attribute for the container. 085 * @exception NameDuplicationException If the name coincides with 086 * an attribute already in the container. 087 */ 088 public AnnotationEditorFactory(NamedObj container, String name) 089 throws IllegalActionException, NameDuplicationException { 090 super(container, name); 091 _container = container; 092 } 093 094 /////////////////////////////////////////////////////////////////// 095 //// public methods //// 096 097 /** Create an editor for configuring the specified object. 098 */ 099 @Override 100 public void createEditor(NamedObj object, Frame parent) { 101 ComponentDialog dialog = new ComponentDialog(parent, "Edit Annotation", 102 createEditorPane()); 103 104 String button = dialog.buttonPressed(); 105 106 if (!button.equals("OK")) { 107 return; 108 } 109 110 String newText = _textArea.getText(); 111 112 if (newText == null || newText.trim().equals("")) { 113 // NOTE: Should we delete the attribute... no visible text. 114 newText = "Double click to edit text."; 115 } 116 117 String moml = "<configure><svg><text x=\"20\" y=\"20\" " 118 + "style=\"font-size:" 119 + _fontProperties.getStringValue("fontSize") + "; font-family:" 120 + _fontProperties.getStringValue("fontFamily") + "; fill:" 121 + _fontProperties.getStringValue("fontColor") + "\">" + newText 122 + "</text></svg></configure>"; 123 _iconDescription.requestChange( 124 new MoMLChangeRequest(this, _iconDescription, moml)); 125 } 126 127 /** Return a new widget for configuring the container. 128 * @return A JPanel that is a text editor for editing the annotation text. 129 */ 130 public Component createEditorPane() { 131 _textArea = new JTextArea(); 132 _iconDescription = (ConfigurableAttribute) _container 133 .getAttribute("_iconDescription"); 134 135 if (_iconDescription == null) { 136 try { 137 _iconDescription = new SingletonConfigurableAttribute( 138 _container, "_iconDescription"); 139 } catch (KernelException ex) { 140 // Cannot occur. 141 throw new InternalErrorException(ex.toString()); 142 } 143 } 144 145 // Parse the SVG to find the text. 146 String text = _iconDescription.getExpression(); 147 148 // Default font characteristics. 149 _fontSize = "14"; 150 _fontFamily = "SansSerif"; 151 _fontColor = "blue"; 152 153 try { 154 Reader in = new StringReader(text); 155 156 // NOTE: Do we need a base here? 157 XmlDocument document = new XmlDocument((URL) null); 158 XmlReader reader = new XmlReader(); 159 reader.parse(document, in); 160 161 XmlElement root = document.getRoot(); 162 String name = root.getType(); 163 164 if (name.equals("svg")) { 165 Iterator children = root.elements(); 166 167 while (children.hasNext()) { 168 XmlElement child = (XmlElement) children.next(); 169 name = child.getType(); 170 171 if (name.equals("text")) { 172 text = child.getPCData(); 173 174 String style = (String) child.getAttributeMap() 175 .get("style"); 176 177 if (style != null) { 178 StringTokenizer tokenizer = new StringTokenizer( 179 style, ";"); 180 181 while (tokenizer.hasMoreTokens()) { 182 String token = tokenizer.nextToken(); 183 int colon = token.indexOf(":"); 184 185 if (colon > 0) { 186 String property = token.substring(0, colon) 187 .trim(); 188 189 if (property.equals("fill")) { 190 _fontColor = token.substring(colon + 1); 191 } else if (property.equals("font-size")) { 192 _fontSize = token.substring(colon + 1); 193 } else if (property.equals("font-family")) { 194 _fontFamily = token 195 .substring(colon + 1); 196 } 197 } 198 } 199 } 200 201 // We are done once we find a text element. 202 break; 203 } 204 } 205 } 206 } catch (Exception ex) { 207 // If we fail, then we use the text as is. 208 } 209 210 _textArea.setText(text); 211 212 AnnotationTextEditor editor = new AnnotationTextEditor(_textArea); 213 return editor; 214 } 215 216 /////////////////////////////////////////////////////////////////// 217 //// private members //// 218 219 /** The container. */ 220 private NamedObj _container; 221 222 /** Query box for font properties. */ 223 Query _fontProperties; 224 225 /** Font characteristic. */ 226 private String _fontSize = "14"; 227 228 private String _fontFamily = "sanserif"; 229 230 private String _fontColor = "blue"; 231 232 /** The attribute containing the icon description. */ 233 private ConfigurableAttribute _iconDescription; 234 235 /** The text area of the editor. */ 236 private JTextArea _textArea; 237 238 /////////////////////////////////////////////////////////////////// 239 //// inner classes //// 240 241 /** A text widget for editing textual annotations (which are 242 * visible attributes). 243 */ 244 @SuppressWarnings("serial") 245 public class AnnotationTextEditor extends JPanel { 246 /** Create an annotation text editor. 247 * @param textArea The text area. 248 */ 249 public AnnotationTextEditor(JTextArea textArea) { 250 super(); 251 252 JScrollPane pane = new JScrollPane(textArea); 253 254 // NOTE: Should the size be hardwired here? 255 pane.setPreferredSize(new Dimension(600, 300)); 256 add(pane); 257 258 // Add a query with font properties. 259 _fontProperties = new Query(); 260 261 String[] sizes = { "9", "10", "11", "12", "14", "18", "24", "32" }; 262 _fontProperties.addChoice("fontSize", "font size", sizes, _fontSize, 263 true); 264 265 // FIXME: Need a way to specify Italic, Bold (style). 266 // Check SVG standard and SVGParser. 267 // Get font family names from the Font class in Java. 268 // This includes logical font names, per Font class in Java: 269 // Dialog, DialogInput, Monospaced, Serif, SansSerif, or Symbol. 270 String[] families = GraphicsEnvironment 271 .getLocalGraphicsEnvironment() 272 .getAvailableFontFamilyNames(); 273 _fontProperties.addChoice("fontFamily", "font family", families, 274 _fontFamily, false); 275 276 // FIXME: Add a facility to invoke a color chooser using 277 // JColorChooser. 278 // public static Color showDialog(Component component (parent), 279 // String title, 280 // Color initialColor) 281 String[] colors = SVGParser.colorNames(); 282 283 // The last argument makes this editable. 284 // Colors can be given in hex #rrggbb. 285 _fontProperties.addChoice("fontColor", "font color", colors, 286 _fontColor, true); 287 288 add(_fontProperties); 289 } 290 } 291}