1212 * IBM Corporation - initial API and implementation
1313 *******************************************************************************/
1414package org .eclipse .ui .internal .handlers ;
15-
1615import java .lang .reflect .Method ;
16+ import java .util .Arrays ;
1717import org .eclipse .core .commands .ExecutionEvent ;
1818import org .eclipse .swt .SWT ;
19+ import org .eclipse .swt .custom .CTabFolder ;
20+ import org .eclipse .swt .custom .CTabItem ;
1921import org .eclipse .swt .widgets .Control ;
2022import org .eclipse .swt .widgets .Display ;
2123import 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
2829 * @since 3.5
2930 */
3031public 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 traversal = getTraversalDirection (forward );
4242 Control control = focusControl ;
4343 do {
44+ if (control instanceof CTabFolder folder && isFinalItemInCTabFolder (folder , forward )
45+ && !areHiddenItems (folder )) {
46+ loopToFirstOrLastItem (folder , forward );
47+ traversal = getTraversalDirection (!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+ }
4450 if (control .traverse (traversal ))
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 areHiddenItems (CTabFolder folder ) {
61+ return Arrays .stream (folder .getItems ()).anyMatch (i -> !i .isShowing ());
62+ }
63+
64+ private int getTraversalDirection (boolean direction ) {
65+ return direction ? 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 *
@@ -71,4 +119,4 @@ protected Method getMethodToExecute() {
71119 return null ;
72120 }
73121
74- }
122+ }
0 commit comments