Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Keller2015-11-05 15:13:46 -0500
committerArun Thondapu2016-01-06 05:58:05 -0500
commita7bc9ddae7b09350e5d1aae1fce1a716bff1161f (patch)
tree1b8b7e1f9b8f65b71d7bb2687722241190158806
parentec03e19476aeea45050065c44f0f136900f59df8 (diff)
downloadeclipse.platform.swt-a7bc9ddae7b09350e5d1aae1fce1a716bff1161f.tar.gz
eclipse.platform.swt-a7bc9ddae7b09350e5d1aae1fce1a716bff1161f.tar.xz
eclipse.platform.swt-a7bc9ddae7b09350e5d1aae1fce1a716bff1161f.zip
Bug 480794: [GTK3] TabFolder cannot be traversed with Tab key; TabFolder#getChildren() is empty
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java7
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabFolder.java89
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java39
-rw-r--r--tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_TabFolder.java18
4 files changed, 101 insertions, 52 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java
index f45c716ef3..23d8dd009a 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java
@@ -115,15 +115,8 @@ static int checkStyle (int style) {
return style;
}
-//Containers such as Tabfolder have two sets of children,
-//e.g TabItems and actual widget children.
-//thus we need to pass in different parenting handles depending on which children we want.
Control [] _getChildren () {
long /*int*/ parentHandle = parentingHandle ();
- return _getChildren (parentHandle);
-}
-
-Control [] _getChildren (long /*int*/ parentHandle) {
long /*int*/ list = OS.gtk_container_get_children (parentHandle);
if (list == 0) return new Control [0];
int count = OS.g_list_length (list);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabFolder.java
index 7b2f4ae1a5..58db9b84a8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabFolder.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabFolder.java
@@ -48,6 +48,43 @@ import org.eclipse.swt.internal.gtk.*;
* @noextend This class is not intended to be subclassed by clients.
*/
public class TabFolder extends Composite {
+ /*
+ * Implementation note (see bug 454936, bug 480794):
+ *
+ * Architecture Change on GTK3:
+ * In TabItem#setControl(Control), we reparent the child to be a child of the 'tab'
+ * rather than tabfolder's parent swtFixed container.
+ * Note, this reparenting is only on the GTK side, not on the SWT side.
+ *
+ * GTK2 and GTK3 child nesting behaviour differs now.
+ * GTK2:
+ * swtFixed
+ * |-- GtkNoteBook
+ * | |-- tabLabel1
+ * | |-- tabLabel2
+ * |-- swtFixed (child1) //child is sibling of Notebook
+ * |-- swtFixed (child2)
+ *
+ * GTK3+:
+ * swtFixed
+ * |-- GtkNoteBook
+ * |-- tabLabel1
+ * |-- tabLabel2
+ * |-- pageHandle (tabItem1)
+ * |-- child1 //child now child of Notebook.pageHandle.
+ * |-- pageHandle (tabItem2)
+ * |-- child1
+ *
+ * This changes the hierarchy so that children are beneath gtkNotebook (as oppose to
+ * being siblings) and thus fixes DND and background color issues.
+ * In gtk2, reparenting doesn't function properly (tab content appear blank),
+ * so this is a gtk3-specific behavior.
+ *
+ * Note about the reason for reparenting:
+ * Reparenting (as opposed to adding widget to a tab in the first place) is necessary
+ * because the SWT API allows situation where you create a child control before you create a TabItem.
+ */
+
TabItem [] items;
ImageList imageList;
@@ -331,6 +368,49 @@ long /*int*/ eventHandle () {
return handle;
}
+@Override
+Control[] _getChildren() {
+ Control [] directChildren = super._getChildren ();
+ if (OS.GTK3) {
+ int directCount = directChildren.length;
+ int count = items == null ? 0 : items.length;
+ Control [] children = new Control [count + directCount];
+ int i = 0;
+ for (int j = 0; j < count; j++) {
+ TabItem tabItem = items[j];
+ if (tabItem != null) {
+ long /*int*/ parentHandle = tabItem.pageHandle;
+ long /*int*/ list = OS.gtk_container_get_children (parentHandle);
+ if (list != 0) {
+ long /*int*/ handle = OS.g_list_data (list);
+ if (handle != 0) {
+ Widget widget = display.getWidget (handle);
+ if (widget != null && widget != this) {
+ if (widget instanceof Control) {
+ children [i++] = (Control) widget;
+ }
+ }
+ }
+ OS.g_list_free (list);
+ }
+ }
+ }
+ if (i == count + directCount) return children;
+ Control [] newChildren;
+ if (i == count) {
+ newChildren = children;
+ } else {
+ newChildren = new Control [i + directCount];
+ System.arraycopy (children, 0, newChildren, 0, i);
+ }
+ System.arraycopy (directChildren, 0, newChildren, i, directCount);
+ return newChildren;
+
+ } else {
+ return directChildren;
+ }
+}
+
/**
* Returns the item at the given, zero-relative index in the
* receiver. Throws an exception if the index is out of range.
@@ -536,14 +616,7 @@ public int indexOf (TabItem item) {
@Override
Point minimumSize (int wHint, int hHint, boolean flushCache) {
- Control [] children;
- if (OS.GTK3) {
- //We want the 'Tabcontents' rather than
- //what's nested under the main swtFixed.
- children = _getChildren (clientHandle ());
- } else {
- children = _getChildren ();
- }
+ Control [] children = _getChildren ();
int width = 0, height = 0;
for (int i=0; i<children.length; i++) {
Control child = children [i];
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java
index 87b8fe5ead..90e28ee79f 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java
@@ -12,9 +12,9 @@ package org.eclipse.swt.widgets;
import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gtk.*;
-import org.eclipse.swt.graphics.*;
/**
* Instances of this class represent a selectable user interface object
@@ -288,42 +288,7 @@ public void setControl (Control control) {
}
if (control != null && OS.GTK3) {
- /*
- * Bug 454936 (see also other 454936 references in TabFolder)
- * Architecture Fix:
- * We reparent the child to be a child of the 'tab' rather than tabfolder's parent swtFixed container.
- * Note, this reparenting is only on the GTK side, not on the SWT side.
- *
- * Note, GTK2 and GTK3 child nesting behaviour is different now.
- * GTK2:
- * swtFixed
- * |-- GtkNoteBook
- * | |-- tabLabel1
- * | |-- tabLabel2
- * |-- swtFixed (child1) //child is sibling of Notebook
- * |-- swtFixed (child2)
- *
- * GTK3+:
- * swtFixed
- * |-- GtkNoteBook
- * |-- tabLabel1
- * |-- tabLabel2
- * |-- swtFixed (child1) //child now child of Notebook.
- * |-- swtFixed (child2)
- *
- * This corrects the hierarchy so that children are beneath gtkNotebook (as oppose to
- * being siblings) and thus fixes DND and background color issues.
- * In gtk2, reparenting doesn't function properly (tab content appear blank),
- * so this is a gtk3-specific behavior.
- *
- * Note about the reason for reparenting:
- * Reparenting (as oppose to adding widget to a tab in the first place) is neccessary
- * because you can have a situation where you create a widget before you create a tab. e.g
- * TabFolder tabFolder = new TabFolder(shell, 0);
- * Composite composite = new Composite(tabFolder, 0);
- * TabItem tabItem = new TabItem(tabFolder, 0);
- * tabitem.setControl(composite);
- */
+ // See implementation note about bug 454936 at the start of TabFolder.
OS.gtk_widget_reparent (control.topHandle (), pageHandle);
}
diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_TabFolder.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_TabFolder.java
index 01f32c71cb..33986fc34e 100644
--- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_TabFolder.java
+++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_TabFolder.java
@@ -16,6 +16,8 @@ import java.util.Vector;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
@@ -55,6 +57,22 @@ public void test_computeSizeIIZ() {
public void test_computeTrimIIII() {
}
+public void test_TabFolder_getChildren() {
+ ArrayList<Control> children = new ArrayList<Control>();
+ for (int i = 0; i < 6; i++) {
+ TabItem item = new TabItem(tabFolder, SWT.NONE);
+ item.setText("TabItem " + i);
+ Button button = new Button(tabFolder, SWT.PUSH);
+ button.setText("Page " + i);
+ item.setControl(button);
+ children.add(button);
+ }
+ Label label = new Label(tabFolder, SWT.NONE);
+ label.setText("Unused Child");
+ children.add(label);
+ assertArrayEquals(children.toArray(), tabFolder.getChildren());
+}
+
@Override
public void test_getClientArea() {
}

Back to the top