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.
5 #include "chrome/browser/ui/views/location_bar/location_bar_layout.h"
7 #include "chrome/browser/themes/theme_properties.h"
8 #include "ui/gfx/geometry/rect.h"
9 #include "ui/views/view.h"
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
,
19 int edge_item_padding
,
23 // The y position of the view inside its parent.
26 // The height of the view.
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.
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.
39 // Padding to use if the decoration is the first element next to the edge.
40 int edge_item_padding
;
42 // Padding to use if the decoration follows another decoration.
47 // The width computed by the layout process.
48 double computed_width
;
51 LocationBarDecoration::LocationBarDecoration(int y
,
55 int edge_item_padding
,
60 auto_collapse(auto_collapse
),
61 max_fraction(max_fraction
),
62 edge_item_padding(edge_item_padding
),
63 item_padding(item_padding
),
66 DCHECK((max_fraction
== 0.0) || (!auto_collapse
&& (max_fraction
> 0.0)));
70 // LocationBarLayout ---------------------------------------------------------
72 LocationBarLayout::LocationBarLayout(Position position
,
74 int item_edit_padding
)
75 : position_(position
),
76 item_padding_(item_padding
),
77 item_edit_padding_(item_edit_padding
) {}
79 LocationBarLayout::~LocationBarLayout() {
82 void LocationBarLayout::AddDecoration(int y
,
86 int edge_item_padding
,
89 decorations_
.push_back(new LocationBarDecoration(
90 y
, height
, auto_collapse
, max_fraction
, edge_item_padding
, item_padding
,
94 void LocationBarLayout::AddDecoration(int y
,
97 decorations_
.push_back(new LocationBarDecoration(
98 y
, height
, false, 0, item_padding_
, item_padding_
, view
));
101 void LocationBarLayout::LayoutPass1(int* entry_width
) {
102 bool first_item
= true;
103 for (Decorations::iterator
i(decorations_
.begin()); i
!= decorations_
.end();
105 // Autocollapsing decorations are ignored in this pass.
106 if (!(*i
)->auto_collapse
) {
108 (first_item
? (*i
)->edge_item_padding
: (*i
)->item_padding
);
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
;
117 *entry_width
-= item_edit_padding_
;
120 void LocationBarLayout::LayoutPass2(int *entry_width
) {
121 for (Decorations::iterator
i(decorations_
.begin()); i
!= decorations_
.end();
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
;
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();
137 // Collapse decorations if needed.
138 if ((*i
)->auto_collapse
) {
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);
149 (*i
)->view
->SetVisible(true);
150 (*available_width
) -= (*i
)->computed_width
+ padding
;
153 (*i
)->view
->SetVisible(true);
156 // Layout visible decorations.
157 if (!(*i
)->view
->visible())
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
);
169 bounds
->set_width(bounds
->width() - item_edit_padding_
);
170 if (position_
== LEFT_EDGE
)
171 bounds
->set_x(bounds
->x() + item_edit_padding_
);