001/* A tree model for Ptolemy II objects, for use with JTree.
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
027 */
028package ptolemy.vergil.tree;
029
030import java.util.Collections;
031import java.util.List;
032
033import ptolemy.kernel.CompositeEntity;
034import ptolemy.kernel.Entity;
035import ptolemy.kernel.util.NamedObj;
036
037///////////////////////////////////////////////////////////////////
038//// FullTreeModel
039
040/**
041 A tree model for Ptolemy II models.  Nodes in this tree contain
042 the following child elements, in this order:
043 <ul>
044 <li> attributes
045 <li> ports
046 <li> relations
047 <li> class definitions
048 <li> contained entities
049 </ul>
050 The indexes of the attributes are 0 to a-1, where a is the
051 number of attributes.  The indexes of the ports are a to a+p-1,
052 where p is the number of ports, and so on.
053 Subclasses may return a subset of the attributes, ports, and
054 relations by overriding the protected methods that list these
055 contained objects.
056
057 @author Steve Neuendorffer and Edward A. Lee
058 @version $Id$
059 @since Ptolemy II 1.0
060 @Pt.ProposedRating Red (eal)
061 @Pt.AcceptedRating Red (johnr)
062 */
063public class FullTreeModel extends ClassAndEntityTreeModel {
064    /** Create a new tree model with the specified root.
065     *  @param root The root of the tree.
066     */
067    public FullTreeModel(CompositeEntity root) {
068        super(root);
069    }
070
071    ///////////////////////////////////////////////////////////////////
072    ////                         public methods                    ////
073
074    /** Get the child of the given parent at the given index.
075     *  If the child does not exist, then return null.
076     *  @param parent A node in the tree.
077     *  @param index The index of the desired child.
078     *  @return A node, or null if there is no such child.
079     */
080    @Override
081    public Object getChild(Object parent, int index) {
082        List attributes = _attributes(parent);
083        int numAttributes = attributes.size();
084
085        List ports = _ports(parent);
086        int numPorts = ports.size();
087
088        List relations = _relations(parent);
089        int numRelations = relations.size();
090
091        if (index >= numAttributes + numPorts + numRelations) {
092            return super.getChild(parent,
093                    index - numAttributes - numPorts - numRelations);
094        } else if (index >= numAttributes + numPorts) {
095            return relations.get(index - numAttributes - numPorts);
096        } else if (index >= numAttributes) {
097            return ports.get(index - numAttributes);
098        } else if (index >= 0) {
099            return attributes.get(index);
100        } else {
101            return null;
102        }
103    }
104
105    /** Return the number of children of the given parent.
106     *  This is the number attributes, ports, relations, and contained
107     *  entities, filtered by the filter specified by setFilter(),
108     *  if any has been specified.
109     *  @param parent A parent node.
110     *  @return The number of children.
111     */
112    @Override
113    public int getChildCount(Object parent) {
114        List attributes = _attributes(parent);
115        int numAttributes = attributes.size();
116
117        List ports = _ports(parent);
118        int numPorts = ports.size();
119
120        List relations = _relations(parent);
121        int numRelations = relations.size();
122
123        return numAttributes + numPorts + numRelations
124                + super.getChildCount(parent);
125    }
126
127    /** Return the index of the given child within the given parent.
128     *  If the parent is not contained in the child, return -1.
129     *  @param parent The parent.
130     *  @param child The child.
131     *  @return The index of the specified child.
132     */
133    @Override
134    public int getIndexOfChild(Object parent, Object child) {
135        List attributes = _attributes(parent);
136
137        int index = attributes.indexOf(child);
138
139        if (index >= 0) {
140            return index;
141        } else {
142            // Object is not an attribute.  See whether it's a port.
143            List ports = _ports(parent);
144
145            index = ports.indexOf(child);
146
147            int numAttributes = attributes.size();
148
149            if (index >= 0) {
150                return index + numAttributes;
151            } else {
152                // Not an attribute or port. Try relation.
153                List relations = _relations(parent);
154
155                index = relations.indexOf(child);
156
157                int numPorts = ports.size();
158
159                if (index >= 0) {
160                    return index + numAttributes + numPorts;
161                } else {
162                    // Not an attribute, port, or relation. Defer to base
163                    // class.
164                    index = super.getIndexOfChild(parent, child);
165
166                    if (index >= 0) {
167                        int numRelations = relations.size();
168                        return index + numAttributes + numPorts + numRelations;
169                    }
170                }
171            }
172        }
173
174        return -1;
175    }
176
177    /** Return true if the object is a leaf node.  An object is a leaf
178     *  node if it has no children that are instances of one of the classes
179     *  specified by setFilter(), if a filter has been specified.
180     *  @param object The object.
181     *  @return True if the node has no children.
182     */
183    @Override
184    public boolean isLeaf(Object object) {
185        // FIXME: Ignoring setFilter for now.
186        if (_attributes(object).size() > 0) {
187            return false;
188        }
189
190        if (_ports(object).size() > 0) {
191            return false;
192        }
193
194        if (_relations(object).size() > 0) {
195            return false;
196        }
197
198        return super.isLeaf(object);
199    }
200
201    ///////////////////////////////////////////////////////////////////
202    ////                         protected methods                 ////
203
204    /** Return the list of attributes, or an empty list if there are none.
205     *  Override this method if you wish to show only a subset of the
206     *  attributes.
207     *  @param object The object.
208     *  @return A list of attributes.
209     */
210    protected List _attributes(Object object) {
211        if (!(object instanceof NamedObj)) {
212            return Collections.EMPTY_LIST;
213        }
214
215        return ((NamedObj) object).attributeList();
216    }
217
218    /** Return the list of ports, or an empty list if there are none.
219     *  Override this method if you wish to show only a subset of the
220     *  ports.
221     *  @param object The object.
222     *  @return A list of ports.
223     */
224    protected List _ports(Object object) {
225        if (!(object instanceof Entity)) {
226            return Collections.EMPTY_LIST;
227        }
228
229        return ((Entity) object).portList();
230    }
231
232    /** Return the list of relations, or an empty list if there are none.
233     *  Override this method if you wish to show only a subset of the
234     *  relations.
235     *  @param object The object.
236     *  @return A list of relations.
237     */
238    protected List _relations(Object object) {
239        if (!(object instanceof CompositeEntity)) {
240            return Collections.EMPTY_LIST;
241        }
242
243        return ((CompositeEntity) object).relationList();
244    }
245}