001/*
002 * $Id: AbstractTreeTableModel.java 3780 2010-09-09 16:17:41Z kschaefe $
003 *
004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 * 
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015 * Lesser General Public License for more details.
016 * 
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020 */
021
022package org.jdesktop.swingx.treetable;
023
024import javax.swing.event.TreeModelListener;
025import javax.swing.tree.TreePath;
026
027import org.jdesktop.swingx.tree.TreeModelSupport;
028
029// There is no javax.swing.tree.AbstractTreeModel; There ought to be one.
030
031/**
032 * AbstractTreeTableModel provides an implementation of
033 * {@link org.jdesktop.swingx.treetable.TreeTableModel} as a convenient starting
034 * point in defining custom data models for
035 * {@link org.jdesktop.swingx.JXTreeTable}. It takes care of listener
036 * management and contains convenience methods for creating and dispatching
037 * {@code TreeModelEvent}s. To create a concreate instance of
038 * {@code TreeTableModel} you need only to provide implementations for the
039 * following methods:
040 * 
041 * <pre>
042 * public int getColumnCount();
043 * public Object getValueAt(Object node, int column);
044 * public Object getChild(Object parent, int index);
045 * public int getChildCount(Object parent);
046 * public int getIndexOfChild(Object parent, Object child);
047 * public boolean isLeaf(Object node);
048 * </pre>
049 * 
050 * @author Ramesh Gupta
051 * @author Karl Schaefer
052 */
053public abstract class AbstractTreeTableModel implements TreeTableModel {
054
055    /**
056     * Root node of the model
057     */
058    protected Object root;
059
060    /**
061     * Provides support for event dispatching.
062     */
063    protected TreeModelSupport modelSupport;
064    
065    /**
066     * Constructs an {@code AbstractTreeTableModel} with a {@code null} root
067     * node.
068     */
069    public AbstractTreeTableModel() {
070        this(null);
071    }
072
073    /**
074     * Constructs an {@code AbstractTreeTableModel} with the specified root
075     * node.
076     * 
077     * @param root
078     *            root node
079     */
080    public AbstractTreeTableModel(Object root) {
081        this.root = root;
082        this.modelSupport = new TreeModelSupport(this);
083    }
084
085    /**
086     * {@inheritDoc}
087     */
088    @Override
089    public Class<?> getColumnClass(int column) {
090        return Object.class;
091    }
092
093    /**
094     * {@inheritDoc}
095     */
096    @Override
097    public String getColumnName(int column) {
098        //Copied from AbstractTableModel.
099        //Should use same defaults when possible.
100        String result = "";
101        
102        for (; column >= 0; column = column / 26 - 1) {
103            result = (char) ((char) (column % 26) + 'A') + result;
104        }
105        
106        return result;
107    }
108
109    /**
110     * {@inheritDoc}
111     */
112    @Override
113    public int getHierarchicalColumn() {
114        if (getColumnCount() == 0) {
115            return -1;
116        }
117        
118        return 0;
119    }
120
121    /**
122     * {@inheritDoc}
123     */
124    @Override
125    public Object getRoot() {
126        return root;
127    }
128
129    /**
130     * {@inheritDoc}
131     */
132    @Override
133    public boolean isCellEditable(Object node, int column) {
134        // RG: Fix Issue 49 -- Cell not editable, by default.
135        // Subclasses might override this to return true.
136        return false;
137    }
138
139    /**
140     * Returns <code>true</code> if <code>node</code> is a leaf.
141     *
142     * @impl {@code true} if {@code getChildCount(node) == 0}
143     * @param   node  a node in the tree, obtained from this data source
144     * @return  true if <code>node</code> is a leaf
145     */
146    @Override
147    public boolean isLeaf(Object node) {
148        return getChildCount(node) == 0;
149    }
150
151    /**
152     * Sets the value for the {@code node} at {@code columnIndex} to
153     * {@code value}.
154     * 
155     * @impl is no-op; provided for convenience for uneditable models
156     * @param value
157     *            the new value
158     * @param node
159     *            the node whose value is to be changed
160     * @param column
161     *            the column whose value is to be changed
162     * @see #getValueAt
163     * @see #isCellEditable
164     * @see javax.swing.table.TableModel#setValueAt(Object, int, int)
165     */
166    @Override
167    public void setValueAt(Object value, Object node, int column) {
168        //does nothing
169    }
170    
171    /**
172     * Called when value for the item identified by path has been changed. If
173     * newValue signifies a truly new value the model should post a
174     * {@code treeNodesChanged} event.
175     * <p>
176     * 
177     * @impl is no-op. A {@code JXTreeTable} does not usually edit the node directly.
178     * @param path
179     *            path to the node that has changed
180     * @param newValue
181     *            the new value from the <code>TreeCellEditor</code>
182     */
183    @Override
184    public void valueForPathChanged(TreePath path, Object newValue) {
185        //does nothing
186    }
187
188    /**
189     * {@inheritDoc}
190     */
191    @Override
192    public void addTreeModelListener(TreeModelListener l) {
193        modelSupport.addTreeModelListener(l);
194    }
195
196    /**
197     * {@inheritDoc}
198     */
199    @Override
200    public void removeTreeModelListener(TreeModelListener l) {
201        modelSupport.removeTreeModelListener(l);
202    }
203
204    /**
205     * Returns an array of all the <code>TreeModelListener</code>s added
206     * to this JXTreeTable with addTreeModelListener().
207     *
208     * @return all of the <code>TreeModelListener</code>s added or an empty
209     *         array if no listeners have been added
210     */
211    public TreeModelListener[] getTreeModelListeners() {
212        return modelSupport.getTreeModelListeners();
213    }
214}