diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/handlers/TraversePageHandler.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/handlers/TraversePageHandler.java index ea7b11b14b1..926fb05ff93 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/handlers/TraversePageHandler.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/handlers/TraversePageHandler.java @@ -12,14 +12,14 @@ * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.ui.internal.handlers; - import java.lang.reflect.Method; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CTabFolder; +import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; - /** * This handler is an adaptation of the widget method handler that implements * page traversal via {@link SWT#TRAVERSE_PAGE_NEXT} and @@ -28,19 +28,25 @@ * @since 3.5 */ public class TraversePageHandler extends WidgetMethodHandler { - /** * The parameters for traverse(int). */ private static final Class[] METHOD_PARAMETERS = { int.class }; - @Override public final Object execute(final ExecutionEvent event) { Control focusControl = Display.getCurrent().getFocusControl(); if (focusControl != null) { - int traversal = "next".equals(methodName) ? SWT.TRAVERSE_PAGE_NEXT : SWT.TRAVERSE_PAGE_PREVIOUS; //$NON-NLS-1$ + boolean forward = "next".equals(methodName); //$NON-NLS-1$ + int traversal = getTraversalDirection(forward); Control control = focusControl; + do { + if (control instanceof CTabFolder folder && isFinalItemInCTabFolder(folder, forward) + && !areHiddenItems(folder)) { + loopToSecondToFirstItemInCTabFolder(folder, forward); + traversal = getTraversalDirection(!forward); // we are in the second-to-last item in the given + // direction. Now, use the Traverse-event to move back by one + } if (control.traverse(traversal)) return null; if (control instanceof Shell) @@ -48,10 +54,58 @@ public final Object execute(final ExecutionEvent event) { control = control.getParent(); } while (control != null); } - return null; } + private boolean areHiddenItems(CTabFolder folder) { + CTabItem[] items = folder.getItems(); + for (CTabItem i : items) { + if (!i.isShowing()) { + return true; + } + } + + return false; + } + private int getTraversalDirection(boolean direction) { + return direction ? SWT.TRAVERSE_PAGE_NEXT : SWT.TRAVERSE_PAGE_PREVIOUS; + } + + /** + * Sets the current selection to the second-to-last item in the given direction. + * + * @param folder the CTabFolder which we want to inspect + * @param forward whether we want to traverse forwards of backwards + */ + private void loopToSecondToFirstItemInCTabFolder(CTabFolder folder, boolean forward) { + if (forward) { + folder.showItem(folder.getItem(0)); + folder.setSelection(1); + } else { + int itemCount = folder.getItemCount(); + folder.setSelection(itemCount - 2); + } + } + + /**https://github.com/jannisCode/eclipse.jdt.ui.git + * {@return Returns whether the folder has currently selected the final item in + * the given direction.} + * + * @param folder the CTabFolder which we want to inspect + * @param forward whether we want to traverse forwards of backwards + */ + private boolean isFinalItemInCTabFolder(CTabFolder folder, boolean forward) { + CTabItem currentFolder = folder.getSelection(); + CTabItem lastFolder = null; + if (forward) { + int itemCount = folder.getItemCount(); + lastFolder = folder.getItem(itemCount - 1); + } else { + lastFolder = folder.getItem(0); + } + return currentFolder.equals(lastFolder); + } + /** * Looks up the traverse(int) method on the given focus control. * @@ -70,5 +124,4 @@ protected Method getMethodToExecute() { } return null; } - -} +} \ No newline at end of file