From aa3f7d19092d4704d1a942fa1b80d4df16cb8a04 Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Tue, 12 Nov 2024 11:23:36 +0100 Subject: [PATCH] Find/replace overlay: allow pasting in multi-page editors #2509 While actions of the target editor are properly deactivated when the target is an ordinary, single-page editor, the same does not happen when the target is a multi-page editor. In consequence, for example, you cannot paste clipboard content into the overlay via the according keyboard shortcut (CTRL+V), but it will paste into the target editor instead. With this change, the functionality to deactivate target editor actions is extended to also deactivate the relevant global actions (cut, copy, paste, etc.) that editors like multi-page editors fall back to. Fixes to https://github.com/eclipse-platform/eclipse.platform.ui/issues/2509 --- .../overlay/FindReplaceOverlay.java | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java index 235b584a566..80466fcd7f6 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java @@ -13,9 +13,10 @@ *******************************************************************************/ package org.eclipse.ui.internal.findandreplace.overlay; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import org.osgi.framework.FrameworkUtil; @@ -46,6 +47,7 @@ import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.IAction; import org.eclipse.jface.bindings.keys.KeyStroke; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogSettings; @@ -60,6 +62,7 @@ import org.eclipse.jface.text.IFindReplaceTarget; import org.eclipse.jface.text.ITextViewer; +import org.eclipse.ui.IActionBars; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter; @@ -70,10 +73,12 @@ import org.eclipse.ui.internal.findandreplace.SearchOptions; import org.eclipse.ui.internal.findandreplace.status.IFindReplaceStatus; import org.eclipse.ui.internal.texteditor.TextEditorPlugin; +import org.eclipse.ui.part.MultiPageEditorSite; import org.eclipse.ui.texteditor.AbstractTextEditor; import org.eclipse.ui.texteditor.FindReplaceAction; import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds; +import org.eclipse.ui.texteditor.ITextEditorActionConstants; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; import org.eclipse.ui.texteditor.StatusTextEditor; @@ -148,6 +153,8 @@ private final class KeyboardShortcuts { private ContentAssistCommandAdapter contentAssistSearchField, contentAssistReplaceField; private FocusListener targetActionActivationHandling = new FocusListener() { + private DeactivateGlobalActionHandlers globalActionHandlerDeaction; + @Override public void focusGained(FocusEvent e) { setTextEditorActionsActivated(false); @@ -167,15 +174,48 @@ private void setTextEditorActionsActivated(boolean state) { if (!(targetPart instanceof AbstractTextEditor)) { return; } + if (targetPart.getSite() instanceof MultiPageEditorSite multiEditorSite) { + if (!state && globalActionHandlerDeaction == null) { + globalActionHandlerDeaction = new DeactivateGlobalActionHandlers(multiEditorSite.getActionBars()); + } else if (state && globalActionHandlerDeaction != null) { + globalActionHandlerDeaction.reactivate(); + globalActionHandlerDeaction = null; + } + } try { Method method = AbstractTextEditor.class.getDeclaredMethod("setActionActivation", boolean.class); //$NON-NLS-1$ method.setAccessible(true); method.invoke(targetPart, Boolean.valueOf(state)); - } catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException | SecurityException | NoSuchMethodException ex) { + } catch (IllegalArgumentException | ReflectiveOperationException ex) { TextEditorPlugin.getDefault().getLog() .log(Status.error("cannot (de-)activate actions for text editor", ex)); //$NON-NLS-1$ } } + + static final class DeactivateGlobalActionHandlers { + private final static List ACTIONS = List.of(ITextEditorActionConstants.CUT, + ITextEditorActionConstants.COPY, ITextEditorActionConstants.PASTE, + ITextEditorActionConstants.DELETE, ITextEditorActionConstants.SELECT_ALL, + ITextEditorActionConstants.FIND); + + private final Map deactivatedActions = new HashMap<>(); + private final IActionBars actionBars; + + public DeactivateGlobalActionHandlers(IActionBars actionBars) { + this.actionBars = actionBars; + for (String actionID : ACTIONS) { + deactivatedActions.putIfAbsent(actionID, actionBars.getGlobalActionHandler(actionID)); + actionBars.setGlobalActionHandler(actionID, null); + } + } + + public void reactivate() { + for (String actionID : deactivatedActions.keySet()) { + actionBars.setGlobalActionHandler(actionID, deactivatedActions.get(actionID)); + } + } + } + }; public FindReplaceOverlay(Shell parent, IWorkbenchPart part, IFindReplaceTarget target) {