001/* An icon editor frame for Ptolemy models.
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.icon;
029
030import java.awt.Color;
031import java.awt.geom.AffineTransform;
032import java.awt.geom.Point2D;
033import java.net.URL;
034
035import diva.canvas.FigureLayer;
036import diva.canvas.JCanvas;
037import diva.canvas.toolbox.BasicRectangle;
038import diva.graph.GraphPane;
039import ptolemy.actor.gui.Configuration;
040import ptolemy.actor.gui.Tableau;
041import ptolemy.kernel.CompositeEntity;
042import ptolemy.kernel.util.InternalErrorException;
043import ptolemy.kernel.util.NamedObj;
044import ptolemy.kernel.util.Workspace;
045import ptolemy.moml.LibraryAttribute;
046import ptolemy.moml.MoMLParser;
047import ptolemy.vergil.actor.ActorGraphModel;
048import ptolemy.vergil.basic.BasicGraphFrame;
049
050///////////////////////////////////////////////////////////////////
051//// EditIconFrame
052
053/**
054 This is an icon editor frame for Ptolemy II models.
055 <p>
056 One aspect in which this editor differs from the base class is that it
057 does not support the "drop into" feature, where if you drop a new instance
058 onto an instance of NamedObj, that instance of NamedObj becomes the container
059 of the new object.  This feature is not useful for icon editing, and results
060 in visual elements mysteriously disappearing when they are dropped.
061
062 @author  Edward A. Lee
063 @version $Id$
064 @since Ptolemy II 4.0
065 @Pt.ProposedRating Red (eal)
066 @Pt.AcceptedRating Red (johnr)
067 */
068@SuppressWarnings("serial")
069public class EditIconFrame extends BasicGraphFrame {
070    /** Construct a frame to edit the specified icon.
071     *  After constructing this, it is necessary
072     *  to call setVisible(true) to make the frame appear.
073     *  This is typically done by calling show() on the controlling tableau.
074     *  This constructor results in a frame that obtains its library
075     *  either from the model (if it has one) or the default library defined
076     *  in the configuration.
077     *  @see Tableau#show()
078     *  @param icon The icon to put in this frame.
079     *  @param tableau The tableau responsible for this frame.
080     */
081    public EditIconFrame(EditorIcon icon, Tableau tableau) {
082        this(icon, tableau, null);
083    }
084
085    /** Construct a frame to edit the specified icon.
086     *  After constructing this, it is necessary
087     *  to call setVisible(true) to make the frame appear.
088     *  This is typically done by calling show() on the controlling tableau.
089     *  This constructor results in a graph frame that obtains its library
090     *  either from the model (if it has one), or the <i>defaultLibrary</i>
091     *  argument (if it is non-null), or the default library defined
092     *  in the configuration.
093     *  @see Tableau#show()
094     *  @param entity The model to put in this frame.
095     *  @param tableau The tableau responsible for this frame.
096     *  @param defaultLibrary An attribute specifying the default library
097     *   to use if the model does not have a library.
098     */
099    public EditIconFrame(EditorIcon entity, Tableau tableau,
100            LibraryAttribute defaultLibrary) {
101        super(entity, tableau, defaultLibrary);
102
103        _setDropIntoEnabled(false);
104
105        // Override the default help file.
106        helpFile = "ptolemy/configs/doc/vergilGraphEditorHelp.htm";
107
108        zoomReset();
109
110        _drawReferenceBox();
111    }
112
113    ///////////////////////////////////////////////////////////////////
114    ////                         public methods                    ////
115
116    /** Set zoom to the nominal.  This overrides the base class to set
117     *  a zoom factor and center more appropriate for editing icons.
118     */
119    @Override
120    public void zoomReset() {
121        JCanvas canvas = getJGraph().getGraphPane().getCanvas();
122        AffineTransform current = canvas.getCanvasPane().getTransformContext()
123                .getTransform();
124        current.setToScale(_ZOOM_SCALE, _ZOOM_SCALE);
125        canvas.getCanvasPane().setTransform(current);
126        setCenter(new Point2D.Double(0.0, 0.0));
127
128        if (_graphPanner != null) {
129            _graphPanner.repaint();
130        }
131    }
132
133    ///////////////////////////////////////////////////////////////////
134    ////                         protected methods                 ////
135
136    /** Create the menus that are used by this frame.
137     *  It is essential that _createGraphPane() be called before this.
138     */
139    @Override
140    protected void _addMenus() {
141        super._addMenus();
142    }
143
144    /** Create the default library to use if an entity has no
145     *  LibraryAttribute.  Note that this is called in the
146     *  constructor and therefore overrides in subclasses
147     *  should not refer to any members that may not have been
148     *  initialized.  This method overrides the base class to
149     *  look for a library called "icon library" in the
150     *  configuration. If there is no such library, then
151     *  it provides a simple default library, created in
152     *  the specified workspace.
153     *  @param workspace The workspace in which to create
154     *   the library, if one needs to be created.
155     *  @return The new library, or null if there is no
156     *   configuration.
157     */
158    @Override
159    protected CompositeEntity _createDefaultLibrary(Workspace workspace) {
160        Configuration configuration = getConfiguration();
161
162        if (configuration != null) {
163            CompositeEntity result = (CompositeEntity) configuration
164                    .getEntity("icon editor library");
165
166            if (result == null) {
167                // Create a default library by directly reading the
168                // default XML description.
169                URL source = getClass().getClassLoader().getResource(
170                        "ptolemy/vergil/kernel/attributes/iconEditorLibrary.xml");
171                MoMLParser parser = new MoMLParser(workspace);
172
173                try {
174                    result = (CompositeEntity) parser.parse(null, source);
175                } catch (Exception e) {
176                    throw new InternalErrorException(
177                            "Unable to open default icon editor library: " + e);
178                }
179            }
180
181            return result;
182        } else {
183            return null;
184        }
185    }
186
187    /** Create a new graph pane. Note that this method is called in
188     *  constructor of the base class, so it must be careful to not reference
189     *  local variables that may not have yet been created.
190     *  @param entity The object to be displayed in the pane.
191     *  @return The pane that is created.
192     */
193    @Override
194    protected GraphPane _createGraphPane(NamedObj entity) {
195        _controller = new EditIconGraphController();
196        _controller.setConfiguration(getConfiguration());
197        _controller.setFrame(this);
198
199        ActorGraphModel graphModel = new ActorGraphModel(entity);
200        return new GraphPane(_controller, graphModel);
201    }
202
203    /** Draw a reference box with the default icon size, 60x40.
204     */
205    protected void _drawReferenceBox() {
206        // The background layer is a FigureLayer, despite the fact that
207        // getBackgroundLayer() only returns a CanvasLayer.
208        FigureLayer layer = (FigureLayer) getJGraph().getGraphPane()
209                .getBackgroundLayer();
210        layer.setVisible(true);
211
212        BasicRectangle reference = new BasicRectangle(-30.0, -20.0, 60.0, 40.0,
213                0.1f);
214        reference.setStrokePaint(Color.BLUE);
215        layer.add(reference);
216    }
217
218    ///////////////////////////////////////////////////////////////////
219    ////                         private variables                 ////
220    private EditIconGraphController _controller;
221
222    // The default zoom scale.
223    private double _ZOOM_SCALE = 4.0;
224}