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/ui/views/location_bar/location_bar_view.h"
8 #include "ui/gfx/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
,
24 // The y position of the view inside its parent.
27 // The height of the view.
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.
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.
40 // Padding to use if the decoration is the first element next to the edge.
41 int edge_item_padding
;
43 // Padding to use if the decoration follows another decoration.
46 // Padding built into the decoration and that should be removed, on
47 // both sides, during layout.
52 // The width computed by the layout process.
53 double computed_width
;
56 LocationBarDecoration::LocationBarDecoration(int y
,
60 int edge_item_padding
,
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
),
73 DCHECK((max_fraction
== 0.0) || (!auto_collapse
&& (max_fraction
> 0.0)));
77 // LocationBarLayout ---------------------------------------------------------
79 LocationBarLayout::LocationBarLayout(Position position
, int item_edit_padding
)
80 : position_(position
),
81 item_edit_padding_(item_edit_padding
) {
85 LocationBarLayout::~LocationBarLayout() {
88 void LocationBarLayout::AddDecoration(int y
,
92 int edge_item_padding
,
96 decorations_
.push_back(new LocationBarDecoration(
97 y
, height
, auto_collapse
, max_fraction
, edge_item_padding
, item_padding
,
98 builtin_padding
, view
));
101 void LocationBarLayout::AddDecoration(int y
,
105 decorations_
.push_back(new LocationBarDecoration(
106 y
, height
, false, 0, LocationBarView::GetItemPadding(),
107 LocationBarView::GetItemPadding(), builtin_padding
, view
));
110 void LocationBarLayout::LayoutPass1(int* entry_width
) {
111 bool first_item
= true;
112 for (Decorations::iterator
i(decorations_
.begin()); i
!= decorations_
.end();
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
);
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
;
126 *entry_width
-= item_edit_padding_
;
129 void LocationBarLayout::LayoutPass2(int *entry_width
) {
130 for (Decorations::iterator
i(decorations_
.begin()); i
!= decorations_
.end();
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
;
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();
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);
158 (*i
)->view
->SetVisible(true);
159 (*available_width
) -= (*i
)->computed_width
+ padding
;
162 (*i
)->view
->SetVisible(true);
165 // Layout visible decorations.
166 if (!(*i
)->view
->visible())
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
) {
178 bounds
->x() + padding
+ (*i
)->computed_width
- (*i
)->builtin_padding
);
181 bounds
->set_width(bounds
->width() - item_edit_padding_
);
182 if (position_
== LEFT_EDGE
)
183 bounds
->set_x(bounds
->x() + item_edit_padding_
);