selection dialogs does not use CdmFilteredItemsSelectionDialog anymore
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / dialog / selection / SearchDialog.java
1 // $Id$
2 /**
3 * Copyright (C) 2017 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10 package eu.etaxonomy.taxeditor.ui.dialog.selection;
11
12
13
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
17
18 import org.eclipse.core.commands.AbstractHandler;
19 import org.eclipse.core.commands.ExecutionEvent;
20 import org.eclipse.core.commands.IHandler;
21 import org.eclipse.core.runtime.Assert;
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.core.runtime.ListenerList;
26 import org.eclipse.core.runtime.Status;
27 import org.eclipse.core.runtime.jobs.Job;
28 import org.eclipse.jface.action.IMenuManager;
29 import org.eclipse.jface.action.LegacyActionTools;
30 import org.eclipse.jface.action.MenuManager;
31 import org.eclipse.jface.dialogs.Dialog;
32 import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
33 import org.eclipse.jface.viewers.DoubleClickEvent;
34 import org.eclipse.jface.viewers.IColorProvider;
35 import org.eclipse.jface.viewers.IDoubleClickListener;
36 import org.eclipse.jface.viewers.IFontProvider;
37 import org.eclipse.jface.viewers.ILabelDecorator;
38 import org.eclipse.jface.viewers.ILabelProvider;
39 import org.eclipse.jface.viewers.ILabelProviderListener;
40 import org.eclipse.jface.viewers.ILazyContentProvider;
41 import org.eclipse.jface.viewers.ISelectionChangedListener;
42 import org.eclipse.jface.viewers.IStructuredContentProvider;
43 import org.eclipse.jface.viewers.LabelProvider;
44 import org.eclipse.jface.viewers.LabelProviderChangedEvent;
45 import org.eclipse.jface.viewers.SelectionChangedEvent;
46 import org.eclipse.jface.viewers.StructuredSelection;
47 import org.eclipse.jface.viewers.StyledCellLabelProvider;
48 import org.eclipse.jface.viewers.StyledString;
49 import org.eclipse.jface.viewers.TableViewer;
50 import org.eclipse.jface.viewers.Viewer;
51 import org.eclipse.jface.viewers.ViewerCell;
52 import org.eclipse.swt.SWT;
53 import org.eclipse.swt.accessibility.AccessibleAdapter;
54 import org.eclipse.swt.accessibility.AccessibleEvent;
55 import org.eclipse.swt.events.ModifyEvent;
56 import org.eclipse.swt.events.ModifyListener;
57 import org.eclipse.swt.events.MouseAdapter;
58 import org.eclipse.swt.events.MouseEvent;
59 import org.eclipse.swt.events.SelectionAdapter;
60 import org.eclipse.swt.events.SelectionEvent;
61 import org.eclipse.swt.events.TraverseEvent;
62 import org.eclipse.swt.events.TraverseListener;
63 import org.eclipse.swt.graphics.Color;
64 import org.eclipse.swt.graphics.Font;
65 import org.eclipse.swt.graphics.GC;
66 import org.eclipse.swt.graphics.Point;
67 import org.eclipse.swt.graphics.Rectangle;
68 import org.eclipse.swt.layout.GridData;
69 import org.eclipse.swt.layout.GridLayout;
70 import org.eclipse.swt.widgets.Composite;
71 import org.eclipse.swt.widgets.Control;
72 import org.eclipse.swt.widgets.Display;
73 import org.eclipse.swt.widgets.Event;
74 import org.eclipse.swt.widgets.Label;
75 import org.eclipse.swt.widgets.Menu;
76 import org.eclipse.swt.widgets.Shell;
77 import org.eclipse.swt.widgets.Table;
78 import org.eclipse.swt.widgets.Text;
79 import org.eclipse.swt.widgets.ToolBar;
80 import org.eclipse.swt.widgets.ToolItem;
81 import org.eclipse.ui.IWorkbenchPreferenceConstants;
82 import org.eclipse.ui.PlatformUI;
83 import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
84 import org.eclipse.ui.handlers.IHandlerService;
85 import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
86 import org.eclipse.ui.internal.WorkbenchImages;
87 import org.eclipse.ui.internal.WorkbenchMessages;
88 import org.eclipse.ui.internal.WorkbenchPlugin;
89 import org.eclipse.ui.progress.UIJob;
90
91 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
92 import eu.etaxonomy.cdm.model.common.ICdmBase;
93 import eu.etaxonomy.taxeditor.l10n.Messages;
94 import eu.etaxonomy.taxeditor.ui.dialog.selection.CdmFilteredItemsSelectionDialog.ItemsListSeparator;
95
96 /**
97 * @author k.luther
98 * @date 15.11.2017
99 *
100 */
101 public abstract class SearchDialog<T extends ICdmBase> extends Dialog implements IConversationEnabled{
102
103 private TableViewer list;
104
105
106 private Text searchField;
107 private String title;
108
109 // message to show user
110 private String message = ""; //$NON-NLS-1$
111
112 protected final ContentProvider contentProvider;
113
114 private StructuredSelection currentSelection;
115 ItemsListLabelProvider itemsListLabelProvider;
116
117 private final RefreshCacheJob refreshCacheJob;
118
119 private ToolBar toolBar;
120
121 private ToolItem toolItem;
122 private MenuManager menuManager;
123
124 private ILabelProvider provider;
125
126 private ILabelDecorator selectionDecorator;
127
128 // Need to keep our own list of listeners
129 private final ListenerList listeners = new ListenerList();
130
131
132 private static final String EMPTY_STRING = ""; //$NON-NLS-1$
133 private GridData gd_1;
134
135 public SearchDialog(Shell parent, boolean multi) {
136 super(parent);
137 contentProvider = new ContentProvider();
138 refreshCacheJob = new RefreshCacheJob();
139
140 }
141
142
143 @Override
144 protected Control createDialogArea(Composite parent) {
145 Composite container = (Composite) super.createDialogArea(parent);
146 // Composite content = new Composite(container, SWT.NONE);
147 GridData gd = new GridData(GridData.FILL_BOTH);
148 container.setLayoutData(gd);
149
150 GridLayout layout = new GridLayout();
151 layout.numColumns = 1;
152 layout.marginWidth = 0;
153 layout.marginHeight = 0;
154 container.setLayout(layout);
155
156 final Label headerLabel = createHeader(container);
157
158 searchField = new Text(container, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL);
159 searchField.getAccessible().addAccessibleListener(new AccessibleAdapter() {
160 @Override
161 public void getName(AccessibleEvent e) {
162 e.result = LegacyActionTools.removeMnemonics(headerLabel
163 .getText());
164 }
165 });
166 searchField.addModifyListener(new ModifyListener() {
167 @Override
168 public void modifyText(ModifyEvent e) {
169 search();
170 try {
171 fillContentProvider(null);
172 } catch (CoreException coreException) {
173 // TODO Auto-generated catch block
174 coreException.printStackTrace();
175 }
176 }
177 });
178 gd_1 = new GridData(GridData.FILL_HORIZONTAL);
179 gd_1.horizontalIndent = 2;
180 gd_1.grabExcessHorizontalSpace = false;
181 gd_1.horizontalAlignment = SWT.CENTER;
182 gd_1.widthHint = 575;
183 searchField.setLayoutData(gd_1);
184
185 // final Label listLabel = createLabels(content);
186
187 setList(new TableViewer(container, SWT.SINGLE
188 | SWT.BORDER | SWT.V_SCROLL | SWT.VIRTUAL));
189 // getList().getTable().getAccessible().addAccessibleListener(
190 // new AccessibleAdapter() {
191 // @Override
192 // public void getName(AccessibleEvent e) {
193 // if (e.childID == ACC.CHILDID_SELF) {
194 // e.result = LegacyActionTools
195 // .removeMnemonics(listLabel.getText());
196 // }
197 // }
198 // });
199 getList().setContentProvider(contentProvider);
200 getList().setLabelProvider(getItemsListLabelProvider());
201 getList().setInput(new Object[0]);
202 getList().setItemCount(contentProvider.getNumberOfElements());
203 getList().addSelectionChangedListener(new ISelectionChangedListener() {
204 @Override
205 public void selectionChanged(SelectionChangedEvent event) {
206 StructuredSelection selection = (StructuredSelection) event
207 .getSelection();
208 currentSelection = selection;
209 }
210 });
211 getList().addDoubleClickListener(new IDoubleClickListener() {
212 @Override
213 public void doubleClick(DoubleClickEvent event) {
214 okPressed();
215 }
216 });
217 createExtendedContentArea(container);
218
219 return container;
220 }
221
222 protected abstract void search();
223
224 /**
225 * Creates an extra content area, which will be located above the details.
226 *
227 * @param parent
228 * parent to create the dialog widgets in
229 * @return an extra content area
230 */
231 protected abstract Control createExtendedContentArea(Composite parent);
232
233 /**
234 * Sets the title for this dialog.
235 *
236 * @param title
237 * the title
238 */
239 public void setTitle(String title) {
240 this.title = title;
241 }
242
243 /**
244 * Create a new header which is labelled by headerLabel.
245 *
246 * @param parent
247 * @return Label the label of the header
248 */
249 private Label createHeader(Composite parent) {
250 Composite header = new Composite(parent, SWT.NONE);
251
252 GridLayout layout = new GridLayout();
253 layout.numColumns = 2;
254 layout.marginWidth = 0;
255 layout.marginHeight = 0;
256 header.setLayout(layout);
257 new Label(header, SWT.NONE);
258 new Label(header, SWT.NONE);
259 new Label(header, SWT.NONE);
260
261 Label headerLabel = new Label(header, SWT.NONE);
262 headerLabel.setText((getMessage() != null && getMessage().trim()
263 .length() > 0) ? getMessage()
264 : Messages.SearchDialog_patternLabel);
265 headerLabel.addTraverseListener(new TraverseListener() {
266 @Override
267 public void keyTraversed(TraverseEvent e) {
268 if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) {
269 e.detail = SWT.TRAVERSE_NONE;
270 searchField.setFocus();
271 }
272 }
273 });
274 GridData gd_headerLabel = new GridData(GridData.FILL_HORIZONTAL);
275 gd_headerLabel.horizontalAlignment = SWT.LEFT;
276 gd_headerLabel.grabExcessHorizontalSpace = false;
277 gd_headerLabel.verticalAlignment = SWT.BOTTOM;
278 gd_headerLabel.minimumHeight = 10;
279 headerLabel.setLayoutData(gd_headerLabel);
280
281 // createViewMenu(header);
282
283 return headerLabel;
284 }
285
286 /**
287 * Returns the message for this dialog.
288 *
289 * @return the message for this dialog
290 */
291 protected String getMessage() {
292 return message;
293 }
294
295 protected void setMessage(String message){
296 this.message = message;
297 }
298
299 public Text getSearchField() {
300 return searchField;
301 }
302
303
304 public void setSearchField(Text searchField) {
305 this.searchField = searchField;
306 }
307
308 /**
309 * Returns the item list label provider.
310 *
311 * @return the item list label provider
312 */
313 private ItemsListLabelProvider getItemsListLabelProvider() {
314 if (itemsListLabelProvider == null) {
315 itemsListLabelProvider = new ItemsListLabelProvider(
316 new LabelProvider());
317 }
318 return itemsListLabelProvider;
319 }
320
321 // /**
322 // * Create the labels for the list and the progress. Return the list label.
323 // *
324 // * @param parent
325 // * @return Label
326 // */
327 // private Label createLabels(Composite parent) {
328 // Composite labels = new Composite(parent, SWT.NONE);
329 //
330 // GridLayout layout = new GridLayout();
331 // layout.numColumns = 2;
332 // layout.marginWidth = 0;
333 // layout.marginHeight = 0;
334 // labels.setLayout(layout);
335 //
336 //// Label listLabel = new Label(labels, SWT.NONE);
337 //// listLabel
338 //// .setText(Messages.SearchDialog_listLabel);
339 //
340 // listLabel.addTraverseListener(new TraverseListener() {
341 // @Override
342 // public void keyTraversed(TraverseEvent e) {
343 // if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) {
344 // e.detail = SWT.TRAVERSE_NONE;
345 // getList().getTable().setFocus();
346 // }
347 // }
348 // });
349 // listLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
350 // new Label(labels, SWT.NONE);
351 //
352 //
353 // return listLabel;
354 // }
355
356
357 private void createViewMenu(Composite parent) {
358 toolBar = new ToolBar(parent, SWT.FLAT);
359 toolItem = new ToolItem(toolBar, SWT.PUSH, 0);
360
361 GridData data = new GridData();
362 data.horizontalAlignment = GridData.END;
363 toolBar.setLayoutData(data);
364
365 toolBar.addMouseListener(new MouseAdapter() {
366 @Override
367 public void mouseDown(MouseEvent e) {
368 showViewMenu();
369 }
370 });
371
372 toolItem.setImage(WorkbenchImages
373 .getImage(IWorkbenchGraphicConstants.IMG_LCL_VIEW_MENU));
374 toolItem
375 .setToolTipText(WorkbenchMessages.FilteredItemsSelectionDialog_menu);
376 toolItem.addSelectionListener(new SelectionAdapter() {
377 @Override
378 public void widgetSelected(SelectionEvent e) {
379 showViewMenu();
380 }
381 });
382
383 menuManager = new MenuManager();
384
385 fillViewMenu(menuManager);
386
387 IHandlerService service = PlatformUI.getWorkbench()
388 .getService(IHandlerService.class);
389 IHandler handler = new AbstractHandler() {
390 @Override
391 public Object execute(ExecutionEvent event) {
392 showViewMenu();
393 return null;
394 }
395 };
396 // showViewHandler = service.activateHandler(
397 // IWorkbenchCommandConstants.WINDOW_SHOW_VIEW_MENU, handler,
398 // new ActiveShellExpression(getShell()));
399 }
400
401 /**
402 * Fills the menu of the dialog.
403 *
404 * @param menuManager
405 * the menu manager
406 */
407 protected void fillViewMenu(IMenuManager menuManager) {
408 // toggleStatusLineAction = new ToggleStatusLineAction();
409 // menuManager.add(toggleStatusLineAction);
410 }
411
412 private void showViewMenu() {
413 Menu menu = menuManager.createContextMenu(getShell());
414 Rectangle bounds = toolItem.getBounds();
415 Point topLeft = new Point(bounds.x, bounds.y + bounds.height);
416 topLeft = toolBar.toDisplay(topLeft);
417 menu.setLocation(topLeft.x, topLeft.y);
418 menu.setVisible(true);
419 }
420
421 public TableViewer getList() {
422 return list;
423 }
424
425 public void setList(TableViewer list) {
426 this.list = list;
427 Table table = list.getTable();
428 GridData gd_table = new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 1);
429 gd_table.heightHint = 231;
430 gd_table.widthHint = 543;
431 table.setLayoutData(gd_table);
432 }
433
434 /**
435 * Sets a new label provider for items in the list. If the label provider
436 * also implements {@link
437 * org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider
438 * .IStyledLabelProvider}, the style text labels provided by it will be used
439 * provided that the corresponding preference is set.
440 *
441 * @see IWorkbenchPreferenceConstants#USE_COLORED_LABELS
442 *
443 * @param listLabelProvider
444 * the label provider for items in the list
445 */
446 public void setListLabelProvider(ILabelProvider listLabelProvider) {
447 getItemsListLabelProvider().setProvider(listLabelProvider);
448 }
449
450
451
452 /**
453 * Collects filtered elements. Contains one synchronized, sorted set for
454 * collecting filtered elements. All collected elements are sorted using
455 * comparator. Comparator is returned by getElementComparator() method.
456 * Implementation of <code>ItemsFilter</code> is used to filter elements.
457 * The key function of filter used in to filtering is
458 * <code>matchElement(Object item)</code>.
459 * <p>
460 * The <code>ContentProvider</code> class also provides item filtering
461 * methods. The filtering has been moved from the standard TableView
462 * <code>getFilteredItems()</code> method to content provider, because
463 * <code>ILazyContentProvider</code> and virtual tables are used. This
464 * class is responsible for adding a separator below history items and
465 * marking each items as duplicate if its name repeats more than once on the
466 * filtered list.
467 */
468 class ContentProvider implements
469 IStructuredContentProvider, ILazyContentProvider {
470
471
472
473 /**
474 * Raw result of the searching (unsorted, unfiltered).
475 * <p>
476 * Standard object flow:
477 * <code>items -> lastSortedItems -> lastFilteredItems</code>
478 */
479 private List items;
480
481
482 /**
483 * Creates new instance of <code>ContentProvider</code>.
484 */
485 public ContentProvider() {
486 this.items = Collections.synchronizedList(new ArrayList(2048));
487
488 }
489
490
491
492 /**
493 * Removes all content items and resets progress message.
494 */
495 public void reset() {
496 this.items.clear();
497
498 }
499
500
501
502 /**
503 * Adds filtered item.
504 *
505 * @param item
506 * @param itemsFilter
507 */
508
509 public void add(Object item) {
510 this.items.add(item);
511 }
512
513
514
515 /**
516 * Refresh dialog.
517 */
518 public void refresh() {
519 scheduleRefresh();
520 }
521
522 /**
523 * Schedule refresh job.
524 */
525 public void scheduleRefresh() {
526 refreshCacheJob.cancelAll();
527 refreshCacheJob.schedule();
528 }
529
530
531 /*
532 * (non-Javadoc)
533 *
534 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
535 */
536 @Override
537 public Object[] getElements(Object inputElement) {
538 return items.toArray();
539 // return lastFilteredItems.toArray();
540 }
541
542 public int getNumberOfElements() {
543
544 return items.size();
545 }
546
547 /*
548 * (non-Javadoc)
549 *
550 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
551 */
552 @Override
553 public void dispose() {
554 }
555
556 /*
557 * (non-Javadoc)
558 *
559 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
560 * java.lang.Object, java.lang.Object)
561 */
562 @Override
563 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
564 }
565
566 /*
567 * (non-Javadoc)
568 *
569 * @see org.eclipse.jface.viewers.ILazyContentProvider#updateElement(int)
570 */
571 @Override
572 public void updateElement(int index) {
573
574 SearchDialog.this.getList().replace((items
575 .size() > index) ? items.get(index) : null,
576 index);
577
578 }
579
580
581 }
582
583 // protected static boolean showColoredLabels() {
584 // return PlatformUI.getPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.USE_COLORED_LABELS);
585 // }
586
587 public StructuredSelection getCurrentSelection() {
588 return currentSelection;
589 }
590
591 /**
592 * Fills the content provider with matching items.
593 *
594 * @param contentProvider
595 * collector to add items to.
596 * {@link FilteredItemsSelectionDialog.AbstractContentProvider#add(Object, FilteredItemsSelectionDialog.ItemsFilter)}
597 * only adds items that pass the given <code>itemsFilter</code>.
598 * @param itemsFilter
599 * the items filter
600 * @param progressMonitor
601 * must be used to report search progress. The state of this
602 * progress monitor reflects the state of the filtering process.
603 * @throws CoreException
604 */
605 protected abstract void fillContentProvider(IProgressMonitor progressMonitor) throws CoreException;
606
607
608 /**
609 * Refreshes the dialog - has to be called in UI thread.
610 */
611 public void refresh() {
612 if (getList() != null && !getList().getTable().isDisposed()) {
613
614 List lastRefreshSelection = ((StructuredSelection) getList()
615 .getSelection()).toList();
616 getList().getTable().deselectAll();
617
618 getList().setItemCount(contentProvider.getNumberOfElements());
619 getList().refresh();
620
621 if (getList().getTable().getItemCount() > 0) {
622 // preserve previous selection
623 if ( lastRefreshSelection != null
624 && lastRefreshSelection.size() > 0) {
625 getList().setSelection(new StructuredSelection(
626 lastRefreshSelection));
627 } else {
628
629 getList().getTable().setSelection(0);
630 getList().getTable().notifyListeners(SWT.Selection, new Event());
631 }
632 } else {
633 getList().setSelection(StructuredSelection.EMPTY);
634 }
635
636 }
637
638 // scheduleProgressMessageRefresh();
639 }
640
641 /**
642 * Only refreshes UI on the basis of an already sorted and filtered set of
643 * items.
644 * <p>
645 * Standard invocation scenario:
646 * <ol>
647 * <li>filtering job (<code>FilterJob</code> class extending
648 * <code>Job</code> class)</li>
649 * <li>cache refresh without checking for duplicates (<code>RefreshCacheJob</code>
650 * class extending <code>Job</code> class)</li>
651 * <li>UI refresh (<code>RefreshJob</code> class extending
652 * <code>UIJob</code> class)</li>
653 * <li>cache refresh with checking for duplicates (<cod>CacheRefreshJob</code>
654 * class extending <code>Job</code> class)</li>
655 * <li>UI refresh (<code>RefreshJob</code> class extending <code>UIJob</code>
656 * class)</li>
657 * </ol>
658 * The scenario is rather complicated, but it had to be applied, because:
659 * <ul>
660 * <li> refreshing cache is rather a long action and cannot be run in the UI -
661 * cannot be run in a UIJob</li>
662 * <li> refreshing cache checking for duplicates is twice as long as
663 * refreshing cache without checking for duplicates; results of the search
664 * could be displayed earlier</li>
665 * <li> refreshing the UI have to be run in a UIJob</li>
666 * </ul>
667 *
668 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.FilterJob
669 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.RefreshJob
670 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.RefreshCacheJob
671 */
672 private class RefreshJob extends UIJob {
673
674 /**
675 * Creates a new instance of the class.
676 */
677 public RefreshJob() {
678 super(SearchDialog.this.getParentShell()
679 .getDisplay(),
680 WorkbenchMessages.FilteredItemsSelectionDialog_refreshJob);
681 setSystem(true);
682 }
683
684 /*
685 * (non-Javadoc)
686 *
687 * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
688 */
689 @Override
690 public IStatus runInUIThread(IProgressMonitor monitor) {
691 if (monitor.isCanceled()) {
692 return new Status(IStatus.OK, WorkbenchPlugin.PI_WORKBENCH,
693 IStatus.OK, EMPTY_STRING, null);
694 }
695
696 if (SearchDialog.this != null) {
697 SearchDialog.this.refresh();
698 }
699
700 return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK,
701 EMPTY_STRING, null);
702 }
703
704 }
705
706
707 /**
708 * A job responsible for computing filtered items list presented using
709 * <code>RefreshJob</code>.
710 *
711 * @see FilteredItemsSelectionDialog.RefreshJob
712 *
713 */
714 private class RefreshCacheJob extends Job {
715
716 private final RefreshJob refreshJob = new RefreshJob();
717
718 /**
719 * Creates a new instance of the class.
720 */
721 public RefreshCacheJob() {
722 super(
723 WorkbenchMessages.FilteredItemsSelectionDialog_cacheRefreshJob);
724 setSystem(true);
725 }
726
727 /**
728 * Stops the job and all sub-jobs.
729 */
730 public void cancelAll() {
731 cancel();
732 refreshJob.cancel();
733 }
734
735 /*
736 * (non-Javadoc)
737 *
738 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
739 */
740 @Override
741 protected IStatus run(IProgressMonitor monitor) {
742 if (monitor.isCanceled()) {
743 return new Status(IStatus.CANCEL, WorkbenchPlugin.PI_WORKBENCH,
744 IStatus.CANCEL, EMPTY_STRING, null);
745 }
746
747 if (SearchDialog.this != null) {
748
749 try {
750 SearchDialog.this.fillContentProvider(monitor);
751 } catch (CoreException e) {
752 // TODO Auto-generated catch block
753 e.printStackTrace();
754 }
755 }
756
757 if (!monitor.isCanceled()) {
758 refreshJob.schedule();
759 }
760
761 return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK,
762 EMPTY_STRING, null);
763
764 }
765
766 /*
767 * (non-Javadoc)
768 *
769 * @see org.eclipse.core.runtime.jobs.Job#canceling()
770 */
771 @Override
772 protected void canceling() {
773 super.canceling();
774 // contentProvider.stopReloadingCache();
775 }
776
777 }
778
779 private class ItemsListLabelProvider extends StyledCellLabelProvider
780 implements ILabelProviderListener {
781 private ILabelProvider provider;
782
783 /**
784 * Creates a new instance of the class.
785 *
786 * @param provider
787 * the label provider for all items, not <code>null</code>
788 * @param selectionDecorator
789 * the decorator for selected items, can be <code>null</code>
790 */
791 public ItemsListLabelProvider(ILabelProvider provider) {
792 Assert.isNotNull(provider);
793 this.provider = provider;
794
795
796 // setOwnerDrawEnabled(showColoredLabels() && provider instanceof IStyledLabelProvider);
797
798 provider.addListener(this);
799
800 if (selectionDecorator != null) {
801 selectionDecorator.addListener(this);
802 }
803 }
804
805 /**
806 * Sets new selection decorator.
807 *
808 * @param newSelectionDecorator
809 * new label decorator for selected items in the list
810 */
811 public void setSelectionDecorator(ILabelDecorator newSelectionDecorator) {
812 if (selectionDecorator != null) {
813 selectionDecorator.removeListener(this);
814 selectionDecorator.dispose();
815 }
816
817 selectionDecorator = newSelectionDecorator;
818
819 if (selectionDecorator != null) {
820 selectionDecorator.addListener(this);
821 }
822 }
823
824 /**
825 * Gets selection decorator.
826 *
827 * @return the label decorator for selected items in the list
828 */
829 public ILabelDecorator getSelectionDecorator() {
830 return selectionDecorator;
831 }
832
833 /**
834 * Sets new label provider.
835 *
836 * @param newProvider
837 * new label provider for items in the list, not
838 * <code>null</code>
839 */
840 public void setProvider(ILabelProvider newProvider) {
841 Assert.isNotNull(newProvider);
842 provider.removeListener(this);
843 provider.dispose();
844
845 provider = newProvider;
846
847 if (provider != null) {
848 provider.addListener(this);
849 }
850
851 // setOwnerDrawEnabled(showColoredLabels() && provider instanceof IStyledLabelProvider);
852 }
853
854
855
856 private boolean isSelected(Object element) {
857 if (element != null && getCurrentSelection() != null) {
858 if (element.equals(getCurrentSelection())) {
859 return true;
860 }
861 }
862 return false;
863 }
864
865 /*
866 * (non-Javadoc)
867 *
868 * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
869 */
870 private String getText(Object element) {
871 if (element instanceof ItemsListSeparator) {
872 return getSeparatorLabel(((ItemsListSeparator) element)
873 .getName());
874 }
875
876 String str = provider.getText(element);
877 if (selectionDecorator != null && isSelected(element)) {
878 return selectionDecorator.decorateText(str.toString(), element);
879 }
880
881 return str;
882 }
883
884 private StyledString getStyledText(Object element,
885 IStyledLabelProvider provider) {
886 StyledString string = provider.getStyledText(element);
887
888 if (selectionDecorator != null && isSelected(element)) {
889 String decorated = selectionDecorator.decorateText(string
890 .getString(), element);
891 return StyledCellLabelProvider.styleDecoratedString(decorated, null, string);
892 // no need to add colors when element is selected
893 }
894 return string;
895 }
896
897 @Override
898 public void update(ViewerCell cell) {
899 Object element = cell.getElement();
900
901 if (!(element instanceof ItemsListSeparator)
902 && provider instanceof IStyledLabelProvider) {
903 IStyledLabelProvider styledLabelProvider = (IStyledLabelProvider) provider;
904 StyledString styledString = getStyledText(element,
905 styledLabelProvider);
906
907 cell.setText(styledString.getString());
908 cell.setStyleRanges(styledString.getStyleRanges());
909 cell.setImage(styledLabelProvider.getImage(element));
910 } else {
911 cell.setText(getText(element));
912
913 }
914 cell.setFont(getFont(element));
915 cell.setForeground(getForeground(element));
916 cell.setBackground(getBackground(element));
917
918 super.update(cell);
919 }
920
921 private String getSeparatorLabel(String separatorLabel) {
922 Rectangle rect = getList().getTable().getBounds();
923
924 int borderWidth = getList().getTable().computeTrim(0, 0, 0, 0).width;
925
926 int imageWidth = WorkbenchImages.getImage(
927 IWorkbenchGraphicConstants.IMG_OBJ_SEPARATOR).getBounds().width;
928
929 int width = rect.width - borderWidth - imageWidth;
930
931 GC gc = new GC(getList().getTable());
932 gc.setFont(getList().getTable().getFont());
933
934 int fSeparatorWidth = gc.getAdvanceWidth('-');
935 int fMessageLength = gc.textExtent(separatorLabel).x;
936
937 gc.dispose();
938
939 StringBuffer dashes = new StringBuffer();
940 int chars = (((width - fMessageLength) / fSeparatorWidth) / 2) - 2;
941 for (int i = 0; i < chars; i++) {
942 dashes.append('-');
943 }
944
945 StringBuffer result = new StringBuffer();
946 result.append(dashes);
947 result.append(" " + separatorLabel + " "); //$NON-NLS-1$//$NON-NLS-2$
948 result.append(dashes);
949 return result.toString().trim();
950 }
951
952 /*
953 * (non-Javadoc)
954 *
955 * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
956 */
957 @Override
958 public void addListener(ILabelProviderListener listener) {
959 listeners.add(listener);
960 }
961
962 /*
963 * (non-Javadoc)
964 *
965 * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
966 */
967 @Override
968 public void dispose() {
969 provider.removeListener(this);
970 provider.dispose();
971
972 if (selectionDecorator != null) {
973 selectionDecorator.removeListener(this);
974 selectionDecorator.dispose();
975 }
976
977 super.dispose();
978 }
979
980 /*
981 * (non-Javadoc)
982 *
983 * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object,
984 * java.lang.String)
985 */
986 @Override
987 public boolean isLabelProperty(Object element, String property) {
988 if (provider.isLabelProperty(element, property)) {
989 return true;
990 }
991 if (selectionDecorator != null
992 && selectionDecorator.isLabelProperty(element, property)) {
993 return true;
994 }
995 return false;
996 }
997
998 /*
999 * (non-Javadoc)
1000 *
1001 * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
1002 */
1003 @Override
1004 public void removeListener(ILabelProviderListener listener) {
1005 listeners.remove(listener);
1006 }
1007
1008 private Color getBackground(Object element) {
1009 if (element instanceof ItemsListSeparator) {
1010 return null;
1011 }
1012 if (provider instanceof IColorProvider) {
1013 return ((IColorProvider) provider).getBackground(element);
1014 }
1015 return null;
1016 }
1017
1018 private Color getForeground(Object element) {
1019 if (element instanceof ItemsListSeparator) {
1020 return Display.getCurrent().getSystemColor(
1021 SWT.COLOR_WIDGET_NORMAL_SHADOW);
1022 }
1023 if (provider instanceof IColorProvider) {
1024 return ((IColorProvider) provider).getForeground(element);
1025 }
1026 return null;
1027 }
1028
1029 private Font getFont(Object element) {
1030 if (element instanceof ItemsListSeparator) {
1031 return null;
1032 }
1033 if (provider instanceof IFontProvider) {
1034 return ((IFontProvider) provider).getFont(element);
1035 }
1036 return null;
1037 }
1038
1039 /*
1040 * (non-Javadoc)
1041 *
1042 * @see org.eclipse.jface.viewers.ILabelProviderListener#labelProviderChanged(org.eclipse.jface.viewers.LabelProviderChangedEvent)
1043 */
1044 @Override
1045 public void labelProviderChanged(LabelProviderChangedEvent event) {
1046 Object[] l = listeners.getListeners();
1047 for (int i = 0; i < listeners.size(); i++) {
1048 ((ILabelProviderListener) l[i]).labelProviderChanged(event);
1049 }
1050 }
1051 }
1052
1053 @Override
1054 protected Point getInitialSize() {
1055 return new Point(593, 399);
1056 }
1057 }
1058
1059