diff options
| author | Markus Keller | 2015-11-05 20:13:46 +0000 |
|---|---|---|
| committer | Arun Thondapu | 2016-01-06 10:58:05 +0000 |
| commit | a7bc9ddae7b09350e5d1aae1fce1a716bff1161f (patch) | |
| tree | 1b8b7e1f9b8f65b71d7bb2687722241190158806 | |
| parent | ec03e19476aeea45050065c44f0f136900f59df8 (diff) | |
| download | eclipse.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
Change-Id: Ib9559713fcf327a535b32be3b12de08467eb9c15
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() { } |
