001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU General
007: * Public License Version 2 only ("GPL") or the Common Development and Distribution
008: * License("CDDL") (collectively, the "License"). You may not use this file except in
009: * compliance with the License. You can obtain a copy of the License at
010: * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the
011: * License for the specific language governing permissions and limitations under the
012: * License. When distributing the software, include this License Header Notice in
013: * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun
014: * designates this particular file as subject to the "Classpath" exception as
015: * provided by Sun in the GPL Version 2 section of the License file that
016: * accompanied this code. If applicable, add the following below the License Header,
017: * with the fields enclosed by brackets [] replaced by your own identifying
018: * information: "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Contributor(s):
021: *
022: * The Original Software is NetBeans. The Initial Developer of the Original Software
023: * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All
024: * Rights Reserved.
025: *
026: * If you wish your version of this file to be governed by only the CDDL or only the
027: * GPL Version 2, indicate your decision by adding "[Contributor] elects to include
028: * this software in this distribution under the [CDDL or GPL Version 2] license." If
029: * you do not indicate a single choice of license, a recipient has the option to
030: * distribute your version of this file under either the CDDL, the GPL Version 2 or
031: * to extend the choice of license to its licensees as provided above. However, if
032: * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then
033: * the option applies only if the new code is made subject to such option by the
034: * copyright holder.
035: */
036:
037: package org.netbeans.installer.utils.helper.swing;
038:
039: import java.util.Vector;
040: import javax.swing.JTree;
041: import javax.swing.SwingUtilities;
042: import javax.swing.event.TableModelEvent;
043: import javax.swing.event.TableModelListener;
044: import javax.swing.event.TreeExpansionEvent;
045: import javax.swing.event.TreeExpansionListener;
046: import javax.swing.event.TreeModelEvent;
047: import javax.swing.event.TreeModelListener;
048: import javax.swing.table.TableModel;
049: import javax.swing.tree.TreeModel;
050:
051: /**
052: *
053: * @author Kirill Sorokin
054: */
055: public abstract class NbiTreeTableModel implements TableModel {
056: private Vector<TableModelListener> listeners = new Vector<TableModelListener>();
057:
058: private TreeModel treeModel;
059: private JTree tree;
060:
061: private TreeExpansionListener treeExpansionListener;
062: private TreeModelListener treeModelListener;
063:
064: private boolean consumeNextExpansionEvent = false;
065:
066: public NbiTreeTableModel(final TreeModel treeModel) {
067: setTreeModel(treeModel);
068: }
069:
070: public abstract int getTreeColumnIndex();
071:
072: final public TreeModel getTreeModel() {
073: return treeModel;
074: }
075:
076: final void setTreeModel(final TreeModel treeModel) {
077: removeTreeModelListener();
078: this .treeModel = treeModel;
079: addTreeModelListener();
080: }
081:
082: final public JTree getTree() {
083: return tree;
084: }
085:
086: final void setTree(final JTree tree) {
087: removeTreeExpansionListener();
088: this .tree = tree;
089: addTreeExpansionListener();
090: }
091:
092: final void consumeNextExpansionEvent() {
093: consumeNextExpansionEvent = true;
094: }
095:
096: final void cancelConsume() {
097: consumeNextExpansionEvent = false;
098: }
099:
100: // partial TableModel implementation ////////////////////////////////////////////
101: final public int getRowCount() {
102: return tree.getRowCount();
103: }
104:
105: public abstract int getColumnCount();
106:
107: public abstract String getColumnName(int column);
108:
109: public abstract Class<?> getColumnClass(int column);
110:
111: public abstract boolean isCellEditable(int row, int column);
112:
113: public abstract Object getValueAt(int row, int column);
114:
115: public abstract void setValueAt(Object value, int row, int column);
116:
117: public void addTableModelListener(TableModelListener listener) {
118: synchronized (listeners) {
119: listeners.add(listener);
120: }
121: }
122:
123: public void removeTableModelListener(TableModelListener listener) {
124: synchronized (listeners) {
125: listeners.remove(listener);
126: }
127: }
128:
129: // protected stuff - to be used by extending classes ////////////////////////////
130: protected void fireTableRowsInserted(int firstRow, int lastRow) {
131: fireTableDataChanged(new TableModelEvent(this , firstRow,
132: lastRow, TableModelEvent.ALL_COLUMNS,
133: TableModelEvent.INSERT));
134: }
135:
136: protected void fireTableRowsDeleted(int firstRow, int lastRow) {
137: fireTableDataChanged(new TableModelEvent(this , firstRow,
138: lastRow, TableModelEvent.ALL_COLUMNS,
139: TableModelEvent.DELETE));
140: }
141:
142: protected void fireTableRowsUpdated(int firstRow, int lastRow) {
143: fireTableDataChanged(new TableModelEvent(this , firstRow,
144: lastRow, TableModelEvent.ALL_COLUMNS,
145: TableModelEvent.UPDATE));
146: }
147:
148: // private stuff ////////////////////////////////////////////////////////////////
149: private void removeTreeModelListener() {
150: if (treeModel != null) {
151: treeModel.removeTreeModelListener(treeModelListener);
152: }
153: }
154:
155: private void addTreeModelListener() {
156: if (treeModelListener == null) {
157: treeModelListener = new TreeModelListener() {
158: public void treeNodesChanged(TreeModelEvent event) {
159: delayedFireTableDataChanged();
160: }
161:
162: public void treeNodesInserted(TreeModelEvent event) {
163: delayedFireTableDataChanged();
164: }
165:
166: public void treeNodesRemoved(TreeModelEvent event) {
167: delayedFireTableDataChanged();
168: }
169:
170: public void treeStructureChanged(TreeModelEvent event) {
171: delayedFireTableDataChanged();
172: }
173: };
174: }
175:
176: treeModel.addTreeModelListener(treeModelListener);
177: }
178:
179: private void removeTreeExpansionListener() {
180: if (tree != null) {
181: tree.removeTreeExpansionListener(treeExpansionListener);
182: }
183: }
184:
185: private void addTreeExpansionListener() {
186: if (treeExpansionListener == null) {
187: treeExpansionListener = new TreeExpansionListener() {
188: public void treeCollapsed(TreeExpansionEvent event) {
189: if (consumeNextExpansionEvent) {
190: consumeNextExpansionEvent = false;
191: return;
192: }
193:
194: int row = tree.getRowForPath(event.getPath());
195: int childrenCount = treeModel.getChildCount(event
196: .getPath().getLastPathComponent());
197: fireTableRowsDeleted(row + 1, row + childrenCount);
198: fireTableRowsUpdated(row, row);
199: }
200:
201: public void treeExpanded(TreeExpansionEvent event) {
202: if (consumeNextExpansionEvent) {
203: consumeNextExpansionEvent = false;
204: return;
205: }
206:
207: int row = tree.getRowForPath(event.getPath());
208: int childrenCount = treeModel.getChildCount(event
209: .getPath().getLastPathComponent());
210: fireTableRowsInserted(row + 1, row + childrenCount);
211: fireTableRowsUpdated(row, row);
212: }
213: };
214: }
215:
216: tree.addTreeExpansionListener(treeExpansionListener);
217: }
218:
219: private void fireTableDataChanged(TableModelEvent event) {
220: for (TableModelListener listener : listeners
221: .toArray(new TableModelListener[0])) {
222: listener.tableChanged(event);
223: }
224: }
225:
226: private void fireTableDataChanged() {
227: fireTableDataChanged(new TableModelEvent(this ));
228: }
229:
230: private void delayedFireTableDataChanged() {
231: SwingUtilities.invokeLater(new Runnable() {
232: public void run() {
233: fireTableDataChanged();
234: }
235: });
236: }
237: }
|