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