diff options
author | suzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-03 20:37:45 +0000 |
---|---|---|
committer | suzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-03 20:37:45 +0000 |
commit | ef3e7220440a9810be9d5ed99a0a109ea044691b (patch) | |
tree | 0e1e3ac9af0254b2063888494b99fb4e04314b5f /chrome/browser | |
parent | 45dd12ae7eb2213b04831c987bc8521b4a0bfea6 (diff) | |
download | chromium_src-ef3e7220440a9810be9d5ed99a0a109ea044691b.zip chromium_src-ef3e7220440a9810be9d5ed99a0a109ea044691b.tar.gz chromium_src-ef3e7220440a9810be9d5ed99a0a109ea044691b.tar.bz2 |
Fix issue 42379
Improve GtkChromeShrinkableHBox to show invisible children properly when some children are removed or shrunk.
BUG=42379 gtk_chrome_shrinkable_hbox does not always show children that should be visisble
TEST=See bug report.
Review URL: http://codereview.chromium.org/1703024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46270 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc | 46 | ||||
-rw-r--r-- | chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h | 3 | ||||
-rw-r--r-- | chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc | 5 |
3 files changed, 47 insertions, 7 deletions
diff --git a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc index 0dccb7d..5384ff4 100644 --- a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc +++ b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc @@ -30,6 +30,21 @@ void CountVisibleChildren(GtkWidget* child, gpointer userdata) { ++(*reinterpret_cast<int*>(userdata)); } +void SumChildrenWidthRequisition(GtkWidget* child, gpointer userdata) { + if (GTK_WIDGET_VISIBLE(child)) { + GtkRequisition req; + gtk_widget_get_child_requisition(child, &req); + (*reinterpret_cast<int*>(userdata)) += std::max(req.width, 0); + } +} + +void ShowInvisibleChildren(GtkWidget* child, gpointer userdata) { + if (!GTK_WIDGET_VISIBLE(child)) { + gtk_widget_show(child); + ++(*reinterpret_cast<int*>(userdata)); + } +} + void ChildSizeAllocate(GtkWidget* child, gpointer userdata) { if (!GTK_WIDGET_VISIBLE(child)) return; @@ -118,6 +133,7 @@ static void gtk_chrome_shrinkable_hbox_class_init( static void gtk_chrome_shrinkable_hbox_init(GtkChromeShrinkableHBox* box) { box->hide_child_directly = FALSE; + box->children_width_requisition = 0; } static void gtk_chrome_shrinkable_hbox_set_property(GObject* object, @@ -155,13 +171,23 @@ static void gtk_chrome_shrinkable_hbox_get_property(GObject* object, static void gtk_chrome_shrinkable_hbox_size_allocate( GtkWidget* widget, GtkAllocation* allocation) { - // If we are allocated to more width, then we need to show all invisible - // children before calling parent class's size_allocate method, because the - // new width may be enough to show those hidden children. - if (widget->allocation.width < allocation->width) { - gtk_container_foreach(GTK_CONTAINER(widget), - reinterpret_cast<GtkCallback>(gtk_widget_show), - NULL); + GtkChromeShrinkableHBox* box = GTK_CHROME_SHRINKABLE_HBOX(widget); + gint children_width_requisition = 0; + gtk_container_foreach(GTK_CONTAINER(widget), SumChildrenWidthRequisition, + &children_width_requisition); + + // If we are allocated to more width or some children are removed or shrunk, + // then we need to show all invisible children before calling parent class's + // size_allocate method, because the new width may be enough to show those + // hidden children. + if (widget->allocation.width < allocation->width || + box->children_width_requisition > children_width_requisition) { + gint count = 0; + gtk_container_foreach(GTK_CONTAINER(widget), ShowInvisibleChildren, &count); + + // If there were any invisible children, showing them will trigger another + // allocate, so we can just return here. + if (count > 0) return; } // Let the parent class do size allocation first. After that all children will @@ -174,6 +200,7 @@ static void gtk_chrome_shrinkable_hbox_size_allocate( gtk_chrome_shrinkable_hbox_get_visible_child_count( GTK_CHROME_SHRINKABLE_HBOX(widget)); + box->children_width_requisition = 0; if (visible_children_count == 0) return; @@ -190,6 +217,11 @@ static void gtk_chrome_shrinkable_hbox_size_allocate( // Shrink or hide children if necessary. gtk_container_foreach(GTK_CONTAINER(widget), ChildSizeAllocate, &data); + + // Record current width requisition of visible children, so we can know if + // it's necessary to show invisible children next time. + gtk_container_foreach(GTK_CONTAINER(widget), SumChildrenWidthRequisition, + &box->children_width_requisition); } GtkWidget* gtk_chrome_shrinkable_hbox_new(gboolean hide_child_directly, diff --git a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h index 02be55d..08d0b37 100644 --- a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h +++ b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h @@ -45,6 +45,9 @@ struct _GtkChromeShrinkableHBox { GtkHBox hbox; gboolean hide_child_directly; + + // Private + int children_width_requisition; }; struct _GtkChromeShrinkableHBoxClass { diff --git a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc index dd30c2c..db9981f 100644 --- a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc +++ b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc @@ -149,6 +149,10 @@ class GtkChromeShrinkableHBoxTest : public testing::Test { << " width = " << width); allocation.width = width; + // Expanding the width may cause some invisible children to be shown, + // which will cause queue resize, so it's necessary to do another size + // allocation to emulate the queue resize. + gtk_widget_size_allocate(box_, &allocation); gtk_widget_size_allocate(box_, &allocation); ASSERT_NO_FATAL_FAILURE(Validate(pack_start)); } @@ -171,6 +175,7 @@ class GtkChromeShrinkableHBoxTest : public testing::Test { allocation.width = width; gtk_widget_size_allocate(box_, &allocation); + gtk_widget_size_allocate(box_, &allocation); ASSERT_NO_FATAL_FAILURE(Validate(pack_start)); } } |