Home | History | Annotate | Download | only in location_bar
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/views/location_bar/location_bar_layout.h"
      6 
      7 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
      8 #include "ui/gfx/rect.h"
      9 #include "ui/views/view.h"
     10 
     11 
     12 // Description of a decoration to be added inside the location bar, either to
     13 // the left or to the right.
     14 struct LocationBarDecoration {
     15   LocationBarDecoration(int y,
     16                         int height,
     17                         bool auto_collapse,
     18                         double max_fraction,
     19                         int edge_item_padding,
     20                         int item_padding,
     21                         views::View* view);
     22 
     23   // The y position of the view inside its parent.
     24   int y;
     25 
     26   // The height of the view.
     27   int height;
     28 
     29   // True means that, if there is not enough available space in the location
     30   // bar, the view will reduce its width either to its minimal width or to zero
     31   // (making it invisible), whichever fits. If true, |max_fraction| must be 0.
     32   bool auto_collapse;
     33 
     34   // Used for resizeable decorations, indicates the maximum fraction of the
     35   // location bar that can be taken by this decoration, 0 for non-resizable
     36   // decorations. If non-zero, |auto_collapse| must be false.
     37   double max_fraction;
     38 
     39   // Padding to use if the decoration is the first element next to the edge.
     40   int edge_item_padding;
     41 
     42   // Padding to use if the decoration follows another decoration.
     43   int item_padding;
     44 
     45   views::View* view;
     46 
     47   // The width computed by the layout process.
     48   double computed_width;
     49 };
     50 
     51 LocationBarDecoration::LocationBarDecoration(int y,
     52                                              int height,
     53                                              bool auto_collapse,
     54                                              double max_fraction,
     55                                              int edge_item_padding,
     56                                              int item_padding,
     57                                              views::View* view)
     58     : y(y),
     59       height(height),
     60       auto_collapse(auto_collapse),
     61       max_fraction(max_fraction),
     62       edge_item_padding(edge_item_padding),
     63       item_padding(item_padding),
     64       view(view),
     65       computed_width(0) {
     66   DCHECK((max_fraction == 0.0) || (!auto_collapse && (max_fraction > 0.0)));
     67 }
     68 
     69 
     70 // LocationBarLayout ---------------------------------------------------------
     71 
     72 LocationBarLayout::LocationBarLayout(Position position, int item_edit_padding)
     73     : position_(position),
     74       item_edit_padding_(item_edit_padding) {
     75 }
     76 
     77 
     78 LocationBarLayout::~LocationBarLayout() {
     79 }
     80 
     81 void LocationBarLayout::AddDecoration(int y,
     82                                       int height,
     83                                       bool auto_collapse,
     84                                       double max_fraction,
     85                                       int edge_item_padding,
     86                                       int item_padding,
     87                                       views::View* view) {
     88   decorations_.push_back(new LocationBarDecoration(
     89       y, height, auto_collapse, max_fraction, edge_item_padding, item_padding,
     90       view));
     91 }
     92 
     93 void LocationBarLayout::AddDecoration(int y,
     94                                       int height,
     95                                       views::View* view) {
     96   decorations_.push_back(new LocationBarDecoration(
     97       y, height, false, 0, LocationBarView::kItemPadding,
     98       LocationBarView::kItemPadding, view));
     99 }
    100 
    101 void LocationBarLayout::LayoutPass1(int* entry_width) {
    102   bool first_item = true;
    103   for (Decorations::iterator i(decorations_.begin()); i != decorations_.end();
    104        ++i) {
    105     // Autocollapsing decorations are ignored in this pass.
    106     if (!(*i)->auto_collapse) {
    107       *entry_width -=
    108           (first_item ? (*i)->edge_item_padding : (*i)->item_padding);
    109     }
    110     first_item = false;
    111     // Resizing decorations are ignored in this pass.
    112     if (!(*i)->auto_collapse && ((*i)->max_fraction == 0.0)) {
    113       (*i)->computed_width = (*i)->view->GetPreferredSize().width();
    114       *entry_width -= (*i)->computed_width;
    115     }
    116   }
    117   *entry_width -= item_edit_padding_;
    118 }
    119 
    120 void LocationBarLayout::LayoutPass2(int *entry_width) {
    121   for (Decorations::iterator i(decorations_.begin()); i != decorations_.end();
    122        ++i) {
    123     if ((*i)->max_fraction > 0.0) {
    124       int max_width = static_cast<int>(*entry_width * (*i)->max_fraction);
    125       (*i)->computed_width =
    126           std::min((*i)->view->GetPreferredSize().width(),
    127                    std::max((*i)->view->GetMinimumSize().width(), max_width));
    128       *entry_width -= (*i)->computed_width;
    129     }
    130   }
    131 }
    132 
    133 void LocationBarLayout::LayoutPass3(gfx::Rect* bounds, int* available_width) {
    134   bool first_visible = true;
    135   for (Decorations::iterator i(decorations_.begin()); i != decorations_.end();
    136        ++i) {
    137     // Collapse decorations if needed.
    138     if ((*i)->auto_collapse) {
    139       int padding =
    140           (first_visible ? (*i)->edge_item_padding : (*i)->item_padding);
    141       // Try preferred size, if it fails try minimum size, if it fails collapse.
    142       (*i)->computed_width = (*i)->view->GetPreferredSize().width();
    143       if ((*i)->computed_width + padding > *available_width)
    144         (*i)->computed_width = (*i)->view->GetMinimumSize().width();
    145       if ((*i)->computed_width + padding > *available_width) {
    146         (*i)->computed_width = 0;
    147         (*i)->view->SetVisible(false);
    148       } else {
    149         (*i)->view->SetVisible(true);
    150         (*available_width) -= (*i)->computed_width + padding;
    151       }
    152     } else {
    153       (*i)->view->SetVisible(true);
    154     }
    155 
    156     // Layout visible decorations.
    157     if (!(*i)->view->visible())
    158       continue;
    159     int padding =
    160         (first_visible ? (*i)->edge_item_padding : (*i)->item_padding);
    161     first_visible = false;
    162     int x = (position_ == LEFT_EDGE) ? (bounds->x() + padding) :
    163         (bounds->right() - padding - (*i)->computed_width);
    164     (*i)->view->SetBounds(x, (*i)->y, (*i)->computed_width, (*i)->height);
    165     bounds->set_width(bounds->width() - padding - (*i)->computed_width);
    166     if (position_ == LEFT_EDGE)
    167       bounds->set_x(bounds->x() + padding + (*i)->computed_width);
    168   }
    169   bounds->set_width(bounds->width() - item_edit_padding_);
    170   if (position_ == LEFT_EDGE)
    171     bounds->set_x(bounds->x() + item_edit_padding_);
    172 }
    173