001/* A tableau representing a token in a text editor.
002
003 Copyright (c) 2000-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 */
027package ptolemy.actor.gui;
028
029import java.util.Iterator;
030import java.util.List;
031
032import ptolemy.data.Token;
033import ptolemy.kernel.util.IllegalActionException;
034import ptolemy.kernel.util.NameDuplicationException;
035import ptolemy.kernel.util.NamedObj;
036
037///////////////////////////////////////////////////////////////////
038//// TokenTableau
039
040/**
041 A tableau representing one or more tokens in a top-level window with
042 a text editor.  Subclasses can be created to represent specific token
043 types in more specialized ways.
044
045 @author  Edward A. Lee
046 @version $Id$
047 @since Ptolemy II 2.1
048 @Pt.ProposedRating Yellow (eal)
049 @Pt.AcceptedRating Red (cxh)
050 @see TokenEffigy
051 */
052public class TokenTableau extends Tableau {
053    /** Construct a new tableau for the model represented by the given effigy.
054     *  This constructor creates a default editor frame, which is an instance
055     *  of TextEditor.
056     *  @param container The container.
057     *  @param name The name.
058     *  @exception IllegalActionException If the container does not accept
059     *   this entity (this should not occur).
060     *  @exception NameDuplicationException If the name coincides with an
061     *   attribute already in the container.
062     */
063    public TokenTableau(Effigy container, String name)
064            throws IllegalActionException, NameDuplicationException {
065        super(container, name);
066        createFrame(null);
067    }
068
069    /** Construct a new tableau for the model represented by the given effigy,
070     *  using the specified frame.
071     *  @param container The container.
072     *  @param name The name.
073     *  @param frame The frame to use.
074     *  @exception IllegalActionException If the container does not accept
075     *   this entity (this should not occur).
076     *  @exception NameDuplicationException If the name coincides with an
077     *   attribute already in the container.
078     */
079    public TokenTableau(Effigy container, String name, TableauFrame frame)
080            throws IllegalActionException, NameDuplicationException {
081        super(container, name);
082        createFrame(frame);
083    }
084
085    ///////////////////////////////////////////////////////////////////
086    ////                         public methods                    ////
087
088    /** Append the specified token to the display.
089     *  If the display is not a TextEditor, do nothing.
090     *  Subclasses should override this with display-specific actions.
091     *  @param token The token to append.
092     *  @exception IllegalActionException If the token is not
093     *  acceptable (not thrown in this base class).
094     */
095    public void append(Token token) throws IllegalActionException {
096        if (_editor != null) {
097            _editor.text.append(token.toString());
098        }
099    }
100
101    /** Append the specified tokens to the display.
102     *  @param list A list of tokens.
103     *  @exception IllegalActionException If the tokens are not
104     *  acceptable (not thrown in this base class).
105     */
106    public void append(List list) throws IllegalActionException {
107        if (_editor != null) {
108            Iterator tokens = list.iterator();
109
110            while (tokens.hasNext()) {
111                _editor.text.append(tokens.next().toString());
112            }
113        }
114    }
115
116    /** Return true if this tableau can display the specified token.
117     *  @param token A candidate token to display.
118     *  @return True, since this tableau can display any token.
119     */
120    public static boolean canDisplay(Token token) {
121        return true;
122    }
123
124    /** Clear the display.
125     */
126    public void clear() {
127        if (_editor != null) {
128            _editor.text.setText("");
129        }
130    }
131
132    /** Create a text editor frame to view the data. This can be overridden
133     *  in derived classes to create more specialized viewers/editors.
134     *  If the specified frame is not an instance of TextEditor, then
135     *  it is replaced with a text editor.
136     *  This is called in the constructor.
137     *  @param frame The frame to use, or null if none is specified.
138     *  @exception IllegalActionException If the frame cannot be created.
139     */
140    public void createFrame(TableauFrame frame) throws IllegalActionException {
141        TokenEffigy effigy = (TokenEffigy) getContainer();
142
143        if (!(frame instanceof TextEditor)) {
144            frame = new TextEditor("Token display");
145        }
146
147        setFrame(frame);
148        frame.setTableau(this);
149        ((TextEditor) frame).text.setEditable(false);
150
151        // Display current data.
152        Iterator tokens = effigy.getTokens().iterator();
153
154        while (tokens.hasNext()) {
155            ((TextEditor) frame).text.append(tokens.next().toString());
156            ((TextEditor) frame).text.append("\n");
157        }
158
159        _editor = (TextEditor) frame;
160    }
161
162    ///////////////////////////////////////////////////////////////////
163    ////                         private members                   ////
164    // The frame as a text editor.
165    private TextEditor _editor;
166
167    ///////////////////////////////////////////////////////////////////
168    ////                         inner classes                     ////
169
170    /** A factory that creates a token tableau.
171     */
172    public static class Factory extends TableauFactory {
173        /** Create a factory with the given name and container.
174         *  @param container The container.
175         *  @param name The name.
176         *  @exception IllegalActionException If the container is incompatible
177         *   with this attribute.
178         *  @exception NameDuplicationException If the name coincides with
179         *   an attribute already in the container.
180         */
181        public Factory(NamedObj container, String name)
182                throws IllegalActionException, NameDuplicationException {
183            super(container, name);
184        }
185
186        ///////////////////////////////////////////////////////////////////
187        ////                         public methods                    ////
188
189        /** If the specified effigy already contains a tableau named
190         *  "tokenTableau", then return that tableau; otherwise, create
191         *  a new instance of TokenTableau in the specified
192         *  effigy, and name it "tokenTableau".  If the specified
193         *  effigy is not an instance of TokenEffigy, then do not
194         *  create a tableau and return null. It is the
195         *  responsibility of callers of this method to check the
196         *  return value and call show().
197         *
198         *  @param effigy The effigy, which is expected to be a TokenEffigy.
199         *  @return An instance of TokenTableau, or null if one cannot be
200         *    found or created.
201         *  @exception Exception If the factory should be able to create a
202         *   tableau for the effigy, but something goes wrong.
203         */
204        @Override
205        public Tableau createTableau(Effigy effigy) throws Exception {
206            if (effigy instanceof TokenEffigy) {
207                // First see whether the effigy already contains an
208                // TokenTableau.
209                TokenTableau tableau = (TokenTableau) effigy
210                        .getEntity("tokenTableau");
211
212                if (tableau != null) {
213                    return tableau;
214                }
215
216                // NOTE: Normally need to check effigy tokens for
217                // compatibility here, but they are always compatible,
218                // so we don't bother.
219                return new TokenTableau(effigy, "tokenTableau");
220            }
221
222            return null;
223        }
224    }
225}