| Index: chrome/browser/ui/views/location_bar/location_bar_layout.cc
|
| diff --git a/chrome/browser/ui/views/location_bar/location_bar_layout.cc b/chrome/browser/ui/views/location_bar/location_bar_layout.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..de3252ecfb04a742d2021700b556b417b2aec6ea
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/views/location_bar/location_bar_layout.cc
|
| @@ -0,0 +1,193 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/ui/views/location_bar/location_bar_layout.h"
|
| +
|
| +#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
|
| +#include "ui/gfx/rect.h"
|
| +#include "ui/views/view.h"
|
| +
|
| +// Description of a decoration to be added inside the location bar, either to
|
| +// the left or to the right.
|
| +struct LocationBarDecoration {
|
| + LocationBarDecoration(int y,
|
| + int height,
|
| + bool auto_collapse,
|
| + double max_fraction,
|
| + int edge_item_padding,
|
| + int item_padding,
|
| + int builtin_padding,
|
| + views::View* view);
|
| +
|
| + // The y position of the view inside its parent.
|
| + int y;
|
| +
|
| + // If 0, will use the preferred height of the view.
|
| + int height;
|
| +
|
| + // True means that, if there is not enough available space in the location
|
| + // bar, the view will reduce its width either to its minimal width or to zero
|
| + // (making it invisible), whichever fits. If true, |max_fraction| must be 0.
|
| + bool auto_collapse;
|
| +
|
| + // Used for resizeable decorations, indicates the maximum fraction of the
|
| + // location bar that can be taken by this decoration, 0 for non-resizable
|
| + // decorations. If non-zero, |auto_collapse| must be false.
|
| + double max_fraction;
|
| +
|
| + // Padding to use if the decoration is the first element next to the edge.
|
| + int edge_item_padding;
|
| +
|
| + // Padding to use if the decoration follows another decoration.
|
| + int item_padding;
|
| +
|
| + // Padding built into the decoration and that should be removed, on
|
| + // both sides, during layout.
|
| + int builtin_padding;
|
| +
|
| + views::View* view;
|
| +
|
| + // The width computed by the layout process.
|
| + double computed_width;
|
| +};
|
| +
|
| +LocationBarDecoration::LocationBarDecoration(int y,
|
| + int height,
|
| + bool auto_collapse,
|
| + double max_fraction,
|
| + int edge_item_padding,
|
| + int item_padding,
|
| + int builtin_padding,
|
| + views::View* view)
|
| + : y(y),
|
| + height(height),
|
| + auto_collapse(auto_collapse),
|
| + max_fraction(max_fraction),
|
| + edge_item_padding(edge_item_padding),
|
| + item_padding(item_padding),
|
| + builtin_padding(builtin_padding),
|
| + view(view),
|
| + computed_width(0) {
|
| + DCHECK(!auto_collapse || max_fraction == 0.0);
|
| + DCHECK(max_fraction >= 0.0);
|
| +}
|
| +
|
| +
|
| +// LocationBarLayout ---------------------------------------------------------
|
| +
|
| +LocationBarLayout::LocationBarLayout(Position position,
|
| + int item_edit_padding,
|
| + int edge_edit_padding)
|
| + : position_(position),
|
| + item_edit_padding_(item_edit_padding),
|
| + edge_edit_padding_(edge_edit_padding) {}
|
| +
|
| +
|
| +LocationBarLayout::~LocationBarLayout() {
|
| +}
|
| +
|
| +void LocationBarLayout::AddDecoration(int y,
|
| + int height,
|
| + bool auto_collapse,
|
| + double max_fraction,
|
| + int edge_item_padding,
|
| + int item_padding,
|
| + int builtin_padding,
|
| + views::View* view) {
|
| + decorations_.push_back(new LocationBarDecoration(y, height, auto_collapse,
|
| + max_fraction, edge_item_padding, item_padding, builtin_padding, view));
|
| +}
|
| +
|
| +void LocationBarLayout::AddDecoration(int height,
|
| + int builtin_padding,
|
| + views::View* view) {
|
| + decorations_.push_back(new LocationBarDecoration(
|
| + LocationBarView::kVerticalEdgeThickness, height, false, 0,
|
| + LocationBarView::GetEdgeItemPadding(), LocationBarView::GetItemPadding(),
|
| + builtin_padding, view));
|
| +}
|
| +
|
| +void LocationBarLayout::LayoutPass1(int* entry_width) {
|
| +
|
| + bool first_item = true;
|
| + bool at_least_one_visible = false;
|
| + for (ScopedVector<LocationBarDecoration>::iterator it(decorations_.begin());
|
| + it != decorations_.end(); ++it) {
|
| + // Autocollapsing decorations are ignored in this pass.
|
| + if (!(*it)->auto_collapse) {
|
| + at_least_one_visible = true;
|
| + *entry_width -= -2 * (*it)->builtin_padding +
|
| + (first_item ? (*it)->edge_item_padding : (*it)->item_padding);
|
| + }
|
| + first_item = false;
|
| + // Resizing decorations are ignored in this pass.
|
| + if (!(*it)->auto_collapse && (*it)->max_fraction == 0.0) {
|
| + (*it)->computed_width = (*it)->view->GetPreferredSize().width();
|
| + *entry_width -= (*it)->computed_width;
|
| + }
|
| + }
|
| + *entry_width -= at_least_one_visible ? item_edit_padding_ :
|
| + edge_edit_padding_;
|
| +}
|
| +
|
| +void LocationBarLayout::LayoutPass2(int *entry_width) {
|
| + for (ScopedVector<LocationBarDecoration>::iterator it(decorations_.begin());
|
| + it != decorations_.end(); ++it) {
|
| + if ((*it)->max_fraction > 0.0) {
|
| + int max_width = static_cast<int>(*entry_width * (*it)->max_fraction);
|
| + (*it)->computed_width = std::min((*it)->view->GetPreferredSize().width(),
|
| + std::max((*it)->view->GetMinimumSize().width(), max_width));
|
| + *entry_width -= (*it)->computed_width;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void LocationBarLayout::LayoutPass3(gfx::Rect* bounds, int* available_width) {
|
| + bool first_visible = true;
|
| + for (ScopedVector<LocationBarDecoration>::iterator it(decorations_.begin());
|
| + it != decorations_.end(); ++it) {
|
| + // Collapse decorations if needed.
|
| + if ((*it)->auto_collapse) {
|
| + int padding = -2 * (*it)->builtin_padding +
|
| + (first_visible ? (*it)->edge_item_padding : (*it)->item_padding);
|
| + // Try preferred size, if it fails try minimum size, if it fails collapse.
|
| + (*it)->computed_width = (*it)->view->GetPreferredSize().width();
|
| + if ((*it)->computed_width + padding > *available_width)
|
| + (*it)->computed_width = (*it)->view->GetMinimumSize().width();
|
| + if ((*it)->computed_width + padding > *available_width) {
|
| + (*it)->computed_width = 0;
|
| + (*it)->view->SetVisible(false);
|
| + } else {
|
| + (*it)->view->SetVisible(true);
|
| + (*available_width) -= (*it)->computed_width + padding;
|
| + }
|
| + } else {
|
| + (*it)->view->SetVisible(true);
|
| + }
|
| + // Layout visible decorations.
|
| + if ((*it)->view->visible()) {
|
| + int padding = -(*it)->builtin_padding +
|
| + (first_visible ? (*it)->edge_item_padding : (*it)->item_padding);
|
| + first_visible = false;
|
| + int x;
|
| + if (position_ == LEFT_EDGE)
|
| + x = bounds->x() + padding;
|
| + else
|
| + x = bounds->x() + bounds->width() - padding - (*it)->computed_width;
|
| + int height = (*it)->height == 0 ?
|
| + (*it)->view->GetPreferredSize().height() : (*it)->height;
|
| + (*it)->view->SetBounds(x, (*it)->y, (*it)->computed_width, height);
|
| + bounds->set_width(bounds->width() - padding - (*it)->computed_width +
|
| + (*it)->builtin_padding);
|
| + if (position_ == LEFT_EDGE) {
|
| + bounds->set_x(bounds->x() + padding + (*it)->computed_width -
|
| + (*it)->builtin_padding);
|
| + }
|
| + }
|
| + }
|
| + int final_padding = first_visible ? edge_edit_padding_ : item_edit_padding_;
|
| + bounds->set_width(bounds->width() - final_padding);
|
| + if (position_ == LEFT_EDGE)
|
| + bounds->set_x(bounds->x() + final_padding);
|
| +}
|
|
|