KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > keys > DougsSuperFilteredTableTree


1 /*******************************************************************************
2  * Copyright (c) 2005 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
12 package org.eclipse.ui.internal.keys;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.core.runtime.IProgressMonitor;
18 import org.eclipse.core.runtime.IStatus;
19 import org.eclipse.core.runtime.Status;
20 import org.eclipse.core.runtime.jobs.Job;
21 import org.eclipse.jface.action.Action;
22 import org.eclipse.jface.action.IAction;
23 import org.eclipse.jface.action.ToolBarManager;
24 import org.eclipse.jface.dialogs.IDialogSettings;
25 import org.eclipse.jface.resource.JFaceResources;
26 import org.eclipse.jface.viewers.TableTreeViewer;
27 import org.eclipse.swt.SWT;
28 import org.eclipse.swt.accessibility.AccessibleAdapter;
29 import org.eclipse.swt.accessibility.AccessibleEvent;
30 import org.eclipse.swt.events.ControlAdapter;
31 import org.eclipse.swt.events.ControlEvent;
32 import org.eclipse.swt.events.DisposeEvent;
33 import org.eclipse.swt.events.DisposeListener;
34 import org.eclipse.swt.events.KeyAdapter;
35 import org.eclipse.swt.events.KeyEvent;
36 import org.eclipse.swt.events.SelectionAdapter;
37 import org.eclipse.swt.events.SelectionEvent;
38 import org.eclipse.swt.events.TraverseEvent;
39 import org.eclipse.swt.events.TraverseListener;
40 import org.eclipse.swt.graphics.Point;
41 import org.eclipse.swt.graphics.Rectangle;
42 import org.eclipse.swt.layout.GridData;
43 import org.eclipse.swt.layout.GridLayout;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.swt.widgets.Display;
46 import org.eclipse.swt.widgets.Event;
47 import org.eclipse.swt.widgets.Listener;
48 import org.eclipse.swt.widgets.Shell;
49 import org.eclipse.swt.widgets.Table;
50 import org.eclipse.swt.widgets.TableItem;
51 import org.eclipse.swt.widgets.Text;
52 import org.eclipse.swt.widgets.ToolBar;
53 import org.eclipse.ui.internal.WorkbenchMessages;
54 import org.eclipse.ui.internal.WorkbenchPlugin;
55 import org.eclipse.ui.internal.dialogs.PatternFilter;
56 import org.eclipse.ui.internal.dialogs.PreferenceNodeFilter;
57 import org.eclipse.ui.progress.WorkbenchJob;
58
59 /**
60  * <p>
61  * A table-tree with filtering and grouping capabilities. This provides a
62  * flexible way to display multi-dimensional data to the user. The user may
63  * change the dimension on which the data is grouped, and may type in some
64  * filter text.
65  * </p>
66  *
67  * @since 3.2
68  */

69 public final class DougsSuperFilteredTableTree extends Composite {
70
71     private static final String JavaDoc CLEAR_ICON = "org.eclipse.ui.internal.dialogs.CLEAR_ICON"; //$NON-NLS-1$
72

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

75     /**
76      * The dialog settings key for the search history.
77      */

78     private static final String JavaDoc SEARCHHISTORY = "search"; //$NON-NLS-1$
79

80     private String JavaDoc cachedTitle;
81
82     protected Text filterText;
83
84     private ToolBarManager filterToolBar;
85
86     protected String JavaDoc initialText = ""; //$NON-NLS-1$
87

88     private PatternFilter patternFilter;
89
90     private PreferenceNodeFilter preferenceFilter;
91
92     /**
93      * The job for refreshing the tree.
94      */

95     private Job refreshJob;
96
97     /**
98      * A list containing all the strings in the search history.
99      */

100     private List JavaDoc searchHistory;
101
102     protected TableTreeViewer viewer;
103
104     /**
105      * Constructs a new instance of <code>DougsSuperFilteredTableTree</code>.
106      *
107      * @param parent
108      * The composite in which the filtered table tree will appear;
109      * must not be <code>null</code>.
110      * @param style
111      * The style to be applied to the table tree.
112      */

113     public DougsSuperFilteredTableTree(final Composite parent, final int style) {
114         super(parent, style);
115
116         GridData gridData;
117
118         // The composite containing the tree.
119
final Composite treeComposite = new Composite(this, SWT.NONE);
120         GridLayout layout = new GridLayout(2, false);
121         layout.marginHeight = 0;
122         layout.marginWidth = 0;
123         treeComposite.setLayout(layout);
124         treeComposite.setFont(parent.getFont());
125         gridData = new GridData();
126         gridData.grabExcessHorizontalSpace = true;
127         gridData.grabExcessVerticalSpace = true;
128         gridData.horizontalAlignment = SWT.FILL;
129         gridData.verticalAlignment = SWT.FILL;
130         treeComposite.setLayoutData(gridData);
131
132         // Create the topmost filter control.
133
createFilterControl(treeComposite);
134         gridData = new GridData();
135         gridData.grabExcessHorizontalSpace = true;
136         gridData.horizontalAlignment = SWT.FILL;
137         getFilterControl().setLayoutData(gridData);
138
139         // Place a tool bar with the clear button next to it.
140
final ToolBar toolBar = new ToolBar(treeComposite, SWT.FLAT
141                 | SWT.HORIZONTAL);
142         filterToolBar = new ToolBarManager(toolBar);
143         createClearText(filterToolBar);
144         filterToolBar.update(false);
145         filterToolBar.getControl().setVisible(false);
146         filterToolBar.getControl().setLayoutData(new GridData());
147
148         // Create a table tree viewer.
149
viewer = new TableTreeViewer(treeComposite, SWT.SINGLE
150                 | SWT.FULL_SELECTION);
151         viewer.getControl().addDisposeListener(new DisposeListener() {
152             /*
153              * (non-Javadoc)
154              *
155              * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
156              */

157             public void widgetDisposed(DisposeEvent e) {
158                 refreshJob.cancel();
159
160             }
161         });
162         gridData = new GridData();
163         gridData.grabExcessHorizontalSpace = true;
164         gridData.grabExcessVerticalSpace = true;
165         gridData.horizontalAlignment = SWT.FILL;
166         gridData.verticalAlignment = SWT.FILL;
167         gridData.horizontalSpan = 2;
168         viewer.getControl().setLayoutData(gridData);
169
170         /*
171          * Attach the pattern filter, and create the job for refreshing the
172          * table tree viewer.
173          */

174         patternFilter = new PatternFilter();
175         viewer.addFilter(patternFilter);
176         createRefreshJob();
177     }
178
179     /**
180      * clear the text in the filter text widget
181      */

182     protected void clearText() {
183         setFilterText(""); //$NON-NLS-1$
184

185         if (preferenceFilter != null) {
186             getViewer().removeFilter(preferenceFilter);
187             preferenceFilter = null;
188             getShell().setText(cachedTitle);
189         }
190
191         textChanged();
192     }
193
194     /**
195      * Create the button that clears the text.
196      *
197      * @param filterToolBar
198      */

199     private void createClearText(ToolBarManager filterToolBar) {
200
201         IAction clearTextAction = new Action("", IAction.AS_PUSH_BUTTON) {//$NON-NLS-1$
202
/*
203              * (non-Javadoc)
204              *
205              * @see org.eclipse.jface.action.Action#run()
206              */

207             public void run() {
208                 clearText();
209             }
210         };
211
212         clearTextAction
213                 .setToolTipText(WorkbenchMessages.FilteredTree_ClearToolTip);
214         clearTextAction.setImageDescriptor(JFaceResources.getImageRegistry()
215                 .getDescriptor(CLEAR_ICON));
216         clearTextAction.setDisabledImageDescriptor(JFaceResources
217                 .getImageRegistry().getDescriptor(DCLEAR_ICON));
218
219         filterToolBar.add(clearTextAction);
220     }
221
222     /**
223      * Creates the filter control for the table tree.
224      *
225      * @param parent
226      * The parent composite in which to place the filter control;
227      * must not be <code>null</code>
228      */

229     public void createFilterControl(final Composite parent) {
230         filterText = new Text(parent, SWT.DROP_DOWN | SWT.BORDER);
231         filterText.setFont(parent.getFont());
232         searchHistory = getPreferenceSearchHistory();
233
234         final Shell shell = new Shell(parent.getShell(), SWT.NO_TRIM);
235         shell
236                 .setBackground(parent.getDisplay().getSystemColor(
237                         SWT.COLOR_WHITE));
238         GridLayout shellGL = new GridLayout();
239         shellGL.marginHeight = 0;
240         shellGL.marginWidth = 0;
241         shell.setLayout(shellGL);
242         shell.setLayoutData(new GridData(
243                 (GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL)));
244
245         final Table currentSeachTable = new Table(shell, SWT.SINGLE
246                 | SWT.BORDER);
247         currentSeachTable.setLayoutData(new GridData(
248                 (GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL)));
249
250         filterText.addTraverseListener(new TraverseListener() {
251             public void keyTraversed(TraverseEvent e) {
252                 if (e.detail == SWT.TRAVERSE_RETURN) {
253                     e.doit = false;
254                     shell.setVisible(false);
255                     if (getViewer().getTableTree().getItemCount() == 0) {
256                         Display.getCurrent().beep();
257                         setFilterText(""); //$NON-NLS-1$
258
} else {
259                         getViewer().getTableTree().setFocus();
260                     }
261                 }
262             }
263         });
264
265         filterText.addKeyListener(new KeyAdapter() {
266             /*
267              * (non-Javadoc)
268              *
269              * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent)
270              */

271             public void keyReleased(KeyEvent e) {
272
273                 if (e.keyCode == SWT.ARROW_DOWN) {
274                     if (currentSeachTable.isVisible()) {
275                         // Make selection at popup table
276
if (currentSeachTable.getSelectionCount() < 1)
277                             currentSeachTable.setSelection(0);
278                         currentSeachTable.setFocus();
279                     } else
280                         // Make selection be on the left tree
281
getViewer().getTableTree().setFocus();
282                 } else {
283                     if (e.character == SWT.CR)
284                         return;
285
286                     textChanged();
287                     List JavaDoc result = new ArrayList JavaDoc();
288                     result = reduceSearch(searchHistory, filterText.getText());
289                     updateTable(currentSeachTable, result);
290
291                     if (currentSeachTable.getItemCount() > 0) {
292                         Rectangle textBounds = filterText.getBounds();
293                         Point point = getDisplay().map(parent, null,
294                                 textBounds.x, textBounds.y);
295                         int space = currentSeachTable.getItemHeight();
296                         shell.setBounds(point.x, point.y + textBounds.height,
297                                 textBounds.width, currentSeachTable
298                                         .getItemHeight()
299                                         * currentSeachTable.getItemCount()
300                                         + space);
301
302                         if (shell.isDisposed())
303                             shell.open();
304
305                         if (!shell.getVisible()) {
306                             shell.setVisible(true);
307                             filterText.setFocus();
308                         }
309
310                     } else
311                         shell.setVisible(false);
312                 }
313
314             }
315         });
316
317         parent.getDisplay().addFilter(SWT.MouseDown, new Listener() {
318             /*
319              * (non-Javadoc)
320              *
321              * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Events)
322              */

323             public void handleEvent(Event event) {
324                 if (!shell.isDisposed())
325                     shell.setVisible(false);
326             }
327         });
328
329         getShell().addControlListener(new ControlAdapter() {
330             /*
331              * (non-Javadoc)
332              *
333              * @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.events.ControlEvent)
334              */

335             public void controlMoved(ControlEvent e) {
336                 shell.setVisible(false);
337             }
338         });
339
340         currentSeachTable.addSelectionListener(new SelectionAdapter() {
341             public void widgetDefaultSelected(SelectionEvent e) {
342                 shell.setVisible(false);
343             }
344
345             /*
346              * (non-Javadoc)
347              *
348              * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
349              */

350             public void widgetSelected(SelectionEvent e) {
351
352                 setFilterText(currentSeachTable.getSelection()[0].getText());
353                 textChanged();
354             }
355         });
356
357         filterText.addDisposeListener(new DisposeListener() {
358             /*
359              * (non-Javadoc)
360              *
361              * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
362              */

363             public void widgetDisposed(DisposeEvent e) {
364                 saveDialogSettings();
365             }
366         });
367
368         filterText.getAccessible().addAccessibleListener(
369                 getAccessibleListener());
370
371     }
372
373     /**
374      * Create the refresh job for the receiver.
375      *
376      */

377     private void createRefreshJob() {
378         refreshJob = new WorkbenchJob("Refresh Filter") {//$NON-NLS-1$
379
/*
380              * (non-Javadoc)
381              *
382              * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
383              */

384             public IStatus runInUIThread(IProgressMonitor monitor) {
385                 if (getViewer().getControl().isDisposed())
386                     return Status.CANCEL_STATUS;
387
388                 String JavaDoc filterText = getFilterText();
389                 boolean initial = initialText != null
390                         && filterText.equals(initialText);
391                 if (initial) {
392                     patternFilter.setPattern(null);
393                 } else {
394                     patternFilter.setPattern(getFilterText());
395                 }
396                 getViewer().getControl().setRedraw(false);
397                 getViewer().refresh(true);
398                 getViewer().getControl().setRedraw(true);
399
400                 if (filterText.length() > 0 && !initial) {
401                     getViewer().expandAll();
402                     // enabled toolbar is a hint that there is text to clear
403
// and the list is currently being filtered
404
filterToolBar.getControl().setVisible(true);
405                 } else {
406                     // disabled toolbar is a hint that there is no text to clear
407
// and the list is currently not filtered
408
filterToolBar.getControl().setVisible(
409                             preferenceFilter != null);
410                 }
411                 return Status.OK_STATUS;
412             }
413
414         };
415         refreshJob.setSystem(true);
416     }
417
418     protected AccessibleAdapter getAccessibleListener() {
419         return new AccessibleAdapter() {
420             /*
421              * (non-Javadoc)
422              *
423              * @see org.eclipse.swt.accessibility.AccessibleListener#getName(org.eclipse.swt.accessibility.AccessibleEvent)
424              */

425             public void getName(AccessibleEvent e) {
426                 String JavaDoc filterTextString = getFilterText();
427                 if (filterTextString.length() == 0) {
428                     e.result = initialText;
429                 } else
430                     e.result = filterTextString;
431             }
432
433         };
434     }
435
436     /**
437      * Return a dialog setting section for this dialog
438      *
439      * @return IDialogSettings
440      */

441     private final IDialogSettings getDialogSettings() {
442         final IDialogSettings settings = WorkbenchPlugin.getDefault()
443                 .getDialogSettings();
444         IDialogSettings thisSettings = settings
445                 .getSection(getClass().getName());
446         if (thisSettings == null)
447             thisSettings = settings.addNewSection(getClass().getName());
448
449         return thisSettings;
450     }
451
452     /**
453      * Get the filter text field associated with this control.
454      *
455      * @return the text field
456      */

457     public Text getFilterControl() {
458         return filterText;
459     }
460
461     /**
462      * Get the text from the filter widget.
463      *
464      * @return String
465      */

466     protected String JavaDoc getFilterText() {
467         return filterText.getText();
468     }
469
470     /**
471      * Get the preferences search history for this eclipse's start, Note that
472      * this history will not be cleared until this eclipse closes
473      *
474      * @return a list
475      */

476     public final List JavaDoc getPreferenceSearchHistory() {
477         final List JavaDoc searchList = new ArrayList JavaDoc();
478         final IDialogSettings settings = getDialogSettings();
479         final String JavaDoc[] search = settings.getArray(SEARCHHISTORY); //$NON-NLS-1$
480

481         if (search != null) {
482             for (int i = 0; i < search.length; i++)
483                 searchList.add(search[i]);
484         }
485
486         return searchList;
487     }
488
489     /**
490      * Get the table tree viewer associated with this control.
491      *
492      * @return the table tree viewer; never <code>null</code>.
493      */

494     public final TableTreeViewer getViewer() {
495         return viewer;
496     }
497
498     private void listToArray(List JavaDoc list, String JavaDoc[] string) {
499         int size = list.size();
500         for (int i = 0; i < size; i++)
501             string[i] = (String JavaDoc) list.get(i);
502     }
503
504     /**
505      * Find all items which start with typed words list the list contains all
506      * strings of the search history
507      *
508      * @param list
509      * the list to search
510      * @param wordsEntered
511      * String
512      * @return a list in which all strings start from the typed letter(s)
513      */

514     public List JavaDoc reduceSearch(List JavaDoc list, String JavaDoc wordsEntered) {
515         List JavaDoc result = new ArrayList JavaDoc();
516         if (list == null)
517             return result;
518         for (int i = 0; i < list.size(); i++) {
519             if (filterText.getText() == "") //$NON-NLS-1$
520
return result;
521             else if (((String JavaDoc) list.get(i)).startsWith(wordsEntered))
522                 result.add(list.get(i));
523         }
524
525         return result;
526     }
527
528     /**
529      * Saves the search history.
530      */

531     private void saveDialogSettings() {
532         IDialogSettings settings = getDialogSettings();
533
534         // If the settings contains the same key, the previous value will be
535
// replaced by new one
536
String JavaDoc[] result = new String JavaDoc[searchHistory.size()];
537         listToArray(searchHistory, result);
538         settings.put(SEARCHHISTORY, result);
539     }
540
541     protected void selectAll() {
542         filterText.selectAll();
543     }
544
545     /**
546      * Set the text in the filter area.
547      *
548      * @param string
549      */

550     protected void setFilterText(String JavaDoc string) {
551         filterText.setText(string);
552         selectAll();
553     }
554
555     /**
556      * Schedules a job to update the table tree after the text has changed.
557      */

558     protected void textChanged() {
559         refreshJob.schedule(200);
560     }
561
562     /**
563      * Copy all elements from a list to a table
564      *
565      * @param table
566      * @param list
567      */

568     public void updateTable(Table table, List JavaDoc list) {
569         table.removeAll();
570         if (list.size() > 0) {
571             TableItem newItem;
572             for (int i = 0; i < list.size(); i++) {
573                 newItem = new TableItem(table, SWT.NULL, i);
574                 newItem.setText((String JavaDoc) list.get(i));
575
576             }
577         }
578
579     }
580 }
581
Popular Tags