diff --git a/bundles/org.eclipse.e4.ui.dialogs/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.dialogs/META-INF/MANIFEST.MF
index 3be9ae16f8c..2a20ced09c4 100644
--- a/bundles/org.eclipse.e4.ui.dialogs/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.e4.ui.dialogs/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.e4.ui.dialogs
-Bundle-Version: 1.5.0.qualifier
+Bundle-Version: 1.6.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-Vendor: %providerName
Bundle-Localization: plugin
diff --git a/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/dialogs/filteredtree/FilteredTree.java b/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/dialogs/filteredtree/FilteredTree.java
index 383024c9c44..dab531baaaf 100644
--- a/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/dialogs/filteredtree/FilteredTree.java
+++ b/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/dialogs/filteredtree/FilteredTree.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014, 2020 vogella GmbH and others.
+ * Copyright (c) 2014, 2025 vogella GmbH and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -19,6 +19,7 @@
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.e4.ui.dialogs.textbundles.E4DialogMessages;
import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.AbstractFilteredViewerComposite;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.TreeViewer;
@@ -26,12 +27,8 @@
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
-import org.eclipse.swt.events.FocusAdapter;
-import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
@@ -49,14 +46,7 @@
*
* @since 1.2
*/
-public class FilteredTree extends Composite {
-
- /**
- * The filter text widget to be used by this tree. This value may be
- *
* Note: As of 4.13 not used anymore
* null
if there is no filter widget, or if the controls have
- * not yet been created.
- */
- private Text filterText;
+public class FilteredTree extends AbstractFilteredViewerCompositenull
- * .
- */
- private PatternFilter patternFilter;
-
- /**
- * The text to initially show in the filter text control.
- */
- private String initialText = ""; //$NON-NLS-1$
-
/**
* The job used to refresh the tree.
*/
private Job refreshJob;
- /**
- * Whether or not to show the filter controls (text and clear button). The
- * default is to show these controls.
- */
- private boolean showFilterControls;
-
private Composite treeComposite;
/**
@@ -102,12 +68,6 @@ public class FilteredTree extends Composite {
*/
private static final long SOFT_MAX_EXPAND_TIME = 200;
- /**
- * Time delay after which the search is triggered, acting as a debounce
- * mechanism.
- */
- private final long refreshJobDelayInMillis;
-
/**
* Default time for refresh job delay in ms
*/
@@ -124,8 +84,8 @@ public class FilteredTree extends Composite {
* @since 1.5
*/
public FilteredTree(Composite parent, int treeStyle, PatternFilter filter, long refreshDelayTime) {
- super(parent, SWT.NONE);
- this.refreshJobDelayInMillis = refreshDelayTime;
+ super(parent, SWT.NONE, refreshDelayTime);
+ this.parent = getParent();
init(treeStyle, filter);
}
@@ -148,52 +108,20 @@ public FilteredTree(Composite parent, int treeStyle, PatternFilter filter) {
* @see #init(int, PatternFilter)
*/
protected FilteredTree(Composite parent) {
- super(parent, SWT.NONE);
- this.refreshJobDelayInMillis = DEFAULT_REFRESH_TIME;
+ super(parent, SWT.NONE, DEFAULT_REFRESH_TIME);
}
- /**
- * Create the filtered tree.
- *
- * @param treeStyle
- * the style bits for the Tree
- * @param filter
- * the filter to be used
- *
- * @since 3.3
- */
+ @Override
protected void init(int treeStyle, PatternFilter filter) {
- patternFilter = filter;
setShowFilterControls(true);
- createControl(getParent(), treeStyle);
+ super.init(treeStyle, filter);
createRefreshJob();
setInitialText(E4DialogMessages.FilteredTree_FilterMessage);
- setFont(getParent().getFont());
}
- /**
- * Create the filtered tree's controls. Subclasses should override.
- */
+ @Override
protected void createControl(Composite parent, int treeStyle) {
- GridLayout layout = new GridLayout();
- layout.marginHeight = 0;
- layout.marginWidth = 0;
- setLayout(layout);
- setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
- filterComposite = new Composite(this, SWT.NONE);
-
- GridLayout filterLayout = new GridLayout();
- filterLayout.marginHeight = 0;
- filterLayout.marginWidth = 0;
- filterComposite.setLayout(filterLayout);
- filterComposite.setFont(parent.getFont());
-
- createFilterControls(filterComposite);
- GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
- filterComposite.setVisible(isShowFilterControls());
- gridData.exclude = !isShowFilterControls();
- filterComposite.setLayoutData(gridData);
+ super.createControl(parent, treeStyle);
treeComposite = new Composite(this, SWT.NONE);
GridLayout treeCompositeLayout = new GridLayout();
@@ -206,20 +134,6 @@ protected void createControl(Composite parent, int treeStyle) {
}
- /**
- * Create the filter controls. By default, a text and corresponding tool bar
- * button that clears the contents of the text is created. Subclasses may
- * override.
- *
- * @param parent
- * parent Composite
of the filter controls
- * @return the Composite
that contains the filter controls
- */
- protected Composite createFilterControls(Composite parent) {
- createFilterText(parent);
- return parent;
- }
-
/**
* Creates and set up the tree and tree viewer. This method calls
* {@link #doCreateTreeViewer(Composite, int)} to create the tree viewer.
@@ -239,9 +153,9 @@ protected Control createTreeControl(Composite parent, int style) {
treeViewer.getControl().setLayoutData(data);
treeViewer.getControl().addDisposeListener(e -> refreshJob.cancel());
if (treeViewer instanceof NotifyingTreeViewer) {
- patternFilter.setUseCache(true);
+ getPatternFilter().setUseCache(true);
}
- treeViewer.addFilter(patternFilter);
+ treeViewer.addFilter(getPatternFilter());
return treeViewer.getControl();
}
@@ -267,8 +181,8 @@ protected TreeViewer doCreateTreeViewer(Composite parent, int style) {
*/
private TreeItem getFirstMatchingItem(TreeItem[] items) {
for (TreeItem item : items) {
- if (patternFilter.isLeafMatch(treeViewer, item.getData())
- && patternFilter.isElementSelectable(item.getData())) {
+ if (getPatternFilter().isLeafMatch(treeViewer, item.getData())
+ && getPatternFilter().isElementSelectable(item.getData())) {
return item;
}
TreeItem treeItem = getFirstMatchingItem(item.getItems());
@@ -310,9 +224,9 @@ public IStatus runInUIThread(IProgressMonitor monitor) {
boolean initial = initialText != null && initialText.equals(text);
if (initial) {
- patternFilter.setPattern(null);
+ getPatternFilter().setPattern(null);
} else if (text != null) {
- patternFilter.setPattern(text);
+ getPatternFilter().setPattern(text);
}
Control redrawFalseControl = treeComposite != null ? treeComposite : treeViewer.getControl();
@@ -396,6 +310,10 @@ private boolean recursiveExpand(TreeItem[] items, IProgressMonitor monitor, long
};
}
+ /**
+ * @deprecated As of 4.13 not used anymore
+ */
+ @Deprecated(since = "2025-03", forRemoval = true)
protected void updateToolbar(boolean visible) {
// nothing to do
}
@@ -409,8 +327,9 @@ protected void updateToolbar(boolean visible) {
* @param parent
* Composite
of the filter text
*/
+ @Override
protected void createFilterText(Composite parent) {
- filterText = doCreateFilterText(parent);
+ super.createFilterText(parent);
filterText.getAccessible().addAccessibleListener(new AccessibleAdapter() {
@Override
public void getName(AccessibleEvent e) {
@@ -454,26 +373,6 @@ private int itemCount(TreeItem treeItem) {
}
});
- filterText.addFocusListener(new FocusAdapter() {
-
- @Override
- public void focusLost(FocusEvent e) {
- if (filterText.getText().equals(initialText)) {
- setFilterText(""); //$NON-NLS-1$
- textChanged();
- }
- }
- });
-
- filterText.addMouseListener(new MouseAdapter() {
- @Override
- public void mouseDown(MouseEvent e) {
- if (filterText.getText().equals(initialText)) {
- clearText();
- }
- }
- });
-
filterText.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
@@ -514,23 +413,9 @@ public void keyPressed(KeyEvent e) {
}
}
});
-
- filterText.addModifyListener(e -> textChanged());
-
- GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
- filterText.setLayoutData(gridData);
}
- /**
- * Creates the text control for entering the filter text. Subclasses may
- * override.
- *
- * @param parent
- * the parent composite
- * @return the text widget
- *
- * @since 3.3
- */
+ @Override
protected Text doCreateFilterText(Composite parent) {
return new Text(parent, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL | SWT.ICON_SEARCH);
}
@@ -539,9 +424,7 @@ protected Text doCreateFilterText(Composite parent) {
private boolean narrowingDown;
- /**
- * Update the receiver after the text has changed.
- */
+ @Override
protected void textChanged() {
narrowingDown = previousFilterText == null
|| previousFilterText.equals(E4DialogMessages.FilteredTree_FilterMessage)
@@ -552,18 +435,6 @@ protected void textChanged() {
refreshJob.schedule(getRefreshJobDelay());
}
- /**
- * Return the time delay that should be used when scheduling the filter
- * refresh job. Subclasses may override.
- *
- * @return a time delay in milliseconds before the job should run
- *
- * @since 3.5
- */
- protected long getRefreshJobDelay() {
- return refreshJobDelayInMillis;
- }
-
/**
* Set the background for the widgets that support the filter text area.
*
@@ -578,109 +449,16 @@ public void setBackground(Color background) {
}
}
- /**
- * Clears the text in the filter text widget.
- */
- protected void clearText() {
- setFilterText(""); //$NON-NLS-1$
- textChanged();
- }
-
- /**
- * Set the text in the filter control.
- */
- protected void setFilterText(String string) {
- if (filterText != null) {
- filterText.setText(string);
- selectAll();
- }
- }
-
- /**
- * Returns the pattern filter used by this tree.
- *
- * @return The pattern filter; never null
.
- */
+ @Override
public final PatternFilter getPatternFilter() {
- return patternFilter;
+ return (PatternFilter) super.getPatternFilter();
}
- /**
- * Get the tree viewer of the receiver.
- *
- * @return the tree viewer
- */
+ @Override
public TreeViewer getViewer() {
return treeViewer;
}
- /**
- * Get the filter text for the receiver, if it was created. Otherwise return
- * null
.
- *
- * @return the filter Text, or null if it was not created
- */
- public Text getFilterControl() {
- return filterText;
- }
-
- /**
- * Convenience method to return the text of the filter control. If the text
- * widget is not created, then null is returned.
- *
- * @return String in the text, or null if the text does not exist
- */
- protected String getFilterString() {
- return filterText != null ? filterText.getText() : null;
- }
-
- /**
- * Set the text that will be shown until the first focus. A default value is
- * provided, so this method only need be called if overriding the default
- * initial text is desired.
- *
- * @param text
- * initial text to appear in text field
- */
- public void setInitialText(String text) {
- initialText = text;
- if (filterText != null) {
- filterText.setMessage(text);
- if (filterText.isFocusControl()) {
- setFilterText(initialText);
- textChanged();
- } else {
- getDisplay().asyncExec(() -> {
- if (!filterText.isDisposed() && filterText.isFocusControl()) {
- setFilterText(initialText);
- textChanged();
- }
- });
- }
- } else {
- setFilterText(initialText);
- textChanged();
- }
- }
-
- /**
- * Select all text in the filter text field.
- */
- protected void selectAll() {
- if (filterText != null) {
- filterText.selectAll();
- }
- }
-
- /**
- * Get the initial text for the receiver.
- *
- * @return String
- */
- protected String getInitialText() {
- return initialText;
- }
-
/**
* Return a bold font if the given element matches the given pattern.
* Clients can opt to call this method from a Viewer's label provider to get
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractFilteredViewerComposite.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractFilteredViewerComposite.java
new file mode 100644
index 00000000000..c5618ccc13a
--- /dev/null
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractFilteredViewerComposite.java
@@ -0,0 +1,325 @@
+/*******************************************************************************
+ * Copyright (c) 2025 Patrick Ziegler and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Patrick Ziegler - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.viewers;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * @since 3.36
+ */
+public abstract class AbstractFilteredViewerCompositenull
.
+ */
+ private ViewerFilter patternFilter;
+
+ /**
+ * The filter text widget to be used by this tree. This value may be
+ * {@code null} if there is no filter widget, or if the controls have not yet
+ * been created.
+ */
+ protected Text filterText;
+
+ /**
+ * The Composite on which the filter controls are created. This is used to set
+ * the background color of the filter controls to match the surrounding
+ * controls.
+ */
+ protected Composite filterComposite;
+
+ /**
+ * Whether or not to show the filter controls (text and clear button). The
+ * default is to show these controls. This can be overridden by providing a
+ * setting in the product configuration file. For example, the setting to add to
+ * not show these controls in an 3x based application is:
+ *
+ * org.eclipse.ui/SHOW_FILTERED_TEXTS=false
+ */
+ protected boolean showFilterControls;
+
+ /**
+ * The text to initially show in the filter text control.
+ */
+ protected String initialText = ""; //$NON-NLS-1$
+
+ /**
+ * The parent composite of the filtered viewer.
+ */
+ protected Composite parent;
+
+ /**
+ * Time for refresh job delay in terms of expansion in long value
+ */
+ private final long refreshJobDelayInMillis;
+
+ /**
+ * Create a new instance of the receiver.
+ *
+ * @param parent a widget which will be the parent this
+ * composite
+ * @param style the style used to construct this widget
+ * @param refreshJobDelayInMillis refresh delay in ms, the time to expand the
+ * tree after debounce
+ */
+ public AbstractFilteredViewerComposite(Composite parent, int style, long refreshJobDelayInMillis) {
+ super(parent, style);
+ this.refreshJobDelayInMillis = refreshJobDelayInMillis;
+ }
+
+ /**
+ * Create the filtered viewer.
+ *
+ * @param style the style bits for the viewer's {@code Control}
+ * @param filter the filter to be used
+ */
+ protected void init(int style, T filter) {
+ patternFilter = filter;
+ createControl(parent, style);
+ setFont(parent.getFont());
+
+ }
+
+ /**
+ * Create the filtered viewer's controls. Subclasses should override.
+ *
+ * @param parent the parent
+ * @param style SWT style bits used to create the control
+ */
+ protected void createControl(Composite parent, int style) {
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ setLayout(layout);
+
+ if (parent.getLayout() instanceof GridLayout) {
+ setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ }
+
+ if (showFilterControls) {
+ filterComposite = new Composite(this, SWT.NONE);
+ GridLayout filterLayout = new GridLayout();
+ filterLayout.marginHeight = 0;
+ filterLayout.marginWidth = 0;
+ filterComposite.setLayout(filterLayout);
+ filterComposite.setFont(parent.getFont());
+
+ createFilterControls(filterComposite);
+ filterComposite.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
+ }
+ }
+
+ /**
+ * Create the filter controls. By default, a text and corresponding tool bar
+ * button that clears the contents of the text is created. Subclasses may
+ * override.
+ *
+ * @param parent parent Composite
of the filter controls
+ * @return the Composite
that contains the filter controls
+ */
+ protected Composite createFilterControls(Composite parent) {
+ createFilterText(parent);
+ return parent;
+ }
+
+ /**
+ * Creates the filter text and adds listeners. This method calls
+ * {@link #doCreateFilterText(Composite)} to create the text control. Subclasses
+ * should override {@link #doCreateFilterText(Composite)} instead of overriding
+ * this method.
+ *
+ * @param parent Composite
of the filter text
+ */
+ protected void createFilterText(Composite parent) {
+ filterText = doCreateFilterText(parent);
+
+ filterText.addFocusListener(new FocusAdapter() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ /*
+ * Running in an asyncExec because the selectAll() does not appear to work when
+ * using mouse to give focus to text.
+ */
+ Display display = filterText.getDisplay();
+ display.asyncExec(() -> {
+ if (!filterText.isDisposed()) {
+ if (getInitialText().equals(filterText.getText().trim())) {
+ filterText.selectAll();
+ }
+ }
+ });
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ if (filterText.getText().equals(initialText)) {
+ setFilterText(""); //$NON-NLS-1$
+ textChanged();
+ }
+ }
+ });
+
+ filterText.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ if (filterText.getText().equals(initialText)) {
+ // XXX: We cannot call clearText() due to
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=260664
+ setFilterText(""); //$NON-NLS-1$
+ textChanged();
+ }
+ }
+ });
+
+ filterText.addModifyListener(e -> textChanged());
+
+ GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
+ filterText.setLayoutData(gridData);
+ }
+
+ /**
+ * Creates the text control for entering the filter text. Subclasses may
+ * override.
+ *
+ * @param parent the parent composite
+ * @return the text widget
+ */
+ protected abstract Text doCreateFilterText(Composite parent);
+
+ /**
+ * Update the receiver after the text has changed.
+ */
+ protected abstract void textChanged();
+
+ /**
+ * Return the time delay that should be used when scheduling the filter refresh
+ * job. Subclasses may override.
+ *
+ * @return a time delay in milliseconds before the job should run
+ */
+ protected long getRefreshJobDelay() {
+ return refreshJobDelayInMillis;
+ }
+
+ /**
+ * Clears the text in the filter text widget.
+ */
+ protected void clearText() {
+ setFilterText(""); //$NON-NLS-1$
+ textChanged();
+ }
+
+ /**
+ * Set the text in the filter control.
+ *
+ * @param filterText the text to set.
+ */
+ protected void setFilterText(String filterText) {
+ if (this.filterText != null) {
+ this.filterText.setText(filterText);
+ selectAll();
+ }
+ }
+
+ /**
+ * Returns the pattern filter used by this tree.
+ *
+ * @return The pattern filter; never {@code null}.
+ */
+ public ViewerFilter getPatternFilter() {
+ return patternFilter;
+ }
+
+ /**
+ * Get the structured viewer of the receiver.
+ *
+ * @return the structured viewer
+ */
+ public abstract StructuredViewer getViewer();
+
+ /**
+ * Get the filter text for the receiver, if it was created. Otherwise return
+ * {@code null}.
+ *
+ * @return the filter Text, or null if it was not created
+ */
+ public Text getFilterControl() {
+ return filterText;
+ }
+
+ /**
+ * Convenience method to return the text of the filter control. If the text
+ * widget is not created, then null is returned.
+ *
+ * @return String in the text, or null if the text does not exist
+ */
+ protected String getFilterString() {
+ return filterText != null ? filterText.getText() : null;
+ }
+
+ /**
+ * Set the text that will be shown until the first focus. A default value is
+ * provided, so this method only need be called if overriding the default
+ * initial text is desired.
+ *
+ * @param text initial text to appear in text field
+ */
+ public void setInitialText(String text) {
+ initialText = text;
+ if (filterText != null) {
+ filterText.setMessage(text);
+ if (filterText.isFocusControl()) {
+ setFilterText(initialText);
+ textChanged();
+ } else {
+ getDisplay().asyncExec(() -> {
+ if (!filterText.isDisposed() && filterText.isFocusControl()) {
+ setFilterText(initialText);
+ textChanged();
+ }
+ });
+ }
+ } else {
+ setFilterText(initialText);
+ textChanged();
+ }
+ }
+
+ /**
+ * Select all text in the filter text field.
+ */
+ protected void selectAll() {
+ if (filterText != null) {
+ filterText.selectAll();
+ }
+ }
+
+ /**
+ * Get the initial text for the receiver.
+ *
+ * @return String
+ */
+ protected String getInitialText() {
+ return initialText;
+ }
+}
diff --git a/bundles/org.eclipse.ui.workbench/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.workbench/META-INF/MANIFEST.MF
index e80a10825d7..2e8dd48038b 100644
--- a/bundles/org.eclipse.ui.workbench/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.ui.workbench/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.ui.workbench; singleton:=true
-Bundle-Version: 3.134.100.qualifier
+Bundle-Version: 3.135.0.qualifier
Bundle-Activator: org.eclipse.ui.internal.WorkbenchPlugin
Bundle-ActivationPolicy: lazy
Bundle-Vendor: %providerName
diff --git a/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/dialogs/FilteredTree.java b/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/dialogs/FilteredTree.java
index 24e2d884217..f41a283ee63 100644
--- a/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/dialogs/FilteredTree.java
+++ b/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/dialogs/FilteredTree.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2015 IBM Corporation and others.
+ * Copyright (c) 2004, 2025 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -22,6 +22,7 @@
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.AbstractFilteredViewerComposite;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.TreeViewer;
@@ -29,13 +30,8 @@
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
-import org.eclipse.swt.events.FocusAdapter;
-import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
@@ -57,20 +53,16 @@
* @see org.eclipse.ui.dialogs.PatternFilter
* @since 3.2
*/
-public class FilteredTree extends Composite {
-
- /**
- * The filter text widget to be used by this tree. This value may be
- * null
if there is no filter widget, or if the controls have not
- * yet been created.
- */
- protected Text filterText;
+public class FilteredTree extends AbstractFilteredViewerComposite
null
.
- */
- private PatternFilter patternFilter;
-
- /**
- * The text to initially show in the filter text control.
- */
- protected String initialText = ""; //$NON-NLS-1$
-
/**
* The job used to refresh the tree.
*/
private Job refreshJob;
- /**
- * The parent composite of the filtered tree.
- *
- * @since 3.3
- */
- protected Composite parent;
-
- /**
- * Whether or not to show the filter controls (text and clear button). The
- * default is to show these controls. This can be overridden by providing a
- * setting in the product configuration file. The setting to add to not show
- * these controls is:
- *
- * org.eclipse.ui/SHOW_FILTERED_TEXTS=false
- */
- protected boolean showFilterControls;
-
/**
* @since 3.3
*/
@@ -147,11 +107,6 @@ public class FilteredTree extends Composite {
*/
private static final long SOFT_MAX_EXPAND_TIME = 200;
- /**
- * Time for refresh job delay in terms of expansion in long value
- */
- private final long refreshJobDelayInMillis;
-
/**
* Default time for refresh job delay in ms
*/
@@ -179,9 +134,8 @@ public class FilteredTree extends Composite {
* @since 3.116
*/
public FilteredTree(Composite parent, boolean useNewLook, boolean useFastHashLookup) {
- super(parent, SWT.NONE);
+ super(parent, SWT.NONE, DEFAULT_REFRESH_TIME);
this.parent = parent;
- this.refreshJobDelayInMillis = DEFAULT_REFRESH_TIME;
if (treeViewer != null) {
treeViewer.setUseHashlookup(useFastHashLookup);
}
@@ -225,9 +179,8 @@ public FilteredTree(Composite parent, int treeStyle, PatternFilter filter, boole
*/
public FilteredTree(Composite parent, int treeStyle, PatternFilter filter, boolean useNewLook,
boolean useFastHashLookup, long refreshJobDelayInMillis) {
- super(parent, SWT.NONE);
+ super(parent, SWT.NONE, refreshJobDelayInMillis);
this.parent = parent;
- this.refreshJobDelayInMillis = refreshJobDelayInMillis;
init(treeStyle, filter);
if (treeViewer != null) {
treeViewer.setUseHashlookup(useFastHashLookup);
@@ -257,8 +210,7 @@ public FilteredTree(Composite parent, int treeStyle, PatternFilter filter, boole
*/
@Deprecated
protected FilteredTree(Composite parent) {
- super(parent, SWT.NONE);
- this.refreshJobDelayInMillis = DEFAULT_REFRESH_TIME;
+ super(parent, SWT.NONE, DEFAULT_REFRESH_TIME);
this.parent = parent;
}
@@ -337,52 +289,18 @@ public FilteredTree(Composite parent, int treeStyle, PatternFilter filter, boole
this(parent, treeStyle, filter);
}
- /**
- * Create the filtered tree.
- *
- * @param treeStyle the style bits for the Tree
- * @param filter the filter to be used
- *
- * @since 3.3
- */
+ @Override
protected void init(int treeStyle, PatternFilter filter) {
- patternFilter = filter;
showFilterControls = PlatformUI.getPreferenceStore()
.getBoolean(IWorkbenchPreferenceConstants.SHOW_FILTERED_TEXTS);
- createControl(parent, treeStyle);
+ super.init(treeStyle, filter);
createRefreshJob();
setInitialText(WorkbenchMessages.FilteredTree_FilterMessage);
- setFont(parent.getFont());
-
}
- /**
- * Create the filtered tree's controls. Subclasses should override.
- *
- * @param parent the parent
- * @param treeStyle SWT style bits used to create the tree
- */
+ @Override
protected void createControl(Composite parent, int treeStyle) {
- GridLayout layout = new GridLayout();
- layout.marginHeight = 0;
- layout.marginWidth = 0;
- setLayout(layout);
-
- if (parent.getLayout() instanceof GridLayout) {
- setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- }
-
- if (showFilterControls) {
- filterComposite = new Composite(this, SWT.NONE);
- GridLayout filterLayout = new GridLayout();
- filterLayout.marginHeight = 0;
- filterLayout.marginWidth = 0;
- filterComposite.setLayout(filterLayout);
- filterComposite.setFont(parent.getFont());
-
- createFilterControls(filterComposite);
- filterComposite.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
- }
+ super.createControl(parent, treeStyle);
treeComposite = new Composite(this, SWT.NONE);
GridLayout treeCompositeLayout = new GridLayout();
@@ -394,19 +312,6 @@ protected void createControl(Composite parent, int treeStyle) {
createTreeControl(treeComposite, treeStyle);
}
- /**
- * Create the filter controls. By default, a text and corresponding tool bar
- * button that clears the contents of the text is created. Subclasses may
- * override.
- *
- * @param parent parent Composite
of the filter controls
- * @return the Composite
that contains the filter controls
- */
- protected Composite createFilterControls(Composite parent) {
- createFilterText(parent);
- return parent;
- }
-
/**
* Creates and set up the tree and tree viewer. This method calls
* {@link #doCreateTreeViewer(Composite, int)} to create the tree viewer.
@@ -423,9 +328,9 @@ protected Control createTreeControl(Composite parent, int style) {
treeViewer.getControl().setLayoutData(data);
treeViewer.getControl().addDisposeListener(e -> refreshJob.cancel());
if (treeViewer instanceof NotifyingTreeViewer) {
- patternFilter.setUseCache(true);
+ getPatternFilter().setUseCache(true);
}
- treeViewer.addFilter(patternFilter);
+ treeViewer.addFilter(getPatternFilter());
return treeViewer.getControl();
}
@@ -449,8 +354,8 @@ protected TreeViewer doCreateTreeViewer(Composite parent, int style) {
*/
private TreeItem getFirstMatchingItem(TreeItem[] items) {
for (TreeItem item : items) {
- if (patternFilter.isLeafMatch(treeViewer, item.getData())
- && patternFilter.isElementSelectable(item.getData())) {
+ if (getPatternFilter().isLeafMatch(treeViewer, item.getData())
+ && getPatternFilter().isElementSelectable(item.getData())) {
return item;
}
TreeItem treeItem = getFirstMatchingItem(item.getItems());
@@ -492,9 +397,9 @@ public IStatus runInUIThread(IProgressMonitor monitor) {
boolean initial = initialText != null && initialText.equals(text);
if (initial) {
- patternFilter.setPattern(null);
+ getPatternFilter().setPattern(null);
} else if (text != null) {
- patternFilter.setPattern(text);
+ getPatternFilter().setPattern(text);
}
Control redrawFalseControl = treeComposite != null ? treeComposite : treeViewer.getControl();
@@ -583,7 +488,9 @@ private boolean recursiveExpand(TreeItem[] items, IProgressMonitor monitor, long
* override.
*
* @param visible boolean
+ * @deprecated As of 4.13 not used anymore
*/
+ @Deprecated(since = "2025-03", forRemoval = true)
protected void updateToolbar(boolean visible) {
// nothing to do
}
@@ -596,8 +503,9 @@ protected void updateToolbar(boolean visible) {
*
* @param parent Composite
of the filter text
*/
+ @Override
protected void createFilterText(Composite parent) {
- filterText = doCreateFilterText(parent);
+ super.createFilterText(parent);
filterText.getAccessible().addAccessibleListener(new AccessibleAdapter() {
@Override
public void getName(AccessibleEvent e) {
@@ -641,44 +549,6 @@ private int itemCount(TreeItem treeItem) {
}
});
- filterText.addFocusListener(new FocusAdapter() {
- @Override
- public void focusGained(FocusEvent e) {
- /*
- * Running in an asyncExec because the selectAll() does not appear to work when
- * using mouse to give focus to text.
- */
- Display display = filterText.getDisplay();
- display.asyncExec(() -> {
- if (!filterText.isDisposed()) {
- if (getInitialText().equals(filterText.getText().trim())) {
- filterText.selectAll();
- }
- }
- });
- }
-
- @Override
- public void focusLost(FocusEvent e) {
- if (filterText.getText().equals(initialText)) {
- setFilterText(""); //$NON-NLS-1$
- textChanged();
- }
- }
- });
-
- filterText.addMouseListener(new MouseAdapter() {
- @Override
- public void mouseDown(MouseEvent e) {
- if (filterText.getText().equals(initialText)) {
- // XXX: We cannot call clearText() due to
- // https://bugs.eclipse.org/bugs/show_bug.cgi?id=260664
- setFilterText(""); //$NON-NLS-1$
- textChanged();
- }
- }
- });
-
filterText.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
@@ -701,11 +571,6 @@ public void keyPressed(KeyEvent e) {
updateTreeSelection(true);
}
});
-
- filterText.addModifyListener(e -> textChanged());
-
- GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
- filterText.setLayoutData(gridData);
}
/**
@@ -740,15 +605,7 @@ protected void updateTreeSelection(boolean setFocus) {
}
}
- /**
- * Creates the text control for entering the filter text. Subclasses may
- * override.
- *
- * @param parent the parent composite
- * @return the text widget
- *
- * @since 3.3
- */
+ @Override
protected Text doCreateFilterText(Composite parent) {
return new Text(parent, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL);
}
@@ -757,9 +614,7 @@ protected Text doCreateFilterText(Composite parent) {
private boolean narrowingDown;
- /**
- * Update the receiver after the text has changed.
- */
+ @Override
protected void textChanged() {
narrowingDown = previousFilterText == null
|| previousFilterText.equals(WorkbenchMessages.FilteredTree_FilterMessage)
@@ -770,114 +625,16 @@ protected void textChanged() {
refreshJob.schedule(getRefreshJobDelay());
}
- /**
- * Return the time delay that should be used when scheduling the filter refresh
- * job. Subclasses may override.
- *
- * @return a time delay in milliseconds before the job should run
- *
- * @since 3.5
- */
- protected long getRefreshJobDelay() {
- return refreshJobDelayInMillis;
- }
-
- /**
- * Set the background for the widgets that support the filter text area.
- *
- * @param background background Color
to set
- */
@Override
- public void setBackground(Color background) {
- super.setBackground(background);
- }
-
- /**
- * Clears the text in the filter text widget.
- */
- protected void clearText() {
- setFilterText(""); //$NON-NLS-1$
- textChanged();
- }
-
- /**
- * Set the text in the filter control.
- *
- * @param filterText the text to set.
- */
- protected void setFilterText(String filterText) {
- if (this.filterText != null) {
- this.filterText.setText(filterText);
- selectAll();
- }
- }
-
- /**
- * Returns the pattern filter used by this tree.
- *
- * @return The pattern filter; never null
.
- */
public final PatternFilter getPatternFilter() {
- return patternFilter;
+ return (PatternFilter) super.getPatternFilter();
}
- /**
- * Get the tree viewer of the receiver.
- *
- * @return the tree viewer
- */
+ @Override
public TreeViewer getViewer() {
return treeViewer;
}
- /**
- * Get the filter text for the receiver, if it was created. Otherwise return
- * null
.
- *
- * @return the filter Text, or null if it was not created
- */
- public Text getFilterControl() {
- return filterText;
- }
-
- /**
- * Convenience method to return the text of the filter control. If the text
- * widget is not created, then null is returned.
- *
- * @return String in the text, or null if the text does not exist
- */
- protected String getFilterString() {
- return filterText != null ? filterText.getText() : null;
- }
-
- /**
- * Set the text that will be shown until the first focus. A default value is
- * provided, so this method only need be called if overriding the default
- * initial text is desired.
- *
- * @param text initial text to appear in text field
- */
- public void setInitialText(String text) {
- initialText = text;
- if (filterText != null) {
- filterText.setMessage(text);
- if (filterText.isFocusControl()) {
- setFilterText(initialText);
- textChanged();
- } else {
- getDisplay().asyncExec(() -> {
- if (!filterText.isDisposed() && filterText.isFocusControl()) {
- setFilterText(initialText);
- textChanged();
- }
- });
- }
- } else {
- setFilterText(initialText);
- textChanged();
- }
- }
-
/**
* Sets whether this filtered tree is used to make quick selections. In this
* mode the first match in the tree is automatically selected while filtering
@@ -894,24 +651,6 @@ public void setQuickSelectionMode(boolean enabled) {
this.quickSelectionMode = enabled;
}
- /**
- * Select all text in the filter text field.
- */
- protected void selectAll() {
- if (filterText != null) {
- filterText.selectAll();
- }
- }
-
- /**
- * Get the initial text for the receiver.
- *
- * @return String
- */
- protected String getInitialText() {
- return initialText;
- }
-
/**
* Return a bold font if the given element matches the given pattern. Clients
* can opt to call this method from a Viewer's label provider to get a bold font