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
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.ui.components.tree;
042:
043: import java.util.Collection;
044: import java.util.LinkedList;
045: import javax.swing.Icon;
046: import javax.swing.tree.DefaultMutableTreeNode;
047: import javax.swing.tree.TreeNode;
048:
049: /**
050: *
051: * @author Jiri Sedlacek
052: */
053: public class CheckTreeNode extends DefaultMutableTreeNode {
054: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
055:
056: public static final int STATE_CHECKED = 1;
057: public static final int STATE_UNCHECKED = 2;
058: public static final int STATE_PARTIALLY_CHECKED = 4;
059:
060: //~ Instance fields ----------------------------------------------------------------------------------------------------------
061:
062: protected int checkState = STATE_UNCHECKED;
063: private Icon icon;
064:
065: //~ Constructors -------------------------------------------------------------------------------------------------------------
066:
067: // --- Public interface ------------------------------------------------------
068:
069: // Creates new CheckTreeNode, no user object, initially unchecked
070: public CheckTreeNode() {
071: this (null);
072: }
073:
074: // Creates new CheckTreeNode with user object, initially unchecked
075: public CheckTreeNode(Object userObject) {
076: this (userObject, null);
077: }
078:
079: /**
080: * Creates new CheckTreeNode with given icon, initially unchecked
081: */
082: public CheckTreeNode(Object userObject, final Icon icon) {
083: super (userObject);
084: setChecked(false);
085: this .icon = icon;
086: }
087:
088: //~ Methods ------------------------------------------------------------------------------------------------------------------
089:
090: // Returns CheckTreeNode's check state - STATE_CHECKED, STATE_UNCHECKED or STATE_PARTIALLY_CHECKED
091: public int getCheckState() {
092: return checkState;
093: }
094:
095: // Sets the CheckTreeNode to be fully checked or fully unchecked
096: // Returns Collection of leaf nodes changed by this operation
097: public Collection setChecked(boolean checked) {
098: if (checked == true) {
099: return setFullyChecked();
100: } else {
101: return setUnchecked();
102: }
103: }
104:
105: // Check if CheckTreeNode is fully checked
106: public boolean isFullyChecked() {
107: return getCheckState() == STATE_CHECKED;
108: }
109:
110: /**
111: * The icon property getter
112: */
113: public Icon getIcon() {
114: return icon;
115: }
116:
117: // Check if CheckTreeNode is partially checked
118: public boolean isPartiallyChecked() {
119: return getCheckState() == STATE_PARTIALLY_CHECKED;
120: }
121:
122: // Toggles CheckTreeNode's check state to next state
123: // Returns Collection of leaf nodes changed by this operation
124: public Collection toggleState() {
125: if (getCheckState() == STATE_CHECKED) {
126: return setUnchecked();
127: } else {
128: return setFullyChecked();
129: }
130: }
131:
132: protected Collection setPartiallyChecked() {
133: LinkedList changedNodes = new LinkedList();
134: changedNodes.add(this );
135:
136: // Check if change is needed
137: if (checkState == STATE_PARTIALLY_CHECKED) {
138: return changedNodes;
139: }
140:
141: // Update checkState of this node
142: checkState = STATE_PARTIALLY_CHECKED;
143:
144: // Update checkState of parent
145: TreeNode parent = getParent();
146:
147: if ((parent != null) && parent instanceof CheckTreeNode) {
148: changedNodes.addAll(((CheckTreeNode) parent)
149: .setPartiallyChecked());
150: }
151:
152: // Return Collection of leaf nodes changed by this operation
153: return changedNodes;
154: }
155:
156: // ---------------------------------------------------------------------------
157:
158: // --- Private implementation ------------------------------------------------
159: private Collection setFullyChecked() {
160: LinkedList changedNodes = new LinkedList();
161: changedNodes.add(this );
162:
163: // Check if change is needed
164: if (checkState == STATE_CHECKED) {
165: return changedNodes;
166: }
167:
168: // Update checkState of this node
169: checkState = STATE_CHECKED;
170:
171: // Update checkState of all children if any
172: if (!isLeaf()) {
173: for (int i = 0; i < getChildCount(); i++) {
174: TreeNode node = getChildAt(i);
175:
176: if (node instanceof CheckTreeNode) {
177: changedNodes.addAll(((CheckTreeNode) node)
178: .setFullyChecked());
179: }
180: }
181: }
182:
183: // Update checkState of parent
184: TreeNode parent = getParent();
185:
186: if ((parent != null) && parent instanceof CheckTreeNode) {
187: if (areSiblingsFullyChecked()) {
188: changedNodes.addAll(((CheckTreeNode) parent)
189: .setFullyChecked());
190: } else {
191: changedNodes.addAll(((CheckTreeNode) parent)
192: .setPartiallyChecked());
193: }
194: }
195:
196: // Return Collection of leaf nodes changed by this operation
197: return changedNodes;
198: }
199:
200: private Collection setUnchecked() {
201: LinkedList changedNodes = new LinkedList();
202: changedNodes.add(this );
203:
204: // Check if change is needed
205: if (checkState == STATE_UNCHECKED) {
206: return changedNodes;
207: }
208:
209: // Update checkState of this node
210: checkState = STATE_UNCHECKED;
211:
212: // Update checkState of all children if any
213: if (!isLeaf()) {
214: for (int i = 0; i < getChildCount(); i++) {
215: TreeNode node = getChildAt(i);
216:
217: if (node instanceof CheckTreeNode) {
218: changedNodes.addAll(((CheckTreeNode) node)
219: .setUnchecked());
220: }
221: }
222: }
223:
224: // Update checkState of parent
225: TreeNode parent = getParent();
226:
227: if ((parent != null) && parent instanceof CheckTreeNode) {
228: if (areSiblingsUnchecked()) {
229: changedNodes.addAll(((CheckTreeNode) parent)
230: .setUnchecked());
231: } else {
232: changedNodes.addAll(((CheckTreeNode) parent)
233: .setPartiallyChecked());
234: }
235: }
236:
237: // Return Collection of leaf nodes changed by this operation
238: return changedNodes;
239: }
240:
241: private boolean areSiblingsFullyChecked() {
242: TreeNode parent = getParent();
243:
244: for (int i = 0; i < parent.getChildCount(); i++) {
245: TreeNode node = parent.getChildAt(i);
246:
247: if (node == this ) {
248: continue;
249: }
250:
251: if (!(node instanceof CheckTreeNode)
252: || (((CheckTreeNode) node).getCheckState() != STATE_CHECKED)) {
253: return false;
254: }
255: }
256:
257: return true;
258: }
259:
260: private boolean areSiblingsUnchecked() {
261: TreeNode parent = getParent();
262:
263: for (int i = 0; i < parent.getChildCount(); i++) {
264: TreeNode node = parent.getChildAt(i);
265:
266: if (node == this ) {
267: continue;
268: }
269:
270: if (!(node instanceof CheckTreeNode)
271: || (((CheckTreeNode) node).getCheckState() != STATE_UNCHECKED)) {
272: return false;
273: }
274: }
275:
276: return true;
277: }
278:
279: // ---------------------------------------------------------------------------
280: }
|