KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > dialogs > FilteredTree


1 /*******************************************************************************
2  * Copyright (c) 2004, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.dialogs;
12
13 import org.eclipse.core.runtime.IProgressMonitor;
14 import org.eclipse.core.runtime.IStatus;
15 import org.eclipse.core.runtime.Status;
16 import org.eclipse.core.runtime.jobs.Job;
17 import org.eclipse.jface.action.Action;
18 import org.eclipse.jface.action.IAction;
19 import org.eclipse.jface.action.ToolBarManager;
20 import org.eclipse.jface.resource.ImageDescriptor;
21 import org.eclipse.jface.resource.JFaceResources;
22 import org.eclipse.jface.viewers.IContentProvider;
23 import org.eclipse.jface.viewers.ISelection;
24 import org.eclipse.jface.viewers.TreeViewer;
25 import org.eclipse.swt.SWT;
26 import org.eclipse.swt.accessibility.AccessibleAdapter;
27 import org.eclipse.swt.accessibility.AccessibleEvent;
28 import org.eclipse.swt.events.DisposeEvent;
29 import org.eclipse.swt.events.DisposeListener;
30 import org.eclipse.swt.events.FocusAdapter;
31 import org.eclipse.swt.events.FocusEvent;
32 import org.eclipse.swt.events.KeyAdapter;
33 import org.eclipse.swt.events.KeyEvent;
34 import org.eclipse.swt.events.ModifyEvent;
35 import org.eclipse.swt.events.ModifyListener;
36 import org.eclipse.swt.events.TraverseEvent;
37 import org.eclipse.swt.events.TraverseListener;
38 import org.eclipse.swt.graphics.Color;
39 import org.eclipse.swt.graphics.Font;
40 import org.eclipse.swt.layout.GridData;
41 import org.eclipse.swt.layout.GridLayout;
42 import org.eclipse.swt.widgets.Composite;
43 import org.eclipse.swt.widgets.Control;
44 import org.eclipse.swt.widgets.Display;
45 import org.eclipse.swt.widgets.Text;
46 import org.eclipse.swt.widgets.TreeItem;
47 import org.eclipse.ui.IWorkbenchPreferenceConstants;
48 import org.eclipse.ui.PlatformUI;
49 import org.eclipse.ui.internal.WorkbenchMessages;
50 import org.eclipse.ui.plugin.AbstractUIPlugin;
51 import org.eclipse.ui.progress.WorkbenchJob;
52
53 /**
54  * A simple control that provides a text widget and a tree viewer. The contents
55  * of the text widget are used to drive a PatternFilter that is on the viewer.
56  *
57  * @see org.eclipse.ui.dialogs.PatternFilter
58  * @since 3.2
59  */

60 public class FilteredTree extends Composite {
61
62     /**
63      * The filter text widget to be used by this tree. This value may be
64      * <code>null</code> if there is no filter widget, or if the controls have
65      * not yet been created.
66      */

67     protected Text filterText;
68     
69     /**
70      * The control representing the clear button for the filter text entry. This
71      * value may be <code>null</code> if no such button exists, or if the
72      * controls have not yet been created.
73      */

74     protected ToolBarManager filterToolBar;
75
76     /**
77      * The viewer for the filtered tree. This value should never be <code>null</code>
78      * after the widget creation methods are complete.
79      */

80     protected TreeViewer treeViewer;
81
82     /**
83      * The Composite on which the filter controls are created. This is used to set
84      * the background color of the filter controls to match the surrounding controls.
85      */

86     protected Composite filterComposite;
87     
88     /**
89      * The pattern filter for the tree. This value must not be <code>null</code>.
90      */

91     private PatternFilter patternFilter;
92
93     /**
94      * The text to initially show in the filter text control.
95      */

96     protected String JavaDoc initialText = ""; //$NON-NLS-1$
97

98     /**
99      * The job used to refresh the tree.
100      */

101     private Job refreshJob;
102     
103     /**
104      * The parent composite of the filtered tree.
105      * @since 3.3
106      */

107     protected Composite parent;
108
109     /**
110      * Whether or not to show the filter controls (text and clear button).
111      * The default is to show these controls. This can be overridden by
112      * providing a setting in the product configuration file. The setting
113      * to add to not show these controls is:
114      *
115      * org.eclipse.ui/SHOW_FILTERED_TEXTS=false
116      */

117     protected boolean showFilterControls;
118
119     /**
120      * @since 3.3
121      */

122     protected Composite treeComposite;
123     
124     /**
125      * Image descriptor for enabled clear button.
126      */

127     private static final String JavaDoc CLEAR_ICON = "org.eclipse.ui.internal.dialogs.CLEAR_ICON"; //$NON-NLS-1$
128

129     /**
130      * Image descriptor for disabled clear button.
131      */

132     private static final String JavaDoc DCLEAR_ICON = "org.eclipse.ui.internal.dialogs.DCLEAR_ICON"; //$NON-NLS-1$
133

134     /**
135      * Maximum time spent expanding the tree after the filter text has been updated
136      * (this is only used if we were able to at least expand the visible nodes)
137      */

138     private static final long SOFT_MAX_EXPAND_TIME = 200;
139
140     /**
141      * Get image descriptors for the clear button.
142      */

143     static {
144         ImageDescriptor descriptor = AbstractUIPlugin
145                 .imageDescriptorFromPlugin(PlatformUI.PLUGIN_ID,
146                         "$nl$/icons/full/etool16/clear_co.gif"); //$NON-NLS-1$
147
if (descriptor != null) {
148             JFaceResources.getImageRegistry().put(CLEAR_ICON, descriptor);
149         }
150         descriptor = AbstractUIPlugin.imageDescriptorFromPlugin(
151                 PlatformUI.PLUGIN_ID, "$nl$/icons/full/dtool16/clear_co.gif"); //$NON-NLS-1$
152
if (descriptor != null) {
153             JFaceResources.getImageRegistry().put(DCLEAR_ICON, descriptor);
154         }
155     }
156
157     /**
158      * Create a new instance of the receiver.
159      *
160      * @param parent
161      * the parent <code>Composite</code>
162      * @param treeStyle
163      * the style bits for the <code>Tree</code>
164      * @param filter
165      * the filter to be used
166      */

167     public FilteredTree(Composite parent, int treeStyle, PatternFilter filter) {
168         super(parent, SWT.NONE);
169         this.parent = parent;
170         init(treeStyle, filter);
171     }
172
173     /**
174      * Create a new instance of the receiver. Subclasses that wish to override
175      * the default creation behavior may use this constructor, but must ensure
176      * that the <code>init(composite, int, PatternFilter)</code> method is
177      * called in the overriding constructor.
178      *
179      * @param parent
180      * the parent <code>Composite</code>
181      * @see #init(int, PatternFilter)
182      *
183      * @since 3.3
184      */

185     protected FilteredTree(Composite parent) {
186         super(parent, SWT.NONE);
187         this.parent = parent;
188     }
189
190     /**
191      * Create the filtered tree.
192      *
193      * @param treeStyle
194      * the style bits for the <code>Tree</code>
195      * @param filter
196      * the filter to be used
197      *
198      * @since 3.3
199      */

200     protected void init(int treeStyle, PatternFilter filter) {
201         patternFilter = filter;
202         showFilterControls = PlatformUI.getPreferenceStore().getBoolean(
203                 IWorkbenchPreferenceConstants.SHOW_FILTERED_TEXTS);
204         createControl(parent, treeStyle);
205         createRefreshJob();
206         setInitialText(WorkbenchMessages.FilteredTree_FilterMessage);
207         setFont(parent.getFont());
208     }
209
210     /**
211      * Create the filtered tree's controls.
212      * Subclasses should override.
213      *
214      * @param parent
215      * @param treeStyle
216      */

217     protected void createControl(Composite parent, int treeStyle){
218         GridLayout layout = new GridLayout();
219         layout.marginHeight = 0;
220         layout.marginWidth = 0;
221         setLayout(layout);
222         setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
223
224         if (showFilterControls){
225             filterComposite = new Composite(this, SWT.NONE);
226             GridLayout filterLayout = new GridLayout(2, false);
227             filterLayout.marginHeight = 0;
228             filterLayout.marginWidth = 0;
229             filterComposite.setLayout(filterLayout);
230             filterComposite.setFont(parent.getFont());
231             
232             createFilterControls(filterComposite);
233             filterComposite.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING,
234                     true, false));
235         }
236         
237         treeComposite = new Composite(this, SWT.NONE);
238         GridLayout treeCompositeLayout = new GridLayout();
239         treeCompositeLayout.marginHeight = 0;
240         treeCompositeLayout.marginWidth = 0;
241         treeComposite.setLayout(treeCompositeLayout);
242         GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
243         treeComposite.setLayoutData(data);
244         createTreeControl(treeComposite, treeStyle);
245     }
246     
247     /**
248      * Create the filter controls. By default, a text and corresponding tool bar
249      * button that clears the contents of the text is created.
250      * Subclasses may override.
251      *
252      * @param parent parent <code>Composite</code> of the filter controls
253      * @return the <code>Composite</code> that contains the filter controls
254      */

255     protected Composite createFilterControls(Composite parent){
256         createFilterText(parent);
257         createClearText(parent);
258         if (filterToolBar != null) {
259         filterToolBar.update(false);
260         // initially there is no text to clear
261
filterToolBar.getControl().setVisible(false);
262         }
263         return parent;
264     }
265     
266     /**
267      * Creates and set up the tree and tree viewer. This method calls
268      * {@link #doCreateTreeViewer(Composite, int)} to create the tree viewer.
269      * Subclasses should override {@link #doCreateTreeViewer(Composite, int)}
270      * instead of overriding this method.
271      *
272      * @param parent
273      * parent <code>Composite</code>
274      * @param style
275      * SWT style bits used to create the tree
276      * @return the tree
277      */

278     protected Control createTreeControl(Composite parent, int style){
279         treeViewer = doCreateTreeViewer(parent, style);
280         GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
281         treeViewer.getControl().setLayoutData(data);
282         treeViewer.getControl().addDisposeListener(new DisposeListener(){
283             /* (non-Javadoc)
284              * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
285              */

286             public void widgetDisposed(DisposeEvent e) {
287                 refreshJob.cancel();
288             }
289         });
290         if (treeViewer instanceof NotifyingTreeViewer) {
291             patternFilter.setUseCache(true);
292         }
293         treeViewer.addFilter(patternFilter);
294         return treeViewer.getControl();
295     }
296
297     /**
298      * Creates the tree viewer. Subclasses may override.
299      *
300      * @param parent the parent composite
301      * @param style SWT style bits used to create the tree viewer
302      * @return the tree viewer
303      *
304      * @since 3.3
305      */

306     protected TreeViewer doCreateTreeViewer(Composite parent, int style) {
307         return new NotifyingTreeViewer(parent, style);
308     }
309     
310     /**
311      * Return the first item in the tree that matches the filter pattern.
312      *
313      * @param items
314      * @return the first matching TreeItem
315      */

316     private TreeItem getFirstMatchingItem(TreeItem[] items){
317         for (int i = 0; i < items.length; i++){
318             if (patternFilter.isLeafMatch(treeViewer, items[i].getData())
319                     && patternFilter.isElementSelectable(items[i].getData())) {
320                 return items[i];
321             }
322             return getFirstMatchingItem(items[i].getItems());
323         }
324         return null;
325     }
326     
327     /**
328      * Create the refresh job for the receiver.
329      *
330      */

331     private void createRefreshJob() {
332         refreshJob = new WorkbenchJob("Refresh Filter"){//$NON-NLS-1$
333
/* (non-Javadoc)
334              * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
335              */

336             public IStatus runInUIThread(IProgressMonitor monitor) {
337                 if(treeViewer.getControl().isDisposed()) {
338                     return Status.CANCEL_STATUS;
339                 }
340                 
341                 String JavaDoc text = getFilterString();
342                 if (text == null) {
343                     return Status.OK_STATUS;
344                 }
345                 
346                 boolean initial = initialText != null && initialText.equals(text);
347                 if (initial) {
348                     patternFilter.setPattern(null);
349                 } else if (text != null){
350                     patternFilter.setPattern(text);
351                 }
352                 
353                 Control redrawFalseControl = treeComposite != null ? treeComposite : treeViewer.getControl();
354                 try {
355                     // don't want the user to see updates that will be made to the tree
356
// we are setting redraw(false) on the composite to avoid dancing scrollbar
357
redrawFalseControl.setRedraw(false);
358                     if (!narrowingDown) {
359                         // collapse all
360
TreeItem[] is = treeViewer.getTree().getItems();
361                         for (int i = 0; i < is.length; i++) {
362                             TreeItem item = is[i];
363                             if (item.getExpanded()) {
364                                 treeViewer.setExpandedState(item.getData(), false);
365                             }
366                         }
367                     }
368                     treeViewer.refresh(true);
369                    
370                     if (text.length() > 0 && !initial) {
371                         /* Expand elements one at a time. After each is expanded, check
372                          * to see if the filter text has been modified. If it has, then
373                          * cancel the refresh job so the user doesn't have to endure
374                          * expansion of all the nodes.
375                          */

376                         TreeItem[] items = getViewer().getTree().getItems();
377                         int treeHeight = getViewer().getTree().getBounds().height;
378                         int numVisibleItems = treeHeight / getViewer().getTree().getItemHeight();
379                         long stopTime = SOFT_MAX_EXPAND_TIME + System.currentTimeMillis();
380                         if (items.length > 0
381                                 && recursiveExpand(items, monitor, stopTime, new int[] { numVisibleItems })) {
382                             return Status.CANCEL_STATUS;
383                         }
384                         
385                         // enabled toolbar - there is text to clear
386
// and the list is currently being filtered
387
updateToolbar(true);
388                     } else {
389                         // disabled toolbar - there is no text to clear
390
// and the list is currently not filtered
391
updateToolbar(false);
392                     }
393                 }
394                 finally {
395                     // done updating the tree - set redraw back to true
396
TreeItem[] items = getViewer().getTree().getItems();
397                     if (items.length > 0 && getViewer().getTree().getSelectionCount()==0) {
398                         treeViewer.getTree().setTopItem(items[0]);
399                     }
400                     redrawFalseControl.setRedraw(true);
401                 }
402                 return Status.OK_STATUS;
403             }
404
405             /**
406              * Returns true if the job should be canceled (because of timeout or actual cancellation).
407              * @param items
408              * @param provider
409              * @param monitor
410              * @param cancelTime
411              * @param numItemsLeft
412              * @return true if canceled
413              */

414             private boolean recursiveExpand(TreeItem[] items,
415                     IProgressMonitor monitor, long cancelTime, int[] numItemsLeft) {
416                 boolean canceled = false;
417                 for (int i = 0; !canceled && i < items.length; i++) {
418                     TreeItem item = items[i];
419                     boolean visible = numItemsLeft[0]-- >= 0;
420                     if (monitor.isCanceled()
421                             || (!visible && System.currentTimeMillis() > cancelTime)) {
422                         canceled = true;
423                     } else {
424                         Object JavaDoc itemData = item.getData();
425                         if (itemData != null) {
426                             if (!item.getExpanded()) {
427                                 // do the expansion through the viewer so that it can refresh children appropriately.
428
treeViewer.setExpandedState(itemData, true);
429                             }
430                             TreeItem[] children = item.getItems();
431                             if (items.length > 0) {
432                                 canceled = recursiveExpand(children,
433                                         monitor, cancelTime, numItemsLeft);
434                             }
435                         }
436                     }
437                 }
438                 return canceled;
439             }
440             
441         };
442         refreshJob.setSystem(true);
443     }
444
445     protected void updateToolbar(boolean visible){
446         if (filterToolBar != null) {
447             filterToolBar.getControl().setVisible(visible);
448         }
449     }
450     
451     /**
452      * Creates the filter text and adds listeners. This method calls
453      * {@link #doCreateFilterText(Composite)} to create the text control.
454      * Subclasses should override {@link #doCreateFilterText(Composite)}
455      * instead of overriding this method.
456      *
457      * @param parent <code>Composite</code> of the filter text
458      */

459     protected void createFilterText(Composite parent) {
460         filterText = doCreateFilterText(parent);
461         filterText.getAccessible().addAccessibleListener(
462                 new AccessibleAdapter(){
463                     /* (non-Javadoc)
464                      * @see org.eclipse.swt.accessibility.AccessibleListener#getName(org.eclipse.swt.accessibility.AccessibleEvent)
465                      */

466                     public void getName(AccessibleEvent e) {
467                         String JavaDoc filterTextString = filterText.getText();
468                         if(filterTextString.length() == 0){
469                             e.result = initialText;
470                         } else {
471                             e.result = filterTextString;
472                         }
473                     }
474                 });
475
476         filterText.addFocusListener(
477                 new FocusAdapter(){
478                     /* (non-Javadoc)
479                      * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
480                      */

481                     public void focusGained(FocusEvent e) {
482                         /* Running in an asyncExec because the selectAll() does not
483                          * appear to work when using mouse to give focus to text.
484                          */

485                         Display display = filterText.getDisplay();
486                         display.asyncExec(new Runnable JavaDoc() {
487                             public void run() {
488                                 if (!filterText.isDisposed()){
489                                     if (getInitialText().equals(filterText.getText().trim())){
490                                         filterText.selectAll();
491                                     }
492                                 }
493                             }
494                         });
495                     }
496                 });
497         
498         filterText.addKeyListener(new KeyAdapter() {
499             /*
500              * (non-Javadoc)
501              *
502              * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent)
503              */

504             public void keyPressed(KeyEvent e) {
505                 // on a CR we want to transfer focus to the list
506
boolean hasItems = getViewer().getTree().getItemCount() > 0;
507                 if(hasItems && e.keyCode == SWT.ARROW_DOWN){
508                         treeViewer.getTree().setFocus();
509                 } else if (e.character == SWT.CR){
510                     return;
511                 }
512             }
513         });
514         
515         // enter key set focus to tree
516
filterText.addTraverseListener(new TraverseListener () {
517             public void keyTraversed(TraverseEvent e) {
518                 if (e.detail == SWT.TRAVERSE_RETURN) {
519                     e.doit = false;
520                     if (getViewer().getTree().getItemCount() == 0) {
521                         Display.getCurrent().beep();
522                     } else {
523                         // if the initial filter text hasn't changed, do not try to match
524
boolean hasFocus = getViewer().getTree().setFocus();
525                         boolean textChanged = !getInitialText().equals(
526                                 filterText.getText().trim());
527                         if (hasFocus && textChanged
528                                 && filterText.getText().trim().length() > 0) {
529                             TreeItem item = getFirstMatchingItem(getViewer()
530                                     .getTree().getItems());
531                             if (item != null) {
532                                 getViewer().getTree().setSelection(
533                                         new TreeItem[] { item });
534                                 ISelection sel = getViewer().getSelection();
535                                 getViewer().setSelection(sel, true);
536                             }
537                         }
538                     }
539                 }
540             }
541         });
542         
543         filterText.addModifyListener(new ModifyListener(){
544             /* (non-Javadoc)
545              * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
546              */

547             public void modifyText(ModifyEvent e) {
548                 textChanged();
549             }
550         });
551
552         GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
553         // if the text widget supported cancel then it will have it's own
554
// integrated button. We can take all of the space.
555
if ((filterText.getStyle() & SWT.CANCEL) != 0)
556             gridData.horizontalSpan = 2;
557         filterText.setLayoutData(gridData);
558     }
559
560     /**
561      * Creates the text control for entering the filter text. Subclasses may
562      * override.
563      *
564      * @param parent
565      * the parent composite
566      * @return the text widget
567      *
568      * @since 3.3
569      */

570     protected Text doCreateFilterText(Composite parent) {
571         return new Text(parent, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.CANCEL);
572     }
573
574     private String JavaDoc previousFilterText;
575
576     private boolean narrowingDown;
577     
578     /**
579      * Update the receiver after the text has changed.
580      */

581     protected void textChanged() {
582         narrowingDown = previousFilterText==null || getFilterString().startsWith(previousFilterText);
583         previousFilterText = getFilterString();
584         // cancel currently running job first, to prevent unnecessary redraw
585
refreshJob.cancel();
586         refreshJob.schedule(200);
587     }
588
589     /**
590      * Set the background for the widgets that support the filter text area.
591      *
592      * @param background background <code>Color</code> to set
593      */

594     public void setBackground(Color background) {
595         super.setBackground(background);
596         if (filterComposite != null) {
597             filterComposite.setBackground(background);
598         }
599         if (filterToolBar != null && filterToolBar.getControl() != null) {
600             filterToolBar.getControl().setBackground(background);
601         }
602     }
603
604     /**
605      * Create the button that clears the text.
606      *
607      * @param parent parent <code>Composite</code> of toolbar button
608      */

609     private void createClearText(Composite parent) {
610         // only create the button if the text widget doesn't support one natively
611
if ((filterText.getStyle() & SWT.CANCEL) == 0) {
612             filterToolBar = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL);
613             filterToolBar.createControl(parent);
614
615             IAction clearTextAction = new Action("", IAction.AS_PUSH_BUTTON) {//$NON-NLS-1$
616
/*
617                  * (non-Javadoc)
618                  *
619                  * @see org.eclipse.jface.action.Action#run()
620                  */

621                 public void run() {
622                     clearText();
623                 }
624             };
625
626             clearTextAction
627                     .setToolTipText(WorkbenchMessages.FilteredTree_ClearToolTip);
628             clearTextAction.setImageDescriptor(JFaceResources
629                     .getImageRegistry().getDescriptor(CLEAR_ICON));
630             clearTextAction.setDisabledImageDescriptor(JFaceResources
631                     .getImageRegistry().getDescriptor(DCLEAR_ICON));
632
633             filterToolBar.add(clearTextAction);
634         }
635     }
636
637     /**
638      * Clears the text in the filter text widget. Also removes the optional
639      * additional filter that is provided via addFilter(ViewerFilter).
640      */

641     protected void clearText() {
642         setFilterText(""); //$NON-NLS-1$
643
textChanged();
644     }
645
646     /**
647      * Set the text in the filter control.
648      * @param string
649      */

650     protected void setFilterText(String JavaDoc string) {
651         if (filterText != null){
652             filterText.setText(string);
653             selectAll();
654         }
655     }
656
657     /**
658      * Returns the pattern filter used by this tree.
659      *
660      * @return The pattern filter; never <code>null</code>.
661      */

662     public final PatternFilter getPatternFilter() {
663         return patternFilter;
664     }
665     
666     /**
667      * Get the tree viewer of the receiver.
668      *
669      * @return the tree viewer
670      */

671     public TreeViewer getViewer() {
672         return treeViewer;
673     }
674
675     /**
676      * Get the filter text for the receiver, if it was created.
677      * Otherwise return <code>null</code>.
678      *
679      * @return the filter Text, or null if it was not created
680      */

681     public Text getFilterControl() {
682         return filterText;
683     }
684     
685     /**
686      * Convenience method to return the text of the filter control.
687      * If the text widget is not created, then null is returned.
688      *
689      * @return String in the text, or null if the text does not exist
690      */

691     protected String JavaDoc getFilterString(){
692         return filterText != null ? filterText.getText() : null;
693     }
694
695     /**
696      * Set the text that will be shown until the first focus.
697      * A default value is provided, so this method only need be
698      * called if overriding the default initial text is desired.
699      *
700      * @param text initial text to appear in text field
701      */

702     public void setInitialText(String JavaDoc text) {
703         initialText = text;
704         setFilterText(initialText);
705         textChanged();
706     }
707
708     /**
709      * Select all text in the filter text field.
710      *
711      */

712     protected void selectAll() {
713         if (filterText != null) {
714             filterText.selectAll();
715         }
716     }
717
718     /**
719      * Get the initial text for the receiver.
720      * @return String
721      */

722     protected String JavaDoc getInitialText() {
723         return initialText;
724     }
725
726     /**
727      * Return a bold font if the given element matches the given pattern.
728      * Clients can opt to call this method from a Viewer's label provider to get
729      * a bold font for which to highlight the given element in the tree.
730      *
731      * @param element
732      * element for which a match should be determined
733      * @param tree
734      * FilteredTree in which the element resides
735      * @param filter
736      * PatternFilter which determines a match
737      *
738      * @return bold font
739      */

740     public static Font getBoldFont(Object JavaDoc element, FilteredTree tree,
741             PatternFilter filter) {
742         String JavaDoc filterText = tree.getFilterString();
743
744         if (filterText == null) {
745             return null;
746         }
747         
748         // Do nothing if it's empty string
749
String JavaDoc initialText = tree.getInitialText();
750         if (!("".equals(filterText) || initialText.equals(filterText))) {//$NON-NLS-1$
751
boolean initial = initialText != null
752                     && initialText.equals(filterText);
753             if (initial) {
754                 filter.setPattern(null);
755             } else if (filterText != null){
756                 filter.setPattern(filterText);
757             }
758
759             if (filter.isElementVisible(tree.getViewer(), element) &&
760                     filter.isLeafMatch(tree.getViewer(),element)) {
761                 return JFaceResources.getFontRegistry().getBold(
762                         JFaceResources.DIALOG_FONT);
763             }
764         }
765         return null;
766     }
767     
768     /**
769      * Custom tree viewer subclass that clears the caches in patternFilter on
770      * any change to the tree. See bug 187200.
771      *
772      * @since 3.3
773      *
774      */

775     class NotifyingTreeViewer extends TreeViewer {
776
777         /**
778          * @param parent
779          * @param style
780          */

781         public NotifyingTreeViewer(Composite parent, int style) {
782             super(parent, style);
783         }
784
785         public void add(Object JavaDoc parentElementOrTreePath, Object JavaDoc childElement) {
786             getPatternFilter().clearCaches();
787             super.add(parentElementOrTreePath, childElement);
788         }
789
790         public void add(Object JavaDoc parentElementOrTreePath, Object JavaDoc[] childElements) {
791             getPatternFilter().clearCaches();
792             super.add(parentElementOrTreePath, childElements);
793         }
794         
795         protected void inputChanged(Object JavaDoc input, Object JavaDoc oldInput) {
796             getPatternFilter().clearCaches();
797             super.inputChanged(input, oldInput);
798         }
799
800         public void insert(Object JavaDoc parentElementOrTreePath, Object JavaDoc element,
801                 int position) {
802             getPatternFilter().clearCaches();
803             super.insert(parentElementOrTreePath, element, position);
804         }
805
806         public void refresh() {
807             getPatternFilter().clearCaches();
808             super.refresh();
809         }
810
811         public void refresh(boolean updateLabels) {
812             getPatternFilter().clearCaches();
813             super.refresh(updateLabels);
814         }
815
816         public void refresh(Object JavaDoc element) {
817             getPatternFilter().clearCaches();
818             super.refresh(element);
819         }
820
821         public void refresh(Object JavaDoc element, boolean updateLabels) {
822             getPatternFilter().clearCaches();
823             super.refresh(element, updateLabels);
824         }
825
826         public void remove(Object JavaDoc elementsOrTreePaths) {
827             getPatternFilter().clearCaches();
828             super.remove(elementsOrTreePaths);
829         }
830
831         public void remove(Object JavaDoc parent, Object JavaDoc[] elements) {
832             getPatternFilter().clearCaches();
833             super.remove(parent, elements);
834         }
835
836         public void remove(Object JavaDoc[] elementsOrTreePaths) {
837             getPatternFilter().clearCaches();
838             super.remove(elementsOrTreePaths);
839         }
840
841         public void replace(Object JavaDoc parentElementOrTreePath, int index,
842                 Object JavaDoc element) {
843             getPatternFilter().clearCaches();
844             super.replace(parentElementOrTreePath, index, element);
845         }
846
847         public void setChildCount(Object JavaDoc elementOrTreePath, int count) {
848             getPatternFilter().clearCaches();
849             super.setChildCount(elementOrTreePath, count);
850         }
851
852         public void setContentProvider(IContentProvider provider) {
853             getPatternFilter().clearCaches();
854             super.setContentProvider(provider);
855         }
856
857         public void setHasChildren(Object JavaDoc elementOrTreePath, boolean hasChildren) {
858             getPatternFilter().clearCaches();
859             super.setHasChildren(elementOrTreePath, hasChildren);
860         }
861         
862     }
863     
864 }
865
Popular Tags