• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
LocationBarDecoration(int y,int height,bool auto_collapse,double max_fraction,int edge_item_padding,int item_padding,views::View * view)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 
LocationBarLayout(Position position,int item_edit_padding)72 LocationBarLayout::LocationBarLayout(Position position, int item_edit_padding)
73     : position_(position),
74       item_edit_padding_(item_edit_padding) {
75 }
76 
77 
~LocationBarLayout()78 LocationBarLayout::~LocationBarLayout() {
79 }
80 
AddDecoration(int y,int height,bool auto_collapse,double max_fraction,int edge_item_padding,int item_padding,views::View * view)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 
AddDecoration(int y,int height,views::View * view)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 
LayoutPass1(int * entry_width)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 
LayoutPass2(int * entry_width)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 
LayoutPass3(gfx::Rect * bounds,int * available_width)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