This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 200020
Collapse All | Expand All

(-)a/api.search/src/org/netbeans/modules/search/MatchingObject.java (-4 / +44 lines)
Lines 45-50 Link Here
45
package org.netbeans.modules.search;
45
package org.netbeans.modules.search;
46
46
47
import java.awt.EventQueue;
47
import java.awt.EventQueue;
48
import java.beans.PropertyChangeEvent;
48
import java.beans.PropertyChangeListener;
49
import java.beans.PropertyChangeListener;
49
import java.beans.PropertyChangeSupport;
50
import java.beans.PropertyChangeSupport;
50
import java.io.BufferedReader;
51
import java.io.BufferedReader;
Lines 89-94 Link Here
89
    public static final String PROP_INVALIDITY_STATUS =
90
    public static final String PROP_INVALIDITY_STATUS =
90
            "invalidityStatus";                                         //NOI18N
91
            "invalidityStatus";                                         //NOI18N
91
    public static final String PROP_SELECTED = "selected";              //NOI18N
92
    public static final String PROP_SELECTED = "selected";              //NOI18N
93
    /** Fired when the matching object is removed (hidden) from results. */
94
    public static final String PROP_REMOVED = "removed";                //NOI18N
95
    /** Fired when some child of this object is removed from results. */
96
    public static final String PROP_CHILD_REMOVED = "child_removed";    //NOI18N
92
97
93
    /** */
98
    /** */
94
    private static final Logger LOG =
99
    private static final Logger LOG =
Lines 269-274 Link Here
269
        }
274
        }
270
        dataObject = null;
275
        dataObject = null;
271
        nodeDelegate = null;
276
        nodeDelegate = null;
277
        changeSupport.firePropertyChange(PROP_REMOVED, null, null);
272
    }
278
    }
273
279
274
    private void setInvalid(InvalidityStatus invalidityStatus) {
280
    private void setInvalid(InvalidityStatus invalidityStatus) {
Lines 535-548 Link Here
535
541
536
        List<Node> detailNodes = new ArrayList<Node>(textDetails.size());
542
        List<Node> detailNodes = new ArrayList<Node>(textDetails.size());
537
        for (TextDetail txtDetail : textDetails) {
543
        for (TextDetail txtDetail : textDetails) {
538
            detailNodes.add(new TextDetail.DetailNode(txtDetail, false));
544
            detailNodes.add(new TextDetail.DetailNode(txtDetail, false, this));
539
        }
545
        }
540
546
541
        return detailNodes.toArray(new Node[detailNodes.size()]);
547
        return detailNodes.toArray(new Node[detailNodes.size()]);
542
    }
548
    }
543
549
544
    public Children getDetailsChildren(boolean replacing) {
550
    public Children getDetailsChildren(boolean replacing) {
545
        return new DetailsChildren(replacing);
551
        return new DetailsChildren(replacing, resultModel);
546
    }
552
    }
547
553
548
    /**
554
    /**
Lines 990-995 Link Here
990
    }
996
    }
991
997
992
    /**
998
    /**
999
     * Remove text detail, update precomputed values, inform listeners.
1000
     *
1001
     * @return True if the detail was removed, false otherwise.
1002
     */
1003
    public void removeDetail(TextDetail textDetail) {
1004
        boolean removed = textDetails.remove(textDetail);
1005
        if (removed) {
1006
            matchesCount = getDetailsCount();
1007
            resultModel.removeDetailMatch(this, textDetail);
1008
            changeSupport.firePropertyChange(PROP_CHILD_REMOVED, null, null);
1009
        }
1010
    }
1011
1012
    /**
1013
     * Remove this matching object from its result model and inform listeners.
1014
     */
1015
    public void remove() {
1016
        resultModel.remove(this);
1017
    }
1018
1019
    /**
993
     * Bridge between new API and legacy implementation, will be deleted.
1020
     * Bridge between new API and legacy implementation, will be deleted.
994
     */
1021
     */
995
    public static class Def {
1022
    public static class Def {
Lines 1033-1046 Link Here
1033
1060
1034
        private boolean replacing;
1061
        private boolean replacing;
1035
1062
1036
        public DetailsChildren(boolean replacing) {
1063
        public DetailsChildren(boolean replacing, ResultModel model) {
1037
            this.replacing = replacing;
1064
            this.replacing = replacing;
1038
            setKeys(getTextDetails());
1065
            setKeys(getTextDetails());
1066
1067
            MatchingObject.this.addPropertyChangeListener(PROP_CHILD_REMOVED,
1068
                    new PropertyChangeListener() {
1069
                @Override
1070
                public void propertyChange(PropertyChangeEvent evt) {
1071
                    update();
1072
                }
1073
            });
1039
        }
1074
        }
1040
1075
1041
        @Override
1076
        @Override
1042
        protected Node[] createNodes(TextDetail key) {
1077
        protected Node[] createNodes(TextDetail key) {
1043
            return new Node[]{new TextDetail.DetailNode(key, replacing)};
1078
            return new Node[]{new TextDetail.DetailNode(key, replacing,
1079
                MatchingObject.this)};
1080
        }
1081
1082
        public void update() {
1083
            setKeys(getTextDetails());
1044
        }
1084
        }
1045
    }
1085
    }
1046
1086
(-)a/api.search/src/org/netbeans/modules/search/ResultModel.java (-1 / +44 lines)
Lines 64-74 Link Here
64
 * @author  Marian Petras
64
 * @author  Marian Petras
65
 */
65
 */
66
public final class ResultModel {
66
public final class ResultModel {
67
68
    public static final String PROP_SELECTION = "selection";            //NOI18N
67
    public static final String PROP_SELECTION = "selection";            //NOI18N
69
    public static final String PROP_VALID = "valid";                    //NOI18N
68
    public static final String PROP_VALID = "valid";                    //NOI18N
70
    public static final String PROP_MATCHING_OBJECTS =
69
    public static final String PROP_MATCHING_OBJECTS =
71
            "matchingObjects";                                          //NOI18N
70
            "matchingObjects";                                          //NOI18N
71
    /** Fired when results were modified by the user. */
72
    public static final String PROP_RESULTS_EDIT = "resultsEdit";       //NOI18N
72
73
73
    /** */
74
    /** */
74
    private long startTime;
75
    private long startTime;
Lines 115-120 Link Here
115
	isFullText = (basicCriteria != null) && basicCriteria.isFullText();        
116
	isFullText = (basicCriteria != null) && basicCriteria.isFullText();        
116
        startTime = -1;
117
        startTime = -1;
117
    }
118
    }
119
120
    /**
121
     * Remove the {@link MatchingObject} from the model and inform the
122
     * listeners.
123
     *
124
     * @param mo Matching object to remove.
125
     */
126
    public synchronized boolean remove(MatchingObject mo) {
127
        if (matchingObjects.remove(mo)) {
128
            totalDetailsCount -= mo.getMatchesCount();
129
            int deselected = 0;
130
            if (mo.getTextDetails() != null) {
131
                for (TextDetail td : mo.getTextDetails()) {
132
                    deselected += td.isSelected() ? -1 : 0;
133
                }
134
            }
135
            mo.cleanup();
136
            // inform model listeners, old object contains removed object
137
            propertyChangeSupport.firePropertyChange(PROP_RESULTS_EDIT,
138
                    null, null);
139
            if (deselected < 0) {
140
                updateSelected(deselected);
141
            }
142
            return true;
143
        }
144
        return false;
145
    }
146
147
    public synchronized void removeDetailMatch(MatchingObject mo,
148
            TextDetail txtDetail) {
149
150
        if (txtDetail.isSelected()) {
151
            updateSelected(-1);
152
        }
153
        totalDetailsCount--;
154
        propertyChangeSupport.firePropertyChange(PROP_RESULTS_EDIT,
155
                null, null);
156
        // delete parent node if no children left
157
        if (mo.textDetails.isEmpty()) {
158
            remove(mo);
159
        }
160
    }
118
    
161
    
119
    /**
162
    /**
120
     */
163
     */
(-)a/api.search/src/org/netbeans/modules/search/TextDetail.java (-2 / +16 lines)
Lines 50-55 Link Here
50
import java.awt.datatransfer.Transferable;
50
import java.awt.datatransfer.Transferable;
51
import java.awt.event.ActionEvent;
51
import java.awt.event.ActionEvent;
52
import java.io.CharConversionException;
52
import java.io.CharConversionException;
53
import java.io.IOException;
53
import java.util.List;
54
import java.util.List;
54
import java.util.logging.Level;
55
import java.util.logging.Level;
55
import java.util.logging.Logger;
56
import java.util.logging.Logger;
Lines 451-456 Link Here
451
        /** Cached toString value. */
452
        /** Cached toString value. */
452
        private String name;
453
        private String name;
453
        private String htmlDisplayName;
454
        private String htmlDisplayName;
455
        private final MatchingObject mo;
454
        
456
        
455
        /**
457
        /**
456
         * Constructs a node representing the specified information about
458
         * Constructs a node representing the specified information about
Lines 458-468 Link Here
458
         *
460
         *
459
         * @param txtDetail  information to be represented by this node
461
         * @param txtDetail  information to be represented by this node
460
         */
462
         */
461
        public DetailNode(TextDetail txtDetail, boolean replacing) {
463
        public DetailNode(TextDetail txtDetail, boolean replacing,
464
                MatchingObject mo) {
462
            super(Children.LEAF, Lookups.fixed(txtDetail,
465
            super(Children.LEAF, Lookups.fixed(txtDetail,
463
                    new ReplaceCheckableNode(txtDetail, replacing)));
466
                    new ReplaceCheckableNode(txtDetail, replacing)));
464
            
467
            
465
            this.txtDetail = txtDetail;
468
            this.txtDetail = txtDetail;
469
            this.mo = mo;
466
            
470
            
467
            setValue(SearchDisplayer.ATTR_OUTPUT_LINE,
471
            setValue(SearchDisplayer.ATTR_OUTPUT_LINE,
468
                     DetailNode.getFullDesc(txtDetail));
472
                     DetailNode.getFullDesc(txtDetail));
Lines 475-481 Link Here
475
                @Override
479
                @Override
476
                public void stateChanged(ChangeEvent e) {
480
                public void stateChanged(ChangeEvent e) {
477
                    fireIconChange();
481
                    fireIconChange();
478
                    ResultsOutlineSupport.toggleParentSelected(DetailNode.this);
482
                    ResultsOutlineSupport.toggleParentSelected(
483
                            DetailNode.this.getParentNode());
479
                }
484
                }
480
            });
485
            });
481
            setIconBaseWithExtension(ICON);
486
            setIconBaseWithExtension(ICON);
Lines 823-828 Link Here
823
        protected void createPasteTypes(Transferable t, List<PasteType> s) {
828
        protected void createPasteTypes(Transferable t, List<PasteType> s) {
824
        }
829
        }
825
        
830
        
831
        @Override
832
        public boolean canDestroy() {
833
            return true;
834
        }
835
836
        @Override
837
        public void destroy() throws IOException {
838
            this.mo.removeDetail(txtDetail);
839
        }
826
    } // End of DetailNode class.
840
    } // End of DetailNode class.
827
841
828
    /**
842
    /**
(-)a/api.search/src/org/netbeans/modules/search/ui/AbstractSearchResultsPanel.java (+6 lines)
Lines 126-131 Link Here
126
        this.searchProviderPresenter = searchProviderPresenter;
126
        this.searchProviderPresenter = searchProviderPresenter;
127
        initComponents();
127
        initComponents();
128
        explorerManager = new ExplorerManager();
128
        explorerManager = new ExplorerManager();
129
130
        ActionMap map = this.getActionMap();
131
        // map delete key to delete action
132
        map.put("delete", //NOI18N
133
                ExplorerUtils.actionDelete(explorerManager, false));
134
129
        lookup = ExplorerUtils.createLookup(explorerManager,
135
        lookup = ExplorerUtils.createLookup(explorerManager,
130
                ResultView.getInstance().getActionMap());
136
                ResultView.getInstance().getActionMap());
131
        initActions();
137
        initActions();
(-)a/api.search/src/org/netbeans/modules/search/ui/BasicAbstractResultsPanel.java (-2 / +17 lines)
Lines 45-50 Link Here
45
import java.awt.EventQueue;
45
import java.awt.EventQueue;
46
import java.awt.event.ActionEvent;
46
import java.awt.event.ActionEvent;
47
import java.awt.event.ActionListener;
47
import java.awt.event.ActionListener;
48
import java.beans.PropertyChangeEvent;
49
import java.beans.PropertyChangeListener;
48
import java.beans.PropertyVetoException;
50
import java.beans.PropertyVetoException;
49
import java.util.ResourceBundle;
51
import java.util.ResourceBundle;
50
import javax.accessibility.AccessibleContext;
52
import javax.accessibility.AccessibleContext;
Lines 74-80 Link Here
74
 * @author jhavlin
76
 * @author jhavlin
75
 */
77
 */
76
public abstract class BasicAbstractResultsPanel
78
public abstract class BasicAbstractResultsPanel
77
        extends AbstractSearchResultsPanel {
79
        extends AbstractSearchResultsPanel implements PropertyChangeListener {
78
80
79
    @StaticResource
81
    @StaticResource
80
    private static final String SHOW_DETAILS_ICON =
82
    private static final String SHOW_DETAILS_ICON =
Lines 95-100 Link Here
95
    protected BasicComposition composition;
97
    protected BasicComposition composition;
96
    protected final ResultsOutlineSupport resultsOutlineSupport;
98
    protected final ResultsOutlineSupport resultsOutlineSupport;
97
    private NodeListener resultsNodeAdditionListener;
99
    private NodeListener resultsNodeAdditionListener;
100
    private volatile boolean finished = false;
98
    protected static final boolean isMacLaf =
101
    protected static final boolean isMacLaf =
99
            "Aqua".equals(UIManager.getLookAndFeel().getID());          //NOI18N
102
            "Aqua".equals(UIManager.getLookAndFeel().getID());          //NOI18N
100
    protected static final Color macBackground =
103
    protected static final Color macBackground =
Lines 120-127 Link Here
120
        setRootDisplayName(NbBundle.getMessage(ResultView.class,
123
        setRootDisplayName(NbBundle.getMessage(ResultView.class,
121
                "TEXT_SEARCHING___"));                                  //NOI18N
124
                "TEXT_SEARCHING___"));                                  //NOI18N
122
        initAccessibility();
125
        initAccessibility();
126
        this.resultModel.addPropertyChangeListener(
127
                ResultModel.PROP_RESULTS_EDIT, this);
123
    }
128
    }
124
129
130
    @Override
131
    public void propertyChange(PropertyChangeEvent evt) {
132
        // update the root node after change in model
133
        if (finished) {
134
            setFinalRootNodeText();
135
        } else {
136
            updateRootNodeText();
137
        }
138
    }
125
139
126
    public void update() {
140
    public void update() {
127
        if (details && btnExpand.isVisible() && !btnExpand.isEnabled()) {
141
        if (details && btnExpand.isVisible() && !btnExpand.isEnabled()) {
Lines 246-251 Link Here
246
    @Override
260
    @Override
247
    public void searchFinished() {
261
    public void searchFinished() {
248
        super.searchFinished();
262
        super.searchFinished();
263
        this.finished = true;
249
        if (details && resultModel.size() > 0 && showDetailsButton != null) {
264
        if (details && resultModel.size() > 0 && showDetailsButton != null) {
250
            showDetailsButton.setEnabled(true);
265
            showDetailsButton.setEnabled(true);
251
        }
266
        }
Lines 409-412 Link Here
409
    public void closed() {
424
    public void closed() {
410
        resultsOutlineSupport.closed();
425
        resultsOutlineSupport.closed();
411
    }
426
    }
412
}
427
}
(-)a/api.search/src/org/netbeans/modules/search/ui/HideResultAction.java (+79 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.search.ui;
43
44
import java.awt.event.ActionEvent;
45
import org.openide.actions.DeleteAction;
46
import org.openide.util.HelpCtx;
47
import org.openide.util.NbBundle;
48
import org.openide.util.actions.CallbackSystemAction;
49
import org.openide.util.actions.SystemAction;
50
51
/**
52
 *
53
 * @author jhavlin
54
 */
55
@NbBundle.Messages({"HideResultAction.displayName=Hide"})
56
public class HideResultAction extends CallbackSystemAction {
57
58
    CallbackSystemAction delegate = SystemAction.get(DeleteAction.class);
59
60
    @Override
61
    public void actionPerformed(ActionEvent e) {
62
        delegate.actionPerformed(e);
63
    }
64
65
    @Override
66
    public String getName() {
67
        return Bundle.HideResultAction_displayName();
68
    }
69
70
    @Override
71
    public HelpCtx getHelpCtx() {
72
        return delegate.getHelpCtx();
73
    }
74
75
    @Override
76
    public boolean isEnabled() {
77
        return true;
78
    }
79
}
(-)a/api.search/src/org/netbeans/modules/search/ui/MatchingObjectNode.java (-7 / +13 lines)
Lines 103-110 Link Here
103
    PropertySet[] propertySets;
103
    PropertySet[] propertySets;
104
104
105
    public MatchingObjectNode(Node original,
105
    public MatchingObjectNode(Node original,
106
            org.openide.nodes.Children children,
106
            org.openide.nodes.Children children, MatchingObject matchingObject,
107
            MatchingObject matchingObject, final boolean replacing) {
107
            final boolean replacing) {
108
        this(original, children, matchingObject,
108
        this(original, children, matchingObject,
109
                new ReplaceCheckableNode(matchingObject, replacing));
109
                new ReplaceCheckableNode(matchingObject, replacing));
110
    }
110
    }
Lines 130-137 Link Here
130
                MatchingObject.PROP_INVALIDITY_STATUS,
130
                MatchingObject.PROP_INVALIDITY_STATUS,
131
                validityListener);
131
                validityListener);
132
        selectionListener = new SelectionListener();
132
        selectionListener = new SelectionListener();
133
        matchingObject.addPropertyChangeListener(MatchingObject.PROP_SELECTED,
133
        matchingObject.addPropertyChangeListener(selectionListener);
134
                selectionListener);
135
    }
134
    }
136
135
137
    @Override
136
    @Override
Lines 165-171 Link Here
165
        if (!context) {
164
        if (!context) {
166
            return new Action[]{
165
            return new Action[]{
167
                        SystemAction.get(OpenMatchingObjectsAction.class),
166
                        SystemAction.get(OpenMatchingObjectsAction.class),
168
                        new CopyPathAction()
167
                        new CopyPathAction(),
168
                        SystemAction.get(HideResultAction.class)
169
                    };
169
                    };
170
        } else {
170
        } else {
171
            return new Action[0];
171
            return new Action[0];
Lines 234-240 Link Here
234
234
235
    @Override
235
    @Override
236
    public boolean canDestroy() {
236
    public boolean canDestroy() {
237
        return false;
237
        return true;
238
    }
238
    }
239
239
240
    public void clean() {
240
    public void clean() {
Lines 274-279 Link Here
274
        return propertySets;
274
        return propertySets;
275
    }
275
    }
276
276
277
    @Override
278
    public void destroy () throws IOException {
279
        // when removing the node, the node's content is removed from model
280
        this.matchingObject.remove();
281
    }
282
277
    /**
283
    /**
278
     * Check whether the file object is valid and a valid data object can be
284
     * Check whether the file object is valid and a valid data object can be
279
     * found for it. It should be checked after original node is destroyed. It
285
     * found for it. It should be checked after original node is destroyed. It
Lines 443-449 Link Here
443
449
444
            fireIconChange();
450
            fireIconChange();
445
            ResultsOutlineSupport.toggleParentSelected(
451
            ResultsOutlineSupport.toggleParentSelected(
446
                    MatchingObjectNode.this);
452
                    MatchingObjectNode.this.getParentNode());
447
        }
453
        }
448
    }
454
    }
449
}
455
}
(-)a/api.search/src/org/netbeans/modules/search/ui/ResultsOutlineSupport.java (-13 / +77 lines)
Lines 88-93 Link Here
88
import org.openide.nodes.Node;
88
import org.openide.nodes.Node;
89
import org.openide.util.Exceptions;
89
import org.openide.util.Exceptions;
90
import org.openide.util.ImageUtilities;
90
import org.openide.util.ImageUtilities;
91
import org.openide.util.actions.SystemAction;
91
import org.openide.util.datatransfer.PasteType;
92
import org.openide.util.datatransfer.PasteType;
92
import org.openide.util.lookup.Lookups;
93
import org.openide.util.lookup.Lookups;
93
94
Lines 125-131 Link Here
125
        this.details = details;
126
        this.details = details;
126
        this.resultModel = resultModel;
127
        this.resultModel = resultModel;
127
        this.basicComposition = basicComposition;
128
        this.basicComposition = basicComposition;
128
        this.resultsNode = new ResultsNode();
129
        this.resultsNode = new ResultsNode(resultModel);
129
        this.infoNode = infoNode;
130
        this.infoNode = infoNode;
130
        this.invisibleRoot = new RootNode(resultsNode, infoNode);
131
        this.invisibleRoot = new RootNode(resultsNode, infoNode);
131
        this.matchingObjectNodes = new LinkedList<MatchingObjectNode>();
132
        this.matchingObjectNodes = new LinkedList<MatchingObjectNode>();
Lines 312-318 Link Here
312
        private FolderTreeChildren folderTreeChildren;
313
        private FolderTreeChildren folderTreeChildren;
313
        private String htmlDisplayName = null;
314
        private String htmlDisplayName = null;
314
315
315
        public ResultsNode() {
316
        public ResultsNode(ResultModel model) {
316
            super(new FlatChildren());
317
            super(new FlatChildren());
317
            this.flatChildren = (FlatChildren) this.getChildren();
318
            this.flatChildren = (FlatChildren) this.getChildren();
318
            this.folderTreeChildren = new FolderTreeChildren(rootPathItem);
319
            this.folderTreeChildren = new FolderTreeChildren(rootPathItem);
Lines 387-392 Link Here
387
     */
388
     */
388
    private class FlatChildren extends Children.Keys<MatchingObject> {
389
    private class FlatChildren extends Children.Keys<MatchingObject> {
389
390
391
        public FlatChildren() {
392
            resultModel.addPropertyChangeListener(ResultModel.PROP_RESULTS_EDIT,
393
                    new PropertyChangeListener() {
394
                @Override
395
                public void propertyChange(PropertyChangeEvent evt) {
396
                    update();
397
                }
398
            });
399
        }
400
390
        @Override
401
        @Override
391
        protected Node[] createNodes(MatchingObject key) {
402
        protected Node[] createNodes(MatchingObject key) {
392
            return new Node[]{createNodeForMatchingObject(key)};
403
            return new Node[]{createNodeForMatchingObject(key)};
Lines 479-489 Link Here
479
                    return;
490
                    return;
480
                }
491
                }
481
            }
492
            }
482
            parentItem.addChild(new FolderTreeItem(matchingObject));
493
            parentItem.addChild(new FolderTreeItem(matchingObject, parentItem));
483
        } else {
494
        } else {
484
            try {
495
            try {
485
                FolderTreeItem newChild = new FolderTreeItem(
496
                FolderTreeItem newChild = new FolderTreeItem(
486
                        DataObject.find(path.get(0)));
497
                        DataObject.find(path.get(0)), parentItem);
487
                parentItem.addChild(newChild);
498
                parentItem.addChild(newChild);
488
                createInTreeView(newChild, path.subList(1, path.size()),
499
                createInTreeView(newChild, path.subList(1, path.size()),
489
                        matchingObject);
500
                        matchingObject);
Lines 497-502 Link Here
497
508
498
        private static final String PROP_SELECTED = "selected";         //NOI18N
509
        private static final String PROP_SELECTED = "selected";         //NOI18N
499
        private static final String PROP_CHILDREN = "children";         //NOI18N
510
        private static final String PROP_CHILDREN = "children";         //NOI18N
511
        private FolderTreeItem parent;
500
        private DataObject folder = null;
512
        private DataObject folder = null;
501
        private MatchingObject matchingObject = null;
513
        private MatchingObject matchingObject = null;
502
        private List<FolderTreeItem> children =
514
        private List<FolderTreeItem> children =
Lines 508-516 Link Here
508
         * Constructor for root node
520
         * Constructor for root node
509
         */
521
         */
510
        public FolderTreeItem() {
522
        public FolderTreeItem() {
523
            this.parent = null;
511
        }
524
        }
512
525
513
        public FolderTreeItem(MatchingObject matchingObject) {
526
        public FolderTreeItem(MatchingObject matchingObject,
527
                FolderTreeItem parent) {
528
            this.parent = parent;
514
            this.matchingObject = matchingObject;
529
            this.matchingObject = matchingObject;
515
            matchingObject.addPropertyChangeListener(
530
            matchingObject.addPropertyChangeListener(
516
                    new PropertyChangeListener() {
531
                    new PropertyChangeListener() {
Lines 520-535 Link Here
520
                    if (pn.equals(MatchingObject.PROP_SELECTED)) {
535
                    if (pn.equals(MatchingObject.PROP_SELECTED)) {
521
                        setSelected(FolderTreeItem.this.matchingObject
536
                        setSelected(FolderTreeItem.this.matchingObject
522
                                .isSelected());
537
                                .isSelected());
538
                    } else if (pn.equals(MatchingObject.PROP_REMOVED)) {
539
                        remove();
523
                    }
540
                    }
524
                }
541
                }
525
            });
542
            });
526
        }
543
        }
527
544
528
        public FolderTreeItem(DataObject file) {
545
        public FolderTreeItem(DataObject file, FolderTreeItem parent) {
546
            this.parent = parent;
529
            this.folder = file;
547
            this.folder = file;
530
        }
548
        }
531
549
532
        void addChild(FolderTreeItem pathItem) {
550
        synchronized void addChild(FolderTreeItem pathItem) {
533
            children.add(pathItem);
551
            children.add(pathItem);
534
            firePropertyChange(PROP_CHILDREN, null, null);
552
            firePropertyChange(PROP_CHILDREN, null, null);
535
        }
553
        }
Lines 538-545 Link Here
538
            return folder;
556
            return folder;
539
        }
557
        }
540
558
541
        public List<FolderTreeItem> getChildren() {
559
        public synchronized List<FolderTreeItem> getChildren() {
542
            return children;
560
            return new ArrayList<FolderTreeItem>(children);
561
        }
562
563
        public synchronized void remove() {
564
            // remove children first, then...
565
            // NOTE uses a copy of the children to prevent a ConcurrentModifcationException
566
            for (FolderTreeItem fti : new ArrayList<FolderTreeItem>(children)) {
567
                if (fti.isPathLeaf()) {
568
                    // remove the matching node
569
                    fti.getMatchingObject().remove();
570
                } else {
571
                    // remove all folder children - starts a recursion
572
                    fti.remove();
573
                }
574
            }
575
            // ... then try to remove itself
576
            if (parent != null) {
577
                parent.removeChild(this);
578
            }
579
        }
580
581
        private synchronized void removeChild(FolderTreeItem child) {
582
            boolean result = children.remove(child);
583
            if (result) {
584
                child.parent = null;
585
            }
586
            if (children.isEmpty() && parent != null) {
587
                remove();
588
            } else {
589
                firePropertyChange(PROP_CHILDREN, null, null);
590
            }
543
        }
591
        }
544
592
545
        public MatchingObject getMatchingObject() {
593
        public MatchingObject getMatchingObject() {
Lines 607-613 Link Here
607
                @Override
655
                @Override
608
                public void propertyChange(PropertyChangeEvent evt) {
656
                public void propertyChange(PropertyChangeEvent evt) {
609
                    fireIconChange();
657
                    fireIconChange();
610
                    toggleParentSelected(FolderTreeNode.this);
658
                    String prop = evt.getPropertyName();
659
                    if (prop.equals(FolderTreeItem.PROP_SELECTED)) {
660
                        toggleParentSelected(
661
                                FolderTreeNode.this.getParentNode());
662
                    } else if (prop.equals(FolderTreeItem.PROP_CHILDREN)) {
663
                        toggleParentSelected(FolderTreeNode.this);
664
                    }
611
                }
665
                }
612
            });
666
            });
613
            if (!pathItem.isPathLeaf()) {
667
            if (!pathItem.isPathLeaf()) {
Lines 627-639 Link Here
627
        }
681
        }
628
682
629
        @Override
683
        @Override
684
        public boolean canDestroy () {
685
            return true;
686
        }
687
688
        @Override
689
        public void destroy () throws IOException {
690
            FolderTreeItem folder = this.getLookup().lookup(FolderTreeItem.class);
691
            folder.remove();
692
        }
693
694
        @Override
630
        public Transferable drag() throws IOException {
695
        public Transferable drag() throws IOException {
631
            return UiUtils.DISABLE_TRANSFER;
696
            return UiUtils.DISABLE_TRANSFER;
632
        }
697
        }
633
698
634
        @Override
699
        @Override
635
        public Action[] getActions(boolean context) {
700
        public Action[] getActions(boolean context) {
636
            return new Action[0];
701
            return new Action[]{SystemAction.get(HideResultAction.class)};
637
        }
702
        }
638
    }
703
    }
639
704
Lines 675-682 Link Here
675
        }
740
        }
676
    }
741
    }
677
742
678
    public static void toggleParentSelected(Node node) {
743
    public static void toggleParentSelected(Node parent) {
679
        Node parent = node.getParentNode();
680
        if (parent == null) {
744
        if (parent == null) {
681
            return;
745
            return;
682
        }
746
        }
(-)a/api.search/test/unit/src/org/netbeans/modules/search/TextDetailTest.java (-1 / +1 lines)
Lines 144-150 Link Here
144
144
145
    public String createHtmlDisplayName(String line, String match) {
145
    public String createHtmlDisplayName(String line, String match) {
146
        TextDetail td = createMockTextDetail(line, match);
146
        TextDetail td = createMockTextDetail(line, match);
147
        DetailNode detailNode = new TextDetail.DetailNode(td, false);
147
        DetailNode detailNode = new TextDetail.DetailNode(td, false, null);
148
        String htmlDisplayName = detailNode.getHtmlDisplayName();
148
        String htmlDisplayName = detailNode.getHtmlDisplayName();
149
        Pattern p = Pattern.compile("(<html><font .*>\\s*\\d+: </font>)(.*?)(\\s+<font .*>\\[.*\\]</font></html>)");
149
        Pattern p = Pattern.compile("(<html><font .*>\\s*\\d+: </font>)(.*?)(\\s+<font .*>\\[.*\\]</font></html>)");
150
        Matcher m = p.matcher(htmlDisplayName);
150
        Matcher m = p.matcher(htmlDisplayName);

Return to bug 200020