Skip to content

Commit

Permalink
Find/replace overlay: allow pasting in multi-page editors #2509
Browse files Browse the repository at this point in the history
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
#2509
  • Loading branch information
HeikoKlare authored and jannisCode committed Nov 19, 2024
1 parent 64af72a commit aa3f7d1
Showing 1 changed file with 42 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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);
Expand All @@ -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<String> ACTIONS = List.of(ITextEditorActionConstants.CUT,
ITextEditorActionConstants.COPY, ITextEditorActionConstants.PASTE,
ITextEditorActionConstants.DELETE, ITextEditorActionConstants.SELECT_ALL,
ITextEditorActionConstants.FIND);

private final Map<String, IAction> 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) {
Expand Down

0 comments on commit aa3f7d1

Please sign in to comment.