Source Code Cross Referenced for FilteredTree.java in  » IDE-Eclipse » ui-workbench » org » eclipse » ui » dialogs » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » ui workbench » org.eclipse.ui.dialogs 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2004, 2007 IBM Corporation and others.
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         *     IBM Corporation - initial API and implementation
010:         *******************************************************************************/package org.eclipse.ui.dialogs;
011:
012:        import org.eclipse.core.runtime.IProgressMonitor;
013:        import org.eclipse.core.runtime.IStatus;
014:        import org.eclipse.core.runtime.Status;
015:        import org.eclipse.core.runtime.jobs.Job;
016:        import org.eclipse.jface.action.Action;
017:        import org.eclipse.jface.action.IAction;
018:        import org.eclipse.jface.action.ToolBarManager;
019:        import org.eclipse.jface.resource.ImageDescriptor;
020:        import org.eclipse.jface.resource.JFaceResources;
021:        import org.eclipse.jface.viewers.IContentProvider;
022:        import org.eclipse.jface.viewers.ISelection;
023:        import org.eclipse.jface.viewers.TreeViewer;
024:        import org.eclipse.swt.SWT;
025:        import org.eclipse.swt.accessibility.AccessibleAdapter;
026:        import org.eclipse.swt.accessibility.AccessibleEvent;
027:        import org.eclipse.swt.events.DisposeEvent;
028:        import org.eclipse.swt.events.DisposeListener;
029:        import org.eclipse.swt.events.FocusAdapter;
030:        import org.eclipse.swt.events.FocusEvent;
031:        import org.eclipse.swt.events.KeyAdapter;
032:        import org.eclipse.swt.events.KeyEvent;
033:        import org.eclipse.swt.events.ModifyEvent;
034:        import org.eclipse.swt.events.ModifyListener;
035:        import org.eclipse.swt.events.TraverseEvent;
036:        import org.eclipse.swt.events.TraverseListener;
037:        import org.eclipse.swt.graphics.Color;
038:        import org.eclipse.swt.graphics.Font;
039:        import org.eclipse.swt.layout.GridData;
040:        import org.eclipse.swt.layout.GridLayout;
041:        import org.eclipse.swt.widgets.Composite;
042:        import org.eclipse.swt.widgets.Control;
043:        import org.eclipse.swt.widgets.Display;
044:        import org.eclipse.swt.widgets.Text;
045:        import org.eclipse.swt.widgets.TreeItem;
046:        import org.eclipse.ui.IWorkbenchPreferenceConstants;
047:        import org.eclipse.ui.PlatformUI;
048:        import org.eclipse.ui.internal.WorkbenchMessages;
049:        import org.eclipse.ui.plugin.AbstractUIPlugin;
050:        import org.eclipse.ui.progress.WorkbenchJob;
051:
052:        /**
053:         * A simple control that provides a text widget and a tree viewer. The contents
054:         * of the text widget are used to drive a PatternFilter that is on the viewer.
055:         * 
056:         * @see org.eclipse.ui.dialogs.PatternFilter
057:         * @since 3.2
058:         */
059:        public class FilteredTree extends Composite {
060:
061:            /**
062:             * The filter text widget to be used by this tree. This value may be
063:             * <code>null</code> if there is no filter widget, or if the controls have
064:             * not yet been created.
065:             */
066:            protected Text filterText;
067:
068:            /**
069:             * The control representing the clear button for the filter text entry. This
070:             * value may be <code>null</code> if no such button exists, or if the
071:             * controls have not yet been created.
072:             */
073:            protected ToolBarManager filterToolBar;
074:
075:            /**
076:             * The viewer for the filtered tree. This value should never be <code>null</code>
077:             * after the widget creation methods are complete.
078:             */
079:            protected TreeViewer treeViewer;
080:
081:            /**
082:             * The Composite on which the filter controls are created. This is used to set 
083:             * the background color of the filter controls to match the surrounding controls.
084:             */
085:            protected Composite filterComposite;
086:
087:            /**
088:             * The pattern filter for the tree. This value must not be <code>null</code>.
089:             */
090:            private PatternFilter patternFilter;
091:
092:            /**
093:             * The text to initially show in the filter text control. 
094:             */
095:            protected String initialText = ""; //$NON-NLS-1$
096:
097:            /**
098:             * The job used to refresh the tree.
099:             */
100:            private Job refreshJob;
101:
102:            /**
103:             * The parent composite of the filtered tree.
104:             * @since 3.3
105:             */
106:            protected Composite parent;
107:
108:            /**
109:             * Whether or not to show the filter controls (text and clear button).
110:             * The default is to show these controls.  This can be overridden by 
111:             * providing a setting in the product configuration file.  The setting  
112:             * to add to not show these controls is:
113:             * 
114:             * org.eclipse.ui/SHOW_FILTERED_TEXTS=false
115:             */
116:            protected boolean showFilterControls;
117:
118:            /**
119:             * @since 3.3
120:             */
121:            protected Composite treeComposite;
122:
123:            /**
124:             * Image descriptor for enabled clear button.
125:             */
126:            private static final String CLEAR_ICON = "org.eclipse.ui.internal.dialogs.CLEAR_ICON"; //$NON-NLS-1$
127:
128:            /**
129:             * Image descriptor for disabled clear button.
130:             */
131:            private static final String DCLEAR_ICON = "org.eclipse.ui.internal.dialogs.DCLEAR_ICON"; //$NON-NLS-1$
132:
133:            /**
134:             * Maximum time spent expanding the tree after the filter text has been updated
135:             * (this is only used if we were able to at least expand the visible nodes)
136:             */
137:            private static final long SOFT_MAX_EXPAND_TIME = 200;
138:
139:            /**
140:             * Get image descriptors for the clear button.
141:             */
142:            static {
143:                ImageDescriptor descriptor = AbstractUIPlugin
144:                        .imageDescriptorFromPlugin(PlatformUI.PLUGIN_ID,
145:                                "$nl$/icons/full/etool16/clear_co.gif"); //$NON-NLS-1$
146:                if (descriptor != null) {
147:                    JFaceResources.getImageRegistry().put(CLEAR_ICON,
148:                            descriptor);
149:                }
150:                descriptor = AbstractUIPlugin.imageDescriptorFromPlugin(
151:                        PlatformUI.PLUGIN_ID,
152:                        "$nl$/icons/full/dtool16/clear_co.gif"); //$NON-NLS-1$
153:                if (descriptor != null) {
154:                    JFaceResources.getImageRegistry().put(DCLEAR_ICON,
155:                            descriptor);
156:                }
157:            }
158:
159:            /**
160:             * Create a new instance of the receiver.
161:             * 
162:             * @param parent
163:             *            the parent <code>Composite</code>
164:             * @param treeStyle
165:             *            the style bits for the <code>Tree</code>
166:             * @param filter
167:             *            the filter to be used
168:             */
169:            public FilteredTree(Composite parent, int treeStyle,
170:                    PatternFilter filter) {
171:                super (parent, SWT.NONE);
172:                this .parent = parent;
173:                init(treeStyle, filter);
174:            }
175:
176:            /**
177:             * Create a new instance of the receiver. Subclasses that wish to override
178:             * the default creation behavior may use this constructor, but must ensure
179:             * that the <code>init(composite, int, PatternFilter)</code> method is
180:             * called in the overriding constructor.
181:             * 
182:             * @param parent
183:             *            the parent <code>Composite</code>
184:             * @see #init(int, PatternFilter)
185:             * 
186:             * @since 3.3
187:             */
188:            protected FilteredTree(Composite parent) {
189:                super (parent, SWT.NONE);
190:                this .parent = parent;
191:            }
192:
193:            /**
194:             * Create the filtered tree.
195:             * 
196:             * @param treeStyle
197:             *            the style bits for the <code>Tree</code>
198:             * @param filter
199:             *            the filter to be used
200:             * 
201:             * @since 3.3
202:             */
203:            protected void init(int treeStyle, PatternFilter filter) {
204:                patternFilter = filter;
205:                showFilterControls = PlatformUI
206:                        .getPreferenceStore()
207:                        .getBoolean(
208:                                IWorkbenchPreferenceConstants.SHOW_FILTERED_TEXTS);
209:                createControl(parent, treeStyle);
210:                createRefreshJob();
211:                setInitialText(WorkbenchMessages.FilteredTree_FilterMessage);
212:                setFont(parent.getFont());
213:            }
214:
215:            /**
216:             * Create the filtered tree's controls.  
217:             * Subclasses should override.
218:             * 
219:             * @param parent
220:             * @param treeStyle
221:             */
222:            protected void createControl(Composite parent, int treeStyle) {
223:                GridLayout layout = new GridLayout();
224:                layout.marginHeight = 0;
225:                layout.marginWidth = 0;
226:                setLayout(layout);
227:                setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
228:
229:                if (showFilterControls) {
230:                    filterComposite = new Composite(this , SWT.NONE);
231:                    GridLayout filterLayout = new GridLayout(2, false);
232:                    filterLayout.marginHeight = 0;
233:                    filterLayout.marginWidth = 0;
234:                    filterComposite.setLayout(filterLayout);
235:                    filterComposite.setFont(parent.getFont());
236:
237:                    createFilterControls(filterComposite);
238:                    filterComposite.setLayoutData(new GridData(SWT.FILL,
239:                            SWT.BEGINNING, true, false));
240:                }
241:
242:                treeComposite = new Composite(this , SWT.NONE);
243:                GridLayout treeCompositeLayout = new GridLayout();
244:                treeCompositeLayout.marginHeight = 0;
245:                treeCompositeLayout.marginWidth = 0;
246:                treeComposite.setLayout(treeCompositeLayout);
247:                GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
248:                treeComposite.setLayoutData(data);
249:                createTreeControl(treeComposite, treeStyle);
250:            }
251:
252:            /**
253:             * Create the filter controls.  By default, a text and corresponding tool bar 
254:             * button that clears the contents of the text is created.
255:             * Subclasses may override.  
256:             * 
257:             * @param parent parent <code>Composite</code> of the filter controls
258:             * @return the <code>Composite</code> that contains the filter controls
259:             */
260:            protected Composite createFilterControls(Composite parent) {
261:                createFilterText(parent);
262:                createClearText(parent);
263:                if (filterToolBar != null) {
264:                    filterToolBar.update(false);
265:                    // initially there is no text to clear
266:                    filterToolBar.getControl().setVisible(false);
267:                }
268:                return parent;
269:            }
270:
271:            /**
272:             * Creates and set up the tree and tree viewer. This method calls
273:             * {@link #doCreateTreeViewer(Composite, int)} to create the tree viewer.
274:             * Subclasses should override {@link #doCreateTreeViewer(Composite, int)}
275:             * instead of overriding this method.
276:             * 
277:             * @param parent
278:             *            parent <code>Composite</code>
279:             * @param style
280:             *            SWT style bits used to create the tree
281:             * @return the tree
282:             */
283:            protected Control createTreeControl(Composite parent, int style) {
284:                treeViewer = doCreateTreeViewer(parent, style);
285:                GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
286:                treeViewer.getControl().setLayoutData(data);
287:                treeViewer.getControl().addDisposeListener(
288:                        new DisposeListener() {
289:                            /* (non-Javadoc)
290:                             * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
291:                             */
292:                            public void widgetDisposed(DisposeEvent e) {
293:                                refreshJob.cancel();
294:                            }
295:                        });
296:                if (treeViewer instanceof  NotifyingTreeViewer) {
297:                    patternFilter.setUseCache(true);
298:                }
299:                treeViewer.addFilter(patternFilter);
300:                return treeViewer.getControl();
301:            }
302:
303:            /**
304:             * Creates the tree viewer.  Subclasses may override.
305:             * 
306:             * @param parent the parent composite
307:             * @param style SWT style bits used to create the tree viewer
308:             * @return the tree viewer
309:             * 
310:             * @since 3.3
311:             */
312:            protected TreeViewer doCreateTreeViewer(Composite parent, int style) {
313:                return new NotifyingTreeViewer(parent, style);
314:            }
315:
316:            /**
317:             * Return the first item in the tree that matches the filter pattern.
318:             * 
319:             * @param items
320:             * @return the first matching TreeItem
321:             */
322:            private TreeItem getFirstMatchingItem(TreeItem[] items) {
323:                for (int i = 0; i < items.length; i++) {
324:                    if (patternFilter.isLeafMatch(treeViewer, items[i]
325:                            .getData())
326:                            && patternFilter.isElementSelectable(items[i]
327:                                    .getData())) {
328:                        return items[i];
329:                    }
330:                    return getFirstMatchingItem(items[i].getItems());
331:                }
332:                return null;
333:            }
334:
335:            /**
336:             * Create the refresh job for the receiver.
337:             *
338:             */
339:            private void createRefreshJob() {
340:                refreshJob = new WorkbenchJob("Refresh Filter") {//$NON-NLS-1$
341:                    /* (non-Javadoc)
342:                     * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
343:                     */
344:                    public IStatus runInUIThread(IProgressMonitor monitor) {
345:                        if (treeViewer.getControl().isDisposed()) {
346:                            return Status.CANCEL_STATUS;
347:                        }
348:
349:                        String text = getFilterString();
350:                        if (text == null) {
351:                            return Status.OK_STATUS;
352:                        }
353:
354:                        boolean initial = initialText != null
355:                                && initialText.equals(text);
356:                        if (initial) {
357:                            patternFilter.setPattern(null);
358:                        } else if (text != null) {
359:                            patternFilter.setPattern(text);
360:                        }
361:
362:                        Control redrawFalseControl = treeComposite != null ? treeComposite
363:                                : treeViewer.getControl();
364:                        try {
365:                            // don't want the user to see updates that will be made to the tree
366:                            // we are setting redraw(false) on the composite to avoid dancing scrollbar
367:                            redrawFalseControl.setRedraw(false);
368:                            if (!narrowingDown) {
369:                                // collapse all
370:                                TreeItem[] is = treeViewer.getTree().getItems();
371:                                for (int i = 0; i < is.length; i++) {
372:                                    TreeItem item = is[i];
373:                                    if (item.getExpanded()) {
374:                                        treeViewer.setExpandedState(item
375:                                                .getData(), false);
376:                                    }
377:                                }
378:                            }
379:                            treeViewer.refresh(true);
380:
381:                            if (text.length() > 0 && !initial) {
382:                                /* Expand elements one at a time.  After each is expanded, check
383:                                 * to see if the filter text has been modified.  If it has, then 
384:                                 * cancel the refresh job so the user doesn't have to endure 
385:                                 * expansion of all the nodes.
386:                                 */
387:                                TreeItem[] items = getViewer().getTree()
388:                                        .getItems();
389:                                int treeHeight = getViewer().getTree()
390:                                        .getBounds().height;
391:                                int numVisibleItems = treeHeight
392:                                        / getViewer().getTree().getItemHeight();
393:                                long stopTime = SOFT_MAX_EXPAND_TIME
394:                                        + System.currentTimeMillis();
395:                                if (items.length > 0
396:                                        && recursiveExpand(items, monitor,
397:                                                stopTime,
398:                                                new int[] { numVisibleItems })) {
399:                                    return Status.CANCEL_STATUS;
400:                                }
401:
402:                                // enabled toolbar - there is text to clear
403:                                // and the list is currently being filtered		
404:                                updateToolbar(true);
405:                            } else {
406:                                // disabled toolbar - there is no text to clear
407:                                // and the list is currently not filtered		        	
408:                                updateToolbar(false);
409:                            }
410:                        } finally {
411:                            // done updating the tree - set redraw back to true
412:                            TreeItem[] items = getViewer().getTree().getItems();
413:                            if (items.length > 0
414:                                    && getViewer().getTree()
415:                                            .getSelectionCount() == 0) {
416:                                treeViewer.getTree().setTopItem(items[0]);
417:                            }
418:                            redrawFalseControl.setRedraw(true);
419:                        }
420:                        return Status.OK_STATUS;
421:                    }
422:
423:                    /**
424:                     * Returns true if the job should be canceled (because of timeout or actual cancellation).
425:                     * @param items
426:                     * @param provider 
427:                     * @param monitor
428:                     * @param cancelTime
429:                     * @param numItemsLeft 
430:                     * @return true if canceled
431:                     */
432:                    private boolean recursiveExpand(TreeItem[] items,
433:                            IProgressMonitor monitor, long cancelTime,
434:                            int[] numItemsLeft) {
435:                        boolean canceled = false;
436:                        for (int i = 0; !canceled && i < items.length; i++) {
437:                            TreeItem item = items[i];
438:                            boolean visible = numItemsLeft[0]-- >= 0;
439:                            if (monitor.isCanceled()
440:                                    || (!visible && System.currentTimeMillis() > cancelTime)) {
441:                                canceled = true;
442:                            } else {
443:                                Object itemData = item.getData();
444:                                if (itemData != null) {
445:                                    if (!item.getExpanded()) {
446:                                        // do the expansion through the viewer so that it can refresh children appropriately.
447:                                        treeViewer.setExpandedState(itemData,
448:                                                true);
449:                                    }
450:                                    TreeItem[] children = item.getItems();
451:                                    if (items.length > 0) {
452:                                        canceled = recursiveExpand(children,
453:                                                monitor, cancelTime,
454:                                                numItemsLeft);
455:                                    }
456:                                }
457:                            }
458:                        }
459:                        return canceled;
460:                    }
461:
462:                };
463:                refreshJob.setSystem(true);
464:            }
465:
466:            protected void updateToolbar(boolean visible) {
467:                if (filterToolBar != null) {
468:                    filterToolBar.getControl().setVisible(visible);
469:                }
470:            }
471:
472:            /**
473:             * Creates the filter text and adds listeners. This method calls
474:             * {@link #doCreateFilterText(Composite)} to create the text control.
475:             * Subclasses should override {@link #doCreateFilterText(Composite)}
476:             * instead of overriding this method.
477:             * 
478:             * @param parent <code>Composite</code> of the filter text
479:             */
480:            protected void createFilterText(Composite parent) {
481:                filterText = doCreateFilterText(parent);
482:                filterText.getAccessible().addAccessibleListener(
483:                        new AccessibleAdapter() {
484:                            /* (non-Javadoc)
485:                             * @see org.eclipse.swt.accessibility.AccessibleListener#getName(org.eclipse.swt.accessibility.AccessibleEvent)
486:                             */
487:                            public void getName(AccessibleEvent e) {
488:                                String filterTextString = filterText.getText();
489:                                if (filterTextString.length() == 0) {
490:                                    e.result = initialText;
491:                                } else {
492:                                    e.result = filterTextString;
493:                                }
494:                            }
495:                        });
496:
497:                filterText.addFocusListener(new FocusAdapter() {
498:                    /* (non-Javadoc)
499:                     * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
500:                     */
501:                    public void focusGained(FocusEvent e) {
502:                        /* Running in an asyncExec because the selectAll() does not   
503:                         * appear to work when using mouse to give focus to text.
504:                         */
505:                        Display display = filterText.getDisplay();
506:                        display.asyncExec(new Runnable() {
507:                            public void run() {
508:                                if (!filterText.isDisposed()) {
509:                                    if (getInitialText().equals(
510:                                            filterText.getText().trim())) {
511:                                        filterText.selectAll();
512:                                    }
513:                                }
514:                            }
515:                        });
516:                    }
517:                });
518:
519:                filterText.addKeyListener(new KeyAdapter() {
520:                    /*
521:                     * (non-Javadoc)
522:                     * 
523:                     * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent)
524:                     */
525:                    public void keyPressed(KeyEvent e) {
526:                        // on a CR we want to transfer focus to the list
527:                        boolean hasItems = getViewer().getTree().getItemCount() > 0;
528:                        if (hasItems && e.keyCode == SWT.ARROW_DOWN) {
529:                            treeViewer.getTree().setFocus();
530:                        } else if (e.character == SWT.CR) {
531:                            return;
532:                        }
533:                    }
534:                });
535:
536:                // enter key set focus to tree
537:                filterText.addTraverseListener(new TraverseListener() {
538:                    public void keyTraversed(TraverseEvent e) {
539:                        if (e.detail == SWT.TRAVERSE_RETURN) {
540:                            e.doit = false;
541:                            if (getViewer().getTree().getItemCount() == 0) {
542:                                Display.getCurrent().beep();
543:                            } else {
544:                                // if the initial filter text hasn't changed, do not try to match
545:                                boolean hasFocus = getViewer().getTree()
546:                                        .setFocus();
547:                                boolean textChanged = !getInitialText().equals(
548:                                        filterText.getText().trim());
549:                                if (hasFocus
550:                                        && textChanged
551:                                        && filterText.getText().trim().length() > 0) {
552:                                    TreeItem item = getFirstMatchingItem(getViewer()
553:                                            .getTree().getItems());
554:                                    if (item != null) {
555:                                        getViewer().getTree().setSelection(
556:                                                new TreeItem[] { item });
557:                                        ISelection sel = getViewer()
558:                                                .getSelection();
559:                                        getViewer().setSelection(sel, true);
560:                                    }
561:                                }
562:                            }
563:                        }
564:                    }
565:                });
566:
567:                filterText.addModifyListener(new ModifyListener() {
568:                    /* (non-Javadoc)
569:                     * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
570:                     */
571:                    public void modifyText(ModifyEvent e) {
572:                        textChanged();
573:                    }
574:                });
575:
576:                GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true,
577:                        false);
578:                // if the text widget supported cancel then it will have it's own
579:                // integrated button. We can take all of the space.
580:                if ((filterText.getStyle() & SWT.CANCEL) != 0)
581:                    gridData.horizontalSpan = 2;
582:                filterText.setLayoutData(gridData);
583:            }
584:
585:            /**
586:             * Creates the text control for entering the filter text. Subclasses may
587:             * override.
588:             * 
589:             * @param parent
590:             *            the parent composite
591:             * @return the text widget
592:             * 
593:             * @since 3.3
594:             */
595:            protected Text doCreateFilterText(Composite parent) {
596:                return new Text(parent, SWT.SINGLE | SWT.BORDER | SWT.SEARCH
597:                        | SWT.CANCEL);
598:            }
599:
600:            private String previousFilterText;
601:
602:            private boolean narrowingDown;
603:
604:            /**
605:             * Update the receiver after the text has changed.
606:             */
607:            protected void textChanged() {
608:                narrowingDown = previousFilterText == null
609:                        || getFilterString().startsWith(previousFilterText);
610:                previousFilterText = getFilterString();
611:                // cancel currently running job first, to prevent unnecessary redraw
612:                refreshJob.cancel();
613:                refreshJob.schedule(200);
614:            }
615:
616:            /**
617:             * Set the background for the widgets that support the filter text area.
618:             * 
619:             * @param background background <code>Color</code> to set
620:             */
621:            public void setBackground(Color background) {
622:                super .setBackground(background);
623:                if (filterComposite != null) {
624:                    filterComposite.setBackground(background);
625:                }
626:                if (filterToolBar != null && filterToolBar.getControl() != null) {
627:                    filterToolBar.getControl().setBackground(background);
628:                }
629:            }
630:
631:            /**
632:             * Create the button that clears the text.
633:             * 
634:             * @param parent parent <code>Composite</code> of toolbar button 
635:             */
636:            private void createClearText(Composite parent) {
637:                // only create the button if the text widget doesn't support one natively
638:                if ((filterText.getStyle() & SWT.CANCEL) == 0) {
639:                    filterToolBar = new ToolBarManager(SWT.FLAT
640:                            | SWT.HORIZONTAL);
641:                    filterToolBar.createControl(parent);
642:
643:                    IAction clearTextAction = new Action(
644:                            "", IAction.AS_PUSH_BUTTON) {//$NON-NLS-1$
645:                        /*
646:                         * (non-Javadoc)
647:                         * 
648:                         * @see org.eclipse.jface.action.Action#run()
649:                         */
650:                        public void run() {
651:                            clearText();
652:                        }
653:                    };
654:
655:                    clearTextAction
656:                            .setToolTipText(WorkbenchMessages.FilteredTree_ClearToolTip);
657:                    clearTextAction.setImageDescriptor(JFaceResources
658:                            .getImageRegistry().getDescriptor(CLEAR_ICON));
659:                    clearTextAction.setDisabledImageDescriptor(JFaceResources
660:                            .getImageRegistry().getDescriptor(DCLEAR_ICON));
661:
662:                    filterToolBar.add(clearTextAction);
663:                }
664:            }
665:
666:            /**
667:             * Clears the text in the filter text widget. Also removes the optional
668:             * additional filter that is provided via addFilter(ViewerFilter).
669:             */
670:            protected void clearText() {
671:                setFilterText(""); //$NON-NLS-1$
672:                textChanged();
673:            }
674:
675:            /**
676:             * Set the text in the filter control.
677:             * @param string 
678:             */
679:            protected void setFilterText(String string) {
680:                if (filterText != null) {
681:                    filterText.setText(string);
682:                    selectAll();
683:                }
684:            }
685:
686:            /**
687:             * Returns the pattern filter used by this tree.
688:             * 
689:             * @return The pattern filter; never <code>null</code>.
690:             */
691:            public final PatternFilter getPatternFilter() {
692:                return patternFilter;
693:            }
694:
695:            /**
696:             * Get the tree viewer of the receiver.
697:             * 
698:             * @return the tree viewer
699:             */
700:            public TreeViewer getViewer() {
701:                return treeViewer;
702:            }
703:
704:            /**
705:             * Get the filter text for the receiver, if it was created. 
706:             * Otherwise return <code>null</code>.
707:             * 
708:             * @return the filter Text, or null if it was not created
709:             */
710:            public Text getFilterControl() {
711:                return filterText;
712:            }
713:
714:            /**
715:             * Convenience method to return the text of the filter control.
716:             * If the text widget is not created, then null is returned.
717:             * 
718:             * @return String in the text, or null if the text does not exist
719:             */
720:            protected String getFilterString() {
721:                return filterText != null ? filterText.getText() : null;
722:            }
723:
724:            /**
725:             * Set the text that will be shown until the first focus.
726:             * A default value is provided, so this method only need be 
727:             * called if overriding the default initial text is desired.
728:             * 
729:             * @param text initial text to appear in text field
730:             */
731:            public void setInitialText(String text) {
732:                initialText = text;
733:                setFilterText(initialText);
734:                textChanged();
735:            }
736:
737:            /**
738:             * Select all text in the filter text field.
739:             *
740:             */
741:            protected void selectAll() {
742:                if (filterText != null) {
743:                    filterText.selectAll();
744:                }
745:            }
746:
747:            /**
748:             * Get the initial text for the receiver.
749:             * @return String
750:             */
751:            protected String getInitialText() {
752:                return initialText;
753:            }
754:
755:            /**
756:             * Return a bold font if the given element matches the given pattern.
757:             * Clients can opt to call this method from a Viewer's label provider to get
758:             * a bold font for which to highlight the given element in the tree.
759:             * 
760:             * @param element
761:             *            element for which a match should be determined
762:             * @param tree
763:             *            FilteredTree in which the element resides
764:             * @param filter
765:             *            PatternFilter which determines a match
766:             * 
767:             * @return bold font
768:             */
769:            public static Font getBoldFont(Object element, FilteredTree tree,
770:                    PatternFilter filter) {
771:                String filterText = tree.getFilterString();
772:
773:                if (filterText == null) {
774:                    return null;
775:                }
776:
777:                // Do nothing if it's empty string
778:                String initialText = tree.getInitialText();
779:                if (!("".equals(filterText) || initialText.equals(filterText))) {//$NON-NLS-1$
780:                    boolean initial = initialText != null
781:                            && initialText.equals(filterText);
782:                    if (initial) {
783:                        filter.setPattern(null);
784:                    } else if (filterText != null) {
785:                        filter.setPattern(filterText);
786:                    }
787:
788:                    if (filter.isElementVisible(tree.getViewer(), element)
789:                            && filter.isLeafMatch(tree.getViewer(), element)) {
790:                        return JFaceResources.getFontRegistry().getBold(
791:                                JFaceResources.DIALOG_FONT);
792:                    }
793:                }
794:                return null;
795:            }
796:
797:            /**
798:             * Custom tree viewer subclass that clears the caches in patternFilter on
799:             * any change to the tree. See bug 187200.
800:             * 
801:             * @since 3.3
802:             *
803:             */
804:            class NotifyingTreeViewer extends TreeViewer {
805:
806:                /**
807:                 * @param parent
808:                 * @param style
809:                 */
810:                public NotifyingTreeViewer(Composite parent, int style) {
811:                    super (parent, style);
812:                }
813:
814:                public void add(Object parentElementOrTreePath,
815:                        Object childElement) {
816:                    getPatternFilter().clearCaches();
817:                    super .add(parentElementOrTreePath, childElement);
818:                }
819:
820:                public void add(Object parentElementOrTreePath,
821:                        Object[] childElements) {
822:                    getPatternFilter().clearCaches();
823:                    super .add(parentElementOrTreePath, childElements);
824:                }
825:
826:                protected void inputChanged(Object input, Object oldInput) {
827:                    getPatternFilter().clearCaches();
828:                    super .inputChanged(input, oldInput);
829:                }
830:
831:                public void insert(Object parentElementOrTreePath,
832:                        Object element, int position) {
833:                    getPatternFilter().clearCaches();
834:                    super .insert(parentElementOrTreePath, element, position);
835:                }
836:
837:                public void refresh() {
838:                    getPatternFilter().clearCaches();
839:                    super .refresh();
840:                }
841:
842:                public void refresh(boolean updateLabels) {
843:                    getPatternFilter().clearCaches();
844:                    super .refresh(updateLabels);
845:                }
846:
847:                public void refresh(Object element) {
848:                    getPatternFilter().clearCaches();
849:                    super .refresh(element);
850:                }
851:
852:                public void refresh(Object element, boolean updateLabels) {
853:                    getPatternFilter().clearCaches();
854:                    super .refresh(element, updateLabels);
855:                }
856:
857:                public void remove(Object elementsOrTreePaths) {
858:                    getPatternFilter().clearCaches();
859:                    super .remove(elementsOrTreePaths);
860:                }
861:
862:                public void remove(Object parent, Object[] elements) {
863:                    getPatternFilter().clearCaches();
864:                    super .remove(parent, elements);
865:                }
866:
867:                public void remove(Object[] elementsOrTreePaths) {
868:                    getPatternFilter().clearCaches();
869:                    super .remove(elementsOrTreePaths);
870:                }
871:
872:                public void replace(Object parentElementOrTreePath, int index,
873:                        Object element) {
874:                    getPatternFilter().clearCaches();
875:                    super .replace(parentElementOrTreePath, index, element);
876:                }
877:
878:                public void setChildCount(Object elementOrTreePath, int count) {
879:                    getPatternFilter().clearCaches();
880:                    super .setChildCount(elementOrTreePath, count);
881:                }
882:
883:                public void setContentProvider(IContentProvider provider) {
884:                    getPatternFilter().clearCaches();
885:                    super .setContentProvider(provider);
886:                }
887:
888:                public void setHasChildren(Object elementOrTreePath,
889:                        boolean hasChildren) {
890:                    getPatternFilter().clearCaches();
891:                    super.setHasChildren(elementOrTreePath, hasChildren);
892:                }
893:
894:            }
895:
896:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.