Skip to content

Commit 2de3957

Browse files
jannisCodefedejeanne
authored andcommitted
Add circular navigation between open tabs
When navigating the open tabs with Ctrl+Pg Up/Down and only if there is no chevron (i.e. more tabs opened than one can show) then the tab next to the last one is the first one and the tab previous to the first one is the last one.
1 parent 9ee216c commit 2de3957

File tree

1 file changed

+56
-9
lines changed

1 file changed

+56
-9
lines changed

bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/handlers/TraversePageHandler.java

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@
1212
* IBM Corporation - initial API and implementation
1313
*******************************************************************************/
1414
package org.eclipse.ui.internal.handlers;
15-
1615
import java.lang.reflect.Method;
16+
import java.util.Arrays;
1717
import org.eclipse.core.commands.ExecutionEvent;
1818
import org.eclipse.swt.SWT;
19+
import org.eclipse.swt.custom.CTabFolder;
20+
import org.eclipse.swt.custom.CTabItem;
1921
import org.eclipse.swt.widgets.Control;
2022
import org.eclipse.swt.widgets.Display;
2123
import org.eclipse.swt.widgets.Shell;
22-
2324
/**
2425
* This handler is an adaptation of the widget method handler that implements
2526
* page traversal via {@link SWT#TRAVERSE_PAGE_NEXT} and
@@ -28,30 +29,77 @@
2829
* @since 3.5
2930
*/
3031
public class TraversePageHandler extends WidgetMethodHandler {
31-
3232
/**
3333
* The parameters for traverse(int).
3434
*/
3535
private static final Class<?>[] METHOD_PARAMETERS = { int.class };
36-
3736
@Override
3837
public final Object execute(final ExecutionEvent event) {
3938
Control focusControl = Display.getCurrent().getFocusControl();
4039
if (focusControl != null) {
41-
int traversal = "next".equals(methodName) ? SWT.TRAVERSE_PAGE_NEXT : SWT.TRAVERSE_PAGE_PREVIOUS; //$NON-NLS-1$
40+
boolean forward = "next".equals(methodName); //$NON-NLS-1$
41+
int traversalDirection = translateToTraversalDirection(forward);
4242
Control control = focusControl;
4343
do {
44-
if (control.traverse(traversal))
44+
if (control instanceof CTabFolder folder && isFinalItemInCTabFolder(folder, forward)
45+
&& !hasHiddenItem(folder)) {
46+
loopToFirstOrLastItem(folder, forward);
47+
traversalDirection = translateToTraversalDirection(!forward); // we are in the second-to-last item in the given
48+
// direction. Now, use the Traverse-event to move back by one
49+
}
50+
if (control.traverse(traversalDirection))
4551
return null;
4652
if (control instanceof Shell)
4753
return null;
4854
control = control.getParent();
4955
} while (control != null);
5056
}
51-
5257
return null;
5358
}
5459

60+
private boolean hasHiddenItem(CTabFolder folder) {
61+
return Arrays.stream(folder.getItems()).anyMatch(i -> !i.isShowing());
62+
}
63+
64+
private int translateToTraversalDirection(boolean forward) {
65+
return forward ? SWT.TRAVERSE_PAGE_NEXT : SWT.TRAVERSE_PAGE_PREVIOUS;
66+
}
67+
68+
/**
69+
* Sets the current selection to the first or last item the given direction.
70+
*
71+
* @param folder the CTabFolder which we want to inspect
72+
* @param forward whether we want to traverse forwards of backwards
73+
*/
74+
private void loopToFirstOrLastItem(CTabFolder folder, boolean forward) {
75+
if (forward) {
76+
folder.showItem(folder.getItem(0));
77+
folder.setSelection(1);
78+
} else {
79+
int itemCount = folder.getItemCount();
80+
folder.setSelection(itemCount - 2);
81+
}
82+
}
83+
84+
/**
85+
* {@return Returns whether the folder has currently selected the final item in
86+
* the given direction.}
87+
*
88+
* @param folder the CTabFolder which we want to inspect
89+
* @param forward whether we want to traverse forwards of backwards
90+
*/
91+
private boolean isFinalItemInCTabFolder(CTabFolder folder, boolean forward) {
92+
CTabItem currentFolder = folder.getSelection();
93+
CTabItem lastFolder = null;
94+
if (forward) {
95+
int itemCount = folder.getItemCount();
96+
lastFolder = folder.getItem(itemCount - 1);
97+
} else {
98+
lastFolder = folder.getItem(0);
99+
}
100+
return currentFolder.equals(lastFolder);
101+
}
102+
55103
/**
56104
* Looks up the traverse(int) method on the given focus control.
57105
*
@@ -70,5 +118,4 @@ protected Method getMethodToExecute() {
70118
}
71119
return null;
72120
}
73-
74-
}
121+
}

0 commit comments

Comments
 (0)