diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-15 07:38:39 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-15 07:38:39 +0000 |
commit | b3c1185aa4baa0fb007830d0350fc8e8af61144a (patch) | |
tree | 35dd500c143725303cd86416cc5242dc28212c16 /ui | |
parent | ede53873904fc261bd171df9de822a33227e1b03 (diff) | |
download | chromium_src-b3c1185aa4baa0fb007830d0350fc8e8af61144a.zip chromium_src-b3c1185aa4baa0fb007830d0350fc8e8af61144a.tar.gz chromium_src-b3c1185aa4baa0fb007830d0350fc8e8af61144a.tar.bz2 |
make BoxLayout use and respect GetHeightForWidth() (for vertical layouts).
BUG=none
Review URL: https://chromiumcodereview.appspot.com/12575005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188288 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/views/layout/box_layout.cc | 105 | ||||
-rw-r--r-- | ui/views/layout/box_layout.h | 12 | ||||
-rw-r--r-- | ui/views/layout/box_layout_unittest.cc | 38 |
3 files changed, 121 insertions, 34 deletions
diff --git a/ui/views/layout/box_layout.cc b/ui/views/layout/box_layout.cc index 319efa7..0111485 100644 --- a/ui/views/layout/box_layout.cc +++ b/ui/views/layout/box_layout.cc @@ -4,7 +4,6 @@ #include "ui/views/layout/box_layout.h" -#include "ui/gfx/insets.h" #include "ui/gfx/rect.h" #include "ui/views/view.h" @@ -15,8 +14,10 @@ BoxLayout::BoxLayout(BoxLayout::Orientation orientation, int inside_border_vertical_spacing, int between_child_spacing) : orientation_(orientation), - inside_border_horizontal_spacing_(inside_border_horizontal_spacing), - inside_border_vertical_spacing_(inside_border_vertical_spacing), + inside_border_insets_(inside_border_vertical_spacing, + inside_border_horizontal_spacing, + inside_border_vertical_spacing, + inside_border_horizontal_spacing), between_child_spacing_(between_child_spacing), spread_blank_space_(false) { } @@ -27,8 +28,7 @@ BoxLayout::~BoxLayout() { void BoxLayout::Layout(View* host) { gfx::Rect child_area(host->GetLocalBounds()); child_area.Inset(host->GetInsets()); - child_area.Inset(inside_border_horizontal_spacing_, - inside_border_vertical_spacing_); + child_area.Inset(inside_border_insets_); int x = child_area.x(); int y = child_area.y(); @@ -40,10 +40,12 @@ void BoxLayout::Layout(View* host) { View* child = host->child_at(i); if (!child->visible()) continue; - if (orientation_ == kHorizontal) + if (orientation_ == kHorizontal) { total += child->GetPreferredSize().width() + between_child_spacing_; - else - total += child->GetPreferredSize().height() + between_child_spacing_; + } else { + total += child->GetHeightForWidth(child_area.width()) + + between_child_spacing_; + } ++visible; } @@ -63,13 +65,12 @@ void BoxLayout::Layout(View* host) { View* child = host->child_at(i); if (child->visible()) { gfx::Rect bounds(x, y, child_area.width(), child_area.height()); - gfx::Size size(child->GetPreferredSize()); if (orientation_ == kHorizontal) { - bounds.set_width(size.width() + padding); - x += size.width() + between_child_spacing_ + padding; + bounds.set_width(child->GetPreferredSize().width() + padding); + x += bounds.width() + between_child_spacing_; } else { - bounds.set_height(size.height() + padding); - y += size.height() + between_child_spacing_ + padding; + bounds.set_height(child->GetHeightForWidth(bounds.width()) + padding); + y += bounds.height() + between_child_spacing_; } // Clamp child view bounds to |child_area|. bounds.Intersect(child_area); @@ -79,28 +80,70 @@ void BoxLayout::Layout(View* host) { } gfx::Size BoxLayout::GetPreferredSize(View* host) { - gfx::Rect bounds; - int position = 0; - for (int i = 0; i < host->child_count(); ++i) { - View* child = host->child_at(i); - if (child->visible()) { + // Calculate the child views' preferred width. + int width = 0; + if (orientation_ == kVertical) { + for (int i = 0; i < host->child_count(); ++i) { + View* child = host->child_at(i); + if (!child->visible()) + continue; + + width = std::max(width, child->GetPreferredSize().width()); + } + } + + return GetPreferredSizeForChildWidth(host, width); +} + +int BoxLayout::GetPreferredHeightForWidth(View* host, int width) { + int child_width = width - NonChildSize(host).width(); + return GetPreferredSizeForChildWidth(host, child_width).height(); +} + +gfx::Size BoxLayout::GetPreferredSizeForChildWidth(View* host, + int child_area_width) { + gfx::Rect child_area_bounds; + + if (orientation_ == kHorizontal) { + // Horizontal layouts ignore |child_area_width|, meaning they mimic the + // default behavior of GridLayout::GetPreferredHeightForWidth(). + // TODO(estade): fix this if it ever becomes a problem. + int position = 0; + for (int i = 0; i < host->child_count(); ++i) { + View* child = host->child_at(i); + if (!child->visible()) + continue; + gfx::Size size(child->GetPreferredSize()); - if (orientation_ == kHorizontal) { - gfx::Rect child_bounds(position, 0, size.width(), size.height()); - bounds.Union(child_bounds); - position += size.width(); - } else { - gfx::Rect child_bounds(0, position, size.width(), size.height()); - bounds.Union(child_bounds); - position += size.height(); - } - position += between_child_spacing_; + gfx::Rect child_bounds(position, 0, size.width(), size.height()); + child_area_bounds.Union(child_bounds); + position += size.width() + between_child_spacing_; } + } else { + int height = 0; + for (int i = 0; i < host->child_count(); ++i) { + View* child = host->child_at(i); + if (!child->visible()) + continue; + + height += child->GetHeightForWidth(child_area_width); + if (i != 0) + height += between_child_spacing_; + } + + child_area_bounds.set_width(child_area_width); + child_area_bounds.set_height(height); } + + gfx::Size non_child_size = NonChildSize(host); + return gfx::Size(child_area_bounds.width() + non_child_size.width(), + child_area_bounds.height() + non_child_size.height()); +} + +gfx::Size BoxLayout::NonChildSize(View* host) { gfx::Insets insets(host->GetInsets()); - return gfx::Size( - bounds.width() + insets.width() + 2 * inside_border_horizontal_spacing_, - bounds.height() + insets.height() + 2 * inside_border_vertical_spacing_); + return gfx::Size(insets.width() + inside_border_insets_.width(), + insets.height() + inside_border_insets_.height()); } } // namespace views diff --git a/ui/views/layout/box_layout.h b/ui/views/layout/box_layout.h index b592cc6..7670d8c 100644 --- a/ui/views/layout/box_layout.h +++ b/ui/views/layout/box_layout.h @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "ui/gfx/insets.h" #include "ui/views/layout/layout_manager.h" namespace gfx { @@ -46,13 +47,20 @@ class VIEWS_EXPORT BoxLayout : public LayoutManager { // Overridden from views::LayoutManager: virtual void Layout(View* host) OVERRIDE; virtual gfx::Size GetPreferredSize(View* host) OVERRIDE; + virtual int GetPreferredHeightForWidth(View* host, int width) OVERRIDE; private: + // The preferred size for the dialog given the width of the child area. + gfx::Size GetPreferredSizeForChildWidth(View* host, int child_area_width); + + // The amount of space the layout requires in addition to any space for the + // child views. + gfx::Size NonChildSize(View* host); + const Orientation orientation_; // Spacing between child views and host view border. - const int inside_border_horizontal_spacing_; - const int inside_border_vertical_spacing_; + gfx::Insets inside_border_insets_; // Spacing to put in between child views. const int between_child_spacing_; diff --git a/ui/views/layout/box_layout_unittest.cc b/ui/views/layout/box_layout_unittest.cc index 017120d..130e14d 100644 --- a/ui/views/layout/box_layout_unittest.cc +++ b/ui/views/layout/box_layout_unittest.cc @@ -16,13 +16,33 @@ class StaticSizedView : public View { explicit StaticSizedView(const gfx::Size& size) : size_(size) { } + virtual ~StaticSizedView() {} - virtual gfx::Size GetPreferredSize() OVERRIDE{ + virtual gfx::Size GetPreferredSize() OVERRIDE { return size_; } private: gfx::Size size_; + + DISALLOW_COPY_AND_ASSIGN(StaticSizedView); +}; + +class ProportionallySizedView : public View { + public: + explicit ProportionallySizedView(int factor) : factor_(factor) {} + virtual ~ProportionallySizedView() {} + + virtual int GetHeightForWidth(int w) OVERRIDE { + return w * factor_; + } + + private: + // The multiplicative factor between width and height, i.e. + // height = width * factor_. + int factor_; + + DISALLOW_COPY_AND_ASSIGN(ProportionallySizedView); }; class BoxLayoutTest : public testing::Test { @@ -131,4 +151,20 @@ TEST_F(BoxLayoutTest, DistributeEmptySpace) { EXPECT_EQ(gfx::Rect(60, 10, 30, 20).ToString(), v2->bounds().ToString()); } +TEST_F(BoxLayoutTest, UseHeightForWidth) { + layout_.reset(new BoxLayout(BoxLayout::kVertical, 0, 0, 0)); + View* v1 = new StaticSizedView(gfx::Size(20, 10)); + host_->AddChildView(v1); + View* v2 = new ProportionallySizedView(2); + host_->AddChildView(v2); + EXPECT_EQ(gfx::Size(20, 50), layout_->GetPreferredSize(host_.get())); + + host_->SetBounds(0, 0, 20, 50); + layout_->Layout(host_.get()); + EXPECT_EQ(gfx::Rect(0, 0, 20, 10), v1->bounds()); + EXPECT_EQ(gfx::Rect(0, 10, 20, 40), v2->bounds()); + + EXPECT_EQ(110, layout_->GetPreferredHeightForWidth(host_.get(), 50)); +} + } // namespace views |