1+ /*******************************************************************************
2+ * Copyright (c) 2004, 2015 IBM Corporation and others.
3+ *
4+ * This program and the accompanying materials
5+ * are made available under the terms of the Eclipse Public License 2.0
6+ * which accompanies this distribution, and is available at
7+ * https://www.eclipse.org/legal/epl-2.0/
8+ *
9+ * SPDX-License-Identifier: EPL-2.0
10+ *
11+ * Contributors:
12+ * IBM Corporation - initial API and implementation
13+ *******************************************************************************/
14+ package org .eclipse .ui .internal .handlers ;
15+ import java .lang .reflect .Method ;
16+ import org .eclipse .core .commands .ExecutionEvent ;
17+ import org .eclipse .swt .SWT ;
18+ import org .eclipse .swt .custom .CTabFolder ;
19+ import org .eclipse .swt .custom .CTabItem ;
20+ import org .eclipse .swt .widgets .Control ;
21+ import org .eclipse .swt .widgets .Display ;
22+ import org .eclipse .swt .widgets .Shell ;
23+ /**
24+ * This handler is an adaptation of the widget method handler that implements
25+ * page traversal via {@link SWT#TRAVERSE_PAGE_NEXT} and
26+ * {@link SWT#TRAVERSE_PAGE_PREVIOUS} events.
27+ *
28+ * @since 3.5
29+ */
30+ public class TraversePageHandler extends WidgetMethodHandler {
31+ /**
32+ * The parameters for traverse(int).
33+ */
34+ private static final Class <?>[] METHOD_PARAMETERS = { int .class };
35+ @ Override
36+ public final Object execute (final ExecutionEvent event ) {
37+ Control focusControl = Display .getCurrent ().getFocusControl ();
38+ if (focusControl != null ) {
39+ boolean forward = "next" .equals (methodName ); //$NON-NLS-1$
40+ int traversal = getTraversalDirection (forward );
41+ Control control = focusControl ;
42+
43+ do {
44+ if (control instanceof CTabFolder folder && isFinalItemInCTabFolder (folder , forward )
45+ && !areHiddenItems (folder )) {
46+ loopToSecondToFirstItemInCTabFolder (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+ }
50+ if (control .traverse (traversal ))
51+ return null ;
52+ if (control instanceof Shell )
53+ return null ;
54+ control = control .getParent ();
55+ } while (control != null );
56+ }
57+ return null ;
58+ }
59+
60+ private boolean areHiddenItems (CTabFolder folder ) {
61+ CTabItem [] items = folder .getItems ();
62+ for (CTabItem i : items ) {
63+ if (!i .isShowing ()) {
64+ return true ;
65+ }
66+ }
67+
68+ return false ;
69+ }
70+ private int getTraversalDirection (boolean direction ) {
71+ return direction ? SWT .TRAVERSE_PAGE_NEXT : SWT .TRAVERSE_PAGE_PREVIOUS ;
72+ }
73+
74+ /**
75+ * Sets the current selection to the second-to-last item in the given direction.
76+ *
77+ * @param folder the CTabFolder which we want to inspect
78+ * @param forward whether we want to traverse forwards of backwards
79+ */
80+ private void loopToSecondToFirstItemInCTabFolder (CTabFolder folder , boolean forward ) {
81+ if (forward ) {
82+ folder .showItem (folder .getItem (0 ));
83+ folder .setSelection (1 );
84+ } else {
85+ int itemCount = folder .getItemCount ();
86+ folder .setSelection (itemCount - 2 );
87+ }
88+ }
89+
90+ /**https://github.com/jannisCode/eclipse.jdt.ui.git
91+ * {@return Returns whether the folder has currently selected the final item in
92+ * the given direction.}
93+ *
94+ * @param folder the CTabFolder which we want to inspect
95+ * @param forward whether we want to traverse forwards of backwards
96+ */
97+ private boolean isFinalItemInCTabFolder (CTabFolder folder , boolean forward ) {
98+ CTabItem currentFolder = folder .getSelection ();
99+ CTabItem lastFolder = null ;
100+ if (forward ) {
101+ int itemCount = folder .getItemCount ();
102+ lastFolder = folder .getItem (itemCount - 1 );
103+ } else {
104+ lastFolder = folder .getItem (0 );
105+ }
106+ return currentFolder .equals (lastFolder );
107+ }
108+
109+ /**
110+ * Looks up the traverse(int) method on the given focus control.
111+ *
112+ * @return The method on the focus control; <code>null</code> if none.
113+ */
114+ @ Override
115+ protected Method getMethodToExecute () {
116+ final Control focusControl = Display .getCurrent ().getFocusControl ();
117+ if (focusControl != null ) {
118+ try {
119+ return focusControl .getClass ().getMethod ("traverse" , //$NON-NLS-1$
120+ METHOD_PARAMETERS );
121+ } catch (NoSuchMethodException e ) {
122+ // Do nothing.
123+ }
124+ }
125+ return null ;
126+ }
127+ }
0 commit comments