Project

General

Profile

« Previous | Next » 

Revision 7602050a

Added by Katja Luther almost 8 years ago

add new class CdmFilteredSelectionDialog

View differences:

eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/dialog/selection/CdmFilteredItemsSelectionDialog.java
1
// $Id$
2
/**
3
* Copyright (C) 2016 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
import java.io.IOException;
13
import java.io.StringReader;
14
import java.io.StringWriter;
15
import java.util.ArrayList;
16
import java.util.Arrays;
17
import java.util.Collections;
18
import java.util.Comparator;
19
import java.util.HashMap;
20
import java.util.HashSet;
21
import java.util.Iterator;
22
import java.util.LinkedHashSet;
23
import java.util.List;
24
import java.util.Set;
25

  
26
import org.eclipse.core.commands.AbstractHandler;
27
import org.eclipse.core.commands.ExecutionEvent;
28
import org.eclipse.core.commands.IHandler;
29
import org.eclipse.core.runtime.Assert;
30
import org.eclipse.core.runtime.CoreException;
31
import org.eclipse.core.runtime.IProgressMonitor;
32
import org.eclipse.core.runtime.IStatus;
33
import org.eclipse.core.runtime.ListenerList;
34
import org.eclipse.core.runtime.NullProgressMonitor;
35
import org.eclipse.core.runtime.ProgressMonitorWrapper;
36
import org.eclipse.core.runtime.Status;
37
import org.eclipse.core.runtime.SubProgressMonitor;
38
import org.eclipse.core.runtime.jobs.Job;
39
import org.eclipse.jface.action.Action;
40
import org.eclipse.jface.action.ActionContributionItem;
41
import org.eclipse.jface.action.IAction;
42
import org.eclipse.jface.action.IMenuListener;
43
import org.eclipse.jface.action.IMenuManager;
44
import org.eclipse.jface.action.LegacyActionTools;
45
import org.eclipse.jface.action.MenuManager;
46
import org.eclipse.jface.dialogs.IDialogSettings;
47
import org.eclipse.jface.viewers.ContentViewer;
48
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
49
import org.eclipse.jface.viewers.DoubleClickEvent;
50
import org.eclipse.jface.viewers.IColorProvider;
51
import org.eclipse.jface.viewers.IContentProvider;
52
import org.eclipse.jface.viewers.IDoubleClickListener;
53
import org.eclipse.jface.viewers.IFontProvider;
54
import org.eclipse.jface.viewers.ILabelDecorator;
55
import org.eclipse.jface.viewers.ILabelProvider;
56
import org.eclipse.jface.viewers.ILabelProviderListener;
57
import org.eclipse.jface.viewers.ILazyContentProvider;
58
import org.eclipse.jface.viewers.ISelection;
59
import org.eclipse.jface.viewers.ISelectionChangedListener;
60
import org.eclipse.jface.viewers.IStructuredContentProvider;
61
import org.eclipse.jface.viewers.LabelProvider;
62
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
63
import org.eclipse.jface.viewers.SelectionChangedEvent;
64
import org.eclipse.jface.viewers.StructuredSelection;
65
import org.eclipse.jface.viewers.StyledCellLabelProvider;
66
import org.eclipse.jface.viewers.StyledString;
67
import org.eclipse.jface.viewers.TableViewer;
68
import org.eclipse.jface.viewers.Viewer;
69
import org.eclipse.jface.viewers.ViewerCell;
70
import org.eclipse.jface.viewers.ViewerFilter;
71
import org.eclipse.osgi.util.NLS;
72
import org.eclipse.swt.SWT;
73
import org.eclipse.swt.accessibility.ACC;
74
import org.eclipse.swt.accessibility.AccessibleAdapter;
75
import org.eclipse.swt.accessibility.AccessibleEvent;
76
import org.eclipse.swt.custom.CLabel;
77
import org.eclipse.swt.custom.ViewForm;
78
import org.eclipse.swt.events.KeyAdapter;
79
import org.eclipse.swt.events.KeyEvent;
80
import org.eclipse.swt.events.ModifyEvent;
81
import org.eclipse.swt.events.ModifyListener;
82
import org.eclipse.swt.events.MouseAdapter;
83
import org.eclipse.swt.events.MouseEvent;
84
import org.eclipse.swt.events.SelectionAdapter;
85
import org.eclipse.swt.events.SelectionEvent;
86
import org.eclipse.swt.events.TraverseEvent;
87
import org.eclipse.swt.events.TraverseListener;
88
import org.eclipse.swt.graphics.Color;
89
import org.eclipse.swt.graphics.Font;
90
import org.eclipse.swt.graphics.GC;
91
import org.eclipse.swt.graphics.Image;
92
import org.eclipse.swt.graphics.Point;
93
import org.eclipse.swt.graphics.Rectangle;
94
import org.eclipse.swt.layout.GridData;
95
import org.eclipse.swt.layout.GridLayout;
96
import org.eclipse.swt.widgets.Composite;
97
import org.eclipse.swt.widgets.Control;
98
import org.eclipse.swt.widgets.Display;
99
import org.eclipse.swt.widgets.Event;
100
import org.eclipse.swt.widgets.Label;
101
import org.eclipse.swt.widgets.Menu;
102
import org.eclipse.swt.widgets.Shell;
103
import org.eclipse.swt.widgets.Table;
104
import org.eclipse.swt.widgets.Text;
105
import org.eclipse.swt.widgets.ToolBar;
106
import org.eclipse.swt.widgets.ToolItem;
107
import org.eclipse.ui.ActiveShellExpression;
108
import org.eclipse.ui.IMemento;
109
import org.eclipse.ui.IWorkbenchCommandConstants;
110
import org.eclipse.ui.IWorkbenchPreferenceConstants;
111
import org.eclipse.ui.PlatformUI;
112
import org.eclipse.ui.WorkbenchException;
113
import org.eclipse.ui.XMLMemento;
114
import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
115
import org.eclipse.ui.dialogs.SearchPattern;
116
import org.eclipse.ui.dialogs.SelectionStatusDialog;
117
import org.eclipse.ui.handlers.IHandlerActivation;
118
import org.eclipse.ui.handlers.IHandlerService;
119
import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
120
import org.eclipse.ui.internal.WorkbenchImages;
121
import org.eclipse.ui.internal.WorkbenchMessages;
122
import org.eclipse.ui.internal.WorkbenchPlugin;
123
import org.eclipse.ui.progress.UIJob;
124
import org.eclipse.ui.statushandlers.StatusManager;
125

  
126
/**
127
 * @author k.luther
128
 * @date 10.06.2016
129
 *
130
 */
131
public abstract class CdmFilteredItemsSelectionDialog extends SelectionStatusDialog {
132

  
133

  
134

  
135
        private static final String DIALOG_BOUNDS_SETTINGS = "DialogBoundsSettings"; //$NON-NLS-1$
136

  
137
        private static final String SHOW_STATUS_LINE = "ShowStatusLine"; //$NON-NLS-1$
138

  
139
        private static final String HISTORY_SETTINGS = "History"; //$NON-NLS-1$
140

  
141
        private static final String DIALOG_HEIGHT = "DIALOG_HEIGHT"; //$NON-NLS-1$
142

  
143
        private static final String DIALOG_WIDTH = "DIALOG_WIDTH"; //$NON-NLS-1$
144

  
145
        /**
146
         * Represents an empty selection in the pattern input field (used only for
147
         * initial pattern).
148
         */
149
        public static final int NONE = 0;
150

  
151
        /**
152
         * Pattern input field selection where caret is at the beginning (used only
153
         * for initial pattern).
154
         */
155
        public static final int CARET_BEGINNING = 1;
156

  
157
        /**
158
         * Represents a full selection in the pattern input field (used only for
159
         * initial pattern).
160
         */
161
        public static final int FULL_SELECTION = 2;
162

  
163
        private Text pattern;
164

  
165
        private TableViewer list;
166

  
167
        private DetailsContentViewer details;
168

  
169
        /**
170
         * It is a duplicate of a field in the CLabel class in DetailsContentViewer.
171
         * It is maintained, because the <code>setDetailsLabelProvider()</code>
172
         * could be called before content area is created.
173
         */
174
        private ILabelProvider detailsLabelProvider;
175

  
176
        private ItemsListLabelProvider itemsListLabelProvider;
177

  
178
        private MenuManager menuManager;
179

  
180
        private MenuManager contextMenuManager;
181

  
182
        private final boolean multi;
183

  
184
        private ToolBar toolBar;
185

  
186
        private ToolItem toolItem;
187

  
188
        private Label progressLabel;
189

  
190
        private ToggleStatusLineAction toggleStatusLineAction;
191

  
192
        private RemoveHistoryItemAction removeHistoryItemAction;
193

  
194
        private ActionContributionItem removeHistoryActionContributionItem;
195

  
196
        private IStatus status;
197

  
198
        private final RefreshCacheJob refreshCacheJob;
199

  
200
        private final RefreshProgressMessageJob refreshProgressMessageJob = new RefreshProgressMessageJob();
201

  
202
        private Object[] currentSelection;
203

  
204
        private final ContentProvider contentProvider;
205

  
206
        private final FilterHistoryJob filterHistoryJob;
207

  
208
        private final FilterJob filterJob;
209

  
210
        private ItemsFilter filter;
211

  
212
        private List lastCompletedResult;
213

  
214
        private ItemsFilter lastCompletedFilter;
215

  
216
        private String initialPatternText;
217

  
218
        private int selectionMode;
219

  
220
        private ItemsListSeparator itemsListSeparator;
221

  
222
        private static final String EMPTY_STRING = ""; //$NON-NLS-1$
223

  
224
        private boolean refreshWithLastSelection = false;
225

  
226
        private IHandlerActivation showViewHandler;
227

  
228
        /**
229
         * Creates a new instance of the class.
230
         *
231
         * @param shell
232
         *            shell to parent the dialog on
233
         * @param multi
234
         *            indicates whether dialog allows to select more than one
235
         *            position in its list of items
236
         */
237
        public CdmFilteredItemsSelectionDialog(Shell shell, boolean multi) {
238
            super(shell);
239
            this.multi = multi;
240
            filterHistoryJob = new FilterHistoryJob();
241
            filterJob = new FilterJob();
242
            contentProvider = new ContentProvider();
243
            refreshCacheJob = new RefreshCacheJob();
244
            itemsListSeparator = new ItemsListSeparator(
245
                    WorkbenchMessages.FilteredItemsSelectionDialog_separatorLabel);
246
            selectionMode = NONE;
247
        }
248

  
249
        /**
250
         * Creates a new instance of the class. Created dialog won't allow to select
251
         * more than one item.
252
         *
253
         * @param shell
254
         *            shell to parent the dialog on
255
         */
256
        public CdmFilteredItemsSelectionDialog(Shell shell) {
257
            this(shell, false);
258
        }
259

  
260
        /**
261
         * Adds viewer filter to the dialog items list.
262
         *
263
         * @param filter
264
         *            the new filter
265
         */
266
        protected void addListFilter(ViewerFilter filter) {
267
            contentProvider.addFilter(filter);
268
        }
269

  
270
        /**
271
         * Sets a new label provider for items in the list. If the label provider
272
         * also implements {@link
273
         * org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider
274
         * .IStyledLabelProvider}, the style text labels provided by it will be used
275
         * provided that the corresponding preference is set.
276
         *
277
         * @see IWorkbenchPreferenceConstants#USE_COLORED_LABELS
278
         *
279
         * @param listLabelProvider
280
         *      the label provider for items in the list
281
         */
282
        public void setListLabelProvider(ILabelProvider listLabelProvider) {
283
            getItemsListLabelProvider().setProvider(listLabelProvider);
284
        }
285

  
286
        /**
287
         * Returns the label decorator for selected items in the list.
288
         *
289
         * @return the label decorator for selected items in the list
290
         */
291
        private ILabelDecorator getListSelectionLabelDecorator() {
292
            return getItemsListLabelProvider().getSelectionDecorator();
293
        }
294

  
295
        /**
296
         * Sets the label decorator for selected items in the list.
297
         *
298
         * @param listSelectionLabelDecorator
299
         *            the label decorator for selected items in the list
300
         */
301
        public void setListSelectionLabelDecorator(
302
                ILabelDecorator listSelectionLabelDecorator) {
303
            getItemsListLabelProvider().setSelectionDecorator(
304
                    listSelectionLabelDecorator);
305
        }
306

  
307
        /**
308
         * Returns the item list label provider.
309
         *
310
         * @return the item list label provider
311
         */
312
        private ItemsListLabelProvider getItemsListLabelProvider() {
313
            if (itemsListLabelProvider == null) {
314
                itemsListLabelProvider = new ItemsListLabelProvider(
315
                        new LabelProvider(), null);
316
            }
317
            return itemsListLabelProvider;
318
        }
319

  
320
        /**
321
         * Sets label provider for the details field.
322
         *
323
         * For a single selection, the element sent to
324
         * {@link ILabelProvider#getImage(Object)} and
325
         * {@link ILabelProvider#getText(Object)} is the selected object, for
326
         * multiple selection a {@link String} with amount of selected items is the
327
         * element.
328
         *
329
         * @see #getSelectedItems() getSelectedItems() can be used to retrieve
330
         *      selected items and get the items count.
331
         *
332
         * @param detailsLabelProvider
333
         *            the label provider for the details field
334
         */
335
        public void setDetailsLabelProvider(ILabelProvider detailsLabelProvider) {
336
            this.detailsLabelProvider = detailsLabelProvider;
337
            if (details != null) {
338
                details.setLabelProvider(detailsLabelProvider);
339
            }
340
        }
341

  
342
        private ILabelProvider getDetailsLabelProvider() {
343
            if (detailsLabelProvider == null) {
344
                detailsLabelProvider = new LabelProvider();
345
            }
346
            return detailsLabelProvider;
347
        }
348

  
349
        /*
350
         * (non-Javadoc)
351
         *
352
         * @see org.eclipse.jface.window.Window#create()
353
         */
354
        @Override
355
        public void create() {
356
            super.create();
357
            pattern.setFocus();
358
        }
359

  
360
        /**
361
         * Restores dialog using persisted settings. The default implementation
362
         * restores the status of the details line and the selection history.
363
         *
364
         * @param settings
365
         *            settings used to restore dialog
366
         */
367
        protected void restoreDialog(IDialogSettings settings) {
368
            boolean toggleStatusLine = true;
369

  
370
            if (settings.get(SHOW_STATUS_LINE) != null) {
371
                toggleStatusLine = settings.getBoolean(SHOW_STATUS_LINE);
372
            }
373

  
374
            toggleStatusLineAction.setChecked(toggleStatusLine);
375

  
376
            details.setVisible(toggleStatusLine);
377

  
378
            String setting = settings.get(HISTORY_SETTINGS);
379
            if (setting != null) {
380
                try {
381
                    IMemento memento = XMLMemento.createReadRoot(new StringReader(
382
                            setting));
383
                    this.contentProvider.loadHistory(memento);
384
                } catch (WorkbenchException e) {
385
                    // Simply don't restore the settings
386
                    StatusManager
387
                            .getManager()
388
                            .handle(
389
                                    new Status(
390
                                            IStatus.ERROR,
391
                                            PlatformUI.PLUGIN_ID,
392
                                            IStatus.ERROR,
393
                                            WorkbenchMessages.FilteredItemsSelectionDialog_restoreError,
394
                                            e));
395
                }
396
            }
397
        }
398

  
399
        /*
400
         * (non-Javadoc)
401
         *
402
         * @see org.eclipse.jface.window.Window#close()
403
         */
404
        @Override
405
        public boolean close() {
406
            this.filterJob.cancel();
407
            this.refreshCacheJob.cancel();
408
            this.refreshProgressMessageJob.cancel();
409
            if (showViewHandler != null) {
410
                IHandlerService service = (IHandlerService) PlatformUI
411
                        .getWorkbench().getService(IHandlerService.class);
412
                service.deactivateHandler(showViewHandler);
413
                showViewHandler.getHandler().dispose();
414
                showViewHandler = null;
415
            }
416
            if (menuManager != null) {
417
                menuManager.dispose();
418
            }
419
            if (contextMenuManager != null) {
420
                contextMenuManager.dispose();
421
            }
422
            storeDialog(getDialogSettings());
423
            return super.close();
424
        }
425

  
426
        /**
427
         * Stores dialog settings.
428
         *
429
         * @param settings
430
         *            settings used to store dialog
431
         */
432
        protected void storeDialog(IDialogSettings settings) {
433
            settings.put(SHOW_STATUS_LINE, toggleStatusLineAction.isChecked());
434

  
435
            XMLMemento memento = XMLMemento.createWriteRoot(HISTORY_SETTINGS);
436
            this.contentProvider.saveHistory(memento);
437
            StringWriter writer = new StringWriter();
438
            try {
439
                memento.save(writer);
440
                settings.put(HISTORY_SETTINGS, writer.getBuffer().toString());
441
            } catch (IOException e) {
442
                // Simply don't store the settings
443
                StatusManager
444
                        .getManager()
445
                        .handle(
446
                                new Status(
447
                                        IStatus.ERROR,
448
                                        PlatformUI.PLUGIN_ID,
449
                                        IStatus.ERROR,
450
                                        WorkbenchMessages.FilteredItemsSelectionDialog_storeError,
451
                                        e));
452
            }
453
        }
454

  
455
        /**
456
         * Create a new header which is labelled by headerLabel.
457
         *
458
         * @param parent
459
         * @return Label the label of the header
460
         */
461
        private Label createHeader(Composite parent) {
462
            Composite header = new Composite(parent, SWT.NONE);
463

  
464
            GridLayout layout = new GridLayout();
465
            layout.numColumns = 2;
466
            layout.marginWidth = 0;
467
            layout.marginHeight = 0;
468
            header.setLayout(layout);
469

  
470
            Label headerLabel = new Label(header, SWT.NONE);
471
            headerLabel.setText((getMessage() != null && getMessage().trim()
472
                    .length() > 0) ? getMessage()
473
                    : WorkbenchMessages.FilteredItemsSelectionDialog_patternLabel);
474
            headerLabel.addTraverseListener(new TraverseListener() {
475
                @Override
476
                public void keyTraversed(TraverseEvent e) {
477
                    if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) {
478
                        e.detail = SWT.TRAVERSE_NONE;
479
                        pattern.setFocus();
480
                    }
481
                }
482
            });
483

  
484
            GridData gd = new GridData(GridData.FILL_HORIZONTAL);
485
            headerLabel.setLayoutData(gd);
486

  
487
            createViewMenu(header);
488
            header.setLayoutData(gd);
489
            return headerLabel;
490
        }
491

  
492
        /**
493
         * Create the labels for the list and the progress. Return the list label.
494
         *
495
         * @param parent
496
         * @return Label
497
         */
498
        private Label createLabels(Composite parent) {
499
            Composite labels = new Composite(parent, SWT.NONE);
500

  
501
            GridLayout layout = new GridLayout();
502
            layout.numColumns = 2;
503
            layout.marginWidth = 0;
504
            layout.marginHeight = 0;
505
            labels.setLayout(layout);
506

  
507
            Label listLabel = new Label(labels, SWT.NONE);
508
            listLabel
509
                    .setText(WorkbenchMessages.FilteredItemsSelectionDialog_listLabel);
510

  
511
            listLabel.addTraverseListener(new TraverseListener() {
512
                @Override
513
                public void keyTraversed(TraverseEvent e) {
514
                    if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) {
515
                        e.detail = SWT.TRAVERSE_NONE;
516
                        list.getTable().setFocus();
517
                    }
518
                }
519
            });
520

  
521
            GridData gd = new GridData(GridData.FILL_HORIZONTAL);
522
            listLabel.setLayoutData(gd);
523

  
524
            progressLabel = new Label(labels, SWT.RIGHT);
525
            progressLabel.setLayoutData(gd);
526

  
527
            labels.setLayoutData(gd);
528
            return listLabel;
529
        }
530

  
531
        private void createViewMenu(Composite parent) {
532
            toolBar = new ToolBar(parent, SWT.FLAT);
533
            toolItem = new ToolItem(toolBar, SWT.PUSH, 0);
534

  
535
            GridData data = new GridData();
536
            data.horizontalAlignment = GridData.END;
537
            toolBar.setLayoutData(data);
538

  
539
            toolBar.addMouseListener(new MouseAdapter() {
540
                @Override
541
                public void mouseDown(MouseEvent e) {
542
                    showViewMenu();
543
                }
544
            });
545

  
546
            toolItem.setImage(WorkbenchImages
547
                    .getImage(IWorkbenchGraphicConstants.IMG_LCL_VIEW_MENU));
548
            toolItem
549
                    .setToolTipText(WorkbenchMessages.FilteredItemsSelectionDialog_menu);
550
            toolItem.addSelectionListener(new SelectionAdapter() {
551
                @Override
552
                public void widgetSelected(SelectionEvent e) {
553
                    showViewMenu();
554
                }
555
            });
556

  
557
            menuManager = new MenuManager();
558

  
559
            fillViewMenu(menuManager);
560

  
561
            IHandlerService service = (IHandlerService) PlatformUI.getWorkbench()
562
                    .getService(IHandlerService.class);
563
            IHandler handler = new AbstractHandler() {
564
                @Override
565
                public Object execute(ExecutionEvent event) {
566
                    showViewMenu();
567
                    return null;
568
                }
569
            };
570
            showViewHandler = service.activateHandler(
571
                    IWorkbenchCommandConstants.WINDOW_SHOW_VIEW_MENU, handler,
572
                    new ActiveShellExpression(getShell()));
573
        }
574

  
575
        /**
576
         * Fills the menu of the dialog.
577
         *
578
         * @param menuManager
579
         *            the menu manager
580
         */
581
        protected void fillViewMenu(IMenuManager menuManager) {
582
            toggleStatusLineAction = new ToggleStatusLineAction();
583
            menuManager.add(toggleStatusLineAction);
584
        }
585

  
586
        private void showViewMenu() {
587
            Menu menu = menuManager.createContextMenu(getShell());
588
            Rectangle bounds = toolItem.getBounds();
589
            Point topLeft = new Point(bounds.x, bounds.y + bounds.height);
590
            topLeft = toolBar.toDisplay(topLeft);
591
            menu.setLocation(topLeft.x, topLeft.y);
592
            menu.setVisible(true);
593
        }
594

  
595
        /**
596
         * Hook that allows to add actions to the context menu.
597
         * <p>
598
         * Subclasses may extend in order to add other actions.</p>
599
         *
600
         * @param menuManager the context menu manager
601
         * @since 3.5
602
         */
603
        protected void fillContextMenu(IMenuManager menuManager) {
604
            List selectedElements= ((StructuredSelection)list.getSelection()).toList();
605

  
606
            Object item= null;
607

  
608
            for (Iterator it= selectedElements.iterator(); it.hasNext();) {
609
                item= it.next();
610
                if (item instanceof ItemsListSeparator || !isHistoryElement(item)) {
611
                    return;
612
                }
613
            }
614

  
615
            if (selectedElements.size() > 0) {
616
                removeHistoryItemAction.setText(WorkbenchMessages.FilteredItemsSelectionDialog_removeItemsFromHistoryAction);
617

  
618
                menuManager.add(removeHistoryActionContributionItem);
619

  
620
            }
621
        }
622

  
623
        private void createPopupMenu() {
624
            removeHistoryItemAction = new RemoveHistoryItemAction();
625
            removeHistoryActionContributionItem = new ActionContributionItem(
626
                    removeHistoryItemAction);
627

  
628
            contextMenuManager = new MenuManager();
629
            contextMenuManager.setRemoveAllWhenShown(true);
630
            contextMenuManager.addMenuListener(new IMenuListener() {
631
                @Override
632
                public void menuAboutToShow(IMenuManager manager) {
633
                    fillContextMenu(manager);
634
                }
635
            });
636

  
637
            final Table table = list.getTable();
638
            Menu menu= contextMenuManager.createContextMenu(table);
639
            table.setMenu(menu);
640
        }
641

  
642
        /**
643
         * Creates an extra content area, which will be located above the details.
644
         *
645
         * @param parent
646
         *            parent to create the dialog widgets in
647
         * @return an extra content area
648
         */
649
        protected abstract Control createExtendedContentArea(Composite parent);
650

  
651
        /*
652
         * (non-Javadoc)
653
         *
654
         * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
655
         */
656
        @Override
657
        protected Control createDialogArea(Composite parent) {
658
            Composite dialogArea = (Composite) super.createDialogArea(parent);
659

  
660
            Composite content = new Composite(dialogArea, SWT.NONE);
661
            GridData gd = new GridData(GridData.FILL_BOTH);
662
            content.setLayoutData(gd);
663

  
664
            GridLayout layout = new GridLayout();
665
            layout.numColumns = 1;
666
            layout.marginWidth = 0;
667
            layout.marginHeight = 0;
668
            content.setLayout(layout);
669

  
670
            final Label headerLabel = createHeader(content);
671

  
672
            pattern = new Text(content, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL);
673
            pattern.getAccessible().addAccessibleListener(new AccessibleAdapter() {
674
                @Override
675
                public void getName(AccessibleEvent e) {
676
                    e.result = LegacyActionTools.removeMnemonics(headerLabel
677
                            .getText());
678
                }
679
            });
680
            gd = new GridData(GridData.FILL_HORIZONTAL);
681
            pattern.setLayoutData(gd);
682

  
683
            final Label listLabel = createLabels(content);
684

  
685
            list = new TableViewer(content, (multi ? SWT.MULTI : SWT.SINGLE)
686
                    | SWT.BORDER | SWT.V_SCROLL | SWT.VIRTUAL);
687
            list.getTable().getAccessible().addAccessibleListener(
688
                    new AccessibleAdapter() {
689
                        @Override
690
                        public void getName(AccessibleEvent e) {
691
                            if (e.childID == ACC.CHILDID_SELF) {
692
                                e.result = LegacyActionTools
693
                                        .removeMnemonics(listLabel.getText());
694
                            }
695
                        }
696
                    });
697
            list.setContentProvider(contentProvider);
698
            list.setLabelProvider(getItemsListLabelProvider());
699
            list.setInput(new Object[0]);
700
            list.setItemCount(contentProvider.getNumberOfElements());
701
            gd = new GridData(GridData.FILL_BOTH);
702
            applyDialogFont(list.getTable());
703
            gd.heightHint= list.getTable().getItemHeight() * 15;
704
            list.getTable().setLayoutData(gd);
705

  
706
            createPopupMenu();
707

  
708
            pattern.addModifyListener(new ModifyListener() {
709
                @Override
710
                public void modifyText(ModifyEvent e) {
711
                    applyFilter();
712
                }
713
            });
714

  
715
            pattern.addKeyListener(new KeyAdapter() {
716
                @Override
717
                public void keyPressed(KeyEvent e) {
718
                    if (e.keyCode == SWT.ARROW_DOWN) {
719
                        if (list.getTable().getItemCount() > 0) {
720
                            list.getTable().setFocus();
721
                        }
722
                    }
723
                }
724
            });
725

  
726
            list.addSelectionChangedListener(new ISelectionChangedListener() {
727
                @Override
728
                public void selectionChanged(SelectionChangedEvent event) {
729
                    StructuredSelection selection = (StructuredSelection) event
730
                            .getSelection();
731
                    handleSelected(selection);
732
                }
733
            });
734

  
735
            list.addDoubleClickListener(new IDoubleClickListener() {
736
                @Override
737
                public void doubleClick(DoubleClickEvent event) {
738
                    handleDoubleClick();
739
                }
740
            });
741

  
742
            list.getTable().addKeyListener(new KeyAdapter() {
743
                @Override
744
                public void keyPressed(KeyEvent e) {
745

  
746
                    if (e.keyCode == SWT.DEL) {
747

  
748
                        List selectedElements = ((StructuredSelection) list
749
                                .getSelection()).toList();
750

  
751
                        Object item = null;
752
                        boolean isSelectedHistory = true;
753

  
754
                        for (Iterator it = selectedElements.iterator(); it
755
                                .hasNext();) {
756
                            item = it.next();
757
                            if (item instanceof ItemsListSeparator
758
                                    || !isHistoryElement(item)) {
759
                                isSelectedHistory = false;
760
                                break;
761
                            }
762
                        }
763
                        if (isSelectedHistory) {
764
                            removeSelectedItems(selectedElements);
765
                        }
766

  
767
                    }
768

  
769
                    if (e.keyCode == SWT.ARROW_UP && (e.stateMask & SWT.SHIFT) != 0
770
                            && (e.stateMask & SWT.CTRL) != 0) {
771
                        StructuredSelection selection = (StructuredSelection) list
772
                                .getSelection();
773

  
774
                        if (selection.size() == 1) {
775
                            Object element = selection.getFirstElement();
776
                            if (element.equals(list.getElementAt(0))) {
777
                                pattern.setFocus();
778
                            }
779
                            if (list.getElementAt(list.getTable()
780
                                    .getSelectionIndex() - 1) instanceof ItemsListSeparator) {
781
                                list.getTable().setSelection(
782
                                        list.getTable().getSelectionIndex() - 1);
783
                            }
784
                            list.getTable().notifyListeners(SWT.Selection,
785
                                    new Event());
786

  
787
                        }
788
                    }
789

  
790
                    if (e.keyCode == SWT.ARROW_DOWN
791
                            && (e.stateMask & SWT.SHIFT) != 0
792
                            && (e.stateMask & SWT.CTRL) != 0) {
793

  
794
                        if (list
795
                                .getElementAt(list.getTable().getSelectionIndex() + 1) instanceof ItemsListSeparator) {
796
                            list.getTable().setSelection(
797
                                    list.getTable().getSelectionIndex() + 1);
798
                        }
799
                        list.getTable().notifyListeners(SWT.Selection, new Event());
800
                    }
801

  
802
                }
803
            });
804

  
805
            createExtendedContentArea(content);
806

  
807
            details = new DetailsContentViewer(content, SWT.BORDER | SWT.FLAT);
808
            details.setVisible(toggleStatusLineAction.isChecked());
809
            details.setContentProvider(new NullContentProvider());
810
            details.setLabelProvider(getDetailsLabelProvider());
811

  
812
            applyDialogFont(content);
813

  
814
            restoreDialog(getDialogSettings());
815

  
816
            if (initialPatternText != null) {
817
                pattern.setText(initialPatternText);
818
            }
819

  
820
            switch (selectionMode) {
821
            case CARET_BEGINNING:
822
                pattern.setSelection(0, 0);
823
                break;
824
            case FULL_SELECTION:
825
                pattern.setSelection(0, initialPatternText.length());
826
                break;
827
            }
828

  
829
            // apply filter even if pattern is empty (display history)
830
            applyFilter();
831

  
832
            return dialogArea;
833
        }
834

  
835
        /**
836
         * This method is a hook for subclasses to override default dialog behavior.
837
         * The <code>handleDoubleClick()</code> method handles double clicks on
838
         * the list of filtered elements.
839
         * <p>
840
         * Current implementation makes double-clicking on the list do the same as
841
         * pressing <code>OK</code> button on the dialog.
842
         */
843
        protected void handleDoubleClick() {
844
            okPressed();
845
        }
846

  
847
        /**
848
         * Refreshes the details field according to the current selection in the
849
         * items list.
850
         */
851
        private void refreshDetails() {
852
            StructuredSelection selection = getSelectedItems();
853

  
854
            switch (selection.size()) {
855
            case 0:
856
                details.setInput(null);
857
                break;
858
            case 1:
859
                details.setInput(selection.getFirstElement());
860
                break;
861
            default:
862
                details
863
                        .setInput(NLS
864
                                .bind(
865
                                        WorkbenchMessages.FilteredItemsSelectionDialog_nItemsSelected,
866
                                        new Integer(selection.size())));
867
                break;
868
            }
869

  
870
        }
871

  
872
        /**
873
         * Handle selection in the items list by updating labels of selected and
874
         * unselected items and refresh the details field using the selection.
875
         *
876
         * @param selection
877
         *            the new selection
878
         */
879
        protected void handleSelected(StructuredSelection selection) {
880
            IStatus status = new Status(IStatus.OK, PlatformUI.PLUGIN_ID,
881
                    IStatus.OK, EMPTY_STRING, null);
882

  
883
            Object[] lastSelection = currentSelection;
884

  
885
            currentSelection = selection.toArray();
886

  
887
            if (selection.size() == 0) {
888
                status = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
889
                        IStatus.ERROR, EMPTY_STRING, null);
890

  
891
                if (lastSelection != null
892
                        && getListSelectionLabelDecorator() != null) {
893
                    list.update(lastSelection, null);
894
                }
895

  
896
                currentSelection = null;
897

  
898
            } else {
899
                status = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
900
                        IStatus.ERROR, EMPTY_STRING, null);
901

  
902
                List items = selection.toList();
903

  
904
                Object item = null;
905
                IStatus tempStatus = null;
906

  
907
                for (Iterator it = items.iterator(); it.hasNext();) {
908
                    Object o = it.next();
909

  
910
                    if (o instanceof ItemsListSeparator) {
911
                        continue;
912
                    }
913

  
914
                    item = o;
915
                    tempStatus = validateItem(item);
916

  
917
                    if (tempStatus.isOK()) {
918
                        status = new Status(IStatus.OK, PlatformUI.PLUGIN_ID,
919
                                IStatus.OK, EMPTY_STRING, null);
920
                    } else {
921
                        status = tempStatus;
922
                        // if any selected element is not valid status is set to
923
                        // ERROR
924
                        break;
925
                    }
926
                }
927

  
928
                if (lastSelection != null
929
                        && getListSelectionLabelDecorator() != null) {
930
                    list.update(lastSelection, null);
931
                }
932

  
933
                if (getListSelectionLabelDecorator() != null) {
934
                    list.update(currentSelection, null);
935
                }
936
            }
937

  
938
            refreshDetails();
939
            updateStatus(status);
940
        }
941

  
942
        /*
943
         * (non-Javadoc)
944
         *
945
         * @see org.eclipse.jface.window.Dialog#getDialogBoundsSettings()
946
         */
947
        @Override
948
        protected IDialogSettings getDialogBoundsSettings() {
949
            IDialogSettings settings = getDialogSettings();
950
            IDialogSettings section = settings.getSection(DIALOG_BOUNDS_SETTINGS);
951
            if (section == null) {
952
                section = settings.addNewSection(DIALOG_BOUNDS_SETTINGS);
953
                section.put(DIALOG_HEIGHT, 500);
954
                section.put(DIALOG_WIDTH, 600);
955
            }
956
            return section;
957
        }
958

  
959
        /**
960
         * Returns the dialog settings. Returned object can't be null.
961
         *
962
         * @return return dialog settings for this dialog
963
         */
964
        protected abstract IDialogSettings getDialogSettings();
965

  
966
        /**
967
         * Refreshes the dialog - has to be called in UI thread.
968
         */
969
        public void refresh() {
970
            if (list != null && !list.getTable().isDisposed()) {
971

  
972
                List lastRefreshSelection = ((StructuredSelection) list
973
                        .getSelection()).toList();
974
                list.getTable().deselectAll();
975

  
976
                list.setItemCount(contentProvider.getNumberOfElements());
977
                list.refresh();
978

  
979
                if (list.getTable().getItemCount() > 0) {
980
                    // preserve previous selection
981
                    if (refreshWithLastSelection && lastRefreshSelection != null
982
                            && lastRefreshSelection.size() > 0) {
983
                        list.setSelection(new StructuredSelection(
984
                                lastRefreshSelection));
985
                    } else {
986
                        refreshWithLastSelection = true;
987
                        list.getTable().setSelection(0);
988
                        list.getTable().notifyListeners(SWT.Selection, new Event());
989
                    }
990
                } else {
991
                    list.setSelection(StructuredSelection.EMPTY);
992
                }
993

  
994
            }
995

  
996
            scheduleProgressMessageRefresh();
997
        }
998

  
999
        /**
1000
         * Updates the progress label.
1001
         *
1002
         * @deprecated
1003
         */
1004
        @Deprecated
1005
        public void updateProgressLabel() {
1006
            scheduleProgressMessageRefresh();
1007
        }
1008

  
1009
        /**
1010
         * Notifies the content provider - fires filtering of content provider
1011
         * elements. During the filtering, a separator between history and workspace
1012
         * matches is added.
1013
         * <p>
1014
         * This is a long running operation and should be called in a job.
1015
         *
1016
         * @param checkDuplicates
1017
         *            <code>true</code> if data concerning elements duplication
1018
         *            should be computed - it takes much more time than the standard
1019
         *            filtering
1020
         * @param monitor
1021
         *            a progress monitor or <code>null</code> if no monitor is
1022
         *            available
1023
         */
1024
        public void reloadCache(boolean checkDuplicates, IProgressMonitor monitor) {
1025
            if (list != null && !list.getTable().isDisposed()
1026
                    && contentProvider != null) {
1027
                contentProvider.reloadCache(checkDuplicates, monitor);
1028
            }
1029
        }
1030

  
1031
        /**
1032
         * Schedule refresh job.
1033
         */
1034
        public void scheduleRefresh() {
1035
            refreshCacheJob.cancelAll();
1036
            refreshCacheJob.schedule();
1037
        }
1038

  
1039
        /**
1040
         * Schedules progress message refresh.
1041
         */
1042
        public void scheduleProgressMessageRefresh() {
1043
            if (filterJob.getState() != Job.RUNNING
1044
                    && refreshProgressMessageJob.getState() != Job.RUNNING) {
1045
                refreshProgressMessageJob.scheduleProgressRefresh(null);
1046
            }
1047
        }
1048

  
1049
        /*
1050
         * (non-Javadoc)
1051
         *
1052
         * @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult()
1053
         */
1054
        @Override
1055
        protected void computeResult() {
1056

  
1057
            List selectedElements = ((StructuredSelection) list.getSelection())
1058
                    .toList();
1059

  
1060
            List objectsToReturn = new ArrayList();
1061

  
1062
            Object item = null;
1063

  
1064
            for (Iterator it = selectedElements.iterator(); it.hasNext();) {
1065
                item = it.next();
1066

  
1067
                if (!(item instanceof ItemsListSeparator)) {
1068
                    accessedHistoryItem(item);
1069
                    objectsToReturn.add(item);
1070
                }
1071
            }
1072

  
1073
            setResult(objectsToReturn);
1074
        }
1075

  
1076
        /*
1077
         * @see org.eclipse.ui.dialogs.SelectionStatusDialog#updateStatus(org.eclipse.core.runtime.IStatus)
1078
         */
1079
        @Override
1080
        protected void updateStatus(IStatus status) {
1081
            this.status = status;
1082
            super.updateStatus(status);
1083
        }
1084

  
1085
        /*
1086
         * @see Dialog#okPressed()
1087
         */
1088
        @Override
1089
        protected void okPressed() {
1090
            if (status != null
1091
                    && (status.isOK() || status.getCode() == IStatus.INFO)) {
1092
                super.okPressed();
1093
            }
1094
        }
1095

  
1096
        /**
1097
         * Sets the initial pattern used by the filter. This text is copied into the
1098
         * selection input on the dialog. A full selection is used in the pattern
1099
         * input field.
1100
         *
1101
         * @param text
1102
         *            initial pattern for the filter
1103
         * @see FilteredItemsSelectionDialog#FULL_SELECTION
1104
         */
1105
        public void setInitialPattern(String text) {
1106
            setInitialPattern(text, FULL_SELECTION);
1107
        }
1108

  
1109
        /**
1110
         * Sets the initial pattern used by the filter. This text is copied into the
1111
         * selection input on the dialog. The <code>selectionMode</code> is used
1112
         * to choose selection type for the input field.
1113
         *
1114
         * @param text
1115
         *            initial pattern for the filter
1116
         * @param selectionMode
1117
         *            one of: {@link FilteredItemsSelectionDialog#NONE},
1118
         *            {@link FilteredItemsSelectionDialog#CARET_BEGINNING},
1119
         *            {@link FilteredItemsSelectionDialog#FULL_SELECTION}
1120
         */
1121
        public void setInitialPattern(String text, int selectionMode) {
1122
            this.initialPatternText = text;
1123
            this.selectionMode = selectionMode;
1124
        }
1125

  
1126
        /**
1127
         * Gets initial pattern.
1128
         *
1129
         * @return initial pattern, or <code>null</code> if initial pattern is not
1130
         *         set
1131
         */
1132
        protected String getInitialPattern() {
1133
            return this.initialPatternText;
1134
        }
1135

  
1136
        /**
1137
         * Returns the current selection.
1138
         *
1139
         * @return the current selection
1140
         */
1141
        protected StructuredSelection getSelectedItems() {
1142

  
1143
            StructuredSelection selection = (StructuredSelection) list
1144
                    .getSelection();
1145

  
1146
            List selectedItems = selection.toList();
1147
            Object itemToRemove = null;
1148

  
1149
            for (Iterator it = selection.iterator(); it.hasNext();) {
1150
                Object item = it.next();
1151
                if (item instanceof ItemsListSeparator) {
1152
                    itemToRemove = item;
1153
                    break;
1154
                }
1155
            }
1156

  
1157
            if (itemToRemove == null) {
1158
                return new StructuredSelection(selectedItems);
1159
            }
1160
            // Create a new selection without the collision
1161
            List newItems = new ArrayList(selectedItems);
1162
            newItems.remove(itemToRemove);
1163
            return new StructuredSelection(newItems);
1164

  
1165
        }
1166

  
1167
        /**
1168
         * Validates the item. When items on the items list are selected or
1169
         * deselected, it validates each item in the selection and the dialog status
1170
         * depends on all validations.
1171
         *
1172
         * @param item
1173
         *            an item to be checked
1174
         * @return status of the dialog to be set
1175
         */
1176
        protected abstract IStatus validateItem(Object item);
1177

  
1178
        /**
1179
         * Creates an instance of a filter.
1180
         *
1181
         * @return a filter for items on the items list. Can be <code>null</code>,
1182
         *         no filtering will be applied then, causing no item to be shown in
1183
         *         the list.
1184
         */
1185
        protected abstract ItemsFilter createFilter();
1186

  
1187
        /**
1188
         * Applies the filter created by <code>createFilter()</code> method to the
1189
         * items list. When new filter is different than previous one it will cause
1190
         * refiltering.
1191
         */
1192
        protected void applyFilter() {
1193

  
1194
            ItemsFilter newFilter = createFilter();
1195

  
1196
            // don't apply filtering for patterns which mean the same, for example:
1197
            // *a**b and ***a*b
1198
            if (filter != null && filter.equalsFilter(newFilter)) {
1199
                return;
1200
            }
1201

  
1202
            filterHistoryJob.cancel();
1203
            filterJob.cancel();
1204

  
1205
            this.filter = newFilter;
1206

  
1207
            if (this.filter != null) {
1208
                filterHistoryJob.schedule();
1209
            }
1210
        }
1211

  
1212
        /**
1213
         * Returns comparator to sort items inside content provider. Returned object
1214
         * will be probably created as an anonymous class. Parameters passed to the
1215
         * <code>compare(java.lang.Object, java.lang.Object)</code> are going to
1216
         * be the same type as the one used in the content provider.
1217
         *
1218
         * @return comparator to sort items content provider
1219
         */
1220
        protected abstract Comparator getItemsComparator();
1221

  
1222
        /**
1223
         * Fills the content provider with matching items.
1224
         *
1225
         * @param contentProvider
1226
         *            collector to add items to.
1227
         *            {@link FilteredItemsSelectionDialog.AbstractContentProvider#add(Object, FilteredItemsSelectionDialog.ItemsFilter)}
1228
         *            only adds items that pass the given <code>itemsFilter</code>.
1229
         * @param itemsFilter
1230
         *            the items filter
1231
         * @param progressMonitor
1232
         *            must be used to report search progress. The state of this
1233
         *            progress monitor reflects the state of the filtering process.
1234
         * @throws CoreException
1235
         */
1236
        protected abstract void fillContentProvider(
1237
                AbstractContentProvider contentProvider, ItemsFilter itemsFilter,
1238
                IProgressMonitor progressMonitor) throws CoreException;
1239

  
1240
        /**
1241
         * Removes selected items from history.
1242
         *
1243
         * @param items
1244
         *            items to be removed
1245
         */
1246
        private void removeSelectedItems(List items) {
1247
            for (Iterator iter = items.iterator(); iter.hasNext();) {
1248
                Object item = iter.next();
1249
                removeHistoryItem(item);
1250
            }
1251
            refreshWithLastSelection = false;
1252
            contentProvider.refresh();
1253
        }
1254

  
1255
        /**
1256
         * Removes an item from history.
1257
         *
1258
         * @param item
1259
         *            an item to remove
1260
         * @return removed item
1261
         */
1262
        protected Object removeHistoryItem(Object item) {
1263
            return contentProvider.removeHistoryElement(item);
1264
        }
1265

  
1266
        /**
1267
         * Adds item to history.
1268
         *
1269
         * @param item
1270
         *            the item to be added
1271
         */
1272
        protected void accessedHistoryItem(Object item) {
1273
            contentProvider.addHistoryElement(item);
1274
        }
1275

  
1276
        /**
1277
         * Returns a history comparator.
1278
         *
1279
         * @return decorated comparator
1280
         */
1281
        private Comparator getHistoryComparator() {
1282
            return new HistoryComparator();
1283
        }
1284

  
1285
        /**
1286
         * Returns the history of selected elements.
1287
         *
1288
         * @return history of selected elements, or <code>null</code> if it is not
1289
         *         set
1290
         */
1291
        protected SelectionHistory getSelectionHistory() {
1292
            return this.contentProvider.getSelectionHistory();
1293
        }
1294

  
1295
        /**
1296
         * Sets new history.
1297
         *
1298
         * @param selectionHistory
1299
         *            the history
1300
         */
1301
        protected void setSelectionHistory(SelectionHistory selectionHistory) {
1302
            if (this.contentProvider != null) {
1303
                this.contentProvider.setSelectionHistory(selectionHistory);
1304
            }
1305
        }
1306

  
1307
        /**
1308
         * Indicates whether the given item is a history item.
1309
         *
1310
         * @param item
1311
         *            the item to be investigated
1312
         * @return <code>true</code> if the given item exists in history,
1313
         *         <code>false</code> otherwise
1314
         */
1315
        public boolean isHistoryElement(Object item) {
1316
            return this.contentProvider.isHistoryElement(item);
1317
        }
1318

  
1319
        /**
1320
         * Indicates whether the given item is a duplicate.
1321
         *
1322
         * @param item
1323
         *            the item to be investigated
1324
         * @return <code>true</code> if the item is duplicate, <code>false</code>
1325
         *         otherwise
1326
         */
1327
        public boolean isDuplicateElement(Object item) {
1328
            return this.contentProvider.isDuplicateElement(item);
1329
        }
1330

  
1331
        /**
1332
         * Sets separator label
1333
         *
1334
         * @param separatorLabel
1335
         *            the label showed on separator
1336
         */
1337
        public void setSeparatorLabel(String separatorLabel) {
1338
            this.itemsListSeparator = new ItemsListSeparator(separatorLabel);
1339
        }
1340

  
1341
        /**
1342
         * Returns name for then given object.
1343
         *
1344
         * @param item
1345
         *            an object from the content provider. Subclasses should pay
1346
         *            attention to the passed argument. They should either only pass
1347
         *            objects of a known type (one used in content provider) or make
1348
         *            sure that passed parameter is the expected one (by type
1349
         *            checking like <code>instanceof</code> inside the method).
1350
         * @return name of the given item
1351
         */
1352
        public abstract String getElementName(Object item);
1353

  
1354
        private class ToggleStatusLineAction extends Action {
1355

  
1356
            /**
1357
             * Creates a new instance of the class.
1358
             */
1359
            public ToggleStatusLineAction() {
1360
                super(
1361
                        WorkbenchMessages.FilteredItemsSelectionDialog_toggleStatusAction,
1362
                        IAction.AS_CHECK_BOX);
1363
            }
1364

  
1365
            @Override
1366
            public void run() {
1367
                details.setVisible(isChecked());
1368
            }
1369
        }
1370

  
1371
        /**
1372
         * Only refreshes UI on the basis of an already sorted and filtered set of
1373
         * items.
1374
         * <p>
1375
         * Standard invocation scenario:
1376
         * <ol>
1377
         * <li>filtering job (<code>FilterJob</code> class extending
1378
         * <code>Job</code> class)</li>
1379
         * <li>cache refresh without checking for duplicates (<code>RefreshCacheJob</code>
1380
         * class extending <code>Job</code> class)</li>
1381
         * <li>UI refresh (<code>RefreshJob</code> class extending
1382
         * <code>UIJob</code> class)</li>
1383
         * <li>cache refresh with checking for duplicates (<cod>CacheRefreshJob</code>
1384
         * class extending <code>Job</code> class)</li>
1385
         * <li>UI refresh (<code>RefreshJob</code> class extending <code>UIJob</code>
1386
         * class)</li>
1387
         * </ol>
1388
         * The scenario is rather complicated, but it had to be applied, because:
1389
         * <ul>
1390
         * <li> refreshing cache is rather a long action and cannot be run in the UI -
1391
         * cannot be run in a UIJob</li>
1392
         * <li> refreshing cache checking for duplicates is twice as long as
1393
         * refreshing cache without checking for duplicates; results of the search
1394
         * could be displayed earlier</li>
1395
         * <li> refreshing the UI have to be run in a UIJob</li>
1396
         * </ul>
1397
         *
1398
         * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.FilterJob
1399
         * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.RefreshJob
1400
         * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.RefreshCacheJob
1401
         */
1402
        private class RefreshJob extends UIJob {
1403

  
1404
            /**
1405
             * Creates a new instance of the class.
1406
             */
1407
            public RefreshJob() {
1408
                super(CdmFilteredItemsSelectionDialog.this.getParentShell()
1409
                        .getDisplay(),
1410
                        WorkbenchMessages.FilteredItemsSelectionDialog_refreshJob);
1411
                setSystem(true);
1412
            }
1413

  
1414
            /*
1415
             * (non-Javadoc)
1416
             *
1417
             * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
1418
             */
1419
            @Override
1420
            public IStatus runInUIThread(IProgressMonitor monitor) {
1421
                if (monitor.isCanceled()) {
1422
                    return new Status(IStatus.OK, WorkbenchPlugin.PI_WORKBENCH,
1423
                            IStatus.OK, EMPTY_STRING, null);
1424
                }
1425

  
1426
                if (CdmFilteredItemsSelectionDialog.this != null) {
1427
                    CdmFilteredItemsSelectionDialog.this.refresh();
1428
                }
1429

  
1430
                return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK,
1431
                        EMPTY_STRING, null);
1432
            }
1433

  
1434
        }
1435

  
1436
        /**
1437
         * Refreshes the progress message cyclically with 500 milliseconds delay.
1438
         * <code>RefreshProgressMessageJob</code> is strictly connected with
1439
         * <code>GranualProgressMonitor</code> and use it to to get progress
1440
         * message and to decide about break of cyclical refresh.
1441
         */
1442
        private class RefreshProgressMessageJob extends UIJob {
1443

  
1444
            private GranualProgressMonitor progressMonitor;
1445

  
1446
            /**
1447
             * Creates a new instance of the class.
1448
             */
1449
            public RefreshProgressMessageJob() {
1450
                super(
1451
                        CdmFilteredItemsSelectionDialog.this.getParentShell()
1452
                                .getDisplay(),
1453
                        WorkbenchMessages.FilteredItemsSelectionDialog_progressRefreshJob);
1454
                setSystem(true);
1455
            }
1456

  
1457
            /*
1458
             * (non-Javadoc)
1459
             *
1460
             * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
1461
             */
1462
            @Override
1463
            public IStatus runInUIThread(IProgressMonitor monitor) {
1464

  
1465
                if (!progressLabel.isDisposed()) {
1466
                    progressLabel.setText(progressMonitor != null ? progressMonitor
1467
                            .getMessage() : EMPTY_STRING);
1468
                }
1469

  
1470
                if (progressMonitor == null || progressMonitor.isDone()) {
1471
                    return new Status(IStatus.CANCEL, PlatformUI.PLUGIN_ID,
1472
                            IStatus.CANCEL, EMPTY_STRING, null);
1473
                }
1474

  
1475
                // Schedule cyclical with 500 milliseconds delay
1476
                schedule(500);
1477

  
1478
                return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK,
1479
                        EMPTY_STRING, null);
1480
            }
1481

  
1482
            /**
1483
             * Schedule progress refresh job.
1484
             *
1485
             * @param progressMonitor
1486
             *            used during refresh progress label
1487
             */
1488
            public void scheduleProgressRefresh(
1489
                    GranualProgressMonitor progressMonitor) {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff