From 1ecc87fd16fba312bc2aa1d4eeb47f0f2436d898 Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Tue, 12 Nov 2024 16:42:13 +0100 Subject: [PATCH] Find/replace overlay: improve focus/tab order #2161 The FindReplaceOverlay currently uses the default focus order. When tabbing through the widgets, this means that when starting from the find input field you have to tab over all the search options before coming to the replace input field. Since the most often used navigation is between the two input fields for find and replace, they should come after each other in the focus order. This change adapts the focus order of the involved elements: - Tab between find and replace input field - Tab between replace input field and the tools (starting from the search tools) - Tab between search/close and replace search tools (instead of coming from search/close tools to the replace input field) Fixes https://github.com/eclipse-platform/eclipse.platform.ui/issues/2161 --- .../overlay/AccessibleToolBar.java | 5 ++ .../overlay/FindReplaceOverlay.java | 79 +++++++++++++++++++ .../overlay/HistoryTextWrapper.java | 4 + 3 files changed, 88 insertions(+) diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/AccessibleToolBar.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/AccessibleToolBar.java index 63053127871..5c3cc32fd02 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/AccessibleToolBar.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/AccessibleToolBar.java @@ -74,4 +74,9 @@ void registerActionShortcutsAtControl(Control control) { } } + Control getFirstControl() { + Control[] children = getChildren(); + return children.length == 0 ? null : getChildren()[0]; + } + } 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 80466fcd7f6..78b22e07c60 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 @@ -38,6 +38,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.swt.widgets.Scrollable; import org.eclipse.swt.widgets.Shell; @@ -218,6 +219,81 @@ public void reactivate() { }; + private final CustomFocusOrder customFocusOrder = new CustomFocusOrder(); + + private class CustomFocusOrder { + private final Listener searchBarToReplaceBar = e -> { + if (e.detail == SWT.TRAVERSE_TAB_NEXT) { + e.doit = false; + replaceBar.forceFocus(); + } + }; + + private final Listener replaceBarToSearchBarAndTools = e -> { + switch (e.detail) { + case SWT.TRAVERSE_TAB_NEXT: + e.doit = false; + searchBar.getDropDownTool().getFirstControl().forceFocus(); + break; + case SWT.TRAVERSE_TAB_PREVIOUS: + e.doit = false; + searchBar.getTextBar().forceFocus(); + break; + default: + // Proceed as normal + } + }; + + private final Listener searchToolsToReplaceBar = e -> { + switch (e.detail) { + case SWT.TRAVERSE_TAB_PREVIOUS: + e.doit = false; + replaceBar.forceFocus(); + break; + default: + // Proceed as normal + } + }; + + private final Listener closeToolsToReplaceTools = e -> { + switch (e.detail) { + case SWT.TRAVERSE_TAB_NEXT: + e.doit = false; + replaceBar.getDropDownTool().getFirstControl().forceFocus(); + break; + default: + // Proceed as normal + } + }; + + private final Listener replaceToolsToCloseTools = e -> { + switch (e.detail) { + case SWT.TRAVERSE_TAB_PREVIOUS: + e.doit = false; + closeTools.getFirstControl().forceFocus(); + break; + default: + // Proceed as normal + } + }; + + void apply() { + searchBar.getTextBar().addListener(SWT.Traverse, searchBarToReplaceBar); + replaceBar.getTextBar().addListener(SWT.Traverse, replaceBarToSearchBarAndTools); + searchBar.getDropDownTool().getFirstControl().addListener(SWT.Traverse, searchToolsToReplaceBar); + closeTools.getFirstControl().addListener(SWT.Traverse, closeToolsToReplaceTools); + replaceBar.getDropDownTool().getFirstControl().addListener(SWT.Traverse, replaceToolsToCloseTools); + } + + void dispose() { + searchBar.getTextBar().removeListener(SWT.Traverse, searchBarToReplaceBar); + replaceBar.getTextBar().removeListener(SWT.Traverse, replaceBarToSearchBarAndTools); + searchBar.getDropDownTool().getFirstControl().removeListener(SWT.Traverse, searchToolsToReplaceBar); + closeTools.getFirstControl().removeListener(SWT.Traverse, closeToolsToReplaceTools); + replaceBar.getDropDownTool().getFirstControl().removeListener(SWT.Traverse, replaceToolsToCloseTools); + } + } + public FindReplaceOverlay(Shell parent, IWorkbenchPart part, IFindReplaceTarget target) { targetPart = part; targetControl = getTargetControl(parent, part); @@ -647,6 +723,7 @@ public void focusLost(FocusEvent e) { searchBar.addModifyListener(Event -> { decorate(); }); + searchBar.setTabList(null); } private void updateIncrementalSearch() { @@ -710,6 +787,7 @@ private void hideReplace() { if (!replaceBarOpen) { return; } + customFocusOrder.dispose(); searchBar.forceFocus(); contentAssistReplaceField = null; replaceBarOpen = false; @@ -728,6 +806,7 @@ private void createReplaceDialog() { updatePlacementAndVisibility(); assignIDs(); replaceBar.forceFocus(); + customFocusOrder.apply(); } private void initializeReplaceShortcutHandlers() { diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/HistoryTextWrapper.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/HistoryTextWrapper.java index afd66ac03c0..0f5303f7c15 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/HistoryTextWrapper.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/HistoryTextWrapper.java @@ -207,4 +207,8 @@ public Text getTextBar() { return textBar; } + AccessibleToolBar getDropDownTool() { + return tools; + } + }