opaque_browser_frame_view_layout.cc revision f2477e01787aa58f445919b809d89e252beef54f
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. 4 5#include "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h" 6 7#include "chrome/browser/profiles/profiles_state.h" 8#include "ui/gfx/font.h" 9#include "ui/views/controls/button/image_button.h" 10#include "ui/views/controls/label.h" 11 12#if defined(OS_WIN) 13#include "win8/util/win8_util.h" 14#endif // OS_WIN 15 16namespace { 17 18// Besides the frame border, there's another 9 px of empty space atop the 19// window in restored mode, to use to drag the window around. 20const int kNonClientRestoredExtraThickness = 9; 21 22// The titlebar never shrinks too short to show the caption button plus some 23// padding below it. 24const int kCaptionButtonHeightWithPadding = 19; 25 26// There is a 5 px gap between the title text and the caption buttons. 27const int kTitleLogoSpacing = 5; 28 29// The frame border is only visible in restored mode and is hardcoded to 4 px on 30// each side regardless of the system window border size. 31const int kFrameBorderThickness = 4; 32 33// The titlebar has a 2 px 3D edge along the top and bottom. 34const int kTitlebarTopAndBottomEdgeThickness = 2; 35 36// The icon is inset 2 px from the left frame border. 37const int kIconLeftSpacing = 2; 38 39// There is a 4 px gap between the icon and the title text. 40const int kIconTitleSpacing = 4; 41 42// The avatar ends 2 px above the bottom of the tabstrip (which, given the 43// way the tabstrip draws its bottom edge, will appear like a 1 px gap to the 44// user). 45const int kAvatarBottomSpacing = 2; 46 47// Space between the frame border and the left edge of the avatar. 48const int kAvatarLeftSpacing = 2; 49 50// Space between the right edge of the avatar and the tabstrip. 51const int kAvatarRightSpacing = -4; 52 53// How far the new avatar button is from the closest caption button. 54const int kNewAvatarButtonOffset = 5; 55 56// In restored mode, the New Tab button isn't at the same height as the caption 57// buttons, but the space will look cluttered if it actually slides under them, 58// so we stop it when the gap between the two is down to 5 px. 59const int kNewTabCaptionRestoredSpacing = 5; 60 61// In maximized mode, where the New Tab button and the caption buttons are at 62// similar vertical coordinates, we need to reserve a larger, 16 px gap to avoid 63// looking too cluttered. 64const int kNewTabCaptionMaximizedSpacing = 16; 65 66// The top 3 px of the tabstrip is shadow; in maximized mode we push this off 67// the top of the screen so the tabs appear flush against the screen edge. 68const int kTabstripTopShadowThickness = 3; 69 70// How far to indent the tabstrip from the left side of the screen when there 71// is no avatar icon. 72const int kTabStripIndent = -6; 73 74#if defined(OS_LINUX) && !defined(OS_CHROMEOS) 75// Default extra space between the top of the frame and the top of the window 76// caption buttons. 77const int kExtraCaption = 2; 78 79// Default extra spacing between individual window caption buttons. 80const int kCaptionButtonSpacing = 2; 81#else 82const int kExtraCaption = 0; 83const int kCaptionButtonSpacing = 0; 84#endif 85 86} // namespace 87 88/////////////////////////////////////////////////////////////////////////////// 89// OpaqueBrowserFrameView, public: 90 91OpaqueBrowserFrameViewLayout::OpaqueBrowserFrameViewLayout( 92 OpaqueBrowserFrameViewLayoutDelegate* delegate) 93 : delegate_(delegate), 94 leading_button_start_(0), 95 trailing_button_start_(0), 96 minimum_size_for_buttons_(0), 97 has_leading_buttons_(false), 98 has_trailing_buttons_(false), 99 extra_caption_y_(kExtraCaption), 100 window_caption_spacing_(kCaptionButtonSpacing), 101 minimize_button_(NULL), 102 maximize_button_(NULL), 103 restore_button_(NULL), 104 close_button_(NULL), 105 window_icon_(NULL), 106 window_title_(NULL), 107 avatar_label_(NULL), 108 avatar_button_(NULL), 109 new_avatar_button_(NULL) { 110 trailing_buttons_.push_back(views::FRAME_BUTTON_MINIMIZE); 111 trailing_buttons_.push_back(views::FRAME_BUTTON_MAXIMIZE); 112 trailing_buttons_.push_back(views::FRAME_BUTTON_CLOSE); 113} 114 115OpaqueBrowserFrameViewLayout::~OpaqueBrowserFrameViewLayout() {} 116 117// static 118bool OpaqueBrowserFrameViewLayout::ShouldAddDefaultCaptionButtons() { 119#if defined(OS_WIN) 120 return !win8::IsSingleWindowMetroMode(); 121#endif // OS_WIN 122 return true; 123} 124 125void OpaqueBrowserFrameViewLayout::SetButtonOrdering( 126 const std::vector<views::FrameButton>& leading_buttons, 127 const std::vector<views::FrameButton>& trailing_buttons) { 128 leading_buttons_ = leading_buttons; 129 trailing_buttons_ = trailing_buttons; 130} 131 132gfx::Rect OpaqueBrowserFrameViewLayout::GetBoundsForTabStrip( 133 const gfx::Size& tabstrip_preferred_size, 134 int available_width) const { 135 available_width -= trailing_button_start_; 136 available_width -= leading_button_start_; 137 138 if (delegate_->GetAdditionalReservedSpaceInTabStrip()) 139 available_width -= delegate_->GetAdditionalReservedSpaceInTabStrip(); 140 141 const int caption_spacing = delegate_->IsMaximized() ? 142 kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing; 143 const int tabstrip_width = available_width - caption_spacing; 144 gfx::Rect bounds(leading_button_start_, GetTabStripInsetsTop(false), 145 std::max(0, tabstrip_width), 146 tabstrip_preferred_size.height()); 147 148 int leading_tabstrip_indent = kTabStripIndent; 149 if (delegate_->ShouldShowAvatar()) { 150 if (avatar_label_ && avatar_label_->bounds().width()) { 151 // Space between the trailing edge of the avatar label and the tabstrip. 152 const int kAvatarLabelRightSpacing = -10; 153 leading_tabstrip_indent -= kAvatarLabelRightSpacing; 154 } else { 155 leading_tabstrip_indent -= kAvatarRightSpacing; 156 } 157 } 158 bounds.Inset(leading_tabstrip_indent, 0, 0, 0); 159 return bounds; 160} 161 162gfx::Size OpaqueBrowserFrameViewLayout::GetMinimumSize( 163 int available_width) const { 164 gfx::Size min_size = delegate_->GetBrowserViewMinimumSize(); 165 int border_thickness = NonClientBorderThickness(); 166 min_size.Enlarge(2 * border_thickness, 167 NonClientTopBorderHeight(false) + border_thickness); 168 169 // Ensure that we can, at minimum, hold our window controls and avatar icon. 170 min_size.set_width(std::max(min_size.width(), minimum_size_for_buttons_)); 171 172 // Ensure that the minimum width is enough to hold a minimum width tab strip 173 // at its usual insets. 174 if (delegate_->IsTabStripVisible()) { 175 gfx::Size preferred_size = delegate_->GetTabstripPreferredSize(); 176 const int min_tabstrip_width = preferred_size.width(); 177 const int caption_spacing = delegate_->IsMaximized() ? 178 kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing; 179 min_size.Enlarge(min_tabstrip_width + caption_spacing, 0); 180 } 181 182 return min_size; 183} 184 185gfx::Rect OpaqueBrowserFrameViewLayout::GetWindowBoundsForClientBounds( 186 const gfx::Rect& client_bounds) const { 187 int top_height = NonClientTopBorderHeight(false); 188 int border_thickness = NonClientBorderThickness(); 189 return gfx::Rect(std::max(0, client_bounds.x() - border_thickness), 190 std::max(0, client_bounds.y() - top_height), 191 client_bounds.width() + (2 * border_thickness), 192 client_bounds.height() + top_height + border_thickness); 193} 194 195int OpaqueBrowserFrameViewLayout::FrameBorderThickness(bool restored) const { 196 return (!restored && (delegate_->IsMaximized() || 197 delegate_->IsFullscreen())) ? 198 0 : kFrameBorderThickness; 199} 200 201int OpaqueBrowserFrameViewLayout::NonClientBorderThickness() const { 202 // When we fill the screen, we don't show a client edge. 203 return FrameBorderThickness(false) + 204 ((delegate_->IsMaximized() || delegate_->IsFullscreen()) ? 205 0 : views::NonClientFrameView::kClientEdgeThickness); 206} 207 208int OpaqueBrowserFrameViewLayout::NonClientTopBorderHeight( 209 bool restored) const { 210 if (delegate_->ShouldShowWindowTitle()) { 211 return std::max(FrameBorderThickness(restored) + delegate_->GetIconSize(), 212 CaptionButtonY(restored) + kCaptionButtonHeightWithPadding) + 213 TitlebarBottomThickness(restored); 214 } 215 216 return FrameBorderThickness(restored) - 217 ((delegate_->IsTabStripVisible() && 218 !restored && !delegate_->ShouldLeaveOffsetNearTopBorder()) 219 ? kTabstripTopShadowThickness : 0); 220} 221 222int OpaqueBrowserFrameViewLayout::GetTabStripInsetsTop(bool restored) const { 223 return NonClientTopBorderHeight(restored) + ((!restored && 224 (!delegate_->ShouldLeaveOffsetNearTopBorder() || 225 delegate_->IsFullscreen())) ? 226 0 : kNonClientRestoredExtraThickness); 227} 228 229int OpaqueBrowserFrameViewLayout::TitlebarBottomThickness(bool restored) const { 230 return kTitlebarTopAndBottomEdgeThickness + 231 ((!restored && delegate_->IsMaximized()) ? 0 : 232 views::NonClientFrameView::kClientEdgeThickness); 233} 234 235int OpaqueBrowserFrameViewLayout::CaptionButtonY(bool restored) const { 236 // Maximized buttons start at window top so that even if their images aren't 237 // drawn flush with the screen edge, they still obey Fitts' Law. 238 return ((!restored && delegate_->IsMaximized()) ? 239 FrameBorderThickness(false) : 240 views::NonClientFrameView::kFrameShadowThickness) + extra_caption_y_; 241} 242 243gfx::Rect OpaqueBrowserFrameViewLayout::IconBounds() const { 244 return window_icon_bounds_; 245} 246 247gfx::Rect OpaqueBrowserFrameViewLayout::CalculateClientAreaBounds( 248 int width, 249 int height) const { 250 int top_height = NonClientTopBorderHeight(false); 251 int border_thickness = NonClientBorderThickness(); 252 return gfx::Rect(border_thickness, top_height, 253 std::max(0, width - (2 * border_thickness)), 254 std::max(0, height - top_height - border_thickness)); 255} 256 257/////////////////////////////////////////////////////////////////////////////// 258// OpaqueBrowserFrameView, private: 259 260void OpaqueBrowserFrameViewLayout::LayoutWindowControls(views::View* host) { 261 if (!ShouldAddDefaultCaptionButtons()) 262 return; 263 264 int caption_y = CaptionButtonY(false); 265 266 // Keep a list of all buttons that we don't show. 267 std::vector<views::FrameButton> buttons_not_shown; 268 buttons_not_shown.push_back(views::FRAME_BUTTON_MAXIMIZE); 269 buttons_not_shown.push_back(views::FRAME_BUTTON_MINIMIZE); 270 buttons_not_shown.push_back(views::FRAME_BUTTON_CLOSE); 271 272 for (std::vector<views::FrameButton>::const_iterator it = 273 leading_buttons_.begin(); it != leading_buttons_.end(); ++it) { 274 ConfigureButton(host, *it, ALIGN_LEADING, caption_y); 275 buttons_not_shown.erase( 276 std::remove(buttons_not_shown.begin(), buttons_not_shown.end(), *it), 277 buttons_not_shown.end()); 278 } 279 280 for (std::vector<views::FrameButton>::const_reverse_iterator it = 281 trailing_buttons_.rbegin(); it != trailing_buttons_.rend(); ++it) { 282 ConfigureButton(host, *it, ALIGN_TRAILING, caption_y); 283 buttons_not_shown.erase( 284 std::remove(buttons_not_shown.begin(), buttons_not_shown.end(), *it), 285 buttons_not_shown.end()); 286 } 287 288 for (std::vector<views::FrameButton>::const_iterator it = 289 buttons_not_shown.begin(); it != buttons_not_shown.end(); ++it) { 290 HideButton(*it); 291 } 292} 293 294void OpaqueBrowserFrameViewLayout::LayoutTitleBar(views::View* host) { 295 bool use_hidden_icon_location = true; 296 297 int size = delegate_->GetIconSize(); 298 int frame_thickness = FrameBorderThickness(false); 299 bool should_show_icon = delegate_->ShouldShowWindowIcon(); 300 bool should_show_title = delegate_->ShouldShowWindowTitle(); 301 302 if (should_show_icon || should_show_title) { 303 use_hidden_icon_location = false; 304 305 // Our frame border has a different "3D look" than Windows'. Theirs has 306 // a more complex gradient on the top that they push their icon/title 307 // below; then the maximized window cuts this off and the icon/title are 308 // centered in the remaining space. Because the apparent shape of our 309 // border is simpler, using the same positioning makes things look 310 // slightly uncentered with restored windows, so when the window is 311 // restored, instead of calculating the remaining space from below the 312 // frame border, we calculate from below the 3D edge. 313 int unavailable_px_at_top = delegate_->IsMaximized() ? 314 frame_thickness : kTitlebarTopAndBottomEdgeThickness; 315 // When the icon is shorter than the minimum space we reserve for the 316 // caption button, we vertically center it. We want to bias rounding to 317 // put extra space above the icon, since the 3D edge (+ client edge, for 318 // restored windows) below looks (to the eye) more like additional space 319 // than does the 3D edge (or nothing at all, for maximized windows) 320 // above; hence the +1. 321 int y = unavailable_px_at_top + (NonClientTopBorderHeight(false) - 322 unavailable_px_at_top - size - 323 TitlebarBottomThickness(false) + 1) / 2; 324 325 window_icon_bounds_ = gfx::Rect(leading_button_start_ + kIconLeftSpacing, y, 326 size, size); 327 leading_button_start_ += size + kIconLeftSpacing; 328 minimum_size_for_buttons_ += size + kIconLeftSpacing; 329 } 330 331 if (should_show_icon) 332 window_icon_->SetBoundsRect(window_icon_bounds_); 333 334 if (window_title_) { 335 window_title_->SetVisible(should_show_title); 336 if (should_show_title) { 337 window_title_->SetText(delegate_->GetWindowTitle()); 338 339 int text_width = std::max( 340 0, host->width() - trailing_button_start_ - kTitleLogoSpacing - 341 leading_button_start_ - kIconTitleSpacing); 342 window_title_->SetBounds(leading_button_start_ + kIconTitleSpacing, 343 window_icon_bounds_.y(), 344 text_width, window_icon_bounds_.height()); 345 leading_button_start_ += text_width + kIconTitleSpacing; 346 } 347 } 348 349 if (use_hidden_icon_location) { 350 if (has_leading_buttons_) { 351 // There are window button icons on the left. Don't size the hidden window 352 // icon that people can double click on to close the window. 353 window_icon_bounds_ = gfx::Rect(); 354 } else { 355 // We set the icon bounds to a small rectangle in the top leading corner 356 // if there are no icons on the leading side. 357 window_icon_bounds_ = gfx::Rect( 358 frame_thickness + kIconLeftSpacing, frame_thickness, size, size); 359 } 360 } 361} 362 363void OpaqueBrowserFrameViewLayout::LayoutNewStyleAvatar(views::View* host) { 364 DCHECK(profiles::IsNewProfileManagementEnabled()); 365 if (!new_avatar_button_) 366 return; 367 368 gfx::Size label_size = new_avatar_button_->GetPreferredSize(); 369 int button_size_with_offset = kNewAvatarButtonOffset + label_size.width(); 370 371 int button_x = host->width() - trailing_button_start_ - 372 button_size_with_offset; 373 int button_y = CaptionButtonY(false); 374 375 trailing_button_start_ += button_size_with_offset; 376 minimum_size_for_buttons_ += button_size_with_offset; 377 378 new_avatar_button_->SetBounds( 379 button_x, 380 button_y, 381 label_size.width(), 382 button_y + kCaptionButtonHeightWithPadding); 383} 384 385void OpaqueBrowserFrameViewLayout::LayoutAvatar() { 386 // Even though the avatar is used for both incognito and profiles we always 387 // use the incognito icon to layout the avatar button. The profile icon 388 // can be customized so we can't depend on its size to perform layout. 389 gfx::ImageSkia incognito_icon = delegate_->GetOTRAvatarIcon(); 390 391 int avatar_bottom = GetTabStripInsetsTop(false) + 392 delegate_->GetTabStripHeight() - kAvatarBottomSpacing; 393 int avatar_restored_y = avatar_bottom - incognito_icon.height(); 394 int avatar_y = delegate_->IsMaximized() ? 395 (NonClientTopBorderHeight(false) + kTabstripTopShadowThickness) : 396 avatar_restored_y; 397 avatar_bounds_.SetRect(leading_button_start_ + kAvatarLeftSpacing, 398 avatar_y, incognito_icon.width(), 399 delegate_->ShouldShowAvatar() ? (avatar_bottom - avatar_y) : 0); 400 if (avatar_button_) { 401 avatar_button_->SetBoundsRect(avatar_bounds_); 402 403 if (avatar_label_) { 404 // Space between the bottom of the avatar and the bottom of the avatar 405 // label. 406 const int kAvatarLabelBottomSpacing = 3; 407 gfx::Size label_size = avatar_label_->GetPreferredSize(); 408 // The x-position of the avatar label should be slightly to the left of 409 // the avatar menu button. Therefore we use the |leading_button_start_| 410 // value directly. 411 gfx::Rect label_bounds( 412 leading_button_start_, 413 avatar_bottom - kAvatarLabelBottomSpacing - label_size.height(), 414 label_size.width(), 415 delegate_->ShouldShowAvatar() ? label_size.height() : 0); 416 avatar_label_->SetBoundsRect(label_bounds); 417 leading_button_start_ += label_size.width(); 418 } else { 419 leading_button_start_ += kAvatarLeftSpacing + incognito_icon.width(); 420 } 421 422 // We just add the avatar button size to the minimum size because clicking 423 // the avatar label does the same thing as clicking the avatar button. 424 minimum_size_for_buttons_ += kAvatarLeftSpacing + incognito_icon.width(); 425 } 426} 427 428void OpaqueBrowserFrameViewLayout::ConfigureButton( 429 views::View* host, 430 views::FrameButton button_id, 431 ButtonAlignment alignment, 432 int caption_y) { 433 switch (button_id) { 434 case views::FRAME_BUTTON_MINIMIZE: { 435 minimize_button_->SetVisible(true); 436 SetBoundsForButton(host, minimize_button_, alignment, caption_y); 437 break; 438 } 439 case views::FRAME_BUTTON_MAXIMIZE: { 440 // When the window is restored, we show a maximized button; otherwise, we 441 // show a restore button. 442 bool is_restored = !delegate_->IsMaximized() && !delegate_->IsMinimized(); 443 views::ImageButton* invisible_button = is_restored ? 444 restore_button_ : maximize_button_; 445 invisible_button->SetVisible(false); 446 447 views::ImageButton* visible_button = is_restored ? 448 maximize_button_ : restore_button_; 449 visible_button->SetVisible(true); 450 SetBoundsForButton(host, visible_button, alignment, caption_y); 451 break; 452 } 453 case views::FRAME_BUTTON_CLOSE: { 454 close_button_->SetVisible(true); 455 SetBoundsForButton(host, close_button_, alignment, caption_y); 456 break; 457 } 458 } 459} 460 461void OpaqueBrowserFrameViewLayout::HideButton(views::FrameButton button_id) { 462 switch (button_id) { 463 case views::FRAME_BUTTON_MINIMIZE: 464 minimize_button_->SetVisible(false); 465 break; 466 case views::FRAME_BUTTON_MAXIMIZE: 467 restore_button_->SetVisible(false); 468 maximize_button_->SetVisible(false); 469 break; 470 case views::FRAME_BUTTON_CLOSE: 471 close_button_->SetVisible(false); 472 break; 473 } 474} 475 476void OpaqueBrowserFrameViewLayout::SetBoundsForButton( 477 views::View* host, 478 views::ImageButton* button, 479 ButtonAlignment alignment, 480 int caption_y) { 481 gfx::Size button_size = button->GetPreferredSize(); 482 483 button->SetImageAlignment( 484 (alignment == ALIGN_LEADING) ? 485 views::ImageButton::ALIGN_RIGHT : views::ImageButton::ALIGN_LEFT, 486 views::ImageButton::ALIGN_BOTTOM); 487 488 // There should always be the same number of non-shadow pixels visible to the 489 // side of the caption buttons. In maximized mode we extend the rightmost 490 // button to the screen corner to obey Fitts' Law. 491 bool is_maximized = delegate_->IsMaximized(); 492 493 // When we are the first button on the leading side and are the close 494 // button, we must flip ourselves, because the close button assets have 495 // a little notch to fit in the rounded frame. 496 button->SetDrawImageMirrored(alignment == ALIGN_LEADING && 497 !has_leading_buttons_ && 498 button == close_button_); 499 500 switch (alignment) { 501 case ALIGN_LEADING: { 502 if (has_leading_buttons_) 503 leading_button_start_ += window_caption_spacing_; 504 505 // If we're the first button on the left and maximized, add with to the 506 // right hand side of the screen. 507 int extra_width = (is_maximized && !has_leading_buttons_) ? 508 (kFrameBorderThickness - 509 views::NonClientFrameView::kFrameShadowThickness) : 0; 510 511 button->SetBounds( 512 leading_button_start_, 513 caption_y, 514 button_size.width() + extra_width, 515 button_size.height()); 516 517 leading_button_start_ += extra_width + button_size.width(); 518 minimum_size_for_buttons_ += extra_width + button_size.width(); 519 has_leading_buttons_ = true; 520 break; 521 } 522 case ALIGN_TRAILING: { 523 if (has_trailing_buttons_) 524 trailing_button_start_ += window_caption_spacing_; 525 526 // If we're the first button on the right and maximized, add with to the 527 // right hand side of the screen. 528 int extra_width = (is_maximized && !has_trailing_buttons_) ? 529 (kFrameBorderThickness - 530 views::NonClientFrameView::kFrameShadowThickness) : 0; 531 532 button->SetBounds( 533 host->width() - trailing_button_start_ - extra_width - 534 button_size.width(), 535 caption_y, 536 button_size.width() + extra_width, 537 button_size.height()); 538 539 trailing_button_start_ += extra_width + button_size.width(); 540 minimum_size_for_buttons_ += extra_width + button_size.width(); 541 has_trailing_buttons_ = true; 542 break; 543 } 544 } 545} 546 547void OpaqueBrowserFrameViewLayout::SetView(int id, views::View* view) { 548 // Why do things this way instead of having an Init() method, where we're 549 // passed the views we'll handle? Because OpaqueBrowserFrameView doesn't own 550 // all the views which are part of it. The avatar stuff, for example, will be 551 // added and removed by the base class of OpaqueBrowserFrameView. 552 switch (id) { 553 case VIEW_ID_MINIMIZE_BUTTON: 554 if (view) { 555 DCHECK_EQ(std::string(views::ImageButton::kViewClassName), 556 view->GetClassName()); 557 } 558 minimize_button_ = static_cast<views::ImageButton*>(view); 559 break; 560 case VIEW_ID_MAXIMIZE_BUTTON: 561 if (view) { 562 DCHECK_EQ(std::string(views::ImageButton::kViewClassName), 563 view->GetClassName()); 564 } 565 maximize_button_ = static_cast<views::ImageButton*>(view); 566 break; 567 case VIEW_ID_RESTORE_BUTTON: 568 if (view) { 569 DCHECK_EQ(std::string(views::ImageButton::kViewClassName), 570 view->GetClassName()); 571 } 572 restore_button_ = static_cast<views::ImageButton*>(view); 573 break; 574 case VIEW_ID_CLOSE_BUTTON: 575 if (view) { 576 DCHECK_EQ(std::string(views::ImageButton::kViewClassName), 577 view->GetClassName()); 578 } 579 close_button_ = static_cast<views::ImageButton*>(view); 580 break; 581 case VIEW_ID_WINDOW_ICON: 582 window_icon_ = view; 583 break; 584 case VIEW_ID_WINDOW_TITLE: 585 if (view) { 586 DCHECK_EQ(std::string(views::Label::kViewClassName), 587 view->GetClassName()); 588 } 589 window_title_ = static_cast<views::Label*>(view); 590 break; 591 case VIEW_ID_AVATAR_LABEL: 592 avatar_label_ = view; 593 break; 594 case VIEW_ID_AVATAR_BUTTON: 595 avatar_button_ = view; 596 break; 597 case VIEW_ID_NEW_AVATAR_BUTTON: 598 new_avatar_button_ = view; 599 break; 600 default: 601 NOTIMPLEMENTED() << "Unknown view id " << id; 602 break; 603 } 604} 605 606/////////////////////////////////////////////////////////////////////////////// 607// OpaqueBrowserFrameView, views::LayoutManager: 608 609void OpaqueBrowserFrameViewLayout::Layout(views::View* host) { 610 // Reset all our data so that everything is invisible. 611 int thickness = FrameBorderThickness(false); 612 leading_button_start_ = thickness; 613 trailing_button_start_ = thickness; 614 minimum_size_for_buttons_ = leading_button_start_ + trailing_button_start_; 615 has_leading_buttons_ = false; 616 has_trailing_buttons_ = false; 617 618 LayoutWindowControls(host); 619 LayoutTitleBar(host); 620 621 // We now add a single pixel to the leading spacing. We do this because the 622 // avatar and tab strip start one pixel inward compared to where things start 623 // on the trailing side. 624 leading_button_start_++; 625 626 if (delegate_->IsRegularOrGuestSession() && 627 profiles::IsNewProfileManagementEnabled()) 628 LayoutNewStyleAvatar(host); 629 else 630 LayoutAvatar(); 631 632 client_view_bounds_ = CalculateClientAreaBounds( 633 host->width(), host->height()); 634} 635 636gfx::Size OpaqueBrowserFrameViewLayout::GetPreferredSize(views::View* host) { 637 // This is never used; NonClientView::GetPreferredSize() will be called 638 // instead. 639 NOTREACHED(); 640 return gfx::Size(); 641} 642 643void OpaqueBrowserFrameViewLayout::ViewAdded(views::View* host, 644 views::View* view) { 645 SetView(view->id(), view); 646} 647 648void OpaqueBrowserFrameViewLayout::ViewRemoved(views::View* host, 649 views::View* view) { 650 SetView(view->id(), NULL); 651} 652