diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/dlcl16/select_next.png b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/dlcl16/select_next.png
new file mode 100644
index 00000000000..1a71a7923a9
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/dlcl16/select_next.png differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/dlcl16/select_prev.png b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/dlcl16/select_prev.png
new file mode 100644
index 00000000000..7eaaff97987
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/dlcl16/select_prev.png differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/elcl16/select_next.png b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/elcl16/select_next.png
new file mode 100644
index 00000000000..9fcc646d92b
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/elcl16/select_next.png differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/elcl16/select_prev.png b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/elcl16/select_prev.png
new file mode 100644
index 00000000000..f2e6a039c5d
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/elcl16/select_prev.png differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/case_sensitive.png b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/case_sensitive.png
new file mode 100644
index 00000000000..7be33cd83c8
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/case_sensitive.png differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/close_replace.png b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/close_replace.png
new file mode 100644
index 00000000000..018dc33f6fe
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/close_replace.png differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/open_replace.png b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/open_replace.png
new file mode 100644
index 00000000000..c6aeae4d462
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/open_replace.png differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/regex_gear.gif b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/regex_gear.gif
new file mode 100644
index 00000000000..81fb7b4a39d
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/regex_gear.gif differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/replace.png b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/replace.png
new file mode 100644
index 00000000000..d9a07e503ef
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/replace.png differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/replace_all.png b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/replace_all.png
new file mode 100644
index 00000000000..b6af9dbf57b
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/replace_all.png differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/search_all.png b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/search_all.png
new file mode 100644
index 00000000000..997b0545b89
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/search_all.png differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/whole_word.png b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/whole_word.png
new file mode 100644
index 00000000000..bd2eacec42d
Binary files /dev/null and b/bundles/org.eclipse.ui.workbench.texteditor/icons/full/obj16/whole_word.png differ
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/FindReplaceLogicFindAllStatus.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/FindReplaceLogicFindAllStatus.java
new file mode 100644
index 00000000000..379d1c6c954
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/FindReplaceLogicFindAllStatus.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2023 Vector Informatik GmbH 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:
+ * Vector Informatik GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ui.internal.findandreplace;
+
+public class FindReplaceLogicFindAllStatus implements IFindReplaceLogicStatus {
+ private int selectCount;
+
+ public FindReplaceLogicFindAllStatus(int selectCount) {
+ if (selectCount <= 0) {
+ // invalid value - what to do? Throw an exception?! @HeikoKlare
+ }
+ this.selectCount = selectCount;
+ }
+
+ public int getSelectCount() {
+ return selectCount;
+ }
+
+ @Override
+ public
- * It can also be used without having an IWorkbenchPart e.g. for
- * dialogs or wizards by just providing a {@link Shell} and an {@link IFindReplaceTarget}.
- * In this case the dialog won't be shared with the one
- * used for the active workbench part.
+ * It can also be used without having an IWorkbenchPart e.g. for dialogs or
+ * wizards by just providing a {@link Shell} and an {@link IFindReplaceTarget}.
+ * In this case the dialog won't be shared with the one used for the active
+ * workbench part.
*
* This class may be instantiated; it is not intended to be subclassed.
@@ -54,16 +55,23 @@
*/
public class FindReplaceAction extends ResourceAction implements IUpdate {
+ private static boolean shouldShowModernOverlay() {
+ IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode("org.eclipse.e4.ui.workbench.renderers.swt"); //$NON-NLS-1$
+ return preferences.getBoolean("USE_FIND_REPLACE_OVERLAY", true);
+ }
+
/**
- * Represents the "global" find/replace dialog. It tracks the active
- * part and retargets the find/replace dialog accordingly. The find/replace
- * target is retrieved from the active part using
+ * Represents the "global" find/replace dialog. It tracks the active part and
+ * retargets the find/replace dialog accordingly. The find/replace target is
+ * retrieved from the active part using
*
- * The stub has the same life cycle as the find/replace dialog.getAdapter(IFindReplaceTarget.class)
.
*
- * If no IWorkbenchPart is available a Shell must be provided - * In this case the IFindReplaceTarget will never change.
+ * If no IWorkbenchPart is available a Shell must be provided In this case the + * IFindReplaceTarget will never change. + * */ static class FindReplaceDialogStub implements IPartListener2, IPageChangedListener, DisposeListener { @@ -86,8 +94,8 @@ static class FindReplaceDialogStub implements IPartListener2, IPageChangedListen */ public FindReplaceDialogStub(IWorkbenchPartSite site) { this(site.getShell()); - fWindow= site.getWorkbenchWindow(); - IPartService service= fWindow.getPartService(); + fWindow = site.getWorkbenchWindow(); + IPartService service = fWindow.getPartService(); service.addPartListener(this); partActivated(service.getActivePart()); } @@ -99,7 +107,7 @@ public FindReplaceDialogStub(IWorkbenchPartSite site) { * @since 3.3 */ public FindReplaceDialogStub(Shell shell) { - fDialog= new FindReplaceDialog(shell); + fDialog = new FindReplaceDialog(shell); fDialog.create(); fDialog.getShell().addDisposeListener(this); } @@ -114,19 +122,19 @@ public FindReplaceDialog getDialog() { } private void partActivated(IWorkbenchPart part) { - IFindReplaceTarget target= part == null ? null : part.getAdapter(IFindReplaceTarget.class); - fPreviousPart= fPart; - fPart= target == null ? null : part; + IFindReplaceTarget target = part == null ? null : part.getAdapter(IFindReplaceTarget.class); + fPreviousPart = fPart; + fPart = target == null ? null : part; if (fPreviousTarget != target) { - fPreviousTarget= target; + fPreviousTarget = target; if (fDialog != null) { - boolean isEditable= false; + boolean isEditable = false; if (fPart instanceof ITextEditorExtension2) { - ITextEditorExtension2 extension= (ITextEditorExtension2) fPart; - isEditable= extension.isEditorInputModifiable(); + ITextEditorExtension2 extension = (ITextEditorExtension2) fPart; + isEditable = extension.isEditorInputModifiable(); } else if (target != null) - isEditable= target.isEditable(); + isEditable = target.isEditable(); fDialog.updateTarget(target, isEditable, false); } } @@ -140,38 +148,38 @@ public void partActivated(IWorkbenchPartReference partRef) { @Override public void pageChanged(PageChangedEvent event) { if (event.getSource() instanceof IWorkbenchPart) - partActivated((IWorkbenchPart)event.getSource()); + partActivated((IWorkbenchPart) event.getSource()); } @Override public void partClosed(IWorkbenchPartReference partRef) { - IWorkbenchPart part= partRef.getPart(true); + IWorkbenchPart part = partRef.getPart(true); if (part == fPreviousPart) { - fPreviousPart= null; - fPreviousTarget= null; + fPreviousPart = null; + fPreviousTarget = null; } if (part == fPart) - partActivated((IWorkbenchPart)null); + partActivated((IWorkbenchPart) null); } @Override public void widgetDisposed(DisposeEvent event) { if (fgFindReplaceDialogStub == this) - fgFindReplaceDialogStub= null; + fgFindReplaceDialogStub = null; - if(fgFindReplaceDialogStubShell == this) - fgFindReplaceDialogStubShell= null; + if (fgFindReplaceDialogStubShell == this) + fgFindReplaceDialogStubShell = null; if (fWindow != null) { fWindow.getPartService().removePartListener(this); - fWindow= null; + fWindow = null; } - fDialog= null; - fPart= null; - fPreviousPart= null; - fPreviousTarget= null; + fDialog = null; + fPart = null; + fPreviousPart = null; + fPreviousTarget = null; } @Override @@ -199,8 +207,8 @@ public void partVisible(IWorkbenchPartReference partRef) { } /** - * Checks if the dialogs shell is the same as the givenshell
and if not clears
- * the stub and closes the dialog.
+ * Checks if the dialogs shell is the same as the given shell
and
+ * if not clears the stub and closes the dialog.
*
* @param shell the shell check
* @since 3.3
@@ -208,10 +216,10 @@ public void partVisible(IWorkbenchPartReference partRef) {
public void checkShell(Shell shell) {
if (fDialog != null && shell != fDialog.getParentShell()) {
if (fgFindReplaceDialogStub == this)
- fgFindReplaceDialogStub= null;
+ fgFindReplaceDialogStub = null;
if (fgFindReplaceDialogStubShell == this)
- fgFindReplaceDialogStubShell= null;
+ fgFindReplaceDialogStubShell = null;
fDialog.close();
}
@@ -219,17 +227,20 @@ public void checkShell(Shell shell) {
}
-
/**
* Listener for disabling the dialog on shell close.
*
- * This stub is shared amongst IWorkbenchPart
s.
IWorkbenchPart
s.
+ *
*/
private static FindReplaceDialogStub fgFindReplaceDialogStub;
- /** Listener for disabling the dialog on shell close.
+ /**
+ * Listener for disabling the dialog on shell close.
*
- * This stub is shared amongst Shell
s.
Shell
s.
+ *
+ *
* @since 3.3
*/
private static FindReplaceDialogStub fgFindReplaceDialogStubShell;
@@ -242,45 +253,51 @@ public void checkShell(Shell shell) {
private IWorkbenchWindow fWorkbenchWindow;
/**
* The shell to use if the action is created with a shell.
+ *
* @since 3.3
*/
private Shell fShell;
+ private FindReplaceOverlay overlay;
+
/**
* Creates a new find/replace action for the given workbench part.
* - * The action configures its visual representation from the given - * resource bundle.
+ * The action configures its visual representation from the given resource + * bundle. + * * - * @param bundle the resource bundle - * @param prefix a prefix to be prepended to the various resource keys - * (described inResourceAction
constructor), or
- * null
if none
- * @param workbenchPart the workbench part
+ * @param bundle the resource bundle
+ * @param prefix a prefix to be prepended to the various resource keys
+ * (described in ResourceAction
constructor),
+ * or null
if none
+ * @param workbenchPart the workbench part
* @see ResourceAction#ResourceAction(ResourceBundle, String)
*/
public FindReplaceAction(ResourceBundle bundle, String prefix, IWorkbenchPart workbenchPart) {
super(bundle, prefix);
Assert.isLegal(workbenchPart != null);
- fWorkbenchPart= workbenchPart;
+ fWorkbenchPart = workbenchPart;
update();
}
/**
* Creates a new find/replace action for the given target and shell.
* - * This can be used without having an IWorkbenchPart e.g. for - * dialogs or wizards.
+ * This can be used without having an IWorkbenchPart e.g. for dialogs or + * wizards. + * *- * The action configures its visual representation from the given - * resource bundle.
+ * The action configures its visual representation from the given resource + * bundle. + * * * @param bundle the resource bundle * @param prefix a prefix to be prepended to the various resource keys - * (described inResourceAction
constructor), or
- * null
if none
+ * (described in ResourceAction
constructor), or
+ * null
if none
* @param target the IFindReplaceTarget to use
- * @param shell the shell
+ * @param shell the shell
* @see ResourceAction#ResourceAction(ResourceBundle, String)
*
* @since 3.3
@@ -288,81 +305,117 @@ public FindReplaceAction(ResourceBundle bundle, String prefix, IWorkbenchPart wo
public FindReplaceAction(ResourceBundle bundle, String prefix, Shell shell, IFindReplaceTarget target) {
super(bundle, prefix);
Assert.isLegal(target != null && shell != null);
- fTarget= target;
- fShell= shell;
+ fTarget = target;
+ fShell = shell;
update();
}
/**
- * Creates a new find/replace action for the given workbench window.
- * The action configures its visual representation from the given
- * resource bundle.
+ * Creates a new find/replace action for the given workbench window. The action
+ * configures its visual representation from the given resource bundle.
*
- * @param bundle the resource bundle
- * @param prefix a prefix to be prepended to the various resource keys
- * (described in ResourceAction
constructor), or
- * null
if none
+ * @param bundle the resource bundle
+ * @param prefix a prefix to be prepended to the various resource keys
+ * (described in ResourceAction
+ * constructor), or null
if none
* @param workbenchWindow the workbench window
* @see ResourceAction#ResourceAction(ResourceBundle, String)
*
- * @deprecated use FindReplaceAction(ResourceBundle, String, IWorkbenchPart) instead
+ * @deprecated use FindReplaceAction(ResourceBundle, String, IWorkbenchPart)
+ * instead
*/
@Deprecated
public FindReplaceAction(ResourceBundle bundle, String prefix, IWorkbenchWindow workbenchWindow) {
super(bundle, prefix);
- fWorkbenchWindow= workbenchWindow;
+ fWorkbenchWindow = workbenchWindow;
update();
}
@Override
public void run() {
- if (fTarget == null)
- return;
+ if (shouldShowModernOverlay()) {
+ showModernOverlay();
+ } else {
+ if (fTarget == null)
+ return;
+ showClassicDialog();
+ }
+ }
+
+ /**
+ * @since 3.17
+ */
+ public void showClassicDialog() {
final FindReplaceDialog dialog;
final boolean isEditable;
- if(fShell == null) {
+ if (fShell == null) {
if (fgFindReplaceDialogStub != null) {
- Shell shell= fWorkbenchPart.getSite().getShell();
+ Shell shell = fWorkbenchPart.getSite().getShell();
fgFindReplaceDialogStub.checkShell(shell);
}
if (fgFindReplaceDialogStub == null)
- fgFindReplaceDialogStub= new FindReplaceDialogStub(fWorkbenchPart.getSite());
+ fgFindReplaceDialogStub = new FindReplaceDialogStub(fWorkbenchPart.getSite());
if (fWorkbenchPart instanceof ITextEditorExtension2)
- isEditable= ((ITextEditorExtension2) fWorkbenchPart).isEditorInputModifiable();
+ isEditable = ((ITextEditorExtension2) fWorkbenchPart).isEditorInputModifiable();
else
- isEditable= fTarget.isEditable();
+ isEditable = fTarget.isEditable();
- dialog= fgFindReplaceDialogStub.getDialog();
+ dialog = fgFindReplaceDialogStub.getDialog();
} else {
if (fgFindReplaceDialogStubShell != null) {
fgFindReplaceDialogStubShell.checkShell(fShell);
}
if (fgFindReplaceDialogStubShell == null)
- fgFindReplaceDialogStubShell= new FindReplaceDialogStub(fShell);
+ fgFindReplaceDialogStubShell = new FindReplaceDialogStub(fShell);
- isEditable= fTarget.isEditable();
- dialog= fgFindReplaceDialogStubShell.getDialog();
+ isEditable = fTarget.isEditable();
+ dialog = fgFindReplaceDialogStubShell.getDialog();
}
dialog.updateTarget(fTarget, isEditable, true);
dialog.open();
}
+ private void showModernOverlay() {
+ if (overlay == null) {
+ Shell shellToUse;
+ if (fShell == null) {
+ shellToUse = fWorkbenchPart.getSite().getShell();
+ } else {
+ shellToUse = fShell;
+ }
+ overlay = new FindReplaceOverlay(shellToUse, fWorkbenchPart, fTarget, this);
+ }
+ overlay.create();
+ overlay.open();
+ }
+
+ /**
+ * Closes the "modern" overlay. Typically called by the overlay itself.
+ *
+ * @since 3.17
+ */
+ public void closeModernOverlay() {
+ if (overlay != null) {
+ overlay.close();
+ }
+ }
+
@Override
public void update() {
- if(fShell == null){
+ if (fShell == null) {
if (fWorkbenchPart == null && fWorkbenchWindow != null)
- fWorkbenchPart= fWorkbenchWindow.getPartService().getActivePart();
+ fWorkbenchPart = fWorkbenchWindow.getPartService().getActivePart();
if (fWorkbenchPart != null)
- fTarget= fWorkbenchPart.getAdapter(IFindReplaceTarget.class);
+ fTarget = fWorkbenchPart.getAdapter(IFindReplaceTarget.class);
else
- fTarget= null;
+ fTarget = null;
}
setEnabled(fTarget != null && fTarget.canPerformFind());
}
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceOverlay.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceOverlay.java
new file mode 100644
index 00000000000..8354552532c
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceOverlay.java
@@ -0,0 +1,756 @@
+/*******************************************************************************
+ * Copyright (c) 2023 Vector Informatik GmbH 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:
+ * Vector Informatik GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ui.texteditor;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.GC;
+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.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Scrollable;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.window.Window;
+
+import org.eclipse.jface.text.IFindReplaceTarget;
+
+import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.internal.findandreplace.FindReplaceLogic;
+import org.eclipse.ui.internal.findandreplace.FindReplaceLogicMessageGenerator;
+import org.eclipse.ui.internal.findandreplace.FindReplaceLogicStatus;
+import org.eclipse.ui.internal.findandreplace.SearchOptions;
+import org.eclipse.ui.internal.findandreplace.status.IFindReplaceStatus;
+
+/**
+ * @since 3.17
+ */
+public class FindReplaceOverlay extends Dialog {
+
+ FindReplaceAction parentAction;
+ FindReplaceLogic findReplacer;
+ IWorkbenchPart targetPart;
+ boolean overlayOpen;
+ boolean replaceBarOpen;
+
+ Composite container;
+ Button replaceToggle;
+
+ Composite contentGroup;
+
+ Composite searchContainer;
+ Composite searchBarContainer;
+ Text searchBar;
+ ToolBar searchTools;
+ ToolItem wholeWordSearchButton;
+ ToolItem caseSensitiveSearchButton;
+ ToolItem regexSearchButton;
+ ToolItem searchUpButton;
+ ToolItem searchDownButton;
+ ToolItem searchAllButton;
+
+ Composite replaceContainer;
+ Composite replaceBarContainer;
+ Text replaceBar;
+ ToolBar replaceTools;
+ ToolItem replaceButton;
+ ToolItem replaceAllButton;
+
+ Link openOldDialog;
+
+ public FindReplaceOverlay(Shell parent, IWorkbenchPart part, IFindReplaceTarget target,
+ FindReplaceAction parentAction) {
+ super(parent);
+ this.parentAction = parentAction;
+ createFindReplacer(target);
+
+ setShellStyle(SWT.MODELESS);
+ setBlockOnOpen(false);
+ targetPart = part;
+ }
+
+ @Override
+ protected boolean isResizable() {
+ return false;
+ }
+
+ private void createFindReplacer(IFindReplaceTarget target) {
+ findReplacer = new FindReplaceLogic();
+ boolean isTargetEditable = false;
+ if (target != null) {
+ isTargetEditable = target.isEditable();
+ }
+ findReplacer.updateTarget(target, isTargetEditable);
+ findReplacer.activate(SearchOptions.INCREMENTAL);
+ findReplacer.activate(SearchOptions.GLOBAL);
+ findReplacer.activate(SearchOptions.WRAP);
+ findReplacer.activate(SearchOptions.FORWARD);
+ }
+
+ KeyListener shortcuts = new KeyListener() {
+
+ private void performEnterAction(KeyEvent e) {
+ // probably not the right way to implement this.
+ // What do you think, @HeikoKlare?
+ boolean isShiftPressed = (e.stateMask & SWT.SHIFT) != 0;
+ boolean isCtrlPressed = (e.stateMask & SWT.CTRL) != 0;
+ if (okayToUse(replaceBar) && replaceBar.isFocusControl()) {
+ if (isCtrlPressed) {
+ findReplacer.performReplaceAll(getFindString(), getReplaceString(), getShell().getDisplay());
+ } else {
+ performSingleReplace();
+ }
+ } else {
+ if (isCtrlPressed) {
+ findReplacer.performSelectAll(getFindString(), getShell().getDisplay());
+ } else {
+ boolean oldForwardSearchSetting = findReplacer.isActive(SearchOptions.FORWARD);
+ activateInFindReplacerIf(SearchOptions.FORWARD, !isShiftPressed);
+ findReplacer.deactivate(SearchOptions.INCREMENTAL);
+ findReplacer.performSearch(getFindString());
+ activateInFindReplacerIf(SearchOptions.FORWARD, oldForwardSearchSetting);
+ findReplacer.activate(SearchOptions.INCREMENTAL);
+ }
+ }
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if ((e.stateMask & SWT.CTRL) != 0 && (e.keyCode == 'F' || e.keyCode == 'f')) {
+ parentAction.closeModernOverlay();
+ } else if ((e.stateMask & SWT.CTRL) != 0 && (e.keyCode == 'R' || e.keyCode == 'r')) {
+ replaceToggle.setSelection(!replaceToggle.getSelection());
+ replaceToggle.notifyListeners(SWT.Selection, null);
+ } else if ((e.stateMask & SWT.CTRL) != 0 && (e.keyCode == 'W' || e.keyCode == 'w')) {
+ wholeWordSearchButton.setSelection(!wholeWordSearchButton.getSelection());
+ wholeWordSearchButton.notifyListeners(SWT.Selection, null);
+ } else if (e.keyCode == SWT.CR) {
+ performEnterAction(e);
+ }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ // Do nothing
+ }
+
+ };
+ ControlListener shellMovementListener = new ControlListener() {
+ @Override
+ public void controlMoved(ControlEvent e) {
+ positionToPart();
+ }
+
+ @Override
+ public void controlResized(ControlEvent e) {
+ positionToPart();
+ }
+ };
+ PaintListener widgetMovementListener = new PaintListener() {
+
+ @Override
+ public void paintControl(PaintEvent e) {
+ positionToPart();
+ }
+
+ };
+ IPartListener partListener = new IPartListener() {
+ @Override
+ public void partActivated(IWorkbenchPart part) {
+ if (getShell() != null) {
+ getShell().setVisible(isPartCurrentlyDisplayedInPartSash());
+ }
+ }
+
+ @Override
+ public void partDeactivated(IWorkbenchPart part) {
+ // Do nothing
+ }
+
+ @Override
+ public void partBroughtToTop(IWorkbenchPart part) {
+ if (getShell() != null) {
+ getShell().setVisible(isPartCurrentlyDisplayedInPartSash());
+ }
+ }
+
+ @Override
+ public void partClosed(IWorkbenchPart part) {
+ close();
+ }
+
+ @Override
+ public void partOpened(IWorkbenchPart part) {
+ // Do nothing
+ }
+ };
+
+ public boolean isPartCurrentlyDisplayedInPartSash() {
+ IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+
+ // Check if the targetPart is currently displayed on the active page
+ boolean isPartDisplayed = false;
+
+ if (activePage != null) {
+ IWorkbenchPart activePart = activePage.getActivePart();
+ if (activePart != null && activePart == targetPart) {
+ isPartDisplayed = true;
+ }
+ }
+
+ return isPartDisplayed;
+ }
+
+ @Override
+ public void create() {
+ if (overlayOpen) {
+ return;
+ }
+ super.create();
+ }
+
+ @Override
+ public boolean close() {
+ if (!overlayOpen) {
+ return true;
+ }
+ overlayOpen = false;
+ replaceBarOpen = false;
+ unbindListeners();
+ container.dispose();
+ return super.close();
+ }
+
+ @Override
+ public int open() {
+ int returnCode;
+ positionToPart();
+ if (overlayOpen) {
+ searchBar.forceFocus();
+ findReplacer.performIncrementalSearch(getFindString());
+ returnCode = Window.CANCEL;
+ } else {
+ bindListeners();
+ returnCode = super.open();
+ }
+ overlayOpen = true;
+ return returnCode;
+ }
+
+ private void unbindListeners() {
+ if (targetPart != null && targetPart instanceof StatusTextEditor textEditor) {
+ Control targetWidget = textEditor.getSourceViewer().getTextWidget();
+ if (targetWidget != null) {
+ targetWidget.getShell().removeControlListener(shellMovementListener);
+ targetWidget.removePaintListener(widgetMovementListener);
+ targetPart.getSite().getPage().removePartListener(partListener);
+ }
+ }
+ }
+
+ private void bindListeners() {
+ if (targetPart instanceof StatusTextEditor textEditor) {
+ Control targetWidget = textEditor.getSourceViewer().getTextWidget();
+
+ targetWidget.getShell().addControlListener(shellMovementListener);
+ targetWidget.addPaintListener(widgetMovementListener);
+ targetPart.getSite().getPage().addPartListener(partListener);
+ }
+ }
+
+ @Override
+ public Control createContents(Composite parent) {
+ Control ret = createDialog(parent);
+ initFindStringFromSelection();
+ positionToPart();
+ return ret;
+ }
+
+ public Control createDialog(final Composite parent) {
+ createMainContainer(parent);
+
+ // createLinks();
+ createFindContainer();
+ createSearchBar();
+ createSearchTools();
+
+ container.layout();
+
+ applyDialogFont(container);
+ return container;
+ }
+
+ @SuppressWarnings("unused")
+ private void createLinks() {
+ openOldDialog = new Link(contentGroup, SWT.NONE);
+ GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.BEGINNING).applyTo(openOldDialog);
+ openOldDialog.setText("classic Find/Replace"); //$NON-NLS-1$
+ openOldDialog.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ parentAction.showClassicDialog();
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // Do nothing
+ }
+
+ });
+ }
+
+ private void createSearchTools() {
+ searchTools = new ToolBar(searchContainer, SWT.HORIZONTAL);
+ GridDataFactory.fillDefaults().grab(false, true).align(GridData.CENTER, GridData.CENTER).applyTo(searchTools);
+ wholeWordSearchButton = new ToolItem(searchTools, SWT.CHECK);
+ wholeWordSearchButton.setImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.OBJ_WHOLE_WORD));
+ wholeWordSearchButton.setToolTipText("Only find in whole words"); //$NON-NLS-1$
+ wholeWordSearchButton.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ activateInFindReplacerIf(SearchOptions.WHOLE_WORD, wholeWordSearchButton.getSelection());
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // Do Nothing
+ }
+ });
+ caseSensitiveSearchButton = new ToolItem(searchTools, SWT.CHECK);
+ caseSensitiveSearchButton.setImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.OBJ_CASE_SENSITIVE));
+ caseSensitiveSearchButton.setToolTipText("Match case"); //$NON-NLS-1$
+ caseSensitiveSearchButton.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ activateInFindReplacerIf(SearchOptions.CASE_SENSITIVE, caseSensitiveSearchButton.getSelection());
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // Do Nothing
+ }
+ });
+ regexSearchButton = new ToolItem(searchTools, SWT.CHECK);
+ regexSearchButton.setImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.OBJ_FIND_REGEX));
+ regexSearchButton.setToolTipText("Search for a regular expression"); //$NON-NLS-1$
+ regexSearchButton.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ activateInFindReplacerIf(SearchOptions.REGEX, regexSearchButton.getSelection());
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // Do nothing
+ }
+ });
+
+ regexSearchButton = new ToolItem(searchTools, SWT.SEPARATOR);
+
+ searchAllButton = new ToolItem(searchTools, SWT.PUSH);
+ searchAllButton.setImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.OBJ_SEARCH_ALL));
+ searchAllButton.setToolTipText("Search all (Ctrl + Enter)"); //$NON-NLS-1$
+ searchAllButton.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ findReplacer.performSelectAll(getFindString(), getShell().getDisplay());
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // Do nothing
+ }
+
+ });
+ searchUpButton = new ToolItem(searchTools, SWT.PUSH);
+ searchUpButton.setImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.ELCL_FIND_PREV));
+ searchUpButton.setToolTipText("Search backward (Shift + Enter)"); //$NON-NLS-1$
+ searchUpButton.addSelectionListener(new SelectionListener() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ findReplacer.deactivate(SearchOptions.FORWARD);
+ findReplacer.performSearch(getFindString());
+ findReplacer.activate(SearchOptions.FORWARD);
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // Do Nothing
+ }
+ });
+ searchDownButton = new ToolItem(searchTools, SWT.PUSH);
+ searchDownButton.setSelection(true); // by default, search down
+ searchDownButton.setImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.ELCL_FIND_NEXT));
+ searchDownButton.setToolTipText("Search forward (Enter)"); //$NON-NLS-1$
+ searchDownButton.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ // TODO extract into transaction
+ findReplacer.activate(SearchOptions.FORWARD);
+ findReplacer.activate(SearchOptions.INCREMENTAL);
+ findReplacer.deactivate(SearchOptions.FORWARD);
+ findReplacer.performSearch(getFindString());
+ findReplacer.deactivate(SearchOptions.INCREMENTAL);
+ findReplacer.activate(SearchOptions.FORWARD);
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // Do nothing
+ }
+ });
+
+ }
+
+ private void createReplaceTools() {
+ replaceTools = new ToolBar(replaceContainer, SWT.HORIZONTAL);
+ GridDataFactory.fillDefaults().grab(false, true).align(GridData.CENTER, GridData.CENTER).applyTo(replaceTools);
+ replaceButton = new ToolItem(replaceTools, SWT.PUSH);
+ replaceButton.setImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.OBJ_REPLACE));
+ replaceButton.setToolTipText("Replace (Enter)"); //$NON-NLS-1$
+ replaceButton.addSelectionListener(new SelectionListener() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ performSingleReplace();
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // Do nothing
+ }
+ });
+ replaceAllButton = new ToolItem(replaceTools, SWT.PUSH);
+ replaceAllButton.setImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.OBJ_REPLACE_ALL));
+ replaceAllButton.setToolTipText("Replace All (Ctrl + Enter)"); //$NON-NLS-1$
+ replaceAllButton.addSelectionListener(new SelectionListener() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ findReplacer.performReplaceAll(getFindString(), getReplaceString(), getShell().getDisplay());
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // Do Nothing
+ }
+ });
+ }
+
+ private void createSearchBar() {
+ searchBar = new Text(searchBarContainer, SWT.SINGLE);
+ GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL).applyTo(searchBar);
+ searchBar.forceFocus();
+ searchBar.selectAll();
+ searchBar.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ findReplacer.performIncrementalSearch(getFindString());
+ }
+ });
+
+ searchBar.addKeyListener(shortcuts);
+
+ searchBar.setMessage("Find"); //$NON-NLS-1$
+ }
+
+ private void createReplaceBar() {
+ replaceBar = new Text(replaceBarContainer, SWT.SINGLE);
+ GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(replaceBar);
+ replaceBar.setMessage("Replace"); //$NON-NLS-1$
+ replaceBar.addKeyListener(shortcuts);
+ }
+
+ private void createFindContainer() {
+ searchContainer = new Composite(contentGroup, SWT.NONE);
+ GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL)
+ .applyTo(searchContainer);
+ GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).applyTo(searchContainer);
+ searchBarContainer = new Composite(searchContainer, SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL).applyTo(searchBarContainer);
+ GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false).applyTo(searchBarContainer);
+ }
+
+ private void createReplaceContainer() {
+ replaceContainer = new Composite(contentGroup, SWT.NONE);
+ GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL).applyTo(replaceContainer);
+ GridLayoutFactory.fillDefaults().margins(0, 1).numColumns(2).equalWidth(false)
+ .applyTo(replaceContainer);
+ replaceBarContainer = new Composite(replaceContainer, SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL)
+ .applyTo(replaceBarContainer);
+ GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false)
+ .applyTo(replaceBarContainer);
+ }
+
+ private void createMainContainer(final Composite parent) {
+ container = new Composite(parent, SWT.NONE);
+ GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).margins(2, 2).spacing(2, 0).applyTo(container);
+ GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL).applyTo(container);
+
+ if (findReplacer.getTarget().isEditable()) {
+ createReplaceToggle();
+ }
+
+ contentGroup = new Composite(container, SWT.NULL);
+ GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false).spacing(2, 2).applyTo(contentGroup);
+ GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL).applyTo(contentGroup);
+ }
+
+ private void createReplaceToggle() {
+ replaceToggle = new Button(container, SWT.PUSH); // https://stackoverflow.com/questions/33161797/how-to-remove-border-of-swt-button-so-that-it-seems-like-a-label
+ GridDataFactory.fillDefaults().grab(false, true).align(GridData.BEGINNING, GridData.FILL)
+ .applyTo(replaceToggle);
+ replaceToggle.setToolTipText("Toggle input for replace (Ctrl+R)"); //$NON-NLS-1$
+ replaceToggle.setImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.OBJ_OPEN_REPLACE));
+ replaceToggle.addSelectionListener(new SelectionListener() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (!replaceBarOpen) {
+ createReplaceDialog();
+ replaceToggle.setImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.OBJ_CLOSE_REPLACE));
+ } else {
+ hideReplace();
+ replaceToggle.setImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.OBJ_OPEN_REPLACE));
+ }
+ replaceToggle.setSelection(false);
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // Do nothing
+ }
+ });
+ }
+
+ public void hideReplace() {
+ if (!replaceBarOpen) {
+ return;
+ }
+ replaceBarOpen = false;
+ replaceContainer.dispose();
+ replaceTools.dispose();
+ replaceBar.dispose();
+ positionToPart();
+ searchBar.forceFocus();
+ }
+
+ public void createReplaceDialog() {
+ if (replaceBarOpen) {
+ return;
+ }
+ replaceBarOpen = true;
+ createReplaceContainer();
+ createReplaceBar();
+ createReplaceTools();
+ positionToPart();
+ replaceBar.forceFocus();
+ }
+
+ private void enableSearchTools(boolean enable) {
+ ((GridData) searchTools.getLayoutData()).exclude = !enable;
+ searchTools.setVisible(enable);
+
+ if (enable) {
+ ((GridLayout) searchTools.getParent().getLayout()).numColumns = 2;
+ } else {
+ ((GridLayout) searchTools.getParent().getLayout()).numColumns = 1;
+ }
+ }
+
+ private void enableReplaceToggle(boolean enable) {
+ if (!okayToUse(replaceToggle)) {
+ return;
+ }
+ ((GridData) replaceToggle.getLayoutData()).exclude = !enable;
+ replaceToggle.setVisible(enable);
+ }
+
+ private void enableReplaceTools(boolean enable) {
+ if (!okayToUse(replaceTools)) {
+ return;
+ }
+ ((GridData) replaceTools.getLayoutData()).exclude = !enable;
+ replaceTools.setVisible(enable);
+
+ if (enable) {
+ ((GridLayout) replaceTools.getParent().getLayout()).numColumns = 2;
+ } else {
+ ((GridLayout) replaceTools.getParent().getLayout()).numColumns = 1;
+ }
+ }
+
+ private int getIdealDialogWidth(Rectangle targetBounds) {
+ enableSearchTools(true);
+ enableReplaceTools(true);
+ enableReplaceToggle(true);
+ Point toolBarWidth = searchTools.getSize();
+ GC gc = new GC(searchBar);
+ gc.setFont(searchBar.getFont());
+ Point idealWidth = gc.stringExtent("THIS TEXT HAS A REASONABLE LENGTH FOR SEARCHING"); //$NON-NLS-1$
+ Point idealCompromiseWidth = gc.stringExtent("THIS TEXT HAS A REASONABLE"); //$NON-NLS-1$
+ Point worstCompromiseWidth = gc.stringExtent("THIS TEXT "); //$NON-NLS-1$
+
+ int newWidth = idealWidth.x + toolBarWidth.x;
+ if (newWidth > targetBounds.width * 0.7) {
+ newWidth = (int) (targetBounds.width * 0.7);
+ }
+ if (newWidth < idealCompromiseWidth.x + toolBarWidth.x) {
+ enableSearchTools(false);
+ enableReplaceTools(false);
+ }
+ if (newWidth < worstCompromiseWidth.x + toolBarWidth.x) {
+ newWidth = (int) (targetBounds.width * 0.95);
+ enableReplaceToggle(false);
+ }
+ return newWidth;
+ }
+
+ private Point getNewPosition(Widget targetTextWidget, Point targetOrigin, Rectangle targetBounds) {
+ Point scrollBarSize = ((Scrollable) targetTextWidget).getVerticalBar().getSize();
+
+ int newX = targetOrigin.x + targetBounds.width - container.getBounds().width - scrollBarSize.x
+ - ((StyledText) targetTextWidget).getRightMargin();
+ int newY = targetOrigin.y;
+ return new Point(newX, newY);
+ }
+
+ /**
+ * When making the text-bar 100% small and then regrowing it, we want the text
+ * to start at the first character again.
+ */
+ private void repositionTextSelection() {
+ if (okayToUse(searchBar) && !searchBar.isFocusControl()) {
+ searchBar.setSelection(0, 0);
+ }
+ if (okayToUse(replaceBar) && !replaceBar.isFocusControl()) {
+ replaceBar.setSelection(0, 0);
+ }
+ }
+
+ public void positionToPart() {
+ getShell().layout(true);
+ container.layout(true);
+ if (targetPart instanceof StatusTextEditor textEditor) {
+ Control targetWidget = textEditor.getSourceViewer().getTextWidget();
+ if (targetWidget == null || targetWidget.isDisposed()) {
+ this.close();
+ return;
+ }
+ StyledText targetTextWidget = textEditor.getSourceViewer().getTextWidget();
+ Point targetOrigin = targetTextWidget.toDisplay(0, 0);
+ Rectangle targetBounds = targetTextWidget.getBounds();
+
+ int newWidth = getIdealDialogWidth(targetBounds);
+ int newHeight = container.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
+ getShell().setSize(new Point(newWidth, newHeight));
+
+ Point newPosition = getNewPosition(targetTextWidget, targetOrigin, targetBounds);
+ getShell().setLocation(newPosition);
+
+ repositionTextSelection();
+ }
+ container.layout(true);
+ getShell().layout(true);
+ }
+
+ private String getFindString() {
+ return searchBar.getText();
+ }
+
+ private String getReplaceString() {
+ if (replaceBar.isDisposed())
+ return ""; //$NON-NLS-1$
+ return replaceBar.getText();
+
+ }
+
+ private void performSingleReplace() {
+ findReplacer.performSelectAndReplace(getFindString(), getReplaceString());
+ findReplacer.performIncrementalSearch(getFindString());
+ evaluateFindReplacerStatus();
+ }
+
+ private void initFindStringFromSelection() {
+ searchBar.setText(findReplacer.getTarget().getSelectionText());
+ }
+
+ private void evaluateFindReplacerStatus() {
+ IFindReplaceStatus status = findReplacer.getStatus();
+
+ String dialogMessage = status.accept(new FindReplaceLogicMessageGenerator());
+
+ if (status instanceof FindReplaceLogicStatus statusMessage) {
+ switch (statusMessage.getMessageCode()) {
+ case NO_MATCH:
+ case READONLY:
+ case WRAPPED:
+ tryToBeep();
+ break;
+ case NONE:
+ default:
+ break;
+ }
+ }
+
+ }
+
+ private void tryToBeep() {
+ Shell dialogShell = getShell();
+ if (dialogShell != null && !dialogShell.isDisposed()) {
+ getShell().getDisplay().beep();
+ }
+ }
+
+ private void activateInFindReplacerIf(SearchOptions option, boolean shouldActivate) {
+ if (shouldActivate) {
+ findReplacer.activate(option);
+ } else {
+ findReplacer.deactivate(option);
+ }
+ }
+
+ private boolean okayToUse(Widget widget) {
+ return widget != null && !widget.isDisposed();
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceOverlayImages.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceOverlayImages.java
new file mode 100644
index 00000000000..5430426e1f8
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceOverlayImages.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * Copyright (c) 2023 Vector Informatik GmbH 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:
+ * Vector Informatik GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ui.texteditor;
+
+import java.net.URL;
+
+import org.osgi.framework.Bundle;
+
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+
+import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
+
+/**
+ * @HeikoKlare Modeled after TemplatePageImages.java - I'm not sure if this
+ * approach is good or bad. I copy-pasted methods, increasing
+ * code-duplication. We should consider implementing a unified
+ * method for inserting icons (.. or does it already exist?)
+ */
+class FindReplaceOverlayImages {
+
+ static final String PREFIX_ELCL = TextEditorPlugin.PLUGIN_ID + ".elcl."; //$NON-NLS-1$
+
+ static final String PREFIX_DLCL = TextEditorPlugin.PLUGIN_ID + ".dlcl."; //$NON-NLS-1$
+
+ static final String PREFIX_OBJ = TextEditorPlugin.PLUGIN_ID + ".obj."; //$NON-NLS-1$
+
+ static final String ELCL_FIND_NEXT = PREFIX_ELCL + "select_next.png"; //$NON-NLS-1$
+
+ static final String ELCL_FIND_PREV = PREFIX_ELCL + "select_prev.png"; //$NON-NLS-1$
+
+ static final String OBJ_FIND_REGEX = PREFIX_OBJ + "regex_gear.gif"; //$NON-NLS-1$
+
+ static final String OBJ_REPLACE = PREFIX_OBJ + "replace.png"; //$NON-NLS-1$
+
+ static final String OBJ_REPLACE_ALL = PREFIX_OBJ + "replace_all.png"; //$NON-NLS-1$
+
+ static final String OBJ_WHOLE_WORD = PREFIX_OBJ + "whole_word.png"; //$NON-NLS-1$
+
+ static final String OBJ_CASE_SENSITIVE = PREFIX_OBJ + "case_sensitive.png"; //$NON-NLS-1$
+
+ static final String OBJ_OPEN_REPLACE = PREFIX_OBJ + "open_replace.png"; //$NON-NLS-1$
+
+ static final String OBJ_CLOSE_REPLACE = PREFIX_OBJ + "close_replace.png"; //$NON-NLS-1$
+
+ static final String OBJ_SEARCH_ALL = PREFIX_OBJ + "search_all.png"; //$NON-NLS-1$
+
+ /**
+ * The image registry containing {@link Image images}.
+ */
+ private static ImageRegistry fgImageRegistry;
+
+ private static String ICONS_PATH = "$nl$/icons/full/"; //$NON-NLS-1$
+
+ // Use IPath and toOSString to build the names to ensure they have the
+ // slashes correct
+ private final static String ELCL = ICONS_PATH + "elcl16/"; //$NON-NLS-1$
+
+ private final static String DLCL = ICONS_PATH + "dlcl16/"; //$NON-NLS-1$
+
+ private final static String OBJ = ICONS_PATH + "obj16/"; //$NON-NLS-1$
+
+ /**
+ * Declare all images
+ */
+ private static void declareImages() {
+ declareRegistryImage(ELCL_FIND_NEXT, ELCL + "select_next.png"); //$NON-NLS-1$
+ declareRegistryImage(ELCL_FIND_PREV, ELCL + "select_prev.png"); //$NON-NLS-1$
+ declareRegistryImage(OBJ_FIND_REGEX, OBJ + "regex_gear.gif"); //$NON-NLS-1$
+ declareRegistryImage(OBJ_REPLACE_ALL, OBJ + "replace_all.png"); //$NON-NLS-1$
+ declareRegistryImage(OBJ_REPLACE, OBJ + "replace.png"); //$NON-NLS-1$
+ declareRegistryImage(OBJ_WHOLE_WORD, OBJ + "whole_word.png"); //$NON-NLS-1$
+ declareRegistryImage(OBJ_CASE_SENSITIVE, OBJ + "case_sensitive.png"); //$NON-NLS-1$
+ declareRegistryImage(OBJ_OPEN_REPLACE, OBJ + "open_replace.png"); //$NON-NLS-1$
+ declareRegistryImage(OBJ_CLOSE_REPLACE, OBJ + "close_replace.png"); //$NON-NLS-1$
+ declareRegistryImage(OBJ_SEARCH_ALL, OBJ + "search_all.png"); //$NON-NLS-1$
+ }
+
+ /**
+ * Declare an Image in the registry table.
+ *
+ * @param key the key to use when registering the image
+ * @param path the path where the image can be found. This path is relative to
+ * where this plugin class is found (i.e. typically the packages
+ * directory)
+ */
+ private final static void declareRegistryImage(String key, String path) {
+ ImageDescriptor desc = ImageDescriptor.getMissingImageDescriptor();
+ Bundle bundle = Platform.getBundle(TextEditorPlugin.PLUGIN_ID);
+ URL url = null;
+ if (bundle != null) {
+ url = FileLocator.find(bundle, IPath.fromOSString(path), null);
+ desc = ImageDescriptor.createFromURL(url);
+ }
+ fgImageRegistry.put(key, desc);
+ }
+
+ /**
+ * Returns the ImageRegistry.
+ *
+ * @return image registry
+ */
+ public static ImageRegistry getImageRegistry() {
+ if (fgImageRegistry == null) {
+ initializeImageRegistry();
+ }
+ return fgImageRegistry;
+ }
+
+ /**
+ * Initialize the image registry by declaring all of the required graphics. This
+ * involves creating JFace image descriptors describing how to create/find the
+ * image should it be needed. The image is not actually allocated until
+ * requested.
+ *
+ * Prefix conventions Wizard Banners WIZBAN_ Preference Banners PREF_BAN_
+ * Property Page Banners PROPBAN_ Color toolbar CTOOL_ Enable toolbar ETOOL_
+ * Disable toolbar DTOOL_ Local enabled toolbar ELCL_ Local Disable toolbar
+ * DLCL_ Object large OBJL_ Object small OBJS_ View VIEW_ Product images PROD_
+ * Misc images MISC_
+ *
+ * Where are the images? The images (typically pngs) are found in the same
+ * location as this plugin class. This may mean the same package directory as
+ * the package holding this class. The images are declared using this.getClass()
+ * to ensure they are looked up via this plugin class.
+ *
+ * @return the image registry
+ * @see org.eclipse.jface.resource.ImageRegistry
+ */
+ public static ImageRegistry initializeImageRegistry() {
+ fgImageRegistry = TextEditorPlugin.getDefault().getImageRegistry();
+ declareImages();
+ return fgImageRegistry;
+ }
+
+ /**
+ * Returns the image managed under the given key in this registry.
+ *
+ * @param key the image's key
+ * @return the image managed under the given key
+ */
+ public static Image get(String key) {
+ return getImageRegistry().get(key);
+ }
+
+ /**
+ * Returns the image descriptor for the given key in this registry.
+ *
+ * @param key the image's key
+ * @return the image descriptor for the given key
+ */
+ public static ImageDescriptor getDescriptor(String key) {
+ return getImageRegistry().getDescriptor(key);
+ }
+}
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/ViewsPreferencePage.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/ViewsPreferencePage.java
index d6f5cf79438..d42427a7f8e 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/ViewsPreferencePage.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/ViewsPreferencePage.java
@@ -98,6 +98,7 @@ public class ViewsPreferencePage extends PreferencePage implements IWorkbenchPre
private ITheme currentTheme;
private String defaultTheme;
private Button useRoundTabs;
+ private Button useFindReplaceOverlay;
private Button enableMru;
private Button useColoredLabels;
@@ -185,6 +186,7 @@ protected Control createContents(Composite parent) {
}
private void createThemeIndependentComposits(Composite comp) {
+ createUseFindReplaceOverlay(comp);
createUseRoundTabs(comp);
createColoredLabelsPref(comp);
createEnableMruPref(comp);
@@ -289,6 +291,12 @@ protected void createUseRoundTabs(Composite composite) {
useRoundTabs = createCheckButton(composite, WorkbenchMessages.ViewsPreference_useRoundTabs, enabled);
}
+ protected void createUseFindReplaceOverlay(Composite composite) {
+ IEclipsePreferences prefs = getSwtRendererPreferences();
+ boolean enabled = prefs.getBoolean("USE_FIND_REPLACE_OVERLAY", true); //$NON-NLS-1$
+ useFindReplaceOverlay = createCheckButton(composite, "use modern Find/Replace-Overlay", enabled); //$NON-NLS-1$
+ }
+
protected void createEnableMruPref(Composite composite) {
createLabel(composite, ""); //$NON-NLS-1$
createLabel(composite, WorkbenchMessages.ViewsPreference_visibleTabs_description);
@@ -332,6 +340,7 @@ public boolean performOk() {
prefs.putBoolean(PartRenderingEngine.ENABLED_THEME_KEY, themingEnabled.getSelection());
prefs.putBoolean(CTabRendering.USE_ROUND_TABS, useRoundTabs.getSelection());
+ prefs.putBoolean("USE_FIND_REPLACE_OVERLAY", useFindReplaceOverlay.getSelection()); //$NON-NLS-1$
try {
prefs.flush();
} catch (BackingStoreException e) {
@@ -407,6 +416,7 @@ protected void performDefaults() {
useColoredLabels.setSelection(apiStore.getDefaultBoolean(IWorkbenchPreferenceConstants.USE_COLORED_LABELS));
useRoundTabs.setSelection(CTabRendering.USE_ROUND_TABS_DEFAULT);
+ useFindReplaceOverlay.setSelection(true);
enableMru.setSelection(getDefaultMRUValue());
super.performDefaults();
}
diff --git a/releng/org.eclipse.text.releng/.project b/releng/org.eclipse.text.releng/.project
new file mode 100644
index 00000000000..c79a93b4658
--- /dev/null
+++ b/releng/org.eclipse.text.releng/.project
@@ -0,0 +1,11 @@
+
+