001/* A simple tree view for Ptolemy models
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.vergil.tree;
029
030import java.awt.BorderLayout;
031import java.awt.Color;
032import java.io.File;
033import java.io.IOException;
034
035import javax.swing.JFrame;
036import javax.swing.JScrollPane;
037
038import ptolemy.actor.gui.Effigy;
039import ptolemy.actor.gui.PtolemyEffigy;
040import ptolemy.actor.gui.PtolemyFrame;
041import ptolemy.actor.gui.Tableau;
042import ptolemy.actor.gui.TableauFactory;
043import ptolemy.kernel.CompositeEntity;
044import ptolemy.kernel.util.IllegalActionException;
045import ptolemy.kernel.util.InternalErrorException;
046import ptolemy.kernel.util.NameDuplicationException;
047import ptolemy.kernel.util.NamedObj;
048
049///////////////////////////////////////////////////////////////////
050//// TreeTableau
051
052/**
053 A tree view for ptolemy models.
054
055 @author  Steve Neuendorffer and Edward A. Lee
056 @version $Id$
057 @since Ptolemy II 1.0
058 @Pt.ProposedRating Red (neuendor)
059 @Pt.AcceptedRating Red (johnr)
060 */
061public class TreeTableau extends Tableau {
062    /** Construct a new tableau for the model represented by the given effigy.
063     *  @param container The container.
064     *  @param name The name.
065     *  @exception IllegalActionException If the container does not accept
066     *   this entity (this should not occur).
067     *  @exception NameDuplicationException If the name coincides with an
068     *   attribute already in the container.
069     */
070    public TreeTableau(PtolemyEffigy container, String name)
071            throws IllegalActionException, NameDuplicationException {
072        super(container, name);
073
074        NamedObj model = container.getModel();
075
076        if (!(model instanceof CompositeEntity)) {
077            throw new IllegalActionException(this,
078                    "Cannot have a tree view of a model that is "
079                            + "not a CompositeEntity.");
080        }
081    }
082
083    ///////////////////////////////////////////////////////////////////
084    ////                         public methods                    ////
085
086    /** Set the top-level window associated with this tableau.
087     *  @param frame The top-level window associated with the tableau.
088     *  @exception IllegalActionException If the frame is not an instance
089     *   of PlotTableauFrame.
090     */
091    @Override
092    public void setFrame(JFrame frame) throws IllegalActionException {
093        if (!(frame instanceof TreeFrame)) {
094            throw new IllegalActionException(this,
095                    "Frame for PlotTableau must be an instance of "
096                            + "PlotTableauFrame.");
097        }
098
099        super.setFrame(frame);
100        ((TreeFrame) frame).setTableau(this);
101    }
102
103    /** Make this tableau visible by calling setVisible(true), and
104     *  raising or deiconifying its window.
105     *  If no frame has been set, then create one, an instance of
106     *  PlotTableauFrame.  If a URL has been specified but not yet
107     *  processed, then process it.
108     */
109    @Override
110    public void show() {
111        JFrame frame = getFrame();
112
113        if (frame == null) {
114            PtolemyEffigy container = (PtolemyEffigy) getContainer();
115            CompositeEntity model = (CompositeEntity) container.getModel();
116
117            frame = new TreeFrame(model);
118            frame.setBackground(BACKGROUND_COLOR);
119
120            // Give a reasonable default size.
121            size.setExpression("300x500");
122            ((TreeFrame) frame).setTableau(this);
123            frame.pack();
124            ((TreeFrame) frame).centerOnScreen();
125            frame.setVisible(true);
126
127            try {
128                setFrame(frame);
129            } catch (IllegalActionException ex) {
130                throw new InternalErrorException(ex);
131            }
132        }
133
134        super.show();
135    }
136
137    ///////////////////////////////////////////////////////////////////
138    ////                         private variables                 ////
139    // The background color.
140    private static Color BACKGROUND_COLOR = new Color(0xe5e5e5);
141
142    ///////////////////////////////////////////////////////////////////
143    ////                     public inner classes                  ////
144
145    /** This is a top-level window containing a tree-view of a composite
146     *  entity.
147     */
148    @SuppressWarnings("serial")
149    public static class TreeFrame extends PtolemyFrame {
150        /** Construct a TreeFrame containing a tree view of the specified
151         *  composite entity.
152         *  @param entity The composite entity to view as a tree.
153         */
154        public TreeFrame(CompositeEntity entity) {
155            super(entity);
156
157            PTree pane = new PTree(new FullTreeModel(entity));
158            getContentPane().add(new JScrollPane(pane), BorderLayout.CENTER);
159        }
160
161        ///////////////////////////////////////////////////////////////
162        ////                     protected methods                 ////
163
164        /** Write the model to the specified file.
165         *  @param file The file to write to.
166         *  @exception IOException If the write fails.
167         */
168        @Override
169        protected void _writeFile(File file) throws IOException {
170            java.io.FileWriter fout = null;
171
172            try {
173                fout = new java.io.FileWriter(file);
174                getModel().exportMoML(fout);
175            } finally {
176                if (fout != null) {
177                    fout.close();
178                }
179            }
180        }
181    }
182
183    /** This is a factory that creates tree-view tableaux for Ptolemy models.
184     */
185    public static class Factory extends TableauFactory {
186        /** Create an factory with the given name and container.
187         *  @param container The container entity.
188         *  @param name The name of the entity.
189         *  @exception IllegalActionException If the container is incompatible
190         *   with this attribute.
191         *  @exception NameDuplicationException If the name coincides with
192         *   an attribute already in the container.
193         */
194        public Factory(NamedObj container, String name)
195                throws IllegalActionException, NameDuplicationException {
196            super(container, name);
197        }
198
199        ///////////////////////////////////////////////////////////////
200        ////                     public methods                    ////
201
202        /** If the effigy is an instance of PtolemyEffigy referencing
203         *  an instance of CompositeEntity, then create a TreeTableau
204         *  contained by the effigy. The tableau will assigned the
205         *  name "treeTableau".  If there is already such a tableau in
206         *  the effigy, then just show it instead of creating a new
207         *  one.  If the effigy is not an instance of PtolemyEffigy
208         *  referencing an instance of CompositeEntity, and there no
209         *  pre-existing tableau named "treeTableau", then return
210         *  null.  It is the responsibility of callers of this method
211         *  to check the return value and call show().
212         *
213         *  @param effigy An effigy of a Ptolemy model.
214         *  @return A new tree-view tableau, or null if the effigy is not
215         *   that of a composite entity.
216         *  @exception Exception If the effigy is a PtolemyEffigy, but
217         *   construction of the tree view fails for some reason.  */
218        @Override
219        public Tableau createTableau(Effigy effigy) throws Exception {
220            if (effigy instanceof PtolemyEffigy) {
221                // First see whether the effigy already contains a TreeTableau.
222                TreeTableau previous = (TreeTableau) effigy
223                        .getEntity("treeTableau");
224
225                if (previous != null) {
226                    return previous;
227                } else {
228                    PtolemyEffigy ptEffigy = (PtolemyEffigy) effigy;
229                    NamedObj model = ptEffigy.getModel();
230
231                    if (model instanceof CompositeEntity) {
232                        return new TreeTableau(ptEffigy, "treeTableau");
233                    }
234                }
235            }
236
237            return null;
238        }
239    }
240}