Please use the Apache issue tracking system for new NetBeans issues (https://issues.apache.org/jira/projects/NETBEANS0/issues) !!
View | Details | Raw Unified | Return to bug 208794 | Differences between
and this patch

Collapse All | Expand All

(-)a/openide.explorer/apichanges.xml (+14 lines)
 Lines 50-55    Link Here 
50
<apidef name="explorer">Explorer API</apidef>
50
<apidef name="explorer">Explorer API</apidef>
51
</apidefs>
51
</apidefs>
52
<changes>
52
<changes>
53
    <change id="OutlineView_with_quicksearch">
54
        <api name="explorer"/>
55
        <summary>QuickSearch attached to OutlineView</summary>
56
        <version major="6" minor="43"/>
57
        <date day="29" month="2" year="2012"/>
58
        <author login="mentlicher"/>
59
        <compatibility binary="compatible" source="compatible" deprecation="no" deletion="no" addition="yes"/>
60
        <description>
61
            Added <a href="@TOP@/org/openide/explorer/view/OutlineView.html#getQuickSearch()">OutlineView.getQuickSearch()</a>
62
            method to get and control quick search functionality on OutlineView.
63
        </description>
64
        <class package="org.openide.explorer.view" name="OutlineView"/>
65
        <issue number="110686"/>
66
    </change>
53
    <change id="PropertyEnv.create">
67
    <change id="PropertyEnv.create">
54
        <api name="explorer"/>
68
        <api name="explorer"/>
55
        <summary>API method for creating a PropertyEnv instance</summary>
69
        <summary>API method for creating a PropertyEnv instance</summary>
(-)a/openide.explorer/manifest.mf (-1 / +1 lines)
 Lines 2-6    Link Here 
2
OpenIDE-Module: org.openide.explorer
2
OpenIDE-Module: org.openide.explorer
3
OpenIDE-Module-Localizing-Bundle: org/openide/explorer/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/openide/explorer/Bundle.properties
4
AutoUpdate-Essential-Module: true
4
AutoUpdate-Essential-Module: true
5
OpenIDE-Module-Specification-Version: 6.42
5
OpenIDE-Module-Specification-Version: 6.43
6
6
(-)a/openide.explorer/nbproject/project.xml (+8 lines)
 Lines 50-55    Link Here 
50
            <code-name-base>org.openide.explorer</code-name-base>
50
            <code-name-base>org.openide.explorer</code-name-base>
51
            <module-dependencies>
51
            <module-dependencies>
52
                <dependency>
52
                <dependency>
53
                    <code-name-base>org.netbeans.spi.quicksearch</code-name-base>
54
                    <build-prerequisite/>
55
                    <compile-dependency/>
56
                    <run-dependency>
57
                        <specification-version>1.14</specification-version>
58
                    </run-dependency>
59
                </dependency>
60
                <dependency>
53
                    <code-name-base>org.netbeans.swing.outline</code-name-base>
61
                    <code-name-base>org.netbeans.swing.outline</code-name-base>
54
                    <build-prerequisite/>
62
                    <build-prerequisite/>
55
                    <compile-dependency/>
63
                    <compile-dependency/>
(-)a/openide.explorer/src/org/openide/explorer/view/OutlineView.java (-15 / +6 lines)
 Lines 120-125    Link Here 
120
import javax.swing.table.TableModel;
120
import javax.swing.table.TableModel;
121
import javax.swing.tree.TreeNode;
121
import javax.swing.tree.TreeNode;
122
import javax.swing.tree.TreePath;
122
import javax.swing.tree.TreePath;
123
import org.netbeans.api.quicksearch.QuickSearch;
123
import org.netbeans.modules.openide.explorer.ExplorerActionsImpl;
124
import org.netbeans.modules.openide.explorer.ExplorerActionsImpl;
124
import org.netbeans.swing.etable.ETable;
125
import org.netbeans.swing.etable.ETable;
125
import org.netbeans.swing.etable.ETableColumnModel;
126
import org.netbeans.swing.etable.ETableColumnModel;
 Lines 681-704    Link Here 
681
    }
682
    }
682
    
683
    
683
    /**
684
    /**
684
     * Test whether the quick search feature is enabled or not.
685
     * Get the quick search support, that is attached to this view.
685
     * Default is enabled (true).
686
     * @return The quick search support.
686
     * @since 
687
     * @since 6.43
687
     * @return <code>true</code> if quick search feature is enabled, <code>false</code> otherwise.
688
     */
688
     */
689
    /*public*/ boolean isQuickSearchAllowed() {
689
    public final QuickSearch getQuickSearch() {
690
        return quickSearch.isEnabled();
690
        return quickSearch;
691
    }
691
    }
692
    
692
    
693
    /**
694
     * Set whether the quick search feature is enabled or not.
695
     * @since 
696
     * @param allowedQuickSearch <code>true</code> if quick search shall be enabled
697
     */
698
    /*public*/ void setQuickSearchAllowed(boolean allowedQuickSearch) {
699
        quickSearch.setEnabled(allowedQuickSearch);
700
    }
701
702
    /** Initializes the component and lookup explorer manager.
693
    /** Initializes the component and lookup explorer manager.
703
     */
694
     */
704
    @Override
695
    @Override
(-)a/openide.explorer/src/org/openide/explorer/view/QuickSearch.java (-514 lines)
 Lines 1-514    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.openide.explorer.view;
43
44
import java.awt.*;
45
import java.awt.event.*;
46
import java.lang.ref.WeakReference;
47
import java.util.LinkedList;
48
import java.util.List;
49
import javax.swing.*;
50
import javax.swing.event.DocumentEvent;
51
import javax.swing.event.DocumentListener;
52
import javax.swing.text.Position.Bias;
53
54
/**
55
 * Quick search infrastructure
56
 * 
57
 * @author Martin Entlicher
58
 */
59
class QuickSearch {
60
    
61
    private static final String ICON_FIND = "org/openide/explorer/view/find.png";
62
    private static final String ICON_FIND_WITH_MENU = "org/openide/explorer/view/findMenu.png";
63
    
64
    private final JComponent component;
65
    private final Object constraints;
66
    private boolean enabled = true;
67
    private final List<QuickSearchListener> listeners = new LinkedList<QuickSearchListener>();
68
    private SearchTextField searchTextField;
69
    private KeyAdapter quickSearchKeyAdapter;
70
    private JPanel searchPanel;
71
    private JMenu popupMenu;
72
    
73
    private QuickSearch(JComponent component, Object constraints) {
74
        this.component = component;
75
        this.constraints = constraints;
76
        setUpSearch();
77
    }
78
    
79
    public static QuickSearch attach(JComponent component, Object constraints) {
80
        Object qso = component.getClientProperty(QuickSearch.class.getName());
81
        if (qso instanceof QuickSearch) {
82
            return (QuickSearch) qso;
83
        } else {
84
            QuickSearch qs = new QuickSearch(component, constraints);
85
            component.putClientProperty(QuickSearch.class.getName(), qs);
86
            return qs;
87
        }
88
    }
89
    
90
    public void detach() {
91
        setEnabled(false);
92
        component.putClientProperty(QuickSearch.class.getName(), null);
93
    }
94
    
95
    public boolean isEnabled() {
96
        return enabled;
97
    }
98
    
99
    public void setEnabled(boolean enabled) {
100
        if (this.enabled == enabled) {
101
            return ;
102
        }
103
        this.enabled = enabled;
104
        if (enabled) {
105
            component.addKeyListener(quickSearchKeyAdapter);
106
        } else {
107
            component.removeKeyListener(quickSearchKeyAdapter);
108
        }
109
    }
110
    
111
    public void addQuickSearchListener(QuickSearchListener qsl) {
112
        synchronized (listeners) {
113
            listeners.add(qsl);
114
        }
115
    }
116
    
117
    public void removeQuickSearchListener(QuickSearchListener qsl) {
118
        synchronized (listeners) {
119
            listeners.remove(qsl);
120
        }
121
    }
122
    
123
    public void setPopupMenu(JMenu popupMenu) {
124
        this.popupMenu = popupMenu;
125
    }
126
    
127
    public void processKeyEvent(KeyEvent ke) {
128
        switch(ke.getID()) {
129
            case KeyEvent.KEY_PRESSED:
130
                quickSearchKeyAdapter.keyPressed(ke);
131
                break;
132
            case KeyEvent.KEY_RELEASED:
133
                quickSearchKeyAdapter.keyReleased(ke);
134
                break;
135
            case KeyEvent.KEY_TYPED:
136
                quickSearchKeyAdapter.keyTyped(ke);
137
                break;
138
        }
139
    }
140
    
141
    private QuickSearchListener[] getQuickSearchListeners() {
142
        QuickSearchListener[] qsls;
143
        synchronized (listeners) {
144
            qsls = listeners.toArray(new QuickSearchListener[] {});
145
        }
146
        return qsls;
147
    }
148
    
149
    private void fireQuickSearchUpdate(String searchText) {
150
        for (QuickSearchListener qsl : getQuickSearchListeners()) {
151
            qsl.quickSearchUpdate(searchText);
152
        }
153
    }
154
    
155
    private void fireShowNextSelection(Bias bias) {
156
        for (QuickSearchListener qsl : getQuickSearchListeners()) {
157
            qsl.showNextSelection(bias);
158
        }
159
    }
160
    
161
    private String findMaxPrefix(String prefix) {
162
        for (QuickSearchListener qsl : getQuickSearchListeners()) {
163
            prefix = qsl.findMaxPrefix(prefix);
164
        }
165
        return prefix;
166
    }
167
    
168
    private void fireQuickSearchConfirmed() {
169
        for (QuickSearchListener qsl : getQuickSearchListeners()) {
170
            qsl.quickSearchConfirmed();
171
        }
172
    }
173
    
174
    private void fireQuickSearchCanceled() {
175
        for (QuickSearchListener qsl : getQuickSearchListeners()) {
176
            qsl.quickSearchCanceled();
177
        }
178
    }
179
    
180
    private void setUpSearch() {
181
        searchTextField = new SearchTextField();
182
        // create new key listeners
183
        quickSearchKeyAdapter = (
184
            new KeyAdapter() {
185
            @Override
186
                public void keyTyped(KeyEvent e) {
187
                    int modifiers = e.getModifiers();
188
                    int keyCode = e.getKeyCode();
189
                    char c = e.getKeyChar();
190
191
                    //#43617 - don't eat + and -
192
                    //#98634 - and all its duplicates dont't react to space
193
                    if ((c == '+') || (c == '-') || (c==' ')) return; // NOI18N
194
195
                    if (((modifiers > 0) && (modifiers != KeyEvent.SHIFT_MASK)) || e.isActionKey()) {
196
                        return;
197
                    }
198
199
                    if (Character.isISOControl(c) ||
200
                            (keyCode == KeyEvent.VK_SHIFT) ||
201
                            (keyCode == KeyEvent.VK_ESCAPE)) return;
202
203
                    final KeyStroke stroke = KeyStroke.getKeyStrokeForEvent(e);
204
                    searchTextField.setText(String.valueOf(stroke.getKeyChar()));
205
206
                    displaySearchField();
207
                    e.consume();
208
                }
209
            }
210
        );
211
        if(isEnabled()){
212
            component.addKeyListener(quickSearchKeyAdapter);
213
        }
214
        // Create a the "multi-event" listener for the text field. Instead of
215
        // adding separate instances of each needed listener, we're using a
216
        // class which implements them all. This approach is used in order 
217
        // to avoid the creation of 4 instances which takes some time
218
        SearchFieldListener searchFieldListener = new SearchFieldListener();
219
        searchTextField.addKeyListener(searchFieldListener);
220
        searchTextField.addFocusListener(searchFieldListener);
221
        searchTextField.getDocument().addDocumentListener(searchFieldListener);
222
        
223
    }
224
    
225
    private void displaySearchField() {
226
        if (searchPanel != null || !isEnabled()) {
227
            return;
228
        }
229
        /*
230
        TreeView previousSearchField = lastSearchField.get();
231
        if (previousSearchField != null && previousSearchField != this) {
232
            previousSearchField.removeSearchField();
233
        }
234
        */
235
        //JViewport vp = getViewport();
236
        //originalScrollMode = vp.getScrollMode();
237
        //vp.setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
238
        searchTextField.setOriginalFocusOwner();
239
        searchTextField.setFont(component.getFont());
240
        searchPanel = new SearchPanel();
241
        //JLabel lbl = new JLabel(NbBundle.getMessage(TreeView.class, "LBL_QUICKSEARCH")); //NOI18N
242
        final JLabel lbl;
243
        if (popupMenu != null) {
244
            lbl = new JLabel(org.openide.util.ImageUtilities.loadImageIcon(ICON_FIND_WITH_MENU, false));
245
            lbl.addMouseListener(new MouseAdapter() {
246
                @Override
247
                public void mousePressed(MouseEvent e) {
248
                    if (e != null && !SwingUtilities.isLeftMouseButton(e)) {
249
                        return;
250
                    }
251
                    JPopupMenu pm = popupMenu.getPopupMenu();
252
                    pm.show(lbl, 0, lbl.getHeight() - 1);
253
                }
254
            });
255
        } else {
256
            lbl = new JLabel(org.openide.util.ImageUtilities.loadImageIcon(ICON_FIND, false));
257
        }
258
        searchPanel.setLayout(new BoxLayout(searchPanel, BoxLayout.X_AXIS));
259
        searchPanel.add(lbl);
260
        searchPanel.add(searchTextField);
261
        lbl.setLabelFor(searchTextField);
262
        searchTextField.setColumns(10);
263
        searchTextField.setMaximumSize(searchTextField.getPreferredSize());
264
        searchTextField.putClientProperty("JTextField.variant", "search"); //NOI18N
265
        lbl.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
266
        //JToggleButton matchCaseButton = new JToggleButton("aA");
267
        //matchCaseButton.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
268
        //searchPanel.add(matchCaseButton);
269
        if (component instanceof JScrollPane) {
270
        //    ((JScrollPane) component).getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
271
        }
272
        if (constraints == null) {
273
            component.add(searchPanel);
274
        } else {
275
            component.add(searchPanel, constraints);
276
        }
277
        component.invalidate();
278
        component.revalidate();
279
        component.repaint();
280
        searchTextField.requestFocus();
281
    }
282
    
283
    private void removeSearchField() {
284
        if (searchPanel == null) {
285
            return;
286
        }
287
        component.remove(searchPanel);
288
        searchPanel = null;
289
        //getViewport().setScrollMode(originalScrollMode);
290
        component.invalidate();
291
        component.revalidate();
292
        component.repaint();
293
    }
294
    
295
    public static String findMaxCommonSubstring(String str1, String str2, boolean ignoreCase) {
296
        int n1 = str1.length();
297
        int n2 = str2.length();
298
        int i = 0;
299
        if (ignoreCase) {
300
            for ( ; i < n1 && i < n2; i++) {
301
                char c1 = Character.toUpperCase(str1.charAt(i));
302
                char c2 = Character.toUpperCase(str2.charAt(i));
303
                if (c1 != c2) {
304
                    break;
305
                }
306
            }
307
        } else {
308
            for ( ; i < n1 && i < n2; i++) {
309
                char c1 = str1.charAt(i);
310
                char c2 = str2.charAt(i);
311
                if (c1 != c2) {
312
                    break;
313
                }
314
            }
315
        }
316
        return str1.substring(0, i);
317
    }
318
319
    public static interface QuickSearchListener {
320
        
321
        void quickSearchUpdate(String searchText);
322
        
323
        void showNextSelection(Bias bias);
324
        
325
        String findMaxPrefix(String prefix);
326
        
327
        void quickSearchConfirmed();
328
        
329
        void quickSearchCanceled();
330
331
    }
332
    
333
    private static class SearchPanel extends JPanel {
334
        
335
        public SearchPanel() {
336
            if (ViewUtil.isAquaLaF) {
337
                setBorder(BorderFactory.createEmptyBorder(9,6,8,2));
338
            } else {
339
                setBorder(BorderFactory.createEmptyBorder(2,6,2,2));
340
            }
341
            setOpaque(true);
342
        }
343
344
        @Override
345
        protected void paintComponent(Graphics g) {
346
            if (ViewUtil.isAquaLaF && g instanceof Graphics2D) {
347
                Graphics2D g2d = (Graphics2D) g;
348
                g2d.setPaint(new GradientPaint(0, 0, UIManager.getColor("NbExplorerView.quicksearch.background.top"),
349
                        0, getHeight(), UIManager.getColor("NbExplorerView.quicksearch.background.bottom")));//NOI18N
350
                g2d.fillRect(0, 0, getWidth(), getHeight());
351
                g2d.setColor(UIManager.getColor("NbExplorerView.quicksearch.border")); //NOI18N
352
                g2d.drawLine(0, 0, getWidth(), 0);
353
            } else {
354
                super.paintComponent(g);
355
            }
356
        }
357
    }
358
359
    /** searchTextField manages focus because it handles VK_ESCAPE key */
360
    private class SearchTextField extends JTextField {
361
        
362
        private WeakReference<Component> originalFocusOwner = new WeakReference<Component>(null);
363
        
364
        public SearchTextField() {
365
        }
366
        
367
        void setOriginalFocusOwner() {
368
            Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
369
            if (focusOwner != null && component.isAncestorOf(focusOwner)) {
370
                originalFocusOwner = new WeakReference<Component>(focusOwner);
371
            } else {
372
                originalFocusOwner = new WeakReference<Component>(component);
373
            }
374
        }
375
        
376
        void requestOriginalFocusOwner() {
377
            SwingUtilities.invokeLater(
378
                new Runnable() {
379
                    //additional bugfix - do focus change later or removing
380
                    //the component while it's focused will cause focus to
381
                    //get transferred to the next component in the
382
                    //parent focusTraversalPolicy *after* our request
383
                    //focus completes, so focus goes into a black hole - Tim
384
                    @Override
385
                    public void run() {
386
                        Component fo = originalFocusOwner.get();
387
                        if (fo != null) {
388
                            fo.requestFocusInWindow();
389
                        }
390
                    }
391
                }
392
            );
393
        }
394
        
395
        @Override
396
        public boolean isManagingFocus() {
397
            return true;
398
        }
399
400
        @Override
401
        public void processKeyEvent(KeyEvent ke) {
402
            //override the default handling so that
403
            //the parent will never receive the escape key and
404
            //close a modal dialog
405
            if (ke.getKeyCode() == KeyEvent.VK_ESCAPE) {
406
                removeSearchField();
407
                ke.consume();
408
                // bugfix #32909, reqest focus when search field is removed
409
                requestOriginalFocusOwner();
410
                fireQuickSearchCanceled();
411
            } else {
412
                super.processKeyEvent(ke);
413
            }
414
        }
415
    };
416
    
417
    private class SearchFieldListener extends KeyAdapter implements DocumentListener, FocusListener {
418
        
419
        private boolean ignoreEvents;
420
421
        SearchFieldListener() {
422
        }
423
424
        @Override
425
        public void changedUpdate(DocumentEvent e) {
426
            if (ignoreEvents) return;
427
            searchForNode();
428
        }
429
430
        @Override
431
        public void insertUpdate(DocumentEvent e) {
432
            if (ignoreEvents) return;
433
            searchForNode();
434
        }
435
436
        @Override
437
        public void removeUpdate(DocumentEvent e) {
438
            if (ignoreEvents) return;
439
            searchForNode();
440
        }
441
442
        @Override
443
        public void keyPressed(KeyEvent e) {
444
            int keyCode = e.getKeyCode();
445
446
            if (keyCode == KeyEvent.VK_ESCAPE) {
447
                removeSearchField();
448
                searchTextField.requestOriginalFocusOwner();
449
                fireQuickSearchCanceled();
450
                e.consume();
451
            } else if (keyCode == KeyEvent.VK_UP || (keyCode == KeyEvent.VK_F3 && e.isShiftDown())) {
452
                fireShowNextSelection(Bias.Backward);
453
                // Stop processing the event here. Otherwise it's dispatched
454
                // to the tree too (which scrolls)
455
                e.consume();
456
            } else if (keyCode == KeyEvent.VK_DOWN || keyCode == KeyEvent.VK_F3) {
457
                fireShowNextSelection(Bias.Forward);
458
                // Stop processing the event here. Otherwise it's dispatched
459
                // to the tree too (which scrolls)
460
                e.consume();
461
            } else if (keyCode == KeyEvent.VK_TAB) {
462
                String maxPrefix = findMaxPrefix(searchTextField.getText());
463
                ignoreEvents = true;
464
                try {
465
                    searchTextField.setText(maxPrefix);
466
                } finally {
467
                    ignoreEvents = false;
468
                }
469
470
                e.consume();
471
            } else if (keyCode == KeyEvent.VK_ENTER) {
472
                removeSearchField();
473
                fireQuickSearchConfirmed();
474
475
                component.requestFocusInWindow();
476
                e.consume();
477
            }
478
        }
479
480
        /** Searches for a node in the tree. */
481
        private void searchForNode() {
482
            String text = searchTextField.getText();
483
            fireQuickSearchUpdate(text);
484
        }
485
486
        @Override
487
        public void focusGained(FocusEvent e) {
488
            if (e.getSource() == searchTextField) {
489
                // make sure nothing is selected
490
                int n = searchTextField.getText().length();
491
                searchTextField.select(n, n);
492
            }
493
        }
494
495
        @Override
496
        public void focusLost(FocusEvent e) {
497
            if (e.isTemporary()) return ;
498
            Component oppositeComponent = e.getOppositeComponent();
499
            if (e.getSource() != searchTextField) {
500
                ((Component) e.getSource()).removeFocusListener(this);
501
            }
502
            if (oppositeComponent instanceof JMenuItem || oppositeComponent instanceof JPopupMenu) {
503
                oppositeComponent.addFocusListener(this);
504
                return ;
505
            }
506
            if (oppositeComponent == searchTextField) {
507
                return ;
508
            }
509
            removeSearchField();
510
            fireQuickSearchConfirmed();
511
        }
512
    }
513
514
}
(-)a/openide.explorer/src/org/openide/explorer/view/TableQuickSearchSupport.java (-1 / +3 lines)
 Lines 64-76    Link Here 
64
import javax.swing.text.Position;
64
import javax.swing.text.Position;
65
import org.openide.util.NbBundle;
65
import org.openide.util.NbBundle;
66
import org.openide.util.NbPreferences;
66
import org.openide.util.NbPreferences;
67
import org.netbeans.api.quicksearch.QuickSearch;
68
import org.netbeans.api.quicksearch.QuickSearchListener;
67
69
68
/**
70
/**
69
 * Quick search support for JTable
71
 * Quick search support for JTable
70
 * 
72
 * 
71
 * @author Martin Entlicher
73
 * @author Martin Entlicher
72
 */
74
 */
73
class TableQuickSearchSupport implements QuickSearch.QuickSearchListener {
75
class TableQuickSearchSupport implements QuickSearchListener {
74
    
76
    
75
    private int quickSearchInitialRow = -1;     // The search was initiated here
77
    private int quickSearchInitialRow = -1;     // The search was initiated here
76
    private int quickSearchInitialColumn = -1;  // The search was initiated here
78
    private int quickSearchInitialColumn = -1;  // The search was initiated here
(-)a/openide.explorer/src/org/openide/explorer/view/TreeTableView.java (+2 lines)
 Lines 85-90    Link Here 
85
import org.openide.nodes.NodeReorderEvent;
85
import org.openide.nodes.NodeReorderEvent;
86
import org.openide.util.Utilities;
86
import org.openide.util.Utilities;
87
87
88
import org.netbeans.api.quicksearch.QuickSearch;
89
88
90
89
/** Explorer view. Allows to view tree of nodes on the left
91
/** Explorer view. Allows to view tree of nodes on the left
90
 * and its properties in table on the right.
92
 * and its properties in table on the right.
(-)a/openide.explorer/src/org/openide/explorer/view/TreeView.java (-328 / +130 lines)
 Lines 141-146    Link Here 
141
import javax.swing.tree.TreeNode;
141
import javax.swing.tree.TreeNode;
142
import javax.swing.tree.TreePath;
142
import javax.swing.tree.TreePath;
143
import javax.swing.tree.TreeSelectionModel;
143
import javax.swing.tree.TreeSelectionModel;
144
import org.netbeans.api.quicksearch.QuickSearch;
145
import org.netbeans.api.quicksearch.QuickSearchListener;
146
import org.openide.awt.Actions;
144
147
145
148
146
/**
149
/**
 Lines 224-231    Link Here 
224
    transient private int allowedDropActions = DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_REFERENCE;
227
    transient private int allowedDropActions = DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_REFERENCE;
225
    
228
    
226
    /** Quick Search support */
229
    /** Quick Search support */
227
    transient private boolean allowedQuickSearch = true;
230
    transient private QuickSearch qs;
228
    transient private KeyAdapter quickSearchKeyAdapter;
229
    
231
    
230
    /** wait cursor is shown automatically during expanding */
232
    /** wait cursor is shown automatically during expanding */
231
    transient private boolean autoWaitCursor = true;
233
    transient private boolean autoWaitCursor = true;
 Lines 454-460    Link Here 
454
     * @return true if quick search feature is enabled, false otherwise.
456
     * @return true if quick search feature is enabled, false otherwise.
455
     */
457
     */
456
    public boolean isQuickSearchAllowed() {
458
    public boolean isQuickSearchAllowed() {
457
        return allowedQuickSearch;
459
        return qs.isEnabled();
458
    }
460
    }
459
    
461
    
460
    /**
462
    /**
 Lines 463-477    Link Here 
463
     * @param allowedQuickSearch <code>true</code> if quick search shall be enabled
465
     * @param allowedQuickSearch <code>true</code> if quick search shall be enabled
464
     */
466
     */
465
    public void setQuickSearchAllowed(boolean allowedQuickSearch) {
467
    public void setQuickSearchAllowed(boolean allowedQuickSearch) {
466
        this.allowedQuickSearch = allowedQuickSearch;
468
        qs.setEnabled(allowedQuickSearch);
467
         if (quickSearchKeyAdapter != null && tree != null) {
468
            if (allowedQuickSearch) {
469
               tree.addKeyListener(quickSearchKeyAdapter);
470
            } else {
471
               removeSearchField();
472
               tree.removeKeyListener(quickSearchKeyAdapter);
473
            }
474
         }
475
    }
469
    }
476
470
477
    
471
    
 Lines 1683-1693    Link Here 
1683
    }
1677
    }
1684
1678
1685
    @Override
1679
    @Override
1680
    public void add(Component comp, Object constraints) {
1681
        if (constraints == searchConstraints) {
1682
            searchPanel = comp;
1683
            constraints = null;
1684
        }
1685
        super.add(comp, constraints);
1686
    }
1687
    
1688
    @Override
1689
    public void remove(Component comp) {
1690
        if (comp == searchPanel) {
1691
            searchPanel = null;
1692
        }
1693
        super.remove(comp);
1694
    }
1695
    
1696
    @Override
1686
    public Insets getInsets() {
1697
    public Insets getInsets() {
1687
        Insets res = getInnerInsets();
1698
        Insets res = getInnerInsets();
1688
        res = new Insets(res.top, res.left, res.bottom, res.right);
1699
        res = new Insets(res.top, res.left, res.bottom, res.right);
1689
        if( null != searchpanel && searchpanel.isVisible() ) {
1700
        if( null != searchPanel && searchPanel.isVisible() ) {
1690
            res.bottom += searchpanel.getPreferredSize().height;
1701
            res.bottom += searchPanel.getPreferredSize().height;
1691
        }
1702
        }
1692
        return res;
1703
        return res;
1693
    }
1704
    }
 Lines 1701-1830    Link Here 
1701
    }
1712
    }
1702
1713
1703
    TreePath[] origSelectionPaths = null;
1714
    TreePath[] origSelectionPaths = null;
1704
    JPanel searchpanel = null;
1715
    private Component searchPanel = null;
1705
    // searchTextField manages focus because it handles VK_TAB key
1716
    private final Object searchConstraints = new Object();
1706
    private JTextField searchTextField = new JTextField() {
1717
    
1707
        @Override
1718
    /** Called from tests */
1708
        public boolean isManagingFocus() {
1719
    Component getSearchPanel() {
1709
            return true;
1720
        return searchPanel;
1710
        }
1711
1712
        @Override
1713
        public void processKeyEvent(KeyEvent ke) {
1714
            //override the default handling so that
1715
            //the parent will never receive the escape key and
1716
            //close a modal dialog
1717
            if (ke.getKeyCode() == KeyEvent.VK_ESCAPE) {
1718
                removeSearchField();
1719
                ke.consume();
1720
1721
                // bugfix #32909, reqest focus when search field is removed
1722
                SwingUtilities.invokeLater(
1723
                    new Runnable() {
1724
                        //additional bugfix - do focus change later or removing
1725
                        //the component while it's focused will cause focus to
1726
                        //get transferred to the next component in the
1727
                        //parent focusTraversalPolicy *after* our request
1728
                        //focus completes, so focus goes into a black hole - Tim
1729
                        @Override
1730
                        public void run() {
1731
                            if( null != tree )
1732
                                tree.requestFocus();
1733
                        }
1734
                    }
1735
                );
1736
            } else {
1737
                super.processKeyEvent(ke);
1738
            }
1739
        }
1740
    };
1741
    private int originalScrollMode;
1742
1743
    private static class SearchPanel extends JPanel {
1744
        public SearchPanel() {
1745
            if( ViewUtil.isAquaLaF )
1746
                setBorder(BorderFactory.createEmptyBorder(9,6,8,2));
1747
            else
1748
                setBorder(BorderFactory.createEmptyBorder(2,6,2,2));
1749
            setOpaque( true );
1750
        }
1751
1752
        @Override
1753
        protected void paintComponent(Graphics g) {
1754
            if( ViewUtil.isAquaLaF && g instanceof Graphics2D ) {
1755
                Graphics2D g2d = (Graphics2D) g;
1756
                g2d.setPaint( new GradientPaint(0, 0, UIManager.getColor("NbExplorerView.quicksearch.background.top"),
1757
                        0, getHeight(), UIManager.getColor("NbExplorerView.quicksearch.background.bottom")));//NOI18N
1758
                g2d.fillRect(0, 0, getWidth(), getHeight());
1759
                g2d.setColor( UIManager.getColor("NbExplorerView.quicksearch.border") ); //NOI18N
1760
                g2d.drawLine(0, 0, getWidth(), 0);
1761
            } else {
1762
                super.paintComponent(g);
1763
            }
1764
        }
1765
    }
1766
1767
1768
    private void prepareSearchPanel() {
1769
        if( searchpanel == null ) {
1770
            searchpanel = new SearchPanel();
1771
1772
            JLabel lbl = new JLabel(NbBundle.getMessage(TreeView.class, "LBL_QUICKSEARCH")); //NOI18N
1773
            searchpanel.setLayout(new BoxLayout(searchpanel, BoxLayout.X_AXIS));
1774
            searchpanel.add(lbl);
1775
            searchpanel.add(searchTextField);
1776
            lbl.setLabelFor(searchTextField);
1777
            searchTextField.setColumns(10);
1778
            searchTextField.setMaximumSize(searchTextField.getPreferredSize());
1779
            searchTextField.putClientProperty("JTextField.variant", "search"); //NOI18N
1780
            lbl.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
1781
        }
1782
    }
1783
1784
    /**
1785
     * Adds the search field to the tree.
1786
     */
1787
    private void displaySearchField() {
1788
        if( null != searchpanel || !isQuickSearchAllowed())
1789
            return;
1790
1791
        TreeView previousSearchField = lastSearchField.get();
1792
        if (previousSearchField != null && previousSearchField != this) {
1793
            previousSearchField.removeSearchField();
1794
        }
1795
1796
        JViewport vp = getViewport();
1797
        originalScrollMode = vp.getScrollMode();
1798
        vp.setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
1799
        searchTextField.setFont(tree.getFont());
1800
        prepareSearchPanel();
1801
        add(searchpanel);
1802
        invalidate();
1803
        revalidate();
1804
        repaint();
1805
        searchTextField.requestFocus();
1806
1807
        lastSearchField = new WeakReference<TreeView>(this);
1808
    }
1809
1810
    /**
1811
     * Removes the search field from the tree.
1812
     */
1813
    private void removeSearchField() {
1814
        if( null == searchpanel )
1815
            return;
1816
1817
        if (tree.getSelectionPaths() == null && origSelectionPaths != null) {
1818
            tree.setSelectionPaths(origSelectionPaths);
1819
        }
1820
1821
        remove(searchpanel);
1822
        searchpanel = null;
1823
        origSelectionPaths = null;
1824
        getViewport().setScrollMode(originalScrollMode);
1825
        invalidate();
1826
        revalidate();
1827
        repaint();
1828
    }
1721
    }
1829
1722
1830
    private class ExplorerScrollPaneLayout extends ScrollPaneLayout {
1723
    private class ExplorerScrollPaneLayout extends ScrollPaneLayout {
 Lines 1832-1851    Link Here 
1832
        @Override
1725
        @Override
1833
        public void layoutContainer( Container parent ) {
1726
        public void layoutContainer( Container parent ) {
1834
            super.layoutContainer(parent);
1727
            super.layoutContainer(parent);
1835
            if( null != searchpanel && searchpanel.isVisible() ) {
1728
            if( null != searchPanel && searchPanel.isVisible() ) {
1836
                Insets innerInsets = getInnerInsets();
1729
                Insets innerInsets = getInnerInsets();
1837
                Dimension prefSize = searchpanel.getPreferredSize();
1730
                Dimension prefSize = searchPanel.getPreferredSize();
1838
                searchpanel.setBounds(innerInsets.left, parent.getHeight()-innerInsets.bottom-prefSize.height,
1731
                searchPanel.setBounds(innerInsets.left, parent.getHeight()-innerInsets.bottom-prefSize.height,
1839
                        parent.getWidth()-innerInsets.left-innerInsets.right, prefSize.height);
1732
                        parent.getWidth()-innerInsets.left-innerInsets.right, prefSize.height);
1840
            }
1733
            }
1841
        }
1734
        }
1842
    }
1735
    }
1843
1736
1844
    private final class ExplorerTree extends JTree implements Autoscroll {
1737
    private final class ExplorerTree extends JTree implements Autoscroll, QuickSearchListener {
1845
        AutoscrollSupport support;
1738
        AutoscrollSupport support;
1846
        private String maxPrefix;
1739
        private String maxPrefix;
1847
        int SEARCH_FIELD_SPACE = 3;
1740
        int SEARCH_FIELD_SPACE = 3;
1848
        private boolean firstPaint = true;
1741
        private boolean firstPaint = true;
1742
        /** The last search searchResults */
1743
        private List<TreePath> searchResults = new ArrayList<TreePath>();
1744
        /** The last selected index from the search searchResults. */
1745
        private int currentSelectionIndex;
1746
        private String lastSearchText;
1849
1747
1850
1748
1851
        ExplorerTree(TreeModel model) {
1749
        ExplorerTree(TreeModel model) {
 Lines 2008-2013    Link Here 
2008
            new GuardedActions(3, fe);
1906
            new GuardedActions(3, fe);
2009
        }
1907
        }
2010
1908
1909
        @Override
1910
        protected void processKeyEvent(KeyEvent e) {
1911
            qs.processKeyEvent(e);
1912
            if (!e.isConsumed()) {
1913
                super.processKeyEvent(e);
1914
            }
1915
        }
1916
        
2011
        private void repaintSelection() {
1917
        private void repaintSelection() {
2012
            int first = getSelectionModel().getMinSelectionRow();
1918
            int first = getSelectionModel().getMinSelectionRow();
2013
            int last = getSelectionModel().getMaxSelectionRow();
1919
            int last = getSelectionModel().getMaxSelectionRow();
 Lines 2039-2096    Link Here 
2039
1945
2040
        private void setupSearch() {
1946
        private void setupSearch() {
2041
            // Remove the default key listeners
1947
            // Remove the default key listeners
2042
            KeyListener[] keyListeners = getListeners(KeyListener.class);
1948
//            KeyListener[] keyListeners = getListeners(KeyListener.class);
2043
1949
//
2044
            for (int i = 0; i < keyListeners.length; i++) {
1950
//            for (int i = 0; i < keyListeners.length; i++) {
2045
                removeKeyListener(keyListeners[i]);
1951
//                removeKeyListener(keyListeners[i]);
2046
            }
1952
//            }
2047
1953
            
2048
            // create new key listeners
1954
            qs = QuickSearch.attach(TreeView.this, searchConstraints);
2049
            quickSearchKeyAdapter = (
1955
            qs.addQuickSearchListener(this);
2050
                new KeyAdapter() {
2051
                @Override
2052
                    public void keyTyped(KeyEvent e) {
2053
                        int modifiers = e.getModifiers();
2054
                        int keyCode = e.getKeyCode();
2055
                        char c = e.getKeyChar();
2056
2057
                        //#43617 - don't eat + and -
2058
                        //#98634 - and all its duplicates dont't react to space
2059
                        if ((c == '+') || (c == '-') || (c==' ')) return; // NOI18N
2060
2061
                        if (((modifiers > 0) && (modifiers != KeyEvent.SHIFT_MASK)) || e.isActionKey()) {
2062
                            return;
2063
                        }
2064
2065
                        if (Character.isISOControl(c) ||
2066
                              (keyCode == KeyEvent.VK_SHIFT) ||
2067
			      (keyCode == KeyEvent.VK_ESCAPE)) return;
2068
2069
                        final KeyStroke stroke = KeyStroke.getKeyStrokeForEvent(e);
2070
                        origSelectionPaths = getSelectionPaths();
2071
                        if (origSelectionPaths != null && origSelectionPaths.length == 0) {
2072
                            origSelectionPaths = null;
2073
                        }
2074
                        searchTextField.setText(String.valueOf(stroke.getKeyChar()));
2075
2076
                        displaySearchField();
2077
                        e.consume();
2078
                    }
2079
                }
2080
            );
2081
            if(isQuickSearchAllowed()){
2082
                addKeyListener(quickSearchKeyAdapter);
2083
            }
2084
            // Create a the "multi-event" listener for the text field. Instead of
2085
            // adding separate instances of each needed listener, we're using a
2086
            // class which implements them all. This approach is used in order 
2087
            // to avoid the creation of 4 instances which takes some time
2088
            SearchFieldListener searchFieldListener = new SearchFieldListener();
2089
            searchTextField.addKeyListener(searchFieldListener);
2090
            searchTextField.addFocusListener(searchFieldListener);
2091
            searchTextField.getDocument().addDocumentListener(searchFieldListener);
2092
        }
1956
        }
2093
        
1957
        
1958
        @Override
1959
        public void quickSearchUpdate(String searchText) {
1960
            lastSearchText = searchText;
1961
            currentSelectionIndex = 0;
1962
            searchResults.clear();
1963
            maxPrefix = null;
1964
1965
            String text = searchText.toUpperCase();
1966
1967
            if (text.length() > 0) {
1968
                searchResults = doSearch(text);
1969
            }
1970
            displaySearchResult();
1971
        }
1972
1973
        @Override
1974
        public void showNextSelection(Position.Bias bias) {
1975
            if (bias == Position.Bias.Forward) {
1976
                currentSelectionIndex++;
1977
            } else {
1978
                currentSelectionIndex--;
1979
            }
1980
            displaySearchResult();
1981
        }
1982
1983
        @Override
1984
        public String findMaxPrefix(String prefix) {
1985
            return maxPrefix;
1986
        }
1987
1988
        @Override
1989
        public void quickSearchConfirmed() {
1990
            TreePath selectedTPath = getSelectionPath();
1991
            if (selectedTPath != null) {
1992
                TreeNode selectedTNode = (TreeNode) selectedTPath.getLastPathComponent();
1993
                Node selectedNode = Visualizer.findNode(selectedTNode);
1994
                performPreferredActionOnNodes(new Node[] { selectedNode });
1995
            }
1996
            origSelectionPaths = null;
1997
            searchResults.clear();
1998
            lastSearchText = null;
1999
        }
2000
2001
        @Override
2002
        public void quickSearchCanceled() {
2003
            origSelectionPaths = null;
2004
            searchResults.clear();
2005
            lastSearchText = null;
2006
        }
2007
2094
        private List<TreePath> doSearch(String prefix) {
2008
        private List<TreePath> doSearch(String prefix) {
2095
            List<TreePath> results = new ArrayList<TreePath>();
2009
            List<TreePath> results = new ArrayList<TreePath>();
2096
            Set<TreePath> resSet = new HashSet<TreePath>();
2010
            Set<TreePath> resSet = new HashSet<TreePath>();
 Lines 2134-2140    Link Here 
2134
                            maxPrefix = elementName;
2048
                            maxPrefix = elementName;
2135
                        }
2049
                        }
2136
2050
2137
                        maxPrefix = findMaxPrefix(maxPrefix, elementName);
2051
                        maxPrefix = QuickSearch.findMaxCommonSubstring(maxPrefix, elementName, true);
2138
                    }
2052
                    }
2139
                    // try next element
2053
                    // try next element
2140
                    startIndex++;
2054
                    startIndex++;
 Lines 2146-2161    Link Here 
2146
            return results;
2060
            return results;
2147
        }
2061
        }
2148
2062
2149
        private String findMaxPrefix(String str1, String str2) {
2150
            String res = null;
2151
2152
            for (int i = 0; str1.regionMatches(true, 0, str2, 0, i); i++) {
2153
                res = str1.substring(0, i);
2154
            }
2155
2156
            return res;
2157
        }
2158
        
2159
        /**
2063
        /**
2160
         * Copied and adapted from JTree.getNextMatch(...).
2064
         * Copied and adapted from JTree.getNextMatch(...).
2161
         * 
2065
         * 
 Lines 2193-2198    Link Here 
2193
            return null;
2097
            return null;
2194
        }
2098
        }
2195
2099
2100
        private void displaySearchResult() {
2101
            int sz = searchResults.size();
2102
2103
            if (sz > 0) {
2104
                if (currentSelectionIndex < 0) {
2105
                    currentSelectionIndex = sz - 1;
2106
                } else if (currentSelectionIndex >= sz) {
2107
                    currentSelectionIndex = 0;
2108
                }
2109
2110
                TreePath path = searchResults.get(currentSelectionIndex);
2111
                setSelectionPath(path);
2112
                scrollPathToVisible(path);
2113
            } else {
2114
                if (lastSearchText.isEmpty() && origSelectionPaths != null) {
2115
                    setSelectionPaths(origSelectionPaths);
2116
                    scrollPathToVisible(origSelectionPaths[0]);
2117
                } else {
2118
                    clearSelection();
2119
                }
2120
            }
2121
        }
2122
2196
        /** notify the Component to autoscroll */
2123
        /** notify the Component to autoscroll */
2197
        @Override
2124
        @Override
2198
        public void autoscroll(Point cursorLoc) {
2125
        public void autoscroll(Point cursorLoc) {
 Lines 2295-2425    Link Here 
2295
            }
2222
            }
2296
        }
2223
        }
2297
2224
2298
        private class SearchFieldListener extends KeyAdapter implements DocumentListener, FocusListener {
2299
            /** The last search results */
2300
            private List<TreePath> results = new ArrayList<TreePath>();
2301
2302
            /** The last selected index from the search results. */
2303
            private int currentSelectionIndex;
2304
2305
            SearchFieldListener() {
2306
            }
2307
2308
            @Override
2309
            public void changedUpdate(DocumentEvent e) {
2310
                searchForNode();
2311
            }
2312
2313
            @Override
2314
            public void insertUpdate(DocumentEvent e) {
2315
                searchForNode();
2316
            }
2317
2318
            @Override
2319
            public void removeUpdate(DocumentEvent e) {
2320
                searchForNode();
2321
            }
2322
2323
            @Override
2324
            public void keyPressed(KeyEvent e) {
2325
                int keyCode = e.getKeyCode();
2326
2327
                if (keyCode == KeyEvent.VK_ESCAPE) {
2328
                    removeSearchField();
2329
                    ExplorerTree.this.requestFocus();
2330
                } else if (keyCode == KeyEvent.VK_UP || (keyCode == KeyEvent.VK_F3 && e.isShiftDown())) {
2331
                    currentSelectionIndex--;
2332
                    displaySearchResult();
2333
2334
                    // Stop processing the event here. Otherwise it's dispatched
2335
                    // to the tree too (which scrolls)
2336
                    e.consume();
2337
                } else if (keyCode == KeyEvent.VK_DOWN || keyCode == KeyEvent.VK_F3) {
2338
                    currentSelectionIndex++;
2339
                    displaySearchResult();
2340
2341
                    // Stop processing the event here. Otherwise it's dispatched
2342
                    // to the tree too (which scrolls)
2343
                    e.consume();
2344
                } else if (keyCode == KeyEvent.VK_TAB) {
2345
                    if (maxPrefix != null) {
2346
                        searchTextField.setText(maxPrefix);
2347
                    }
2348
2349
                    e.consume();
2350
                } else if (keyCode == KeyEvent.VK_ENTER) {
2351
                    removeSearchField();
2352
2353
                    // bugfix #39607, don't expand selected node when default action invoked
2354
                    TreePath selectedTPath = getSelectionPath();
2355
2356
                    if (selectedTPath != null) {
2357
                        TreeNode selectedTNode = (TreeNode) selectedTPath.getLastPathComponent();
2358
                        Node selectedNode = Visualizer.findNode(selectedTNode);
2359
2360
                        if (
2361
                            (selectedNode.getPreferredAction() == null) ||
2362
                                !selectedNode.getPreferredAction().isEnabled()
2363
                        ) {
2364
                            expandPath(getSelectionPath());
2365
                        }
2366
                    }
2367
2368
                    ExplorerTree.this.requestFocus();
2369
                    ExplorerTree.this.dispatchEvent(e);
2370
                }
2371
            }
2372
2373
            /** Searches for a node in the tree. */
2374
            private void searchForNode() {
2375
                currentSelectionIndex = 0;
2376
                results.clear();
2377
                maxPrefix = null;
2378
2379
                String text = searchTextField.getText().toUpperCase();
2380
2381
                if (text.length() > 0) {
2382
                    results = doSearch(text);
2383
                }
2384
                displaySearchResult();
2385
            }
2386
2387
            private void displaySearchResult() {
2388
                int sz = results.size();
2389
2390
                if (sz > 0) {
2391
                    if (currentSelectionIndex < 0) {
2392
                        currentSelectionIndex = sz - 1;
2393
                    } else if (currentSelectionIndex >= sz) {
2394
                        currentSelectionIndex = 0;
2395
                    }
2396
2397
                    TreePath path = results.get(currentSelectionIndex);
2398
                    setSelectionPath(path);
2399
                    scrollPathToVisible(path);
2400
                } else {
2401
                    if (searchTextField.getText().length() == 0 && origSelectionPaths != null) {
2402
                        setSelectionPaths(origSelectionPaths);
2403
                        scrollPathToVisible(origSelectionPaths[0]);
2404
                    } else {
2405
                        clearSelection();
2406
                    }
2407
                }
2408
            }
2409
2410
            @Override
2411
            public void focusGained(FocusEvent e) {
2412
                // make sure nothing is selected
2413
                searchTextField.select(1, 1);
2414
            }
2415
2416
            @Override
2417
            public void focusLost(FocusEvent e) {
2418
                results.clear();
2419
                removeSearchField();
2420
            }
2421
        }
2422
2423
        private class AccessibleExplorerTree extends JTree.AccessibleJTree {
2225
        private class AccessibleExplorerTree extends JTree.AccessibleJTree {
2424
            AccessibleExplorerTree() {
2226
            AccessibleExplorerTree() {
2425
            }
2227
            }
(-)a/openide.explorer/test/unit/src/org/openide/explorer/view/TreeViewQuickSearchTest.java (-2 / +2 lines)
 Lines 219-227    Link Here 
219
219
220
                if (phase[0] != 0) {
220
                if (phase[0] != 0) {
221
                    if (btv.isQuickSearchAllowed()) {
221
                    if (btv.isQuickSearchAllowed()) {
222
                        assertNotNull("Quick Search enabled ", btv.searchpanel);
222
                        assertNotNull("Quick Search enabled ", btv.getSearchPanel());
223
                    } else {
223
                    } else {
224
                        assertNull("Quick Search disable", btv.searchpanel);
224
                        assertNull("Quick Search disable", btv.getSearchPanel());
225
                    }
225
                    }
226
                }
226
                }
227
            }
227
            }

Return to bug 208794
By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2014, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo