[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / views / frame / opaque_browser_frame_view_layout.cc
blob5c5dd456d63fb52de53b72b6773ed609f35b507a
1 // Copyright 2013 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/frame/opaque_browser_frame_view_layout.h"
7 #include "base/command_line.h"
8 #include "chrome/browser/profiles/profiles_state.h"
9 #include "chrome/browser/ui/views/profiles/avatar_label.h"
10 #include "chrome/browser/ui/views/profiles/avatar_menu_button.h"
11 #include "chrome/common/chrome_switches.h"
12 #include "components/signin/core/common/profile_management_switches.h"
13 #include "ui/gfx/font.h"
14 #include "ui/views/controls/button/image_button.h"
15 #include "ui/views/controls/label.h"
17 namespace {
19 // Besides the frame border, there's another 9 px of empty space atop the
20 // window in restored mode, to use to drag the window around.
21 const int kNonClientRestoredExtraThickness = 9;
23 // The titlebar never shrinks too short to show the caption button plus some
24 // padding below it.
25 const int kCaptionButtonHeightWithPadding = 19;
27 // There is a 5 px gap between the title text and the caption buttons.
28 const int kTitleLogoSpacing = 5;
30 // The frame border is only visible in restored mode and is hardcoded to 4 px on
31 // each side regardless of the system window border size.
32 const int kFrameBorderThickness = 4;
34 // The titlebar has a 2 px 3D edge along the top and bottom.
35 const int kTitlebarTopAndBottomEdgeThickness = 2;
37 // The icon is inset 2 px from the left frame border.
38 const int kIconLeftSpacing = 2;
40 // There is a 4 px gap between the icon and the title text.
41 const int kIconTitleSpacing = 4;
43 // The avatar ends 2 px above the bottom of the tabstrip (which, given the
44 // way the tabstrip draws its bottom edge, will appear like a 1 px gap to the
45 // user).
46 const int kAvatarBottomSpacing = 2;
48 // Space between the frame border and the edge of the avatar.
49 const int kAvatarOuterSpacing = 2;
51 // Space between the edge of the avatar and the tabstrip.
52 const int kAvatarInnerSpacing = 4;
54 // Space between the trailing edge of the avatar label and the tabstrip.
55 const int kAvatarLabelInnerSpacing = 10;
57 // How far the new avatar button is from the closest caption button.
58 const int kNewAvatarButtonOffset = 5;
60 // When the title bar is in its normal two row mode (usually the case for
61 // restored windows), the New Tab button isn't at the same height as the caption
62 // buttons, but the space will look cluttered if it actually slides under them,
63 // so we stop it when the gap between the two is down to 5 px.
64 const int kNewTabCaptionNormalSpacing = 5;
66 // When the title bar is condensed to one row (as when maximized), the New Tab
67 // button and the caption buttons are at similar vertical coordinates, so we
68 // need to reserve a larger, 16 px gap to avoid looking too cluttered.
69 const int kNewTabCaptionCondensedSpacing = 16;
71 // If there are no caption buttons to the right of the New Tab button, we
72 // reserve a small 5px gap, regardless of whether the window is maximized. This
73 // overrides the two previous constants.
74 const int kNewTabNoCaptionButtonsSpacing = 5;
76 // The top 3 px of the tabstrip is shadow; in maximized mode we push this off
77 // the top of the screen so the tabs appear flush against the screen edge.
78 const int kTabstripTopShadowThickness = 3;
80 // How far to indent the tabstrip from the left side of the screen when there
81 // is no avatar icon.
82 const int kTabStripIndent = -6;
84 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
85 // Default extra space between the top of the frame and the top of the window
86 // caption buttons.
87 const int kExtraCaption = 2;
89 // Default extra spacing between individual window caption buttons.
90 const int kCaptionButtonSpacing = 2;
91 #else
92 const int kExtraCaption = 0;
93 const int kCaptionButtonSpacing = 0;
94 #endif
96 } // namespace
98 ///////////////////////////////////////////////////////////////////////////////
99 // OpaqueBrowserFrameView, public:
101 OpaqueBrowserFrameViewLayout::OpaqueBrowserFrameViewLayout(
102 OpaqueBrowserFrameViewLayoutDelegate* delegate)
103 : delegate_(delegate),
104 leading_button_start_(0),
105 trailing_button_start_(0),
106 minimum_size_for_buttons_(0),
107 has_leading_buttons_(false),
108 has_trailing_buttons_(false),
109 extra_caption_y_(kExtraCaption),
110 window_caption_spacing_(kCaptionButtonSpacing),
111 minimize_button_(NULL),
112 maximize_button_(NULL),
113 restore_button_(NULL),
114 close_button_(NULL),
115 window_icon_(NULL),
116 window_title_(NULL),
117 avatar_label_(NULL),
118 avatar_button_(NULL),
119 new_avatar_button_(NULL) {
120 trailing_buttons_.push_back(views::FRAME_BUTTON_MINIMIZE);
121 trailing_buttons_.push_back(views::FRAME_BUTTON_MAXIMIZE);
122 trailing_buttons_.push_back(views::FRAME_BUTTON_CLOSE);
125 OpaqueBrowserFrameViewLayout::~OpaqueBrowserFrameViewLayout() {}
127 void OpaqueBrowserFrameViewLayout::SetButtonOrdering(
128 const std::vector<views::FrameButton>& leading_buttons,
129 const std::vector<views::FrameButton>& trailing_buttons) {
130 leading_buttons_ = leading_buttons;
131 trailing_buttons_ = trailing_buttons;
134 gfx::Rect OpaqueBrowserFrameViewLayout::GetBoundsForTabStrip(
135 const gfx::Size& tabstrip_preferred_size,
136 int available_width) const {
137 available_width -= trailing_button_start_;
138 available_width -= leading_button_start_;
140 const int caption_spacing = NewTabCaptionSpacing();
141 const int tabstrip_width = available_width - caption_spacing;
142 gfx::Rect bounds(leading_button_start_, GetTabStripInsetsTop(false),
143 std::max(0, tabstrip_width),
144 tabstrip_preferred_size.height());
146 int leading_tabstrip_indent = kTabStripIndent;
147 if (delegate_->ShouldShowAvatar() && !ShouldAvatarBeOnRight()) {
148 if (avatar_label_ && avatar_label_->bounds().width())
149 leading_tabstrip_indent += kAvatarLabelInnerSpacing;
150 else
151 leading_tabstrip_indent += kAvatarInnerSpacing;
153 bounds.Inset(leading_tabstrip_indent, 0, 0, 0);
154 return bounds;
157 gfx::Size OpaqueBrowserFrameViewLayout::GetMinimumSize(
158 int available_width) const {
159 gfx::Size min_size = delegate_->GetBrowserViewMinimumSize();
160 int border_thickness = NonClientBorderThickness();
161 min_size.Enlarge(2 * border_thickness,
162 NonClientTopBorderHeight(false) + border_thickness);
164 // Ensure that we can, at minimum, hold our window controls and avatar icon.
165 min_size.set_width(std::max(min_size.width(), minimum_size_for_buttons_));
167 // Ensure that the minimum width is enough to hold a minimum width tab strip
168 // at its usual insets.
169 if (delegate_->IsTabStripVisible()) {
170 gfx::Size preferred_size = delegate_->GetTabstripPreferredSize();
171 const int min_tabstrip_width = preferred_size.width();
172 const int caption_spacing = NewTabCaptionSpacing();
173 min_size.Enlarge(min_tabstrip_width + caption_spacing, 0);
176 return min_size;
179 gfx::Rect OpaqueBrowserFrameViewLayout::GetWindowBoundsForClientBounds(
180 const gfx::Rect& client_bounds) const {
181 int top_height = NonClientTopBorderHeight(false);
182 int border_thickness = NonClientBorderThickness();
183 return gfx::Rect(std::max(0, client_bounds.x() - border_thickness),
184 std::max(0, client_bounds.y() - top_height),
185 client_bounds.width() + (2 * border_thickness),
186 client_bounds.height() + top_height + border_thickness);
189 int OpaqueBrowserFrameViewLayout::FrameBorderThickness(bool restored) const {
190 return (!restored && (IsTitleBarCondensed() ||
191 delegate_->IsFullscreen())) ?
192 0 : kFrameBorderThickness;
195 int OpaqueBrowserFrameViewLayout::NonClientBorderThickness() const {
196 // When we fill the screen, we don't show a client edge.
197 return FrameBorderThickness(false) +
198 ((IsTitleBarCondensed() || delegate_->IsFullscreen()) ?
199 0 : views::NonClientFrameView::kClientEdgeThickness);
202 int OpaqueBrowserFrameViewLayout::NonClientTopBorderHeight(
203 bool restored) const {
204 if (delegate_->ShouldShowWindowTitle()) {
205 return std::max(FrameBorderThickness(restored) + delegate_->GetIconSize(),
206 CaptionButtonY(restored) + kCaptionButtonHeightWithPadding) +
207 TitlebarBottomThickness(restored);
210 int thickness = FrameBorderThickness(restored);
211 if (!restored && delegate_->IsTabStripVisible() &&
212 (!delegate_->ShouldLeaveOffsetNearTopBorder() || IsTitleBarCondensed())) {
213 thickness -= kTabstripTopShadowThickness;
215 return thickness;
218 int OpaqueBrowserFrameViewLayout::GetTabStripInsetsTop(bool restored) const {
219 return NonClientTopBorderHeight(restored) + ((!restored &&
220 (!delegate_->ShouldLeaveOffsetNearTopBorder() ||
221 IsTitleBarCondensed() ||
222 delegate_->IsFullscreen())) ?
223 0 : kNonClientRestoredExtraThickness);
226 int OpaqueBrowserFrameViewLayout::TitlebarBottomThickness(bool restored) const {
227 return kTitlebarTopAndBottomEdgeThickness +
228 ((!restored && IsTitleBarCondensed()) ? 0 :
229 views::NonClientFrameView::kClientEdgeThickness);
232 int OpaqueBrowserFrameViewLayout::CaptionButtonY(bool restored) const {
233 // Maximized buttons start at window top, since the window has no border. This
234 // offset is for the image (the actual clickable bounds extend all the way to
235 // the top to take Fitts' Law into account).
236 return ((!restored && IsTitleBarCondensed()) ?
237 FrameBorderThickness(false) :
238 views::NonClientFrameView::kFrameShadowThickness) + extra_caption_y_;
241 gfx::Rect OpaqueBrowserFrameViewLayout::IconBounds() const {
242 return window_icon_bounds_;
245 gfx::Rect OpaqueBrowserFrameViewLayout::CalculateClientAreaBounds(
246 int width,
247 int height) const {
248 int top_height = NonClientTopBorderHeight(false);
249 int border_thickness = NonClientBorderThickness();
250 return gfx::Rect(border_thickness, top_height,
251 std::max(0, width - (2 * border_thickness)),
252 std::max(0, height - top_height - border_thickness));
255 bool OpaqueBrowserFrameViewLayout::IsTitleBarCondensed() const {
256 // If there are no caption buttons, there is no need to have an uncondensed
257 // title bar. If the window is maximized, the title bar is condensed
258 // regardless of whether there are caption buttons.
259 return !delegate_->ShouldShowCaptionButtons() || delegate_->IsMaximized();
262 ///////////////////////////////////////////////////////////////////////////////
263 // OpaqueBrowserFrameView, private:
265 bool OpaqueBrowserFrameViewLayout::ShouldAvatarBeOnRight() const {
266 // The avatar should be shown either on the end of the left or the beginning
267 // of the right depending on which side has fewer buttons.
268 return trailing_buttons_.size() < leading_buttons_.size();
271 int OpaqueBrowserFrameViewLayout::NewTabCaptionSpacing() const {
272 return has_trailing_buttons_
273 ? (IsTitleBarCondensed() ? kNewTabCaptionCondensedSpacing
274 : kNewTabCaptionNormalSpacing)
275 : kNewTabNoCaptionButtonsSpacing;
278 void OpaqueBrowserFrameViewLayout::LayoutWindowControls(views::View* host) {
279 int caption_y = CaptionButtonY(false);
281 // Keep a list of all buttons that we don't show.
282 std::vector<views::FrameButton> buttons_not_shown;
283 buttons_not_shown.push_back(views::FRAME_BUTTON_MAXIMIZE);
284 buttons_not_shown.push_back(views::FRAME_BUTTON_MINIMIZE);
285 buttons_not_shown.push_back(views::FRAME_BUTTON_CLOSE);
287 if (delegate_->ShouldShowCaptionButtons()) {
288 for (std::vector<views::FrameButton>::const_iterator it =
289 leading_buttons_.begin(); it != leading_buttons_.end(); ++it) {
290 ConfigureButton(host, *it, ALIGN_LEADING, caption_y);
291 buttons_not_shown.erase(
292 std::remove(buttons_not_shown.begin(), buttons_not_shown.end(), *it),
293 buttons_not_shown.end());
296 for (std::vector<views::FrameButton>::const_reverse_iterator it =
297 trailing_buttons_.rbegin(); it != trailing_buttons_.rend(); ++it) {
298 ConfigureButton(host, *it, ALIGN_TRAILING, caption_y);
299 buttons_not_shown.erase(
300 std::remove(buttons_not_shown.begin(), buttons_not_shown.end(), *it),
301 buttons_not_shown.end());
305 for (std::vector<views::FrameButton>::const_iterator it =
306 buttons_not_shown.begin(); it != buttons_not_shown.end(); ++it) {
307 HideButton(*it);
311 void OpaqueBrowserFrameViewLayout::LayoutTitleBar(views::View* host) {
312 bool use_hidden_icon_location = true;
314 int size = delegate_->GetIconSize();
315 int frame_thickness = FrameBorderThickness(false);
316 bool should_show_icon = delegate_->ShouldShowWindowIcon();
317 bool should_show_title = delegate_->ShouldShowWindowTitle();
319 if (should_show_icon || should_show_title) {
320 use_hidden_icon_location = false;
322 // Our frame border has a different "3D look" than Windows'. Theirs has
323 // a more complex gradient on the top that they push their icon/title
324 // below; then the maximized window cuts this off and the icon/title are
325 // centered in the remaining space. Because the apparent shape of our
326 // border is simpler, using the same positioning makes things look
327 // slightly uncentered with restored windows, so when the window is
328 // restored, instead of calculating the remaining space from below the
329 // frame border, we calculate from below the 3D edge.
330 int unavailable_px_at_top = IsTitleBarCondensed() ?
331 frame_thickness : kTitlebarTopAndBottomEdgeThickness;
332 // When the icon is shorter than the minimum space we reserve for the
333 // caption button, we vertically center it. We want to bias rounding to
334 // put extra space above the icon, since the 3D edge (+ client edge, for
335 // restored windows) below looks (to the eye) more like additional space
336 // than does the 3D edge (or nothing at all, for maximized windows)
337 // above; hence the +1.
338 int y = unavailable_px_at_top + (NonClientTopBorderHeight(false) -
339 unavailable_px_at_top - size -
340 TitlebarBottomThickness(false) + 1) / 2;
342 window_icon_bounds_ = gfx::Rect(leading_button_start_ + kIconLeftSpacing, y,
343 size, size);
344 leading_button_start_ += size + kIconLeftSpacing;
345 minimum_size_for_buttons_ += size + kIconLeftSpacing;
348 if (should_show_icon)
349 window_icon_->SetBoundsRect(window_icon_bounds_);
351 if (window_title_) {
352 window_title_->SetVisible(should_show_title);
353 if (should_show_title) {
354 window_title_->SetText(delegate_->GetWindowTitle());
356 int text_width = std::max(
357 0, host->width() - trailing_button_start_ - kTitleLogoSpacing -
358 leading_button_start_ - kIconTitleSpacing);
359 window_title_->SetBounds(leading_button_start_ + kIconTitleSpacing,
360 window_icon_bounds_.y(),
361 text_width, window_icon_bounds_.height());
362 leading_button_start_ += text_width + kIconTitleSpacing;
366 if (use_hidden_icon_location) {
367 if (has_leading_buttons_) {
368 // There are window button icons on the left. Don't size the hidden window
369 // icon that people can double click on to close the window.
370 window_icon_bounds_ = gfx::Rect();
371 } else {
372 // We set the icon bounds to a small rectangle in the top leading corner
373 // if there are no icons on the leading side.
374 window_icon_bounds_ = gfx::Rect(
375 frame_thickness + kIconLeftSpacing, frame_thickness, size, size);
380 void OpaqueBrowserFrameViewLayout::LayoutNewStyleAvatar(views::View* host) {
381 DCHECK(switches::IsNewAvatarMenu());
382 if (!new_avatar_button_)
383 return;
385 gfx::Size label_size = new_avatar_button_->GetPreferredSize();
386 int button_size_with_offset = kNewAvatarButtonOffset + label_size.width();
388 int button_x = host->width() - trailing_button_start_ -
389 button_size_with_offset;
390 int button_y = CaptionButtonY(false);
391 // If the window is maximized, the button is 1 pixel too short. Determined
392 // via visual inspection.
393 int extra_height = IsTitleBarCondensed() ? 1 : 0;
395 trailing_button_start_ += button_size_with_offset;
396 minimum_size_for_buttons_ += button_size_with_offset;
398 new_avatar_button_->SetBounds(
399 button_x,
400 button_y,
401 label_size.width(),
402 button_y + kCaptionButtonHeightWithPadding + extra_height);
405 void OpaqueBrowserFrameViewLayout::LayoutAvatar(views::View* host) {
406 // Even though the avatar is used for both incognito and profiles we always
407 // use the incognito icon to layout the avatar button. The profile icon
408 // can be customized so we can't depend on its size to perform layout.
409 gfx::ImageSkia incognito_icon = delegate_->GetOTRAvatarIcon();
411 bool avatar_on_right = ShouldAvatarBeOnRight();
412 int avatar_bottom = GetTabStripInsetsTop(false) +
413 delegate_->GetTabStripHeight() - kAvatarBottomSpacing;
414 int avatar_restored_y = avatar_bottom - incognito_icon.height();
415 int avatar_x = avatar_on_right ?
416 host->width() - trailing_button_start_ - kAvatarOuterSpacing -
417 incognito_icon.width() :
418 leading_button_start_ + kAvatarOuterSpacing;
419 int avatar_y = IsTitleBarCondensed() ?
420 (NonClientTopBorderHeight(false) + kTabstripTopShadowThickness) :
421 avatar_restored_y;
422 avatar_bounds_.SetRect(
423 avatar_x,
424 avatar_y,
425 incognito_icon.width(),
426 delegate_->ShouldShowAvatar() ? (avatar_bottom - avatar_y) : 0);
427 if (avatar_button_) {
428 avatar_button_->set_button_on_right(avatar_on_right);
429 avatar_button_->SetBoundsRect(avatar_bounds_);
431 int edge_offset;
432 if (avatar_label_) {
433 avatar_label_->SetLabelOnRight(avatar_on_right);
434 // Space between the bottom of the avatar and the bottom of the avatar
435 // label.
436 const int kAvatarLabelBottomSpacing = 3;
437 gfx::Size label_size = avatar_label_->GetPreferredSize();
438 // The outside edge of the avatar label should be just outside that of the
439 // avatar menu button.
440 int avatar_label_x = avatar_on_right ?
441 (host->width() - trailing_button_start_ - label_size.width()) :
442 leading_button_start_;
443 gfx::Rect label_bounds(
444 avatar_label_x,
445 avatar_bottom - kAvatarLabelBottomSpacing - label_size.height(),
446 label_size.width(),
447 delegate_->ShouldShowAvatar() ? label_size.height() : 0);
448 avatar_label_->SetBoundsRect(label_bounds);
449 edge_offset = label_size.width();
450 } else {
451 edge_offset = kAvatarOuterSpacing + incognito_icon.width();
453 if (avatar_on_right)
454 trailing_button_start_ += edge_offset;
455 else
456 leading_button_start_ += edge_offset;
458 // We just add the avatar button size to the minimum size because clicking
459 // the avatar label does the same thing as clicking the avatar button.
460 minimum_size_for_buttons_ += kAvatarOuterSpacing + incognito_icon.width();
464 void OpaqueBrowserFrameViewLayout::ConfigureButton(
465 views::View* host,
466 views::FrameButton button_id,
467 ButtonAlignment alignment,
468 int caption_y) {
469 switch (button_id) {
470 case views::FRAME_BUTTON_MINIMIZE: {
471 minimize_button_->SetVisible(true);
472 SetBoundsForButton(host, minimize_button_, alignment, caption_y);
473 break;
475 case views::FRAME_BUTTON_MAXIMIZE: {
476 // When the window is restored, we show a maximized button; otherwise, we
477 // show a restore button.
478 bool is_restored = !delegate_->IsMaximized() && !delegate_->IsMinimized();
479 views::ImageButton* invisible_button = is_restored ?
480 restore_button_ : maximize_button_;
481 invisible_button->SetVisible(false);
483 views::ImageButton* visible_button = is_restored ?
484 maximize_button_ : restore_button_;
485 visible_button->SetVisible(true);
486 SetBoundsForButton(host, visible_button, alignment, caption_y);
487 break;
489 case views::FRAME_BUTTON_CLOSE: {
490 close_button_->SetVisible(true);
491 SetBoundsForButton(host, close_button_, alignment, caption_y);
492 break;
497 void OpaqueBrowserFrameViewLayout::HideButton(views::FrameButton button_id) {
498 switch (button_id) {
499 case views::FRAME_BUTTON_MINIMIZE:
500 minimize_button_->SetVisible(false);
501 break;
502 case views::FRAME_BUTTON_MAXIMIZE:
503 restore_button_->SetVisible(false);
504 maximize_button_->SetVisible(false);
505 break;
506 case views::FRAME_BUTTON_CLOSE:
507 close_button_->SetVisible(false);
508 break;
512 void OpaqueBrowserFrameViewLayout::SetBoundsForButton(
513 views::View* host,
514 views::ImageButton* button,
515 ButtonAlignment alignment,
516 int caption_y) {
517 gfx::Size button_size = button->GetPreferredSize();
519 button->SetImageAlignment(
520 (alignment == ALIGN_LEADING) ?
521 views::ImageButton::ALIGN_RIGHT : views::ImageButton::ALIGN_LEFT,
522 views::ImageButton::ALIGN_BOTTOM);
524 // There should always be the same number of non-shadow pixels visible to the
525 // side of the caption buttons. In maximized mode we extend buttons to the
526 // screen top and the rightmost button to the screen right (or leftmost button
527 // to the screen left, for left-aligned buttons) to obey Fitts' Law.
528 bool title_bar_condensed = IsTitleBarCondensed();
530 // When we are the first button on the leading side and are the close
531 // button, we must flip ourselves, because the close button assets have
532 // a little notch to fit in the rounded frame.
533 button->SetDrawImageMirrored(alignment == ALIGN_LEADING &&
534 !has_leading_buttons_ &&
535 button == close_button_);
536 // If the window is maximized, align the buttons to its upper edge.
537 int extra_height = title_bar_condensed ? extra_caption_y_ : 0;
539 switch (alignment) {
540 case ALIGN_LEADING: {
541 if (has_leading_buttons_)
542 leading_button_start_ += window_caption_spacing_;
544 // If we're the first button on the left and maximized, add width to the
545 // right hand side of the screen.
546 int extra_width = (title_bar_condensed && !has_leading_buttons_) ?
547 (kFrameBorderThickness -
548 views::NonClientFrameView::kFrameShadowThickness) : 0;
550 button->SetBounds(
551 leading_button_start_,
552 caption_y - extra_height,
553 button_size.width() + extra_width,
554 button_size.height() + extra_height);
556 leading_button_start_ += extra_width + button_size.width();
557 minimum_size_for_buttons_ += extra_width + button_size.width();
558 has_leading_buttons_ = true;
559 break;
561 case ALIGN_TRAILING: {
562 if (has_trailing_buttons_)
563 trailing_button_start_ += window_caption_spacing_;
565 // If we're the first button on the right and maximized, add width to the
566 // right hand side of the screen.
567 int extra_width = (title_bar_condensed && !has_trailing_buttons_) ?
568 (kFrameBorderThickness -
569 views::NonClientFrameView::kFrameShadowThickness) : 0;
571 button->SetBounds(
572 host->width() - trailing_button_start_ - extra_width -
573 button_size.width(),
574 caption_y - extra_height,
575 button_size.width() + extra_width,
576 button_size.height() + extra_height);
578 trailing_button_start_ += extra_width + button_size.width();
579 minimum_size_for_buttons_ += extra_width + button_size.width();
580 has_trailing_buttons_ = true;
581 break;
586 void OpaqueBrowserFrameViewLayout::SetView(int id, views::View* view) {
587 // Why do things this way instead of having an Init() method, where we're
588 // passed the views we'll handle? Because OpaqueBrowserFrameView doesn't own
589 // all the views which are part of it. The avatar stuff, for example, will be
590 // added and removed by the base class of OpaqueBrowserFrameView.
591 switch (id) {
592 case VIEW_ID_MINIMIZE_BUTTON:
593 if (view) {
594 DCHECK_EQ(std::string(views::ImageButton::kViewClassName),
595 view->GetClassName());
597 minimize_button_ = static_cast<views::ImageButton*>(view);
598 break;
599 case VIEW_ID_MAXIMIZE_BUTTON:
600 if (view) {
601 DCHECK_EQ(std::string(views::ImageButton::kViewClassName),
602 view->GetClassName());
604 maximize_button_ = static_cast<views::ImageButton*>(view);
605 break;
606 case VIEW_ID_RESTORE_BUTTON:
607 if (view) {
608 DCHECK_EQ(std::string(views::ImageButton::kViewClassName),
609 view->GetClassName());
611 restore_button_ = static_cast<views::ImageButton*>(view);
612 break;
613 case VIEW_ID_CLOSE_BUTTON:
614 if (view) {
615 DCHECK_EQ(std::string(views::ImageButton::kViewClassName),
616 view->GetClassName());
618 close_button_ = static_cast<views::ImageButton*>(view);
619 break;
620 case VIEW_ID_WINDOW_ICON:
621 window_icon_ = view;
622 break;
623 case VIEW_ID_WINDOW_TITLE:
624 if (view) {
625 DCHECK_EQ(std::string(views::Label::kViewClassName),
626 view->GetClassName());
628 window_title_ = static_cast<views::Label*>(view);
629 break;
630 case VIEW_ID_AVATAR_LABEL:
631 avatar_label_ = static_cast<AvatarLabel*>(view);
632 break;
633 case VIEW_ID_AVATAR_BUTTON:
634 if (view) {
635 DCHECK_EQ(std::string(AvatarMenuButton::kViewClassName),
636 view->GetClassName());
638 avatar_button_ = static_cast<AvatarMenuButton*>(view);
639 break;
640 case VIEW_ID_NEW_AVATAR_BUTTON:
641 new_avatar_button_ = view;
642 break;
643 default:
644 NOTIMPLEMENTED() << "Unknown view id " << id;
645 break;
649 ///////////////////////////////////////////////////////////////////////////////
650 // OpaqueBrowserFrameView, views::LayoutManager:
652 void OpaqueBrowserFrameViewLayout::Layout(views::View* host) {
653 // Reset all our data so that everything is invisible.
654 int thickness = FrameBorderThickness(false);
655 leading_button_start_ = thickness;
656 trailing_button_start_ = thickness;
657 minimum_size_for_buttons_ = leading_button_start_ + trailing_button_start_;
658 has_leading_buttons_ = false;
659 has_trailing_buttons_ = false;
661 LayoutWindowControls(host);
662 LayoutTitleBar(host);
664 // We now add a single pixel to the leading spacing. We do this because the
665 // avatar and tab strip start one pixel inward compared to where things start
666 // on the trailing side.
667 leading_button_start_++;
669 if (delegate_->IsRegularOrGuestSession() && switches::IsNewAvatarMenu())
670 LayoutNewStyleAvatar(host);
671 else
672 LayoutAvatar(host);
674 client_view_bounds_ = CalculateClientAreaBounds(
675 host->width(), host->height());
678 gfx::Size OpaqueBrowserFrameViewLayout::GetPreferredSize(
679 const views::View* host) const {
680 // This is never used; NonClientView::GetPreferredSize() will be called
681 // instead.
682 NOTREACHED();
683 return gfx::Size();
686 void OpaqueBrowserFrameViewLayout::ViewAdded(views::View* host,
687 views::View* view) {
688 SetView(view->id(), view);
691 void OpaqueBrowserFrameViewLayout::ViewRemoved(views::View* host,
692 views::View* view) {
693 SetView(view->id(), NULL);