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                         int builtin_padding,
     22                         views::View* view);
     23 
     24   // The y position of the view inside its parent.
     25   int y;
     26 
     27   // The height of the view.
     28   int height;
     29 
     30   // True means that, if there is not enough available space in the location
     31   // bar, the view will reduce its width either to its minimal width or to zero
     32   // (making it invisible), whichever fits. If true, |max_fraction| must be 0.
     33   bool auto_collapse;
     34 
     35   // Used for resizeable decorations, indicates the maximum fraction of the
     36   // location bar that can be taken by this decoration, 0 for non-resizable
     37   // decorations. If non-zero, |auto_collapse| must be false.
     38   double max_fraction;
     39 
     40   // Padding to use if the decoration is the first element next to the edge.
     41   int edge_item_padding;
     42 
     43   // Padding to use if the decoration follows another decoration.
     44   int item_padding;
     45 
     46   // Padding built into the decoration and that should be removed, on
     47   // both sides, during layout.
     48   int builtin_padding;
     49 
     50   views::View* view;
     51 
     52   // The width computed by the layout process.
     53   double computed_width;
     54 };
     55 
     56 LocationBarDecoration::LocationBarDecoration(int y,
     57                                              int height,
     58                                              bool auto_collapse,
     59                                              double max_fraction,
     60                                              int edge_item_padding,
     61                                              int item_padding,
     62                                              int builtin_padding,
     63                                              views::View* view)
     64     : y(y),
     65       height(height),
     66       auto_collapse(auto_collapse),
     67       max_fraction(max_fraction),
     68       edge_item_padding(edge_item_padding),
     69       item_padding(item_padding),
     70       builtin_padding(builtin_padding),
     71       view(view),
     72       computed_width(0) {
     73   DCHECK((max_fraction == 0.0) || (!auto_collapse && (max_fraction > 0.0)));
     74 }
     75 
     76 
     77 // LocationBarLayout ---------------------------------------------------------
     78 
     79 LocationBarLayout::LocationBarLayout(Position position, int item_edit_padding)
     80     : position_(position),
     81       item_edit_padding_(item_edit_padding) {
     82 }
     83 
     84 
     85 LocationBarLayout::~LocationBarLayout() {
     86 }
     87 
     88 void LocationBarLayout::AddDecoration(int y,
     89                                       int height,
     90                                       bool auto_collapse,
     91                                       double max_fraction,
     92                                       int edge_item_padding,
     93                                       int item_padding,
     94                                       int builtin_padding,
     95                                       views::View* view) {
     96   decorations_.push_back(new LocationBarDecoration(
     97       y, height, auto_collapse, max_fraction, edge_item_padding, item_padding,
     98       builtin_padding, view));
     99 }
    100 
    101 void LocationBarLayout::AddDecoration(int y,
    102                                       int height,
    103                                       int builtin_padding,
    104                                       views::View* view) {
    105   decorations_.push_back(new LocationBarDecoration(
    106       y, height, false, 0, LocationBarView::GetItemPadding(),
    107       LocationBarView::GetItemPadding(), builtin_padding, view));
    108 }
    109 
    110 void LocationBarLayout::LayoutPass1(int* entry_width) {
    111   bool first_item = true;
    112   for (Decorations::iterator i(decorations_.begin()); i != decorations_.end();
    113        ++i) {
    114     // Autocollapsing decorations are ignored in this pass.
    115     if (!(*i)->auto_collapse) {
    116       *entry_width -= -2 * (*i)->builtin_padding +
    117           (first_item ? (*i)->edge_item_padding : (*i)->item_padding);
    118     }
    119     first_item = false;
    120     // Resizing decorations are ignored in this pass.
    121     if (!(*i)->auto_collapse && ((*i)->max_fraction == 0.0)) {
    122       (*i)->computed_width = (*i)->view->GetPreferredSize().width();
    123       *entry_width -= (*i)->computed_width;
    124     }
    125   }
    126   *entry_width -= item_edit_padding_;
    127 }
    128 
    129 void LocationBarLayout::LayoutPass2(int *entry_width) {
    130   for (Decorations::iterator i(decorations_.begin()); i != decorations_.end();
    131        ++i) {
    132     if ((*i)->max_fraction > 0.0) {
    133       int max_width = static_cast<int>(*entry_width * (*i)->max_fraction);
    134       (*i)->computed_width =
    135           std::min((*i)->view->GetPreferredSize().width(),
    136                    std::max((*i)->view->GetMinimumSize().width(), max_width));
    137       *entry_width -= (*i)->computed_width;
    138     }
    139   }
    140 }
    141 
    142 void LocationBarLayout::LayoutPass3(gfx::Rect* bounds, int* available_width) {
    143   bool first_visible = true;
    144   for (Decorations::iterator i(decorations_.begin()); i != decorations_.end();
    145        ++i) {
    146     // Collapse decorations if needed.
    147     if ((*i)->auto_collapse) {
    148       int padding = -2 * (*i)->builtin_padding +
    149           (first_visible ? (*i)->edge_item_padding : (*i)->item_padding);
    150       // Try preferred size, if it fails try minimum size, if it fails collapse.
    151       (*i)->computed_width = (*i)->view->GetPreferredSize().width();
    152       if ((*i)->computed_width + padding > *available_width)
    153         (*i)->computed_width = (*i)->view->GetMinimumSize().width();
    154       if ((*i)->computed_width + padding > *available_width) {
    155         (*i)->computed_width = 0;
    156         (*i)->view->SetVisible(false);
    157       } else {
    158         (*i)->view->SetVisible(true);
    159         (*available_width) -= (*i)->computed_width + padding;
    160       }
    161     } else {
    162       (*i)->view->SetVisible(true);
    163     }
    164 
    165     // Layout visible decorations.
    166     if (!(*i)->view->visible())
    167       continue;
    168     int padding = -(*i)->builtin_padding +
    169         (first_visible ? (*i)->edge_item_padding : (*i)->item_padding);
    170     first_visible = false;
    171     int x = (position_ == LEFT_EDGE) ? (bounds->x() + padding) :
    172         (bounds->right() - padding - (*i)->computed_width);
    173     (*i)->view->SetBounds(x, (*i)->y, (*i)->computed_width, (*i)->height);
    174     bounds->set_width(bounds->width() - padding - (*i)->computed_width +
    175         (*i)->builtin_padding);
    176     if (position_ == LEFT_EDGE) {
    177       bounds->set_x(
    178           bounds->x() + padding + (*i)->computed_width - (*i)->builtin_padding);
    179     }
    180   }
    181   bounds->set_width(bounds->width() - item_edit_padding_);
    182   if (position_ == LEFT_EDGE)
    183     bounds->set_x(bounds->x() + item_edit_padding_);
    184 }
    185