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.modules.profiler.selector.ui;
042:
043: import org.netbeans.api.project.Project;
044: import org.netbeans.lib.profiler.client.ClientUtils;
045: import org.netbeans.lib.profiler.ui.SwingWorker;
046: import org.netbeans.lib.profiler.ui.UIUtils;
047: import org.netbeans.lib.profiler.ui.components.JCheckTree;
048: import org.netbeans.lib.profiler.ui.components.JCheckTree.CheckTreeListener;
049: import org.netbeans.lib.profiler.ui.components.tree.CheckTreeNode;
050: import org.netbeans.modules.profiler.selector.spi.SelectionTreeBuilder;
051: import org.netbeans.modules.profiler.selector.spi.nodes.ContainerNode;
052: import org.netbeans.modules.profiler.selector.spi.nodes.SelectorNode;
053: import org.netbeans.modules.profiler.utilities.trees.TreeDecimator;
054: import org.openide.util.Lookup;
055: import org.openide.util.NbBundle;
056: import java.awt.Cursor;
057: import java.util.ArrayList;
058: import java.util.Arrays;
059: import java.util.Collection;
060: import java.util.Enumeration;
061: import java.util.HashMap;
062: import java.util.HashSet;
063: import java.util.List;
064: import java.util.Map;
065: import java.util.Set;
066: import javax.swing.event.TreeExpansionEvent;
067: import javax.swing.event.TreeWillExpandListener;
068: import javax.swing.tree.DefaultMutableTreeNode;
069: import javax.swing.tree.DefaultTreeModel;
070: import javax.swing.tree.ExpandVetoException;
071: import javax.swing.tree.TreeModel;
072: import javax.swing.tree.TreeNode;
073: import javax.swing.tree.TreePath;
074:
075: /**
076: *
077: * @author Jaroslav Bachorik
078: */
079: public class RootSelectorTree extends JCheckTree {
080: //~ Inner Classes ------------------------------------------------------------------------------------------------------------
081:
082: private static class CancellableController implements
083: ProgressDisplayer.ProgressController {
084: //~ Instance fields ------------------------------------------------------------------------------------------------------
085:
086: private volatile boolean cancelled = false;
087:
088: //~ Methods --------------------------------------------------------------------------------------------------------------
089:
090: public boolean isCancelled() {
091: return cancelled;
092: }
093:
094: public boolean cancel() {
095: cancelled = true;
096:
097: return true;
098: }
099: }
100:
101: private class SelectionTreeViewWrapper implements SelectionTreeView {
102: //~ Instance fields ------------------------------------------------------------------------------------------------------
103:
104: private SelectionTreeBuilder wrappedBuilder;
105: private boolean enabled;
106: private boolean preferred;
107:
108: //~ Constructors ---------------------------------------------------------------------------------------------------------
109:
110: public SelectionTreeViewWrapper(SelectionTreeBuilder builder,
111: boolean preferredFlag, boolean enabledFlag) {
112: wrappedBuilder = builder;
113: preferred = preferredFlag;
114: enabled = enabledFlag;
115: }
116:
117: //~ Methods --------------------------------------------------------------------------------------------------------------
118:
119: public SelectionTreeBuilder getBuilder() {
120: return wrappedBuilder;
121: }
122:
123: public String getDisplayName() {
124: return wrappedBuilder.getDisplayName();
125: }
126:
127: public boolean isEnabled() {
128: return enabled;
129: }
130:
131: public void setPreferred(boolean value) {
132: preferred = value;
133: }
134:
135: public boolean isPreferred() {
136: return preferred;
137: }
138:
139: public String toString() {
140: return wrappedBuilder.toString();
141: }
142: }
143:
144: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
145:
146: public static TreeDecimator.NodeFilter<RootSelectorNode> DEFAULT_FILTER = new TreeDecimator.NodeFilter<RootSelectorNode>() {
147: public boolean match(RootSelectorNode node) {
148: return true;
149: }
150:
151: public boolean maymatch(RootSelectorNode node) {
152: return true;
153: }
154: };
155:
156: private static TreeDecimator.NodeFilter<SelectorNode> DEFAULT_FILTER_INNER = new TreeDecimator.NodeFilter<SelectorNode>() {
157: public boolean match(SelectorNode node) {
158: return true;
159: }
160:
161: public boolean maymatch(SelectorNode node) {
162: return true;
163: }
164: };
165:
166: // -----
167: // I18N String constants
168: private static final String EMPTY_STRING = NbBundle.getMessage(
169: RootSelectorTree.class, "RootSelectorTree_EmptyString"); // NOI18N
170: private static final String LOADING_STRING = NbBundle.getMessage(
171: RootSelectorTree.class, "RootSelectorTree_LoadingString"); // NOI18N
172: private static final String ROOT_STRING = NbBundle.getMessage(
173: RootSelectorTree.class, "RootSelectorTree_RootString"); // NOI18N
174: private static final String NO_PROJECT_STRING = NbBundle
175: .getMessage(RootSelectorTree.class,
176: "RootSelectorTree_NoProjectString"); // NOI18N
177: // -----
178: private static final TreeModel DEFAULTMODEL = new DefaultTreeModel(
179: new DefaultMutableTreeNode(EMPTY_STRING));
180: public static final String SELECTION_TREE_VIEW_LIST_PROPERTY = "SELECTION_TREE_VIEW_LIST"; // NO18N
181:
182: //~ Instance fields ----------------------------------------------------------------------------------------------------------
183:
184: private final Set<ClientUtils.SourceCodeSelection> currentSelectionSet = new HashSet<ClientUtils.SourceCodeSelection>();
185: private TreeDecimator.NodeFilter<SelectorNode> nodeFilter = DEFAULT_FILTER_INNER;
186: private ProgressDisplayer progress = ProgressDisplayer.DEFAULT;
187: private SelectionTreeBuilder currentTreeBuilder = SelectionTreeBuilder.NULL;
188: private TreeDecimator<SelectorNode> treeDecimator = new TreeDecimator<SelectorNode>() {
189: @Override
190: protected List<SelectorNode> getChildren(SelectorNode aNode) {
191: aNode.getChildCount(true);
192:
193: Enumeration<SelectorNode> children = aNode.children();
194: List<SelectorNode> newChildren = new ArrayList<SelectorNode>();
195:
196: while (children.hasMoreElements()) {
197: newChildren.add(children.nextElement());
198: }
199:
200: return newChildren;
201: }
202:
203: @Override
204: protected void attachChildren(SelectorNode aNode,
205: List<SelectorNode> children) {
206: for (SelectorNode child : children) {
207: child.setParent(aNode);
208: }
209: }
210:
211: @Override
212: protected void detachChild(SelectorNode aNode,
213: SelectorNode child) {
214: child.setParent(null);
215: }
216:
217: @Override
218: protected void detachChildren(SelectorNode aNode) {
219: aNode.removeAllChildren();
220: }
221: };
222:
223: private Project[] relevantProjects;
224: private boolean showInheritedMethods = false;
225:
226: //~ Constructors -------------------------------------------------------------------------------------------------------------
227:
228: public RootSelectorTree() {
229: init();
230: }
231:
232: public RootSelectorTree(ProgressDisplayer pd) {
233: progress = pd;
234: init();
235: }
236:
237: //~ Methods ------------------------------------------------------------------------------------------------------------------
238:
239: public void setNodeFilter(
240: final TreeDecimator.NodeFilter<RootSelectorNode> customizer) {
241: nodeFilter = new TreeDecimator.NodeFilter<SelectorNode>() {
242: public boolean match(SelectorNode node) {
243: return customizer.match(new RootSelectorNode(node));
244: }
245:
246: public boolean maymatch(SelectorNode node) {
247: return customizer.maymatch(new RootSelectorNode(node));
248: }
249: };
250: }
251:
252: public void setProjects(Project[] projects) {
253: relevantProjects = projects;
254: firePropertyChange(SELECTION_TREE_VIEW_LIST_PROPERTY, null,
255: null);
256: }
257:
258: public void setSelection(
259: final ClientUtils.SourceCodeSelection[] selection) {
260: new SwingWorker(false) {
261: protected void doInBackground() {
262: applySelection(selection);
263: }
264:
265: protected void done() {
266: treeDidChange();
267: }
268: }.execute();
269: }
270:
271: public ClientUtils.SourceCodeSelection[] getSelection() {
272: return currentSelectionSet
273: .toArray(new ClientUtils.SourceCodeSelection[currentSelectionSet
274: .size()]);
275: }
276:
277: public void setSelectionTreeView(SelectionTreeView view) {
278: if (view instanceof SelectionTreeViewWrapper) {
279: currentTreeBuilder = ((SelectionTreeViewWrapper) view)
280: .getBuilder();
281:
282: // notify the tree to rebuild itself
283: refreshTree();
284: }
285: }
286:
287: public List<SelectionTreeView> getSelectionTreeViewList() {
288: List<SelectionTreeView> treeViews = new ArrayList<SelectionTreeView>();
289:
290: Map<SelectionTreeBuilder, Integer> frequencyMap = calculateBuilderUsageFrequency();
291: SelectionTreeViewWrapper defaultView = null;
292: int maxCount = 0;
293:
294: for (Map.Entry<SelectionTreeBuilder, Integer> entry : frequencyMap
295: .entrySet()) {
296: SelectionTreeViewWrapper view = new SelectionTreeViewWrapper(
297: entry.getKey(), false, entry.getValue() > 0);
298:
299: if (entry.getValue() > maxCount) {
300: maxCount = entry.getValue();
301: defaultView = view;
302: }
303:
304: treeViews.add(view);
305: }
306:
307: if (defaultView != null) {
308: defaultView.setPreferred(true);
309: }
310:
311: return treeViews;
312: }
313:
314: public void setShowingInheritedMethods(boolean value) {
315: showInheritedMethods = value;
316: }
317:
318: /**
319: * Override this method to filter showing inherited methods
320: */
321: public boolean isShowingInheritedMethods() {
322: return showInheritedMethods;
323: }
324:
325: public static boolean canBeShown() {
326: return Lookup.getDefault().lookup(SelectionTreeBuilder.class) != null;
327: }
328:
329: /**
330: * Resets the selector tree
331: * Clears the list of selected root methods + sets the default tree model
332: * Should be called right before trying to show the selector tree
333: */
334: public void reset() {
335: setModel(DEFAULTMODEL);
336: currentSelectionSet.clear();
337: relevantProjects = new Project[0];
338: }
339:
340: public void setup(Project[] projects,
341: final ClientUtils.SourceCodeSelection[] selection) {
342: if (this .currentSelectionSet != null) {
343: this .currentSelectionSet.clear();
344: }
345:
346: setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
347: setProjects(projects);
348: applySelection(selection);
349: }
350:
351: protected SelectionTreeBuilder getBuilder() {
352: return currentTreeBuilder;
353: }
354:
355: private static void addRequiredPackages(
356: Collection<ClientUtils.SourceCodeSelection> selection,
357: Collection<ClientUtils.SourceCodeSelection> toAdd) {
358: for (ClientUtils.SourceCodeSelection signature : selection) {
359: boolean appendSignature = true;
360:
361: for (ClientUtils.SourceCodeSelection addSignature : toAdd) {
362: appendSignature = appendSignature
363: && !signature.contains(addSignature);
364: }
365:
366: if (appendSignature) {
367: toAdd.add(signature);
368: }
369: }
370: }
371:
372: private Map<SelectionTreeBuilder, Integer> calculateBuilderUsageFrequency() {
373: Collection<? extends SelectionTreeBuilder> allBuilders = Lookup
374: .getDefault().lookupAll(SelectionTreeBuilder.class);
375: Map<SelectionTreeBuilder, Integer> frequencyMap = new HashMap<SelectionTreeBuilder, Integer>();
376: SelectionTreeBuilder defaultBuilder = SelectionTreeBuilder.NULL;
377:
378: for (Project currentProject : relevantProjects) {
379: boolean defaultBuilderUsed = true;
380:
381: for (SelectionTreeBuilder builder : allBuilders) {
382: if (builder.isDefault()) {
383: defaultBuilder = builder;
384:
385: continue;
386: }
387:
388: if (builder.supports(currentProject)
389: && builder.isPreferred(currentProject)) {
390: defaultBuilderUsed = false;
391:
392: if (!frequencyMap.containsKey(builder)) {
393: frequencyMap.put(builder, 1);
394: } else {
395: frequencyMap.put(builder, frequencyMap
396: .get(builder) + 1);
397: }
398: }
399: }
400:
401: if (defaultBuilderUsed) {
402: if (!frequencyMap.containsKey(defaultBuilder)) {
403: frequencyMap.put(defaultBuilder, 1);
404: } else {
405: frequencyMap.put(defaultBuilder, frequencyMap
406: .get(defaultBuilder) + 1);
407: }
408: }
409: }
410:
411: return frequencyMap;
412: }
413:
414: private static void calculateInflatedSelection(SelectorNode node,
415: SelectorNode root,
416: Collection<ClientUtils.SourceCodeSelection> selection,
417: Collection<ClientUtils.SourceCodeSelection> toRemove) {
418: if ((node == null) || (root == null) || (selection == null)
419: || (toRemove == null)) {
420: return; // don't process an invalid data
421: }
422:
423: if (root.isFullyChecked() || root.isPartiallyChecked()) {
424: if ((root.getSignature() != null)
425: && !toRemove.contains(root.getSignature())) {
426: selection.add(root.getSignature());
427: }
428:
429: if ((root.getSignature() == null)
430: || (node.getSignature() == null)
431: || root.getSignature()
432: .contains(node.getSignature())) {
433: int childrenCount = root.getChildCount();
434:
435: for (int i = 0; i < childrenCount; i++) {
436: SelectorNode childNode = (SelectorNode) root
437: .getChildAt(i);
438: calculateInflatedSelection(node, childNode,
439: selection, toRemove);
440: }
441: }
442: }
443: }
444:
445: private static void checkNodeChildren(
446: final DefaultMutableTreeNode myNode, boolean recurse) {
447: checkNodeChildren(myNode, recurse, null);
448: }
449:
450: private static void checkNodeChildren(
451: final DefaultMutableTreeNode myNode, boolean recurse,
452: CancellableController controller) {
453: if ((controller != null) && controller.isCancelled()) {
454: return;
455: }
456:
457: Enumeration children = myNode.children();
458:
459: if (myNode instanceof CheckTreeNode) {
460: if (((CheckTreeNode) myNode).isFullyChecked()) {
461: while (children.hasMoreElements()) {
462: TreeNode child = (TreeNode) children.nextElement();
463:
464: if (child instanceof CheckTreeNode) {
465: ((CheckTreeNode) child).setChecked(true);
466:
467: if (recurse) {
468: checkNodeChildren((CheckTreeNode) child,
469: recurse, controller);
470: }
471: }
472: }
473: }
474: }
475: }
476:
477: private boolean isSingleSelection() {
478: return (relevantProjects != null)
479: && (relevantProjects.length < 2);
480: }
481:
482: private DefaultMutableTreeNode getTreeRoot() {
483: DefaultMutableTreeNode root = new DefaultMutableTreeNode(
484: ROOT_STRING);
485:
486: if (relevantProjects != null) {
487: for (Project project : relevantProjects) {
488: if (getBuilder().supports(project)) {
489: for (SelectorNode node : getBuilder()
490: .buildSelectionTree(project,
491: isSingleSelection())) {
492: if (node.isValid()) {
493: node = customizeTree(node);
494:
495: if (node != null) {
496: root.add(node);
497: }
498: }
499: }
500: }
501: }
502: } else {
503: root.add(new DefaultMutableTreeNode(NO_PROJECT_STRING));
504: }
505:
506: return root;
507: }
508:
509: private void applySelection(
510: ClientUtils.SourceCodeSelection[] selections) {
511: TreeNode root = (TreeNode) this .getModel().getRoot();
512: Enumeration childrenEnum = root.children();
513:
514: while (childrenEnum.hasMoreElements()) {
515: Object child = childrenEnum.nextElement();
516:
517: if (child instanceof SelectorNode) {
518: for (ClientUtils.SourceCodeSelection selection : selections) {
519: applySelection((SelectorNode) child, selection);
520: }
521: }
522: }
523:
524: currentSelectionSet.addAll(Arrays.asList(selections));
525: }
526:
527: private void applySelection(SelectorNode node,
528: ClientUtils.SourceCodeSelection selection) {
529: ClientUtils.SourceCodeSelection signature = node.getSignature();
530:
531: if (signature != null) {
532: if (signature.equals(selection)) {
533: node.setChecked(true);
534:
535: return;
536: }
537:
538: if (!signature.contains(selection)) {
539: return;
540: }
541: }
542:
543: Enumeration childrenEnum = node.children();
544:
545: while (childrenEnum.hasMoreElements()) {
546: Object child = childrenEnum.nextElement();
547:
548: if (child instanceof SelectorNode) {
549: applySelection((SelectorNode) child, selection);
550: }
551: }
552: }
553:
554: private SelectorNode customizeTree(SelectorNode root) {
555: if (root == null) {
556: return null;
557: }
558:
559: return treeDecimator.decimate(root, nodeFilter);
560: }
561:
562: private void init() {
563: UIUtils.makeTreeAutoExpandable(this , true);
564: this .addCheckTreeListener(new CheckTreeListener() {
565: public void checkTreeChanged(Collection<CheckTreeNode> nodes) {
566: }
567:
568: public void checkNodeToggled(final TreePath treePath,
569: boolean before) {
570: if (!before) { // only after the node check-mark has been changed
571:
572: SelectorNode selectedNode = (SelectorNode) treePath
573: .getLastPathComponent();
574: Collection<ClientUtils.SourceCodeSelection> signatures = selectedNode
575: .getRootMethods(true);
576:
577: if (selectedNode.isFullyChecked()) { // new root method selected
578:
579: Collection<ClientUtils.SourceCodeSelection> toRemove = new ArrayList<ClientUtils.SourceCodeSelection>();
580:
581: // replace with this root method as much as possible from the previously selected root methods (eg. wildcard replacing single root methods within a package etc.)
582: // basically remove all root methods of the selected node's subtree
583: for (ClientUtils.SourceCodeSelection signature : signatures) {
584: for (ClientUtils.SourceCodeSelection rootMethod : currentSelectionSet) {
585: if (signature.contains(rootMethod)) {
586: toRemove.add(rootMethod);
587: }
588: }
589: }
590:
591: removeSelection(toRemove
592: .toArray(new ClientUtils.SourceCodeSelection[toRemove
593: .size()]));
594: applySelection(signatures
595: .toArray(new ClientUtils.SourceCodeSelection[signatures
596: .size()]));
597: } else {
598: // removing a previously selected root method
599: ContainerNode parent = selectedNode.getParent();
600:
601: Collection<ClientUtils.SourceCodeSelection> toAdd = new ArrayList<ClientUtils.SourceCodeSelection>();
602:
603: if (parent != null) {
604: Enumeration siblings = parent.children();
605:
606: // might be changing full-check to partial-check for the selected node parent; in that case replace the parent's wildcarded root method with its children root methods
607: while (siblings.hasMoreElements()) {
608: SelectorNode siblingNode = (SelectorNode) siblings
609: .nextElement();
610:
611: if ((siblingNode != selectedNode)
612: && siblingNode.isFullyChecked()) {
613: toAdd.addAll(siblingNode
614: .getRootMethods(true));
615: }
616: }
617: }
618:
619: Collection<ClientUtils.SourceCodeSelection> toRemove = new ArrayList<ClientUtils.SourceCodeSelection>();
620:
621: for (ClientUtils.SourceCodeSelection signature : signatures) {
622: for (ClientUtils.SourceCodeSelection rootMethod : currentSelectionSet) {
623: if (rootMethod.contains(signature)
624: || signature
625: .contains(rootMethod)) {
626: toRemove.add(rootMethod);
627: }
628: }
629: }
630:
631: toRemove.addAll(signatures);
632:
633: TreeNode root = (TreeNode) getModel().getRoot();
634: Collection<ClientUtils.SourceCodeSelection> selection = new ArrayList<ClientUtils.SourceCodeSelection>();
635: int firstLevelCnt = root.getChildCount();
636:
637: for (int i = 0; i < firstLevelCnt; i++) {
638: calculateInflatedSelection(parent,
639: (SelectorNode) root.getChildAt(i),
640: selection, toRemove);
641: }
642:
643: addRequiredPackages(selection, toAdd);
644:
645: removeSelection(toRemove
646: .toArray(new ClientUtils.SourceCodeSelection[toRemove
647: .size()]));
648:
649: applySelection(toAdd
650: .toArray(new ClientUtils.SourceCodeSelection[toAdd
651: .size()]));
652: }
653: }
654: }
655: });
656: this .addTreeWillExpandListener(new TreeWillExpandListener() {
657: private volatile boolean openingSubtree = false;
658:
659: public void treeWillCollapse(TreeExpansionEvent event)
660: throws ExpandVetoException {
661: }
662:
663: public void treeWillExpand(final TreeExpansionEvent event)
664: throws ExpandVetoException {
665: TreeNode node = (TreeNode) event.getPath()
666: .getLastPathComponent();
667:
668: if (!(node instanceof DefaultMutableTreeNode)) {
669: return;
670: }
671:
672: final DefaultMutableTreeNode myNode = (DefaultMutableTreeNode) node;
673:
674: if (myNode.getChildCount() == -1) {
675: if (openingSubtree) {
676: throw new ExpandVetoException(event);
677: }
678:
679: openingSubtree = true;
680:
681: new SwingWorker() {
682: protected void doInBackground() {
683: checkNodeChildren(myNode, false);
684: }
685:
686: protected void nonResponding() {
687: progress.showProgress(NbBundle.getMessage(
688: this .getClass(),
689: "NodeLoadingMessage")); // NOI18N
690: }
691:
692: protected void done() {
693: progress.close();
694:
695: expandPath(event.getPath());
696: doLayout();
697: openingSubtree = false;
698: }
699: }.execute();
700: throw new ExpandVetoException(event);
701: } else {
702: checkNodeChildren(myNode, false);
703: }
704: }
705: });
706:
707: this .setRootVisible(false);
708: this .setShowsRootHandles(true);
709: this .setModel(DEFAULTMODEL);
710: }
711:
712: private void refreshTree() {
713: setModel(new DefaultTreeModel(new DefaultMutableTreeNode(
714: LOADING_STRING)));
715: setRootVisible(true);
716: setShowsRootHandles(false);
717:
718: setRootVisible(false);
719: setShowsRootHandles(true);
720: setModel(new DefaultTreeModel(getTreeRoot()));
721: treeDidChange();
722: }
723:
724: private void removeSelection(
725: ClientUtils.SourceCodeSelection[] selections) {
726: TreeNode root = (TreeNode) this .getModel().getRoot();
727: Enumeration childrenEnum = root.children();
728:
729: while (childrenEnum.hasMoreElements()) {
730: Object child = childrenEnum.nextElement();
731:
732: if (child instanceof SelectorNode) {
733: for (ClientUtils.SourceCodeSelection selection : selections) {
734: removeSelection((SelectorNode) child, selection);
735: }
736: }
737: }
738:
739: currentSelectionSet.removeAll(Arrays.asList(selections));
740: }
741:
742: private void removeSelection(SelectorNode node,
743: ClientUtils.SourceCodeSelection selection) {
744: ClientUtils.SourceCodeSelection signature = node.getSignature();
745:
746: if (signature != null) {
747: if (signature.equals(selection)) {
748: node.setChecked(false);
749:
750: return;
751: }
752:
753: if (!signature.contains(selection)) {
754: return;
755: }
756: }
757:
758: Enumeration childrenEnum = node.children();
759:
760: while (childrenEnum.hasMoreElements()) {
761: Object child = childrenEnum.nextElement();
762:
763: if (child instanceof SelectorNode) {
764: removeSelection((SelectorNode) child, selection);
765: }
766: }
767: }
768: }
|