| /******************************************************************************* |
| * Copyright (c) 2004, 2009 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 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Jacek Pospychala - bug 187762 |
| * Mohamed Tarief - tarief@eg.ibm.com - IBM - Bug 174481 |
| * Tasktop Technologies - generalized filter code for structured viewers |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.p2.ui.discovery.util; |
| |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.equinox.internal.p2.ui.discovery.wizards.Messages; |
| import org.eclipse.jface.layout.GridDataFactory; |
| import org.eclipse.jface.layout.GridLayoutFactory; |
| import org.eclipse.jface.viewers.StructuredViewer; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.*; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.*; |
| import org.eclipse.ui.progress.WorkbenchJob; |
| |
| /** |
| * Based on {@link org.eclipse.ui.dialogs.FilteredTree}. |
| * |
| * @author Steffen Pingel |
| */ |
| public abstract class FilteredViewer { |
| |
| private boolean automaticFind; |
| |
| private Label clearFilterTextControl; |
| |
| private Composite container; |
| |
| TextSearchControl filterText; |
| |
| private int minimumHeight; |
| |
| String previousFilterText = ""; //$NON-NLS-1$ |
| |
| WorkbenchJob refreshJob; |
| |
| private long refreshJobDelay = 200L; |
| |
| private PatternFilter searchFilter; |
| |
| protected StructuredViewer viewer; |
| |
| private Composite header; |
| |
| public FilteredViewer() { |
| setAutomaticFind(true); |
| } |
| |
| void clearFilterText() { |
| filterText.getTextControl().setText(""); //$NON-NLS-1$ |
| filterTextChanged(); |
| } |
| |
| public void createControl(Composite parent) { |
| container = new Composite(parent, SWT.NONE); |
| GridLayoutFactory.fillDefaults().margins(0, 0).applyTo(container); |
| container.addDisposeListener(new DisposeListener() { |
| public void widgetDisposed(DisposeEvent e) { |
| if (refreshJob != null) { |
| refreshJob.cancel(); |
| } |
| } |
| }); |
| |
| doCreateHeader(); |
| |
| viewer = doCreateViewer(container); |
| searchFilter = doCreateFilter(); |
| viewer.addFilter(searchFilter); |
| GridDataFactory.fillDefaults().grab(true, true).hint(SWT.DEFAULT, minimumHeight).applyTo(viewer.getControl()); |
| } |
| |
| protected PatternFilter doCreateFilter() { |
| return new PatternFilter() { |
| @Override |
| protected boolean isParentMatch(Viewer viewer, Object element) { |
| return false; |
| } |
| }; |
| } |
| |
| private void doCreateFindControl(Composite parent) { |
| Label label = new Label(parent, SWT.NONE); |
| label.setText(Messages.ConnectorDiscoveryWizardMainPage_filterLabel); |
| GridDataFactory.swtDefaults().align(SWT.BEGINNING, SWT.CENTER).applyTo(label); |
| |
| filterText = new TextSearchControl(parent, automaticFind); |
| if (automaticFind) { |
| filterText.addModifyListener(new ModifyListener() { |
| public void modifyText(ModifyEvent e) { |
| filterTextChanged(); |
| } |
| }); |
| } else { |
| filterText.getTextControl().addTraverseListener(new TraverseListener() { |
| public void keyTraversed(TraverseEvent e) { |
| if (e.detail == SWT.TRAVERSE_RETURN) { |
| e.doit = false; |
| filterTextChanged(); |
| } |
| } |
| }); |
| } |
| filterText.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetDefaultSelected(SelectionEvent e) { |
| if (e.detail == SWT.ICON_CANCEL) { |
| clearFilterText(); |
| } else { |
| // search icon and enter |
| filterTextChanged(); |
| } |
| } |
| }); |
| GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(filterText); |
| } |
| |
| private void doCreateHeader() { |
| header = new Composite(container, SWT.NONE); |
| GridLayoutFactory.fillDefaults().applyTo(header); |
| GridDataFactory.fillDefaults().grab(true, false).applyTo(header); |
| |
| doCreateFindControl(header); |
| doCreateHeaderControls(header); |
| |
| // arrange all header controls horizontally |
| GridLayoutFactory.fillDefaults().numColumns(header.getChildren().length).applyTo(header); |
| } |
| |
| protected void doCreateHeaderControls(Composite parent) { |
| // ignore |
| } |
| |
| public void setHeaderVisible(boolean visible) { |
| if (header != null && visible != header.getVisible()) { |
| header.setVisible(visible); |
| GridData headerLayout = (GridData) header.getLayoutData(); |
| headerLayout.exclude = !visible; |
| container.layout(true, true); |
| } |
| } |
| |
| public boolean isHeaderVisible() { |
| return header != null && header.getVisible(); |
| } |
| |
| protected WorkbenchJob doCreateRefreshJob() { |
| return new WorkbenchJob("filter") { //$NON-NLS-1$ |
| @Override |
| public IStatus runInUIThread(IProgressMonitor monitor) { |
| if (filterText.isDisposed()) { |
| return Status.CANCEL_STATUS; |
| } |
| String text = filterText.getTextControl().getText(); |
| text = text.trim(); |
| |
| if (!previousFilterText.equals(text)) { |
| previousFilterText = text; |
| doFind(text); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| } |
| |
| protected abstract StructuredViewer doCreateViewer(Composite parent); |
| |
| protected void doFind(String text) { |
| searchFilter.setPattern(text); |
| if (clearFilterTextControl != null) { |
| clearFilterTextControl.setVisible(text != null && text.length() != 0); |
| } |
| viewer.refresh(true); |
| } |
| |
| /** |
| * Invoked whenever the filter text is changed or the user otherwise causes the filter text to change. |
| */ |
| protected void filterTextChanged() { |
| if (refreshJob == null) { |
| refreshJob = doCreateRefreshJob(); |
| } else { |
| refreshJob.cancel(); |
| } |
| refreshJob.schedule(refreshJobDelay); |
| } |
| |
| /** |
| * Provides the text string of the search widget. |
| */ |
| protected String getFilterText() { |
| return filterText == null ? null : filterText.getTextControl().getText(); |
| } |
| |
| public Control getControl() { |
| return container; |
| } |
| |
| public int getMinimumHeight() { |
| return minimumHeight; |
| } |
| |
| protected long getRefreshJobDelay() { |
| return refreshJobDelay; |
| } |
| |
| public StructuredViewer getViewer() { |
| return viewer; |
| } |
| |
| public void setMinimumHeight(int minimumHeight) { |
| this.minimumHeight = minimumHeight; |
| if (viewer != null) { |
| GridDataFactory.fillDefaults().grab(true, true).hint(SWT.DEFAULT, minimumHeight).applyTo(viewer.getControl()); |
| } |
| } |
| |
| protected void setRefreshJobDelay(long refreshJobDelay) { |
| this.refreshJobDelay = refreshJobDelay; |
| } |
| |
| public final void setAutomaticFind(boolean automaticFind) { |
| if (filterText != null) { |
| throw new IllegalStateException("setAutomaticFind() needs be invoked before controls are created"); //$NON-NLS-1$ |
| } |
| this.automaticFind = automaticFind; |
| } |
| |
| public final boolean isAutomaticFind() { |
| return automaticFind; |
| } |
| |
| } |