Skip to content

Commit 78af158

Browse files
committed
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 #2161
1 parent ea68ca2 commit 78af158

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/AccessibleToolBar.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,9 @@ void registerActionShortcutsAtControl(Control control) {
7474
}
7575
}
7676

77+
Control getFirstControl() {
78+
Control[] children = getChildren();
79+
return children.length == 0 ? null : getChildren()[0];
80+
}
81+
7782
}

bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.eclipse.swt.widgets.Composite;
3939
import org.eclipse.swt.widgets.Control;
4040
import org.eclipse.swt.widgets.Display;
41+
import org.eclipse.swt.widgets.Listener;
4142
import org.eclipse.swt.widgets.ScrollBar;
4243
import org.eclipse.swt.widgets.Scrollable;
4344
import org.eclipse.swt.widgets.Shell;
@@ -218,6 +219,81 @@ public void reactivate() {
218219

219220
};
220221

222+
private final CustomFocusOrder customFocusOrder = new CustomFocusOrder();
223+
224+
private class CustomFocusOrder {
225+
private final Listener searchBarToReplaceBar = e -> {
226+
if (e.detail == SWT.TRAVERSE_TAB_NEXT) {
227+
e.doit = false;
228+
replaceBar.forceFocus();
229+
}
230+
};
231+
232+
private final Listener replaceBarToSearchBarAndTools = e -> {
233+
switch (e.detail) {
234+
case SWT.TRAVERSE_TAB_NEXT:
235+
e.doit = false;
236+
searchBar.getDropDownTool().getFirstControl().forceFocus();
237+
break;
238+
case SWT.TRAVERSE_TAB_PREVIOUS:
239+
e.doit = false;
240+
searchBar.getTextBar().forceFocus();
241+
break;
242+
default:
243+
// Proceed as normal
244+
}
245+
};
246+
247+
private final Listener searchToolsToReplaceBar = e -> {
248+
switch (e.detail) {
249+
case SWT.TRAVERSE_TAB_PREVIOUS:
250+
e.doit = false;
251+
replaceBar.forceFocus();
252+
break;
253+
default:
254+
// Proceed as normal
255+
}
256+
};
257+
258+
private final Listener closeToolsToReplaceTools = e -> {
259+
switch (e.detail) {
260+
case SWT.TRAVERSE_TAB_NEXT:
261+
e.doit = false;
262+
replaceBar.getDropDownTool().getFirstControl().forceFocus();
263+
break;
264+
default:
265+
// Proceed as normal
266+
}
267+
};
268+
269+
private final Listener replaceToolsToCloseTools = e -> {
270+
switch (e.detail) {
271+
case SWT.TRAVERSE_TAB_PREVIOUS:
272+
e.doit = false;
273+
closeTools.getFirstControl().forceFocus();
274+
break;
275+
default:
276+
// Proceed as normal
277+
}
278+
};
279+
280+
void apply() {
281+
searchBar.getTextBar().addListener(SWT.Traverse, searchBarToReplaceBar);
282+
replaceBar.getTextBar().addListener(SWT.Traverse, replaceBarToSearchBarAndTools);
283+
searchBar.getDropDownTool().getFirstControl().addListener(SWT.Traverse, searchToolsToReplaceBar);
284+
closeTools.getFirstControl().addListener(SWT.Traverse, closeToolsToReplaceTools);
285+
replaceBar.getDropDownTool().getFirstControl().addListener(SWT.Traverse, replaceToolsToCloseTools);
286+
}
287+
288+
void dispose() {
289+
searchBar.getTextBar().removeListener(SWT.Traverse, searchBarToReplaceBar);
290+
replaceBar.getTextBar().removeListener(SWT.Traverse, replaceBarToSearchBarAndTools);
291+
searchBar.getDropDownTool().getFirstControl().removeListener(SWT.Traverse, searchToolsToReplaceBar);
292+
closeTools.getFirstControl().removeListener(SWT.Traverse, closeToolsToReplaceTools);
293+
replaceBar.getDropDownTool().getFirstControl().removeListener(SWT.Traverse, replaceToolsToCloseTools);
294+
}
295+
}
296+
221297
public FindReplaceOverlay(Shell parent, IWorkbenchPart part, IFindReplaceTarget target) {
222298
targetPart = part;
223299
targetControl = getTargetControl(parent, part);
@@ -647,6 +723,7 @@ public void focusLost(FocusEvent e) {
647723
searchBar.addModifyListener(Event -> {
648724
decorate();
649725
});
726+
searchBar.setTabList(null);
650727
}
651728

652729
private void updateIncrementalSearch() {
@@ -710,6 +787,7 @@ private void hideReplace() {
710787
if (!replaceBarOpen) {
711788
return;
712789
}
790+
customFocusOrder.dispose();
713791
searchBar.forceFocus();
714792
contentAssistReplaceField = null;
715793
replaceBarOpen = false;
@@ -728,6 +806,7 @@ private void createReplaceDialog() {
728806
updatePlacementAndVisibility();
729807
assignIDs();
730808
replaceBar.forceFocus();
809+
customFocusOrder.apply();
731810
}
732811

733812
private void initializeReplaceShortcutHandlers() {

bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/HistoryTextWrapper.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,8 @@ public Text getTextBar() {
207207
return textBar;
208208
}
209209

210+
AccessibleToolBar getDropDownTool() {
211+
return tools;
212+
}
213+
210214
}

0 commit comments

Comments
 (0)