package org.bndtools.utils.swt; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; 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.Text; public class FilterPanelPart { private static final String PROP_FILTER = "filter"; private static final long SEARCH_DELAY = 1000; private final ScheduledExecutorService scheduler; private String filter; private Composite panel; private Text txtFilter; private final PropertyChangeSupport propSupport = new PropertyChangeSupport(this); private final Lock scheduledFilterLock = new ReentrantLock(); private final Runnable updateFilterTask = new Runnable() { @Override public void run() { Display display = panel.getDisplay(); Runnable update = new Runnable() { @Override public void run() { String newFilter = txtFilter.getText(); setFilter(newFilter); } }; if (display.getThread() == Thread.currentThread()) update.run(); else display.asyncExec(update); } }; private ScheduledFuture< ? > scheduledFilterUpdate = null; public FilterPanelPart(ScheduledExecutorService scheduler) { this.scheduler = scheduler; } public Control createControl(Composite parent) { return createControl(parent, 0, 0); } public Control createControl(Composite parent, int marginWidth, int marginHeight) { // CREATE CONTROLS panel = new Composite(parent, SWT.NONE); panel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); txtFilter = new Text(panel, SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL); txtFilter.setMessage("Enter search string"); // INITIAL PROPERTIES if (filter != null) txtFilter.setText(filter); // LAYOUT GridLayout layout = new GridLayout(2, false); layout.marginHeight = marginHeight; layout.marginWidth = marginWidth; panel.setLayout(layout); txtFilter.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); // LISTENERS txtFilter.addSelectionListener(new SelectionAdapter() { @Override public void widgetDefaultSelected(SelectionEvent ev) { try { scheduledFilterLock.lock(); if (scheduledFilterUpdate != null) scheduledFilterUpdate.cancel(true); } finally { scheduledFilterLock.unlock(); } String newFilter = (ev.detail == SWT.CANCEL) ? "" : txtFilter.getText(); setFilter(newFilter); } }); txtFilter.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent ev) { try { scheduledFilterLock.lock(); if (scheduledFilterUpdate != null) scheduledFilterUpdate.cancel(true); scheduledFilterUpdate = scheduler.schedule(updateFilterTask, SEARCH_DELAY, TimeUnit.MILLISECONDS); } finally { scheduledFilterLock.unlock(); } } }); return panel; } public Text getFilterControl() { return txtFilter; } public String getFilter() { return filter; } public void setFilter(String filter) { String old = this.filter; this.filter = filter; propSupport.firePropertyChange(PROP_FILTER, old, filter); } public void setFocus() { if (txtFilter != null && !txtFilter.isDisposed()) txtFilter.setFocus(); } public void addPropertyChangeListener(PropertyChangeListener listener) { propSupport.addPropertyChangeListener(PROP_FILTER, listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { propSupport.removePropertyChangeListener(PROP_FILTER, listener); } }