/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * This is a copy of FilteredItemsSelectionDialog without use of workbench and memento * * Contributors: * IBM Corporation - initial API and implementation * Willian Mitsuda <wmitsuda@gmail.com> * - Fix for bug 196553 - [Dialogs] Support IColorProvider/IFontProvider in FilteredItemsSelectionDialog * Peter Friese <peter.friese@gentleware.com> * - Fix for bug 208602 - [Dialogs] Open Type dialog needs accessible labels * Simon Muschel <smuschel@gmx.de> - bug 258493 * Peter Grube - fork for Gyrex Admin UI *******************************************************************************/ package org.eclipse.gyrex.admin.ui.internal.widgets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.eclipse.gyrex.admin.ui.internal.AdminUiActivator; import org.eclipse.gyrex.admin.ui.internal.AdminUiImages; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.ProgressMonitorWrapper; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.LegacyActionTools; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.viewers.CellLabelProvider; import org.eclipse.jface.viewers.ContentViewer; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.IFontProvider; import org.eclipse.jface.viewers.ILabelDecorator; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ILazyContentProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.osgi.util.NLS; import org.eclipse.rap.rwt.RWT; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.custom.ViewForm; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; /** * Shows a list of items to the user with a text entry field for a string * pattern used to filter the list of items. * * @since 1.1 */ public abstract class FilteredItemsSelectionDialog extends SelectionStatusDialog { /** * An interface to content providers for * <code>FilterItemsSelectionDialog</code>. */ protected abstract class AbstractContentProvider { /** * Adds the item to the content provider if the filter matches the item. * Otherwise does nothing. * * @param item * the item to add * @param itemsFilter * the filter * @see FilteredItemsSelectionDialog.ItemsFilter#matchItem(Object) */ public abstract void add(Object item, ItemsFilter itemsFilter); } /** * Collects filtered elements. Contains one synchronized, sorted set for * collecting filtered elements. All collected elements are sorted using * comparator. Comparator is returned by getElementComparator() method. * Implementation of <code>ItemsFilter</code> is used to filter elements. * The key function of filter used in to filtering is * <code>matchElement(Object item)</code>. * <p> * The <code>ContentProvider</code> class also provides item filtering * methods. The filtering has been moved from the standard TableView * <code>getFilteredItems()</code> method to content provider, because * <code>ILazyContentProvider</code> and virtual tables are used. This class * is responsible for adding a separator below history items and marking * each items as duplicate if its name repeats more than once on the * filtered list. */ private class ContentProvider extends AbstractContentProvider implements IStructuredContentProvider, ILazyContentProvider { /** serialVersionUID */ private static final long serialVersionUID = 1L; private SelectionHistory selectionHistory; /** * Raw result of the searching (unsorted, unfiltered). * <p> * Standard object flow: * <code>items -> lastSortedItems -> lastFilteredItems</code> */ private final Set<Object> items; /** * Items that are duplicates. */ private final Set<Object> duplicates; /** * List of <code>ViewerFilter</code>s to be used during filtering */ private List<ViewerFilter> filters; /** * Result of the last filtering. * <p> * Standard object flow: * <code>items -> lastSortedItems -> lastFilteredItems</code> */ private List<Object> lastFilteredItems; /** * Result of the last sorting. * <p> * Standard object flow: * <code>items -> lastSortedItems -> lastFilteredItems</code> */ private final List<Object> lastSortedItems; /** * Used for <code>getFilteredItems()</code> method canceling (when the * job that invoked the method was canceled). * <p> * Method canceling could be based (only) on monitor canceling * unfortunately sometimes the method <code>getFilteredElements()</code> * could be run with a null monitor, the <code>reset</code> flag have to * be left intact. */ private boolean reset; /** * Creates new instance of <code>ContentProvider</code>. */ public ContentProvider() { items = Collections.synchronizedSet(new HashSet<Object>(2048)); duplicates = Collections.synchronizedSet(new HashSet<Object>(256)); lastFilteredItems = new ArrayList<Object>(); lastSortedItems = Collections.synchronizedList(new ArrayList<Object>(2048)); } /** * Adds filtered item. * * @param item * @param itemsFilter */ @Override public void add(final Object item, final ItemsFilter itemsFilter) { if (itemsFilter == filter) { if (itemsFilter != null) { if (itemsFilter.matchItem(item)) { items.add(item); } } else { items.add(item); } } } /** * Adds a filter to this content provider. For an example usage of such * filters look at the project <code>org.eclipse.ui.ide</code>, class * <code>org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog.CustomWorkingSetFilter</code> * . * * @param filter * the filter to be added */ public void addFilter(final ViewerFilter filter) { if (filters == null) { filters = new ArrayList<ViewerFilter>(); } filters.add(filter); // currently filters are only added when dialog is restored // if it is changed, refreshing the whole TableViewer should be // added } /** * Adds item to history and refresh view. * * @param item * to add */ public void addHistoryElement(final Object item) { if (selectionHistory != null) { selectionHistory.accessed(item); } if ((filter == null) || !filter.matchItem(item)) { items.remove(item); duplicates.remove(item); lastSortedItems.remove(item); } synchronized (lastSortedItems) { Collections.sort(lastSortedItems, getHistoryComparator()); } refresh(); } /** * Add all history items to <code>contentProvider</code>. * * @param itemsFilter */ public void addHistoryItems(final ItemsFilter itemsFilter) { if (selectionHistory != null) { final Object[] items = selectionHistory.getHistoryItems(); for (final Object item : items) { if (itemsFilter == filter) { if (itemsFilter != null) { if (itemsFilter.matchItem(item)) { if (itemsFilter.isConsistentItem(item)) { this.items.add(item); } else { selectionHistory.remove(item); } } } } } } } private void checkDuplicates(final IProgressMonitor monitor) { synchronized (lastFilteredItems) { IProgressMonitor subMonitor = null; final int reportEvery = lastFilteredItems.size() / 20; if (monitor != null) { subMonitor = new SubProgressMonitor(monitor, 100); subMonitor.beginTask(WidgetMessages.get(display).FilteredItemsSelectionDialog_cacheRefreshJob_checkDuplicates, 5); } final HashMap<String, Object> helperMap = new HashMap<String, Object>(); for (int i = 0; i < lastFilteredItems.size(); i++) { if (reset || ((subMonitor != null) && subMonitor.isCanceled())) return; final Object item = lastFilteredItems.get(i); if (!(item instanceof ItemsListSeparator)) { final Object previousItem = helperMap.put(getElementName(item), item); if (previousItem != null) { setDuplicateElement(previousItem, true); setDuplicateElement(item, true); } else { setDuplicateElement(item, false); } } if ((subMonitor != null) && (reportEvery != 0) && (((i + 1) % reportEvery) == 0)) { subMonitor.worked(1); } } helperMap.clear(); } } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ @Override public void dispose() { } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) */ @Override public Object[] getElements(final Object inputElement) { return lastFilteredItems.toArray(); } /** * Returns an array of items filtered using the provided * <code>ViewerFilter</code>s with a separator added. * * @param parent * the parent * @param monitor * progress monitor, can be <code>null</code> * @return an array of filtered items */ protected Object[] getFilteredItems(final Object parent, IProgressMonitor monitor) { int ticks = 100; if (monitor == null) { monitor = new NullProgressMonitor(); } monitor.beginTask(WidgetMessages.get().FilteredItemsSelectionDialog_cacheRefreshJob_getFilteredElements, ticks); if (filters != null) { ticks /= filters.size() + 2; } else { ticks /= 2; } // get already sorted array Object[] filteredElements = getSortedItems(); monitor.worked(ticks); // filter the elements using provided ViewerFilters if ((filters != null) && (filteredElements != null)) { for (final ViewerFilter f : filters) { filteredElements = f.filter(list, parent, filteredElements); monitor.worked(ticks); } } if ((filteredElements == null) || monitor.isCanceled()) { monitor.done(); return new Object[0]; } final ArrayList<Object> preparedElements = new ArrayList<Object>(); boolean hasHistory = false; if (filteredElements.length > 0) { if (isHistoryElement(filteredElements[0])) { hasHistory = true; } } final int reportEvery = filteredElements.length / ticks; // add separator for (int i = 0; i < filteredElements.length; i++) { final Object item = filteredElements[i]; if (hasHistory && !isHistoryElement(item)) { preparedElements.add(itemsListSeparator); hasHistory = false; } preparedElements.add(item); if ((reportEvery != 0) && (((i + 1) % reportEvery) == 0)) { monitor.worked(1); } } monitor.done(); return preparedElements.toArray(); } public int getNumberOfElements() { return lastFilteredItems.size(); } /** * @return Returns the selectionHistory. */ public SelectionHistory getSelectionHistory() { return selectionHistory; } /** * Gets sorted items. * * @return sorted items */ private Object[] getSortedItems() { if (lastSortedItems.size() != items.size()) { synchronized (lastSortedItems) { lastSortedItems.clear(); lastSortedItems.addAll(items); Collections.sort(lastSortedItems, getHistoryComparator()); } } return lastSortedItems.toArray(); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, * java.lang.Object, java.lang.Object) */ @Override public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) { } /** * Indicates whether given item is a duplicate. * * @param item * item to check * @return <code>true</code> if item is duplicate */ public boolean isDuplicateElement(final Object item) { return duplicates.contains(item); } /** * @param item * @return <code>true</code> if given item is part of the history */ public boolean isHistoryElement(final Object item) { if (selectionHistory != null) return selectionHistory.contains(item); return false; } //[gyrex] we don't need memento in gyrex /** * Load history from memento. * * @param memento * memento from which the history will be retrieved */ // public void loadHistory(IMemento memento) { // if (selectionHistory != null) { // selectionHistory.load(memento); // } // } /** * Refresh dialog. */ public void refresh() { scheduleRefresh(); } /** * Main method responsible for getting the filtered items and checking * for duplicates. It is based on the * {@link FilteredItemsSelectionDialog.ContentProvider#getFilteredItems(Object, IProgressMonitor)} * . * * @param checkDuplicates * <code>true</code> if data concerning elements duplication * should be computed - it takes much more time than standard * filtering * @param monitor * progress monitor */ public void reloadCache(final boolean checkDuplicates, final IProgressMonitor monitor) { reset = false; if (monitor != null) { // the work is divided into two actions of the same length final int totalWork = checkDuplicates ? 200 : 100; monitor.beginTask(WidgetMessages.get(display).FilteredItemsSelectionDialog_cacheRefreshJob, totalWork); } // the TableViewer's root (the input) is treated as parent lastFilteredItems = Arrays.asList(getFilteredItems(list.getInput(), monitor != null ? new SubProgressMonitor(monitor, 100) : null)); if (reset || ((monitor != null) && monitor.isCanceled())) { if (monitor != null) { monitor.done(); } return; } if (checkDuplicates) { checkDuplicates(monitor); } if (monitor != null) { monitor.done(); } } /** * Remember result of filtering. * * @param itemsFilter */ public void rememberResult(final ItemsFilter itemsFilter) { final List<Object> itemsList = Collections.synchronizedList(Arrays.asList(getSortedItems())); // synchronization if (itemsFilter == filter) { lastCompletedFilter = itemsFilter; lastCompletedResult = itemsList; } } /** * Removes items from history and refreshes the view. * * @param item * to remove * @return removed item */ public Object removeHistoryElement(final Object item) { if (selectionHistory != null) { selectionHistory.remove(item); } if ((filter == null) || (filter.getPattern().length() == 0)) { items.remove(item); duplicates.remove(item); lastSortedItems.remove(item); } synchronized (lastSortedItems) { Collections.sort(lastSortedItems, getHistoryComparator()); } return item; } /** * Removes all content items and resets progress message. */ public void reset() { reset = true; items.clear(); duplicates.clear(); lastSortedItems.clear(); } //[gyrex] we don't need memento in gyrex /** * Save history to memento. * * @param memento * memento to which the history will be added */ // public void saveHistory(IMemento memento) { // if (selectionHistory != null) { // selectionHistory.save(memento); // } // } /** * Sets/unsets given item as duplicate. * * @param item * item to change * @param isDuplicate * duplicate flag */ public void setDuplicateElement(final Object item, final boolean isDuplicate) { if (items.contains(item)) { if (isDuplicate) { duplicates.add(item); } else { duplicates.remove(item); } } } /** * Sets selection history. * * @param selectionHistory * The selectionHistory to set. */ public void setSelectionHistory(final SelectionHistory selectionHistory) { this.selectionHistory = selectionHistory; } /** * Stops reloading cache - <code>getFilteredItems()</code> method. */ public void stopReloadingCache() { reset = true; } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.ILazyContentProvider#updateElement(int) */ @Override public void updateElement(final int index) { list.replace(lastFilteredItems.size() > index ? lastFilteredItems.get(index) : null, index); } } /** * DetailsContentViewer objects are wrappers for labels. * DetailsContentViewer provides means to change label's image and text when * the attached LabelProvider is updated. */ private class DetailsContentViewer extends ContentViewer { /** serialVersionUID */ private static final long serialVersionUID = 1L; private final CLabel label; /** * Unfortunately, it was impossible to delegate displaying border to * label. The <code>ViewForm</code> is used because <code>CLabel</code> * displays shadow when border is present. */ private final ViewForm viewForm; /** * Constructs a new instance of this class given its parent and a style * value describing its behavior and appearance. * * @param parent * the parent component * @param style * SWT style bits */ public DetailsContentViewer(final Composite parent, final int style) { viewForm = new ViewForm(parent, style); final GridData gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; viewForm.setLayoutData(gd); label = new CLabel(viewForm, SWT.FLAT); label.setFont(parent.getFont()); viewForm.setContent(label); hookControl(label); } /** * Sets the given text and image to the label. * * @param text * the new text or null * @param image * the new image */ private void doRefresh(String text, final Image image) { if (text != null) { text = LegacyActionTools.escapeMnemonics(text); } label.setText(text); label.setImage(image); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.Viewer#getControl() */ @Override public Control getControl() { return label; } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.Viewer#getSelection() */ @Override public ISelection getSelection() { // not supported return null; } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.ContentViewer#handleLabelProviderChanged(org.eclipse.jface.viewers.LabelProviderChangedEvent) */ @Override protected void handleLabelProviderChanged(final LabelProviderChangedEvent event) { if (event != null) { refresh(event.getElements()); } } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object, * java.lang.Object) */ @Override protected void inputChanged(final Object input, final Object oldInput) { if (oldInput == null) { if (input == null) return; refresh(); return; } refresh(); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.Viewer#refresh() */ @Override public void refresh() { final Object input = getInput(); if (input != null) { final ILabelProvider labelProvider = (ILabelProvider) getLabelProvider(); doRefresh(labelProvider.getText(input), labelProvider.getImage(input)); } else { doRefresh(null, null); } } /** * Refreshes the label if currently chosen element is on the list. * * @param objs * list of changed object */ private void refresh(final Object[] objs) { if ((objs == null) || (getInput() == null)) return; final Object input = getInput(); for (final Object obj : objs) { if (obj.equals(input)) { refresh(); break; } } } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.Viewer#setSelection(org.eclipse.jface.viewers.ISelection, * boolean) */ @Override public void setSelection(final ISelection selection, final boolean reveal) { // not supported } /** * Shows/hides the content viewer. * * @param visible * if the content viewer should be visible. */ public void setVisible(final boolean visible) { final GridData gd = (GridData) viewForm.getLayoutData(); gd.exclude = !visible; viewForm.getParent().layout(); } } /** * Filters items history and schedule filter job. */ private class FilterHistoryJob extends Job { /** * Filter used during the filtering process. */ private ItemsFilter itemsFilter; /** * Creates new instance of receiver. */ public FilterHistoryJob() { super(WidgetMessages.get().FilteredItemsSelectionDialog_jobLabel); setSystem(true); } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) */ @Override protected IStatus run(final IProgressMonitor monitor) { itemsFilter = filter; contentProvider.reset(); refreshWithLastSelection = false; contentProvider.addHistoryItems(itemsFilter); if (!((lastCompletedFilter != null) && lastCompletedFilter.isSubFilter(itemsFilter))) { contentProvider.refresh(); } filterJob.schedule(); return Status.OK_STATUS; } } /** * Filters items in indicated set and history. During filtering, it * refreshes the dialog (progress monitor and elements list). Depending on * the filter, <code>FilterJob</code> decides which kind of search will be * run inside <code>filterContent</code>. If the last filtering is done * (last completed filter), is not null, and the new filter is a sub-filter * ( * {@link FilteredItemsSelectionDialog.ItemsFilter#isSubFilter(FilteredItemsSelectionDialog.ItemsFilter)} * ) of the last, then <code>FilterJob</code> only filters in the cache. If * it is the first filtering or the new filter isn't a sub-filter of the * last one, a full search is run. */ private class FilterJob extends Job { /** * Filter used during the filtering process. */ protected ItemsFilter itemsFilter; /** * Creates new instance of FilterJob */ public FilterJob() { super(WidgetMessages.get().FilteredItemsSelectionDialog_jobLabel); setSystem(true); } /** * Executes job using the given filtering progress monitor. A hook for * subclasses. * * @param monitor * progress monitor * @return result of the execution */ protected IStatus doRun(final GranualProgressMonitor monitor) { try { internalRun(monitor); } catch (final CoreException e) { cancel(); return new Status(IStatus.ERROR, AdminUiActivator.SYMBOLIC_NAME, IStatus.ERROR, WidgetMessages.get(display).FilteredItemsSelectionDialog_jobError, e); } return Status.OK_STATUS; } /** * Filters items. * * @param monitor * for monitoring progress * @throws CoreException */ protected void filterContent(final GranualProgressMonitor monitor) throws CoreException { if ((lastCompletedFilter != null) && lastCompletedFilter.isSubFilter(itemsFilter)) { final int length = lastCompletedResult.size() / 500; monitor.beginTask(WidgetMessages.get(display).FilteredItemsSelectionDialog_cacheSearchJob_taskName, length); for (int pos = 0; pos < lastCompletedResult.size(); pos++) { final Object item = lastCompletedResult.get(pos); if (monitor.isCanceled()) { break; } contentProvider.add(item, itemsFilter); if ((pos % 500) == 0) { monitor.worked(1); } } } else { lastCompletedFilter = null; lastCompletedResult = null; SubProgressMonitor subMonitor = null; if (monitor != null) { monitor.beginTask(WidgetMessages.get(display).FilteredItemsSelectionDialog_searchJob_taskName, 100); subMonitor = new SubProgressMonitor(monitor, 95); } fillContentProvider(contentProvider, itemsFilter, subMonitor); if ((monitor != null) && !monitor.isCanceled()) { monitor.worked(2); contentProvider.rememberResult(itemsFilter); monitor.worked(3); } } } /** * Main method for the job. * * @param monitor * @throws CoreException */ private void internalRun(final GranualProgressMonitor monitor) throws CoreException { try { if (monitor.isCanceled()) return; itemsFilter = filter; if (filter.getPattern().length() != 0) { filterContent(monitor); } if (monitor.isCanceled()) return; contentProvider.refresh(); } finally { monitor.done(); } } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) */ @Override protected final IStatus run(final IProgressMonitor parent) { final GranualProgressMonitor monitor = new GranualProgressMonitor(parent); return doRun(monitor); } } /** * GranualProgressMonitor is used for monitoring progress of filtering * process. It is used by <code>RefreshProgressMessageJob</code> to refresh * progress message. State of this monitor illustrates state of filtering or * cache refreshing process. */ private class GranualProgressMonitor extends ProgressMonitorWrapper { private String name; private String subName; private int totalWork; private double worked; private boolean done; /** * Creates instance of <code>GranualProgressMonitor</code>. * * @param monitor * progress to be wrapped */ public GranualProgressMonitor(final IProgressMonitor monitor) { super(monitor); } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.ProgressMonitorWrapper#beginTask(java.lang.String, * int) */ @Override public void beginTask(final String name, final int totalWork) { super.beginTask(name, totalWork); if (name == null) { this.name = name; } this.totalWork = totalWork; refreshProgressMessageJob.scheduleProgressRefresh(this); } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.ProgressMonitorWrapper#done() */ @Override public void done() { done = true; super.done(); } private String getMessage() { if (done) return ""; //$NON-NLS-1$ String message; if (name == null) { message = subName == null ? "" : subName; //$NON-NLS-1$ } else { message = subName == null ? name : NLS.bind(WidgetMessages.get(display).FilteredItemsSelectionDialog_subtaskProgressMessage, new Object[] { name, subName }); } if (totalWork == 0) return message; return NLS.bind(WidgetMessages.get(display).FilteredItemsSelectionDialog_taskProgressMessage, new Object[] { message, new Integer((int) ((worked * 100) / totalWork)) }); } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.ProgressMonitorWrapper#internalWorked(double) */ @Override public void internalWorked(final double work) { worked = worked + work; } /** * Checks if filtering has been done * * @return true if filtering work has been done false in other way */ public boolean isDone() { return done; } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.ProgressMonitorWrapper#setCanceled(boolean) */ @Override public void setCanceled(final boolean b) { done = b; super.setCanceled(b); } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.ProgressMonitorWrapper#setTaskName(java.lang.String) */ @Override public void setTaskName(final String name) { super.setTaskName(name); this.name = name; subName = null; } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.ProgressMonitorWrapper#subTask(java.lang.String) */ @Override public void subTask(final String name) { super.subTask(name); subName = name; } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.ProgressMonitorWrapper#worked(int) */ @Override public void worked(final int work) { super.worked(work); internalWorked(work); } } /** * Compares items according to the history. */ private class HistoryComparator<T> implements Comparator { /* * (non-Javadoc) * * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ @Override public int compare(final Object o1, final Object o2) { if ((isHistoryElement(o1) && isHistoryElement(o2)) || (!isHistoryElement(o1) && !isHistoryElement(o2))) return getItemsComparator().compare(o1, o2); if (isHistoryElement(o1)) return -2; if (isHistoryElement(o2)) return +2; return 0; } } /** * Filters elements using SearchPattern by comparing the names of items with * the filter pattern. */ protected abstract class ItemsFilter { protected SearchPattern patternMatcher; /** * Creates new instance of ItemsFilter. */ public ItemsFilter() { this(new SearchPattern()); } /** * Creates new instance of ItemsFilter. * * @param searchPattern * the pattern to be used when filtering */ public ItemsFilter(final SearchPattern searchPattern) { patternMatcher = searchPattern; String stringPattern = ""; //$NON-NLS-1$ if (pattern != null/* && !pattern.getText().equals("*")*/) { stringPattern = pattern.getText(); } patternMatcher.setPattern(stringPattern); } /** * Checks whether the provided filter is equal to the current filter. * The default implementation checks if <code>SearchPattern</code> from * current filter is equal to the one from provided filter. * * @param filter * filter to be checked, or <code>null</code> * @return <code>true</code> if the given filter is equal to current * filter, <code>false</code> if given filter isn't equal to * current one or if it is <code>null</code> * @see org.eclipse.ui.dialogs.SearchPattern#equalsPattern(org.eclipse.ui.dialogs.SearchPattern) */ public boolean equalsFilter(final ItemsFilter filter) { if ((filter != null) && filter.patternMatcher.equalsPattern(patternMatcher)) return true; return false; } /** * Returns the rule to apply for matching keys. * * @return an implementation-specific match rule * @see SearchPattern#getMatchRule() for match rules returned by the * default implementation */ public int getMatchRule() { return patternMatcher.getMatchRule(); } /** * Returns the pattern string. * * @return pattern for this filter * @see SearchPattern#getPattern() */ public String getPattern() { return patternMatcher.getPattern(); } /** * Checks whether the pattern's match rule is camel case. * * @return <code>true</code> if pattern's match rule is camel case, * <code>false</code> otherwise */ public boolean isCamelCasePattern() { return patternMatcher.getMatchRule() == SearchPattern.RULE_CAMELCASE_MATCH; } /** * Checks consistency of an item. Item is inconsistent if was changed or * removed. * * @param item * @return <code>true</code> if item is consistent, <code>false</code> * if item is inconsistent */ public abstract boolean isConsistentItem(Object item); /** * Check if the given filter is a sub-filter of this filter. The default * implementation checks if the <code>SearchPattern</code> from the * given filter is a sub-pattern of the one from this filter. * <p> * <i>WARNING: This method is <b>not</b> defined in reading order, i.e. * <code>a.isSubFilter(b)</code> is <code>true</code> iff <code>b</code> * is a sub-filter of <code>a</code>, and not vice-versa. </i> * </p> * * @param filter * the filter to be checked, or <code>null</code> * @return <code>true</code> if the given filter is sub-filter of this * filter, <code>false</code> if the given filter isn't a * sub-filter or is <code>null</code> * @see org.eclipse.ui.dialogs.SearchPattern#isSubPattern(org.eclipse.ui.dialogs.SearchPattern) */ public boolean isSubFilter(final ItemsFilter filter) { if (filter != null) return patternMatcher.isSubPattern(filter.patternMatcher); return false; } /** * Matches text with filter. * * @param text * the text to match with the filter * @return <code>true</code> if text matches with filter pattern, * <code>false</code> otherwise */ protected boolean matches(final String text) { return patternMatcher.matches(text); } /** * General method for matching raw name pattern. Checks whether current * pattern is prefix of name provided item. * * @param item * item to check * @return <code>true</code> if current pattern is a prefix of name * provided item, <code>false</code> if item's name is shorter * than prefix or sequences of characters don't match. */ public boolean matchesRawNamePattern(final Object item) { final String prefix = patternMatcher.getPattern(); final String text = getElementName(item); if (text == null) return false; final int textLength = text.length(); final int prefixLength = prefix.length(); if (textLength < prefixLength) return false; for (int i = prefixLength - 1; i >= 0; i--) { if (Character.toLowerCase(prefix.charAt(i)) != Character.toLowerCase(text.charAt(i))) return false; } return true; } /** * Matches an item against filter conditions. * * @param item * @return <code>true<code> if item matches against filter conditions, <code>false</code> * otherwise */ public abstract boolean matchItem(Object item); } // RAP [rh] StyledCellLabelProvider not supported // private class ItemsListLabelProvider extends StyledCellLabelProvider private class ItemsListLabelProvider extends CellLabelProvider implements ILabelProviderListener { /** serialVersionUID */ private static final long serialVersionUID = 1L; private ILabelProvider provider; private ILabelDecorator selectionDecorator; // Need to keep our own list of listeners private final ListenerList listeners = new ListenerList(); /** * Creates a new instance of the class. * * @param provider * the label provider for all items, not <code>null</code> * @param selectionDecorator * the decorator for selected items, can be <code>null</code> */ public ItemsListLabelProvider(final ILabelProvider provider, final ILabelDecorator selectionDecorator) { Assert.isNotNull(provider); this.provider = provider; this.selectionDecorator = selectionDecorator; // RAP [rh] IStyledLabelProvider not supported // setOwnerDrawEnabled(provider instanceof IStyledLabelProvider); provider.addListener(this); if (selectionDecorator != null) { selectionDecorator.addListener(this); } } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener) */ @Override public void addListener(final ILabelProviderListener listener) { listeners.add(listener); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() */ @Override public void dispose() { provider.removeListener(this); provider.dispose(); if (selectionDecorator != null) { selectionDecorator.removeListener(this); selectionDecorator.dispose(); } super.dispose(); } private Color getBackground(final Object element) { if (element instanceof ItemsListSeparator) return null; if (provider instanceof IColorProvider) return ((IColorProvider) provider).getBackground(element); return null; } private Font getFont(final Object element) { if (element instanceof ItemsListSeparator) return null; if (provider instanceof IFontProvider) return ((IFontProvider) provider).getFont(element); return null; } private Color getForeground(final Object element) { if (element instanceof ItemsListSeparator) return Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW); if (provider instanceof IColorProvider) return ((IColorProvider) provider).getForeground(element); return null; } private Image getImage(final Object element) { if (element instanceof ItemsListSeparator) return AdminUiImages.getImage(AdminUiImages.IMG_VIEW_MENU); return provider.getImage(element); } // RAP [rh] IStyledLabelProvider not supported // private StyledString getStyledText(Object element, // IStyledLabelProvider provider) { // StyledString string = provider.getStyledText(element); // // if (selectionDecorator != null && isSelected(element)) { // String decorated = selectionDecorator.decorateText(string // .getString(), element); // return new StyledString(decorated); // // no need to add colors when element is selected // } // return string; // } /** * Gets selection decorator. * * @return the label decorator for selected items in the list */ public ILabelDecorator getSelectionDecorator() { return selectionDecorator; } private String getSeparatorLabel(final String separatorLabel) { final Rectangle rect = list.getTable().getBounds(); final int borderWidth = list.getTable().computeTrim(0, 0, 0, 0).width; final int imageWidth = AdminUiActivator.getInstance().getImageRegistry().get(AdminUiImages.IMG_VIEW_MENU).getBounds().width; final int width = rect.width - borderWidth - imageWidth; final GC gc = new GC(list.getTable()); gc.setFont(list.getTable().getFont()); //RAP [rh] GC#getAdvanceWidth missing // int fSeparatorWidth = gc.getAdvanceWidth('-'); final int fSeparatorWidth = gc.getCharWidth('-'); final int fMessageLength = gc.textExtent(separatorLabel).x; gc.dispose(); final StringBuffer dashes = new StringBuffer(); final int chars = ((width - fMessageLength) / fSeparatorWidth / 2) - 2; for (int i = 0; i < chars; i++) { dashes.append('-'); } final StringBuffer result = new StringBuffer(); result.append(dashes); result.append(" " + separatorLabel + " "); //$NON-NLS-1$//$NON-NLS-2$ result.append(dashes); return result.toString().trim(); } private String getText(final Object element) { if (element instanceof ItemsListSeparator) return getSeparatorLabel(((ItemsListSeparator) element).getName()); final String str = provider.getText(element); if ((selectionDecorator != null) && isSelected(element)) return selectionDecorator.decorateText(str.toString(), element); return str; } @Override public boolean isLabelProperty(final Object element, final String property) { if (provider.isLabelProperty(element, property)) return true; if ((selectionDecorator != null) && selectionDecorator.isLabelProperty(element, property)) return true; return false; } private boolean isSelected(final Object element) { if ((element != null) && (currentSelection != null)) { for (final Object element2 : currentSelection) { if (element.equals(element2)) return true; } } return false; } @Override public void labelProviderChanged(final LabelProviderChangedEvent event) { final Object[] l = listeners.getListeners(); for (int i = 0; i < listeners.size(); i++) { ((ILabelProviderListener) l[i]).labelProviderChanged(event); } } @Override public void removeListener(final ILabelProviderListener listener) { listeners.remove(listener); } /** * Sets new label provider. * * @param newProvider * new label provider for items in the list, not * <code>null</code> */ public void setProvider(final ILabelProvider newProvider) { Assert.isNotNull(newProvider); provider.removeListener(this); provider.dispose(); provider = newProvider; if (provider != null) { provider.addListener(this); } // RAP [rh] IStyledLabelProvider not supported // setOwnerDrawEnabled(provider instanceof IStyledLabelProvider); } /** * Sets new selection decorator. * * @param newSelectionDecorator * new label decorator for selected items in the list */ public void setSelectionDecorator(final ILabelDecorator newSelectionDecorator) { if (selectionDecorator != null) { selectionDecorator.removeListener(this); selectionDecorator.dispose(); } selectionDecorator = newSelectionDecorator; if (selectionDecorator != null) { selectionDecorator.addListener(this); } } @Override public void update(final ViewerCell cell) { final Object element = cell.getElement(); // RAP [rh] IStyledLabelProvider not supported // if (!(element instanceof ItemsListSeparator) // && provider instanceof IStyledLabelProvider) { // IStyledLabelProvider styledLabelProvider = (IStyledLabelProvider) provider; // StyledString styledString = getStyledText(element, // styledLabelProvider); // // cell.setText(styledString.getString()); // cell.setStyleRanges(styledString.getStyleRanges()); // cell.setImage(styledLabelProvider.getImage(element)); // } else { cell.setText(getText(element)); cell.setImage(getImage(element)); // } cell.setFont(getFont(element)); cell.setForeground(getForeground(element)); cell.setBackground(getBackground(element)); // RAP [rh] Obsolete because of changed inheritance // super.update(cell); } } /** * Used in ItemsListContentProvider, separates history and non-history * items. */ private class ItemsListSeparator { private final String name; /** * Creates a new instance of the class. * * @param name * the name of the separator */ public ItemsListSeparator(final String name) { this.name = name; } /** * Returns the name of this separator. * * @return the name of the separator */ public String getName() { return name; } } /** * A content provider that does nothing. */ private class NullContentProvider implements IContentProvider { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public void dispose() { } @Override public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) { } } /** * A job responsible for computing filtered items list presented using * <code>RefreshJob</code>. * * @see FilteredItemsSelectionDialog.RefreshJob */ private class RefreshCacheJob extends Job { private final RefreshJob refreshJob = new RefreshJob(); /** * Creates a new instance of the class. */ public RefreshCacheJob() { super(WidgetMessages.get().FilteredItemsSelectionDialog_cacheRefreshJob); setSystem(true); } /** * Stops the job and all sub-jobs. */ public void cancelAll() { cancel(); refreshJob.cancel(); } @Override protected void canceling() { super.canceling(); contentProvider.stopReloadingCache(); } @Override protected IStatus run(final IProgressMonitor monitor) { if (monitor.isCanceled()) return new Status(IStatus.CANCEL, AdminUiActivator.SYMBOLIC_NAME, IStatus.CANCEL, EMPTY_STRING, null); if (FilteredItemsSelectionDialog.this != null) { // RAP [if] fake context RWT.getUISession(display).exec(new Runnable() { @Override public void run() { final GranualProgressMonitor wrappedMonitor = new GranualProgressMonitor(monitor); reloadCache(true, wrappedMonitor); } }); } if (!monitor.isCanceled()) { refreshJob.schedule(); } return new Status(IStatus.OK, AdminUiActivator.SYMBOLIC_NAME, IStatus.OK, EMPTY_STRING, null); } } /** * Only refreshes UI on the basis of an already sorted and filtered set of * items. * <p> * Standard invocation scenario: * <ol> * <li>filtering job (<code>FilterJob</code> class extending * <code>Job</code> class)</li> * <li>cache refresh without checking for duplicates ( * <code>RefreshCacheJob</code> class extending <code>Job</code> class)</li> * <li>UI refresh (<code>RefreshJob</code> class extending * <code>UIJob</code> class)</li> * <li>cache refresh with checking for duplicates * (<cod>CacheRefreshJob</code> class extending <code>Job</code> class)</li> * <li>UI refresh (<code>RefreshJob</code> class extending * <code>UIJob</code> class)</li> * </ol> * The scenario is rather complicated, but it had to be applied, because: * <ul> * <li>refreshing cache is rather a long action and cannot be run in the UI * - cannot be run in a UIJob</li> * <li>refreshing cache checking for duplicates is twice as long as * refreshing cache without checking for duplicates; results of the search * could be displayed earlier</li> * <li>refreshing the UI have to be run in a UIJob</li> * </ul> * * @see org.eclipse.FilteredItemsSelectionDialog.dialogs.UpdatedFilteredItemsSelectionDialog.FilterJob * @see org.eclipse.FilteredItemsSelectionDialog.dialogs.UpdatedFilteredItemsSelectionDialog.RefreshJob * @see org.eclipse.FilteredItemsSelectionDialog.dialogs.UpdatedFilteredItemsSelectionDialog.RefreshCacheJob */ private class RefreshJob extends UiJob { /** * Creates a new instance of the class. */ public RefreshJob() { super(getParentShell().getDisplay(), WidgetMessages.get().FilteredItemsSelectionDialog_refreshJob); setSystem(true); } @Override public IStatus runInUIThread(final IProgressMonitor monitor) { if (monitor.isCanceled()) return new Status(IStatus.OK, AdminUiActivator.SYMBOLIC_NAME, IStatus.OK, EMPTY_STRING, null); if (FilteredItemsSelectionDialog.this != null) { refresh(); } return new Status(IStatus.OK, AdminUiActivator.SYMBOLIC_NAME, IStatus.OK, EMPTY_STRING, null); } } /** * Refreshes the progress message cyclically with 500 milliseconds delay. * <code>RefreshProgressMessageJob</code> is strictly connected with * <code>GranualProgressMonitor</code> and use it to to get progress message * and to decide about break of cyclical refresh. */ private class RefreshProgressMessageJob extends UiJob { private GranualProgressMonitor progressMonitor; /** * Creates a new instance of the class. */ public RefreshProgressMessageJob() { super(getParentShell().getDisplay(), WidgetMessages.get().FilteredItemsSelectionDialog_progressRefreshJob); setSystem(true); } @Override public IStatus runInUIThread(final IProgressMonitor monitor) { if (!progressLabel.isDisposed()) { progressLabel.setText(progressMonitor != null ? progressMonitor.getMessage() : EMPTY_STRING); } if ((progressMonitor == null) || progressMonitor.isDone()) return new Status(IStatus.CANCEL, AdminUiActivator.SYMBOLIC_NAME, IStatus.OK, EMPTY_STRING, null); // Schedule cyclical with 500 milliseconds delay schedule(500); return new Status(IStatus.OK, AdminUiActivator.SYMBOLIC_NAME, IStatus.OK, EMPTY_STRING, null); } /** * Schedule progress refresh job. * * @param progressMonitor * used during refresh progress label */ public void scheduleProgressRefresh(final GranualProgressMonitor progressMonitor) { this.progressMonitor = progressMonitor; // Schedule with initial delay to avoid flickering when the user // types quickly schedule(200); } } private class RemoveHistoryItemAction extends Action { /** serialVersionUID */ private static final long serialVersionUID = 1L; /** * Creates a new instance of the class. */ public RemoveHistoryItemAction() { super(WidgetMessages.get().FilteredItemsSelectionDialog_removeItemsFromHistoryAction); } /* * (non-Javadoc) * * @see org.eclipse.jface.action.Action#run() */ @Override public void run() { @SuppressWarnings("unchecked") final List<Object> selectedElements = ((StructuredSelection) list.getSelection()).toList(); removeSelectedItems(selectedElements); } } //[gyrex] we don't need history functions with memento /** * History stores a list of key, object pairs. The list is bounded at a * certain size. If the list exceeds this size the oldest element is removed * from the list. An element can be added/renewed with a call to * <code>accessed(Object)</code>. * <p> * The history can be stored to/loaded from an XML file. */ protected static abstract class SelectionHistory { private static final String DEFAULT_ROOT_NODE_NAME = "historyRootNode"; //$NON-NLS-1$ private static final String DEFAULT_INFO_NODE_NAME = "infoNode"; //$NON-NLS-1$ private static final int MAX_HISTORY_SIZE = 60; private final List<Object> historyList; // private final String rootNodeName; // private final String infoNodeName; /** * Creates new instance of <code>SelectionHistory</code>. */ public SelectionHistory() { this(DEFAULT_ROOT_NODE_NAME, DEFAULT_INFO_NODE_NAME); } private SelectionHistory(final String rootNodeName, final String infoNodeName) { historyList = Collections.synchronizedList(new LinkedList<Object>() { private static final long serialVersionUID = 0L; /* * (non-Javadoc) * * @see java.util.LinkedList#add(java.lang.Object) */ @Override public boolean add(final Object arg0) { if (size() >= MAX_HISTORY_SIZE) { removeFirst(); } if (!contains(arg0)) return super.add(arg0); return false; } }); // this.rootNodeName = rootNodeName; // this.infoNodeName = infoNodeName; } /** * Adds object to history. * * @param object * the item to be added to the history */ public synchronized void accessed(final Object object) { historyList.add(object); } /** * Returns <code>true</code> if history contains object. * * @param object * the item for which check will be executed * @return <code>true</code> if history contains object * <code>false</code> in other way */ public synchronized boolean contains(final Object object) { return historyList.contains(object); } /** * Gets array of history items. * * @return array of history elements */ public synchronized Object[] getHistoryItems() { return historyList.toArray(); } /** * Returns <code>true</code> if history is empty. * * @return <code>true</code> if history is empty */ public synchronized boolean isEmpty() { return historyList.isEmpty(); } /** * Load history elements from memento. * * @param memento * memento from which the history will be retrieved */ // public void load(IMemento memento) { // // XMLMemento historyMemento = (XMLMemento) memento.getChild(rootNodeName); // // if (historyMemento == null) { // return; // } // // IMemento[] mementoElements = historyMemento.getChildren(infoNodeName); // for (int i = 0; i < mementoElements.length; ++i) { // IMemento mementoElement = mementoElements[i]; // Object object = restoreItemFromMemento(mementoElement); // if (object != null) { // historyList.add(object); // } // } // } /** * Remove element from history. * * @param element * to remove form the history * @return <code>true</code> if this list contained the specified * element */ public synchronized boolean remove(final Object element) { return historyList.remove(element); } /** * Creates an object using given memento. * * @param memento * memento used for creating new object * @return the restored object */ // protected abstract Object restoreItemFromMemento(IMemento memento); /** * Save history elements to memento. * * @param memento * memento to which the history will be added */ // public void save(IMemento memento) { // // IMemento historyMemento = memento.createChild(rootNodeName); // // Object[] items = getHistoryItems(); // for (int i = 0; i < items.length; i++) { // Object item = items[i]; // IMemento elementMemento = historyMemento.createChild(infoNodeName); // storeItemToMemento(item, elementMemento); // } // // } /** * Store object in <code>IMemento</code>. * * @param item * the item to store * @param memento * the memento to store to */ // protected abstract void storeItemToMemento(Object item, IMemento memento); } private class ToggleStatusLineAction extends Action { /** serialVersionUID */ private static final long serialVersionUID = 1L; /** * Creates a new instance of the class. */ public ToggleStatusLineAction() { super(WidgetMessages.get().FilteredItemsSelectionDialog_toggleStatusAction, IAction.AS_CHECK_BOX); } @Override public void run() { details.setVisible(isChecked()); } } /** serialVersionUID */ private static final long serialVersionUID = 1L; private static final String DIALOG_BOUNDS_SETTINGS = "DialogBoundsSettings"; //$NON-NLS-1$ // private static final String SHOW_STATUS_LINE = "ShowStatusLine"; //no use in gyrex // private static final String HISTORY_SETTINGS = "History"; //we don't use history in gyrex private static final String DIALOG_HEIGHT = "DIALOG_HEIGHT"; //$NON-NLS-1$ private static final String DIALOG_WIDTH = "DIALOG_WIDTH"; //$NON-NLS-1$ /** * Represents an empty selection in the pattern input field (used only for * initial pattern). */ public static final int NONE = 0; /** * Pattern input field selection where caret is at the beginning (used only * for initial pattern). */ public static final int CARET_BEGINNING = 1; /** * Represents a full selection in the pattern input field (used only for * initial pattern). */ public static final int FULL_SELECTION = 2; // RAP [rh] display used to access NLS messages private final Display display; private Text pattern; private TableViewer list; private DetailsContentViewer details; /** * It is a duplicate of a field in the CLabel class in DetailsContentViewer. * It is maintained, because the <code>setDetailsLabelProvider()</code> * could be called before content area is created. */ private ILabelProvider detailsLabelProvider; private ItemsListLabelProvider itemsListLabelProvider; private MenuManager menuManager; private MenuManager contextMenuManager; private final boolean multi; private ToolBar toolBar; private ToolItem toolItem; private Label progressLabel; private ToggleStatusLineAction toggleStatusLineAction; // private IHandlerActivation showViewHandler; //we don't need this in gyrex private RemoveHistoryItemAction removeHistoryItemAction; private ActionContributionItem removeHistoryActionContributionItem; private IStatus status; private final RefreshCacheJob refreshCacheJob; private final RefreshProgressMessageJob refreshProgressMessageJob = new RefreshProgressMessageJob(); private Object[] currentSelection; private final ContentProvider contentProvider; private final FilterHistoryJob filterHistoryJob; private final FilterJob filterJob; private ItemsFilter filter; private List<Object> lastCompletedResult; private ItemsFilter lastCompletedFilter; private String initialPatternText; private int selectionMode; private ItemsListSeparator itemsListSeparator; private static final String EMPTY_STRING = ""; //$NON-NLS-1$ private boolean refreshWithLastSelection = false; /** * Creates a new instance of the class. Created dialog won't allow to select * more than one item. * * @param shell * shell to parent the dialog on */ public FilteredItemsSelectionDialog(final Shell shell) { this(shell, false); } /** * Creates a new instance of the class. * * @param shell * shell to parent the dialog on * @param multi * indicates whether dialog allows to select more than one * position in its list of items */ public FilteredItemsSelectionDialog(final Shell shell, final boolean multi) { super(shell); // RAP [rh] store display to access NLS messages display = shell.getDisplay(); this.multi = multi; filterHistoryJob = new FilterHistoryJob(); filterJob = new FilterJob(); contentProvider = new ContentProvider(); refreshCacheJob = new RefreshCacheJob(); itemsListSeparator = new ItemsListSeparator(WidgetMessages.get().FilteredItemsSelectionDialog_separatorLabel); selectionMode = NONE; } /** * Adds item to history. * * @param item * the item to be added */ protected void accessedHistoryItem(final Object item) { contentProvider.addHistoryElement(item); } /** * Adds viewer filter to the dialog items list. * * @param filter * the new filter */ protected void addListFilter(final ViewerFilter filter) { contentProvider.addFilter(filter); } /** * Applies the filter created by <code>createFilter()</code> method to the * items list. When new filter is different than previous one it will cause * refiltering. */ protected void applyFilter() { final ItemsFilter newFilter = createFilter(); // don't apply filtering for patterns which mean the same, for example: // *a**b and ***a*b if ((filter != null) && filter.equalsFilter(newFilter)) return; filterHistoryJob.cancel(); filterJob.cancel(); filter = newFilter; if (filter != null) { filterHistoryJob.schedule(); } } //[gyrex] we don't need handler and services /* * (non-Javadoc) * * @see org.eclipse.jface.window.Window#close() */ @Override public boolean close() { filterJob.cancel(); refreshCacheJob.cancel(); refreshProgressMessageJob.cancel(); // if (showViewHandler != null) { // final IHandlerService service = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class); // service.deactivateHandler(showViewHandler); // showViewHandler.getHandler().dispose(); // showViewHandler = null; // } if (menuManager != null) { menuManager.dispose(); } if (contextMenuManager != null) { contextMenuManager.dispose(); } // storeDialog(getDialogSettings()); return super.close(); } /* * (non-Javadoc) * * @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult() */ @SuppressWarnings("unchecked") @Override protected void computeResult() { final List<Object> selectedElements = ((StructuredSelection) list.getSelection()).toList(); final List<Object> objectsToReturn = new ArrayList<Object>(); Object item = null; for (final Iterator<Object> it = selectedElements.iterator(); it.hasNext();) { item = it.next(); if (!(item instanceof ItemsListSeparator)) { accessedHistoryItem(item); objectsToReturn.add(item); } } setResult(objectsToReturn); } /* * (non-Javadoc) * * @see org.eclipse.jface.window.Window#create() */ @Override public void create() { super.create(); pattern.setFocus(); } /* * (non-Javadoc) * * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) */ @Override protected Control createDialogArea(final Composite parent) { final Composite dialogArea = (Composite) super.createDialogArea(parent); final Composite content = new Composite(dialogArea, SWT.NONE); GridData gd = new GridData(GridData.FILL_BOTH); content.setLayoutData(gd); final GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginWidth = 0; layout.marginHeight = 0; content.setLayout(layout); // RAP [rh] workaround "unused variable" compile error // final Label headerLabel = createHeader(content); createHeader(content); pattern = new Text(content, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL); // RAP [rh] Accessibility API missing // pattern.getAccessible().addAccessibleListener(new AccessibleAdapter() { // public void getName(AccessibleEvent e) { // e.result = LegacyActionTools.removeMnemonics(headerLabel // .getText()); // } // }); gd = new GridData(GridData.FILL_HORIZONTAL); pattern.setLayoutData(gd); // RAP [rh] wor around "unused variable" compile error // final Label listLabel = createLabels(content); createLabels(content); list = new TableViewer(content, (multi ? SWT.MULTI : SWT.SINGLE) | SWT.BORDER | SWT.V_SCROLL | SWT.VIRTUAL); // RAP [rh] Accessibility API missing // list.getTable().getAccessible().addAccessibleListener( // new AccessibleAdapter() { // public void getName(AccessibleEvent e) { // e.result = LegacyActionTools.removeMnemonics(listLabel // .getText()); // } // }); list.setContentProvider(contentProvider); list.setLabelProvider(getItemsListLabelProvider()); list.setInput(new Object[0]); list.setItemCount(contentProvider.getNumberOfElements()); gd = new GridData(GridData.FILL_BOTH); applyDialogFont(list.getTable()); gd.heightHint = list.getTable().getItemHeight() * 15; list.getTable().setLayoutData(gd); createPopupMenu(); pattern.addModifyListener(new ModifyListener() { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public void modifyText(final ModifyEvent e) { applyFilter(); } }); // RAP [rh] Key events missing // pattern.addKeyListener(new KeyAdapter() { // public void keyPressed(KeyEvent e) { // if (e.keyCode == SWT.ARROW_DOWN) { // if (list.getTable().getItemCount() > 0) { // list.getTable().setFocus(); // } // } // } // }); list.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(final SelectionChangedEvent event) { final StructuredSelection selection = (StructuredSelection) event.getSelection(); handleSelected(selection); } }); list.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(final DoubleClickEvent event) { handleDoubleClick(); } }); // RAP [rh] missing key events // list.getTable().addKeyListener(new KeyAdapter() { // public void keyPressed(KeyEvent e) { // // if (e.keyCode == SWT.DEL) { // // List selectedElements = ((StructuredSelection) list // .getSelection()).toList(); // // Object item = null; // boolean isSelectedHistory = true; // // for (Iterator it = selectedElements.iterator(); it // .hasNext();) { // item = it.next(); // if (item instanceof ItemsListSeparator // || !isHistoryElement(item)) { // isSelectedHistory = false; // break; // } // } // if (isSelectedHistory) // removeSelectedItems(selectedElements); // // } // // if (e.keyCode == SWT.ARROW_UP && (e.stateMask & SWT.SHIFT) != 0 // && (e.stateMask & SWT.CTRL) != 0) { // StructuredSelection selection = (StructuredSelection) list // .getSelection(); // // if (selection.size() == 1) { // Object element = selection.getFirstElement(); // if (element.equals(list.getElementAt(0))) { // pattern.setFocus(); // } // if (list.getElementAt(list.getTable() // .getSelectionIndex() - 1) instanceof ItemsListSeparator) // list.getTable().setSelection( // list.getTable().getSelectionIndex() - 1); // list.getTable().notifyListeners(SWT.Selection, // new Event()); // // } // } // // if (e.keyCode == SWT.ARROW_DOWN // && (e.stateMask & SWT.SHIFT) != 0 // && (e.stateMask & SWT.CTRL) != 0) { // // if (list // .getElementAt(list.getTable().getSelectionIndex() + 1) instanceof ItemsListSeparator) // list.getTable().setSelection( // list.getTable().getSelectionIndex() + 1); // list.getTable().notifyListeners(SWT.Selection, new Event()); // } // // } // }); createExtendedContentArea(content); details = new DetailsContentViewer(content, SWT.BORDER | SWT.FLAT); details.setVisible(toggleStatusLineAction.isChecked()); details.setContentProvider(new NullContentProvider()); details.setLabelProvider(getDetailsLabelProvider()); applyDialogFont(content); // restoreDialog(getDialogSettings()); if (initialPatternText != null) { pattern.setText(initialPatternText); } switch (selectionMode) { case CARET_BEGINNING: pattern.setSelection(0, 0); break; case FULL_SELECTION: pattern.setSelection(0, initialPatternText.length()); break; } // apply filter even if pattern is empty (display history) applyFilter(); return dialogArea; } /** * Creates an extra content area, which will be located above the details. * * @param parent * parent to create the dialog widgets in * @return an extra content area */ protected abstract Control createExtendedContentArea(Composite parent); /** * Creates an instance of a filter. * * @return a filter for items on the items list. Can be <code>null</code>, * no filtering will be applied then, causing no item to be shown in * the list. */ protected abstract ItemsFilter createFilter(); /** * Create a new header which is labelled by headerLabel. * * @param parent * @return Label the label of the header */ private Label createHeader(final Composite parent) { final Composite header = new Composite(parent, SWT.NONE); final GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginWidth = 0; layout.marginHeight = 0; header.setLayout(layout); final Label headerLabel = new Label(header, SWT.NONE); headerLabel.setText((getMessage() != null) && (getMessage().trim().length() > 0) ? getMessage() : WidgetMessages.get().FilteredItemsSelectionDialog_patternLabel); // RAP [rh] Traverse events missing // headerLabel.addTraverseListener(new TraverseListener() { // public void keyTraversed(TraverseEvent e) { // if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) { // e.detail = SWT.TRAVERSE_NONE; // pattern.setFocus(); // } // } // }); final GridData gd = new GridData(GridData.FILL_HORIZONTAL); headerLabel.setLayoutData(gd); createViewMenu(header); header.setLayoutData(gd); return headerLabel; } /** * Create the labels for the list and the progress. Return the list label. * * @param parent * @return Label */ private Label createLabels(final Composite parent) { final Composite labels = new Composite(parent, SWT.NONE); final GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginWidth = 0; layout.marginHeight = 0; labels.setLayout(layout); final Label listLabel = new Label(labels, SWT.NONE); listLabel.setText(WidgetMessages.get().FilteredItemsSelectionDialog_listLabel); // RAP [rh] Traverse events missing // listLabel.addTraverseListener(new TraverseListener() { // public void keyTraversed(TraverseEvent e) { // if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) { // e.detail = SWT.TRAVERSE_NONE; // list.getTable().setFocus(); // } // } // }); final GridData gd = new GridData(GridData.FILL_HORIZONTAL); listLabel.setLayoutData(gd); progressLabel = new Label(labels, SWT.RIGHT); progressLabel.setLayoutData(gd); labels.setLayoutData(gd); return listLabel; } private void createPopupMenu() { removeHistoryItemAction = new RemoveHistoryItemAction(); removeHistoryActionContributionItem = new ActionContributionItem(removeHistoryItemAction); contextMenuManager = new MenuManager(); contextMenuManager.setRemoveAllWhenShown(true); contextMenuManager.addMenuListener(new IMenuListener() { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public void menuAboutToShow(final IMenuManager manager) { fillContextMenu(manager); } }); final Table table = list.getTable(); final Menu menu = contextMenuManager.createContextMenu(table); table.setMenu(menu); } private void createViewMenu(final Composite parent) { toolBar = new ToolBar(parent, SWT.FLAT); toolItem = new ToolItem(toolBar, SWT.PUSH, 0); final GridData data = new GridData(); data.horizontalAlignment = GridData.END; toolBar.setLayoutData(data); toolBar.addMouseListener(new MouseAdapter() { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public void mouseDown(final MouseEvent e) { showViewMenu(); } }); toolItem.setImage(AdminUiActivator.getInstance().getImageRegistry().get(AdminUiImages.IMG_VIEW_MENU)); toolItem.setToolTipText(WidgetMessages.get().FilteredItemsSelectionDialog_menu); toolItem.addSelectionListener(new SelectionAdapter() { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public void widgetSelected(final SelectionEvent e) { showViewMenu(); } }); menuManager = new MenuManager(); fillViewMenu(menuManager); //[gyrex] we don't need handler and services in gyrex // final IHandlerService service = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class); // final IHandler handler = new AbstractHandler() { //// public Object execute(final ExecutionEvent event) { //// showViewMenu(); //// return null; //// } // // @Override // public Object execute(final ExecutionEvent event) throws ExecutionException { // showViewMenu(); // return null; // } // }; // showViewHandler = service.activateHandler(IWorkbenchCommandConstants.WINDOW_SHOW_VIEW_MENU, handler, new ActiveShellExpression(getShell())); } /** * Fills the content provider with matching items. * * @param contentProvider * collector to add items to. * {@link FilteredItemsSelectionDialog.AbstractContentProvider#add(Object, FilteredItemsSelectionDialog.ItemsFilter)} * only adds items that pass the given <code>itemsFilter</code>. * @param itemsFilter * the items filter * @param progressMonitor * must be used to report search progress. The state of this * progress monitor reflects the state of the filtering process. * @throws CoreException */ protected abstract void fillContentProvider(AbstractContentProvider contentProvider, ItemsFilter itemsFilter, IProgressMonitor progressMonitor) throws CoreException; /** * Hook that allows to add actions to the context menu. * <p> * Subclasses may extend in order to add other actions. * </p> * * @param menuManager * the context menu manager * @since 1.4 */ @SuppressWarnings("unchecked") protected void fillContextMenu(final IMenuManager menuManager) { final List<Object> selectedElements = ((StructuredSelection) list.getSelection()).toList(); Object item = null; for (final Iterator<Object> it = selectedElements.iterator(); it.hasNext();) { item = it.next(); if ((item instanceof ItemsListSeparator) || !isHistoryElement(item)) return; } if (selectedElements.size() > 0) { removeHistoryItemAction.setText(WidgetMessages.get().FilteredItemsSelectionDialog_removeItemsFromHistoryAction); menuManager.add(removeHistoryActionContributionItem); } } /** * Fills the menu of the dialog. * * @param menuManager * the menu manager */ protected void fillViewMenu(final IMenuManager menuManager) { toggleStatusLineAction = new ToggleStatusLineAction(); menuManager.add(toggleStatusLineAction); } private ILabelProvider getDetailsLabelProvider() { if (detailsLabelProvider == null) { detailsLabelProvider = new LabelProvider(); } return detailsLabelProvider; } /* * (non-Javadoc) * * @see org.eclipse.jface.window.Dialog#getDialogBoundsSettings() */ @Override protected IDialogSettings getDialogBoundsSettings() { final IDialogSettings settings = getDialogSettings(); IDialogSettings section = settings.getSection(DIALOG_BOUNDS_SETTINGS); if (section == null) { section = settings.addNewSection(DIALOG_BOUNDS_SETTINGS); section.put(DIALOG_HEIGHT, 500); section.put(DIALOG_WIDTH, 600); } return section; } /** * Returns the dialog settings. Returned object can't be null. * * @return return dialog settings for this dialog */ protected abstract IDialogSettings getDialogSettings(); /** * Returns name for then given object. * * @param item * an object from the content provider. Subclasses should pay * attention to the passed argument. They should either only pass * objects of a known type (one used in content provider) or make * sure that passed parameter is the expected one (by type * checking like <code>instanceof</code> inside the method). * @return name of the given item */ public abstract String getElementName(Object item); /** * Returns a history comparator. * * @return decorated comparator */ @SuppressWarnings("unchecked") private Comparator<Object> getHistoryComparator() { return new HistoryComparator<Object>(); } /** * Gets initial pattern. * * @return initial pattern, or <code>null</code> if initial pattern is not * set */ protected String getInitialPattern() { return initialPatternText; } /** * Returns comparator to sort items inside content provider. Returned object * will be probably created as an anonymous class. Parameters passed to the * <code>compare(java.lang.Object, java.lang.Object)</code> are going to be * the same type as the one used in the content provider. * * @return comparator to sort items content provider */ protected abstract Comparator<Object> getItemsComparator(); /** * Returns the item list label provider. * * @return the item list label provider */ private ItemsListLabelProvider getItemsListLabelProvider() { if (itemsListLabelProvider == null) { itemsListLabelProvider = new ItemsListLabelProvider(new LabelProvider(), null); } return itemsListLabelProvider; } /** * Returns the label decorator for selected items in the list. * * @return the label decorator for selected items in the list */ private ILabelDecorator getListSelectionLabelDecorator() { return getItemsListLabelProvider().getSelectionDecorator(); } /** * Get the control where the search pattern is entered. Any filtering should * be done using an {@link ItemsFilter}. This control should only be * accessed for listeners that wish to handle events that do not affect * filtering such as custom traversal. * * @return Control or <code>null</code> if the pattern control has not been * created. */ public Control getPatternControl() { return pattern; } /** * Returns the current selection. * * @return the current selection */ @SuppressWarnings("unchecked") protected StructuredSelection getSelectedItems() { final StructuredSelection selection = (StructuredSelection) list.getSelection(); final List<Object> selectedItems = selection.toList(); Object itemToRemove = null; for (final Iterator it = selection.iterator(); it.hasNext();) { final Object item = it.next(); if (item instanceof ItemsListSeparator) { itemToRemove = item; break; } } if (itemToRemove == null) return new StructuredSelection(selectedItems); // Create a new selection without the collision final List<Object> newItems = new ArrayList<Object>(selectedItems); newItems.remove(itemToRemove); return new StructuredSelection(newItems); } /** * Returns the history of selected elements. * * @return history of selected elements, or <code>null</code> if it is not * set */ protected SelectionHistory getSelectionHistory() { return contentProvider.getSelectionHistory(); } /** * This method is a hook for subclasses to override default dialog behavior. * The <code>handleDoubleClick()</code> method handles double clicks on the * list of filtered elements. * <p> * Current implementation makes double-clicking on the list do the same as * pressing <code>OK</code> button on the dialog. */ protected void handleDoubleClick() { okPressed(); } /** * Handle selection in the items list by updating labels of selected and * unselected items and refresh the details field using the selection. * * @param selection * the new selection */ @SuppressWarnings("unchecked") protected void handleSelected(final StructuredSelection selection) { IStatus status = new Status(IStatus.OK, AdminUiActivator.SYMBOLIC_NAME, IStatus.OK, EMPTY_STRING, null); final Object[] lastSelection = currentSelection; currentSelection = selection.toArray(); if (selection.size() == 0) { status = new Status(IStatus.ERROR, AdminUiActivator.SYMBOLIC_NAME, IStatus.ERROR, EMPTY_STRING, null); if ((lastSelection != null) && (getListSelectionLabelDecorator() != null)) { list.update(lastSelection, null); } currentSelection = null; } else { status = new Status(IStatus.ERROR, AdminUiActivator.SYMBOLIC_NAME, IStatus.ERROR, EMPTY_STRING, null); final List<Object> items = selection.toList(); Object item = null; IStatus tempStatus = null; for (final Object o : items) { if (o instanceof ItemsListSeparator) { continue; } item = o; tempStatus = validateItem(item); if (tempStatus.isOK()) { status = new Status(IStatus.OK, AdminUiActivator.SYMBOLIC_NAME, IStatus.OK, EMPTY_STRING, null); } else { status = tempStatus; // if any selected element is not valid status is set to // ERROR break; } } if ((lastSelection != null) && (getListSelectionLabelDecorator() != null)) { list.update(lastSelection, null); } if (getListSelectionLabelDecorator() != null) { list.update(currentSelection, null); } } refreshDetails(); updateStatus(status); } /** * Indicates whether the given item is a duplicate. * * @param item * the item to be investigated * @return <code>true</code> if the item is duplicate, <code>false</code> * otherwise */ public boolean isDuplicateElement(final Object item) { return contentProvider.isDuplicateElement(item); } /** * Indicates whether the given item is a history item. * * @param item * the item to be investigated * @return <code>true</code> if the given item exists in history, * <code>false</code> otherwise */ public boolean isHistoryElement(final Object item) { return contentProvider.isHistoryElement(item); } /* * @see Dialog#okPressed() */ @Override protected void okPressed() { if ((status != null) && (status.isOK() || (status.getCode() == IStatus.INFO))) { super.okPressed(); } } /** * Refreshes the dialog - has to be called in UI thread. */ @SuppressWarnings("unchecked") public void refresh() { if ((list != null) && !list.getTable().isDisposed()) { final List<Object> lastRefreshSelection = ((StructuredSelection) list.getSelection()).toList(); list.getTable().deselectAll(); list.setItemCount(contentProvider.getNumberOfElements()); list.refresh(); if (list.getTable().getItemCount() > 0) { // preserve previous selection if (refreshWithLastSelection && (lastRefreshSelection != null) && (lastRefreshSelection.size() > 0)) { list.setSelection(new StructuredSelection(lastRefreshSelection)); } else { refreshWithLastSelection = true; list.getTable().setSelection(0); list.getTable().notifyListeners(SWT.Selection, new Event()); } } else { list.setSelection(StructuredSelection.EMPTY); } } scheduleProgressMessageRefresh(); } /** * Refreshes the details field according to the current selection in the * items list. */ private void refreshDetails() { final StructuredSelection selection = getSelectedItems(); switch (selection.size()) { case 0: details.setInput(null); break; case 1: details.setInput(selection.getFirstElement()); break; default: details.setInput(NLS.bind(WidgetMessages.get().FilteredItemsSelectionDialog_nItemsSelected, new Integer(selection.size()))); break; } } /** * Notifies the content provider - fires filtering of content provider * elements. During the filtering, a separator between history and workspace * matches is added. * <p> * This is a long running operation and should be called in a job. * * @param checkDuplicates * <code>true</code> if data concerning elements duplication * should be computed - it takes much more time than the standard * filtering * @param monitor * a progress monitor or <code>null</code> if no monitor is * available */ public void reloadCache(final boolean checkDuplicates, final IProgressMonitor monitor) { if ((list != null) && !list.getTable().isDisposed() && (contentProvider != null)) { contentProvider.reloadCache(checkDuplicates, monitor); } } /** * Removes an item from history. * * @param item * an item to remove * @return removed item */ protected Object removeHistoryItem(final Object item) { return contentProvider.removeHistoryElement(item); } /** * Removes selected items from history. * * @param items * items to be removed */ private void removeSelectedItems(final List<Object> items) { for (final Object item : items) { removeHistoryItem(item); } refreshWithLastSelection = false; contentProvider.refresh(); } //[gyrex] we don't need history with memento in gyrex /** * Restores dialog using persisted settings. The default implementation * restores the status of the details line and the selection history. * * @param settings * settings used to restore dialog */ // protected void restoreDialog(final IDialogSettings settings) { // boolean toggleStatusLine = true; // // if (settings.get(SHOW_STATUS_LINE) != null) { // toggleStatusLine = settings.getBoolean(SHOW_STATUS_LINE); // } // // toggleStatusLineAction.setChecked(toggleStatusLine); // // details.setVisible(toggleStatusLine); // // final String setting = settings.get(HISTORY_SETTINGS); // if (setting != null) { //// try { ////// IMemento memento = XMLMemento.createReadRoot(new StringReader(setting)); ////// contentProvider.loadHistory(memento); //// } catch (WorkbenchException e) { //// // Simply don't restore the settings //// StatusManager.getManager().handle(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR, FilteredItemsSelectionDialog_restoreError, e)); //// } // } // } /** * Schedules progress message refresh. */ public void scheduleProgressMessageRefresh() { if ((filterJob.getState() != Job.RUNNING) && (refreshProgressMessageJob.getState() != Job.RUNNING)) { refreshProgressMessageJob.scheduleProgressRefresh(null); } } // RAP [bm] not used // private static boolean showColoredLabels() { // return PlatformUI.getPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.USE_COLORED_LABELS); // } /** * Schedule refresh job. */ public void scheduleRefresh() { // RAP [rh] fake context RWT.getUISession(display).exec(new Runnable() { @Override public void run() { refreshCacheJob.cancelAll(); refreshCacheJob.schedule(); } }); } /** * Sets label provider for the details field. For a single selection, the * element sent to {@link ILabelProvider#getImage(Object)} and * {@link ILabelProvider#getText(Object)} is the selected object, for * multiple selection a {@link String} with amount of selected items is the * element. * * @see #getSelectedItems() getSelectedItems() can be used to retrieve * selected items and get the items count. * @param detailsLabelProvider * the label provider for the details field */ public void setDetailsLabelProvider(final ILabelProvider detailsLabelProvider) { this.detailsLabelProvider = detailsLabelProvider; if (details != null) { details.setLabelProvider(detailsLabelProvider); } } /** * Sets the initial pattern used by the filter. This text is copied into the * selection input on the dialog. A full selection is used in the pattern * input field. * * @param text * initial pattern for the filter * @see FilteredItemsSelectionDialog#FULL_SELECTION */ public void setInitialPattern(final String text) { setInitialPattern(text, FULL_SELECTION); } /** * Sets the initial pattern used by the filter. This text is copied into the * selection input on the dialog. The <code>selectionMode</code> is used to * choose selection type for the input field. * * @param text * initial pattern for the filter * @param selectionMode * one of: {@link FilteredItemsSelectionDialog#NONE}, * {@link FilteredItemsSelectionDialog#CARET_BEGINNING}, * {@link FilteredItemsSelectionDialog#FULL_SELECTION} */ public void setInitialPattern(final String text, final int selectionMode) { initialPatternText = text; this.selectionMode = selectionMode; } // RAP [rh] JavaDoc: IStyledLabelProvider not supported /** * Sets a new label provider for items in the list. <!-- If the label * provider also implements * {@link org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider} * , the style text labels provided by it will be used. --> * * @param listLabelProvider * the label provider for items in the list */ public void setListLabelProvider(final ILabelProvider listLabelProvider) { getItemsListLabelProvider().setProvider(listLabelProvider); } /** * Sets the label decorator for selected items in the list. * * @param listSelectionLabelDecorator * the label decorator for selected items in the list */ public void setListSelectionLabelDecorator(final ILabelDecorator listSelectionLabelDecorator) { getItemsListLabelProvider().setSelectionDecorator(listSelectionLabelDecorator); } /** * Sets new history. * * @param selectionHistory * the history */ protected void setSelectionHistory(final SelectionHistory selectionHistory) { if (contentProvider != null) { contentProvider.setSelectionHistory(selectionHistory); } } /** * Sets separator label * * @param separatorLabel * the label showed on separator */ public void setSeparatorLabel(final String separatorLabel) { itemsListSeparator = new ItemsListSeparator(separatorLabel); } private void showViewMenu() { final Menu menu = menuManager.createContextMenu(getShell()); final Rectangle bounds = toolItem.getBounds(); Point topLeft = new Point(bounds.x, bounds.y + bounds.height); topLeft = toolBar.toDisplay(topLeft); menu.setLocation(topLeft.x, topLeft.y); menu.setVisible(true); } //[gyrex] we don't need history with memento in gyrex /** * Stores dialog settings. * * @param settings * settings used to store dialog */ // protected void storeDialog(final IDialogSettings settings) { // settings.put(SHOW_STATUS_LINE, toggleStatusLineAction.isChecked()); // //// XMLMemento memento = XMLMemento.createWriteRoot(HISTORY_SETTINGS); //// contentProvider.saveHistory(memento); // final StringWriter writer = new StringWriter(); //// try { //// memento.save(writer); // settings.put(HISTORY_SETTINGS, writer.getBuffer().toString()); //// } catch (IOException e) { //// // Simply don't store the settings //// StatusManager.getManager().handle(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR, FilteredItemsSelectionDialog_storeError, e)); //// } // } /** * Updates the progress label. * * @deprecated */ @Deprecated public void updateProgressLabel() { scheduleProgressMessageRefresh(); } /* * @see org.eclipse.ui.dialogs.SelectionStatusDialog#updateStatus(org.eclipse.core.runtime.IStatus) */ @Override protected void updateStatus(final IStatus status) { this.status = status; super.updateStatus(status); } /** * Validates the item. When items on the items list are selected or * deselected, it validates each item in the selection and the dialog status * depends on all validations. * * @param item * an item to be checked * @return status of the dialog to be set */ protected abstract IStatus validateItem(Object item); }