001////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code for adherence to a set of rules.
003// Copyright (C) 2001-2002  Oliver Burn
004//
005// This library is free software; you can redistribute it and/or
006// modify it under the terms of the GNU Lesser General Public
007// License as published by the Free Software Foundation; either
008// version 2.1 of the License, or (at your option) any later version.
009//
010// This library is distributed in the hope that it will be useful,
011// but WITHOUT ANY WARRANTY; without even the implied warranty of
012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013// Lesser General Public License for more details.
014//
015// You should have received a copy of the GNU Lesser General Public
016// License along with this library; if not, write to the Free Software
017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
018////////////////////////////////////////////////////////////////////////////////
019
020/*
021 * %W% %E%
022 *
023 * Copyright 1997, 1998 Sun Microsystems, Inc. All Rights Reserved.
024 *
025 * Redistribution and use in source and binary forms, with or
026 * without modification, are permitted provided that the following
027 * conditions are met:
028 *
029 * - Redistributions of source code must retain the above copyright
030 *   notice, this list of conditions and the following disclaimer.
031 *
032 * - Redistribution in binary form must reproduce the above
033 *   copyright notice, this list of conditions and the following
034 *   disclaimer in the documentation and/or other materials
035 *   provided with the distribution.
036 *
037 * Neither the name of Sun Microsystems, Inc. or the names of
038 * contributors may be used to endorse or promote products derived
039 * from this software without specific prior written permission.
040 *
041 * This software is provided "AS IS," without a warranty of any
042 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
043 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
044 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
045 * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY
046 * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR
047 * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE OR
048 * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE
049 * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
050 * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
051 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
052 * THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS
053 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
054 *
055 * You acknowledge that this software is not designed, licensed or
056 * intended for use in the design, construction, operation or
057 * maintenance of any nuclear facility.
058 */
059
060package com.puppycrawl.tools.checkstyle.gui;
061
062import javax.swing.event.EventListenerList;
063import javax.swing.event.TreeModelEvent;
064import javax.swing.event.TreeModelListener;
065import javax.swing.tree.TreePath;
066
067/**
068 * An abstract implementation of the TreeTableModel interface, handling
069 * the list of listeners.
070 *
071 * <a href="http://java.sun.com/products/jfc/tsc/articles/treetable1/index.html">Original&nbsp;Source&nbsp;Location</a>
072 *
073 * @author Philip Milne
074 */
075public abstract class AbstractTreeTableModel implements TreeTableModel
076{
077    private final Object mRoot;
078    private final EventListenerList mListenerList = new EventListenerList();
079
080    public AbstractTreeTableModel(Object root)
081    {
082        mRoot = root;
083    }
084
085    //
086    // Default implmentations for methods in the TreeModel interface.
087    //
088
089    public Object getRoot()
090    {
091        return mRoot;
092    }
093
094    public boolean isLeaf(Object node)
095    {
096        return getChildCount(node) == 0;
097    }
098
099    public void valueForPathChanged(TreePath path, Object newValue)
100    {
101    }
102
103    // This is not called in the JTree's default mode: use a naive implementation.
104    public int getIndexOfChild(Object parent, Object child)
105    {
106        for (int i = 0; i < getChildCount(parent); i++) {
107            if (getChild(parent, i).equals(child)) {
108                return i;
109            }
110        }
111        return -1;
112    }
113
114    public void addTreeModelListener(TreeModelListener l)
115    {
116        mListenerList.add(TreeModelListener.class, l);
117    }
118
119    public void removeTreeModelListener(TreeModelListener l)
120    {
121        mListenerList.remove(TreeModelListener.class, l);
122    }
123
124    /*
125     * Notify all listeners that have registered interest for
126     * notification on this event type.  The event instance
127     * is lazily created using the parameters passed into
128     * the fire method.
129     * @see EventListenerList
130     */
131    protected void fireTreeNodesChanged(Object source, Object[] path,
132            int[] childIndices,
133            Object[] children)
134    {
135        // Guaranteed to return a non-null array
136        final Object[] listeners = mListenerList.getListenerList();
137        TreeModelEvent e = null;
138        // Process the listeners last to first, notifying
139        // those that are interested in this event
140        for (int i = listeners.length - 2; i >= 0; i -= 2) {
141            if (listeners[i] == TreeModelListener.class) {
142                // Lazily create the event:
143                if (e == null) {
144                    e = new TreeModelEvent(source, path,
145                            childIndices, children);
146                }
147                ((TreeModelListener) listeners[i + 1]).treeNodesChanged(e);
148            }
149        }
150    }
151
152    /*
153     * Notify all listeners that have registered interest for
154     * notification on this event type.  The event instance
155     * is lazily created using the parameters passed into
156     * the fire method.
157     * @see EventListenerList
158     */
159    protected void fireTreeNodesInserted(Object source, Object[] path,
160            int[] childIndices,
161            Object[] children)
162    {
163        // Guaranteed to return a non-null array
164        final Object[] listeners = mListenerList.getListenerList();
165        TreeModelEvent e = null;
166        // Process the listeners last to first, notifying
167        // those that are interested in this event
168        for (int i = listeners.length - 2; i >= 0; i -= 2) {
169            if (listeners[i] == TreeModelListener.class) {
170                // Lazily create the event:
171                if (e == null) {
172                    e = new TreeModelEvent(source, path,
173                            childIndices, children);
174                }
175                ((TreeModelListener) listeners[i + 1]).treeNodesInserted(e);
176            }
177        }
178    }
179
180    /*
181     * Notify all listeners that have registered interest for
182     * notification on this event type.  The event instance
183     * is lazily created using the parameters passed into
184     * the fire method.
185     * @see EventListenerList
186     */
187    protected void fireTreeNodesRemoved(Object source, Object[] path,
188            int[] childIndices,
189            Object[] children)
190    {
191        // Guaranteed to return a non-null array
192        final Object[] listeners = mListenerList.getListenerList();
193        TreeModelEvent e = null;
194        // Process the listeners last to first, notifying
195        // those that are interested in this event
196        for (int i = listeners.length - 2; i >= 0; i -= 2) {
197            if (listeners[i] == TreeModelListener.class) {
198                // Lazily create the event:
199                if (e == null) {
200                    e = new TreeModelEvent(source, path,
201                            childIndices, children);
202                }
203                ((TreeModelListener) listeners[i + 1]).treeNodesRemoved(e);
204            }
205        }
206    }
207
208    /*
209     * Notify all listeners that have registered interest for
210     * notification on this event type.  The event instance
211     * is lazily created using the parameters passed into
212     * the fire method.
213     * @see EventListenerList
214     */
215    protected void fireTreeStructureChanged(Object source, Object[] path,
216            int[] childIndices,
217            Object[] children)
218    {
219        // Guaranteed to return a non-null array
220        final Object[] listeners = mListenerList.getListenerList();
221        TreeModelEvent e = null;
222        // Process the listeners last to first, notifying
223        // those that are interested in this event
224        for (int i = listeners.length - 2; i >= 0; i -= 2) {
225            if (listeners[i] == TreeModelListener.class) {
226                // Lazily create the event:
227                if (e == null) {
228                    e = new TreeModelEvent(source, path,
229                            childIndices, children);
230                }
231                ((TreeModelListener) listeners[i + 1]).treeStructureChanged(e);
232            }
233        }
234    }
235
236    //
237    // Default impelmentations for methods in the TreeTableModel interface.
238    //
239
240    public Class<?> getColumnClass(int column)
241    {
242        return Object.class;
243    }
244
245    /** By default, make the column with the Tree in it the only editable one.
246     *  Making this column editable causes the JTable to forward mouse
247     *  and keyboard events in the Tree column to the underlying JTree.
248     */
249    public boolean isCellEditable(Object node, int column)
250    {
251        return getColumnClass(column) == TreeTableModel.class;
252    }
253
254    public void setValueAt(Object aValue, Object node, int column)
255    {
256    }
257
258
259    // Left to be implemented in the subclass:
260
261    /*
262     *   public Object getChild(Object parent, int index)
263     *   public int getChildCount(Object parent)
264     *   public int getColumnCount()
265     *   public String getColumnName(Object node, int column)
266     *   public Object getValueAt(Object node, int column)
267     */
268}