Index: chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc |
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc |
index b11f833b7e16ca814f224450ecc8d315145be1ae..a7ef4172e9943767d3253005d15799f8843e3d77 100644 |
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc |
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc |
@@ -47,7 +47,7 @@ const int kAvatarBottomSpacing = 2; |
const int kAvatarLeftSpacing = 2; |
// Space between the right edge of the avatar and the tabstrip. |
-const int kAvatarRightSpacing = -2; |
+const int kAvatarRightSpacing = -4; |
// In restored mode, the New Tab button isn't at the same height as the caption |
// buttons, but the space will look cluttered if it actually slides under them, |
@@ -75,6 +75,11 @@ const int kTabStripIndent = -6; |
OpaqueBrowserFrameViewLayout::OpaqueBrowserFrameViewLayout( |
OpaqueBrowserFrameViewLayoutDelegate* delegate) |
: delegate_(delegate), |
+ left_button_start_(0), |
+ right_button_start_(0), |
+ minimum_size_for_buttons_(0), |
+ has_left_buttons_(false), |
+ has_right_buttons_(false), |
minimize_button_(NULL), |
maximize_button_(NULL), |
restore_button_(NULL), |
@@ -98,42 +103,33 @@ bool OpaqueBrowserFrameViewLayout::ShouldAddDefaultCaptionButtons() { |
gfx::Rect OpaqueBrowserFrameViewLayout::GetBoundsForTabStrip( |
const gfx::Size& tabstrip_preferred_size, |
int available_width) const { |
- gfx::Rect bounds = GetBoundsForTabStripAndAvatarArea( |
- tabstrip_preferred_size, available_width); |
- int space_left_of_tabstrip = kTabStripIndent; |
+ available_width -= right_button_start_; |
+ available_width -= left_button_start_; |
+ |
+ if (delegate_->GetAdditionalReservedSpaceInTabStrip()) |
+ available_width -= delegate_->GetAdditionalReservedSpaceInTabStrip(); |
+ |
+ const int caption_spacing = delegate_->IsMaximized() ? |
+ kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing; |
+ const int tabstrip_width = available_width - caption_spacing; |
+ gfx::Rect bounds(left_button_start_, GetTabStripInsetsTop(false), |
+ std::max(0, tabstrip_width), |
+ tabstrip_preferred_size.height()); |
+ |
+ int left_tabstrip_indent = kTabStripIndent; |
if (delegate_->ShouldShowAvatar()) { |
if (avatar_label_ && avatar_label_->bounds().width()) { |
// Space between the right edge of the avatar label and the tabstrip. |
const int kAvatarLabelRightSpacing = -10; |
- space_left_of_tabstrip = |
- avatar_label_->bounds().right() + kAvatarLabelRightSpacing; |
+ left_tabstrip_indent -= kAvatarLabelRightSpacing; |
} else { |
- space_left_of_tabstrip = |
- kAvatarLeftSpacing + avatar_bounds_.width() + |
- kAvatarRightSpacing; |
+ left_tabstrip_indent -= kAvatarRightSpacing; |
} |
} |
- bounds.Inset(space_left_of_tabstrip, 0, 0, 0); |
+ bounds.Inset(left_tabstrip_indent, 0, 0, 0); |
return bounds; |
} |
-gfx::Rect OpaqueBrowserFrameViewLayout::GetBoundsForTabStripAndAvatarArea( |
- const gfx::Size& tabstrip_preferred_size, |
- int available_width) const { |
- if (minimize_button_) { |
- available_width = minimize_button_->x(); |
- } else if (delegate_->GetAdditionalReservedSpaceInTabStrip()) { |
- available_width -= delegate_->GetAdditionalReservedSpaceInTabStrip(); |
- } |
- const int caption_spacing = delegate_->IsMaximized() ? |
- kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing; |
- const int tabstrip_x = NonClientBorderThickness(); |
- const int tabstrip_width = available_width - tabstrip_x - caption_spacing; |
- return gfx::Rect(tabstrip_x, GetTabStripInsetsTop(false), |
- std::max(0, tabstrip_width), |
- tabstrip_preferred_size.height()); |
-} |
- |
gfx::Size OpaqueBrowserFrameViewLayout::GetMinimumSize( |
int available_width) const { |
gfx::Size min_size = delegate_->GetBrowserViewMinimumSize(); |
@@ -141,30 +137,17 @@ gfx::Size OpaqueBrowserFrameViewLayout::GetMinimumSize( |
min_size.Enlarge(2 * border_thickness, |
NonClientTopBorderHeight(false) + border_thickness); |
- int min_titlebar_width = (2 * FrameBorderThickness(false)) + |
- kIconLeftSpacing + |
- (delegate_->ShouldShowWindowIcon() ? |
- (delegate_->GetIconSize() + kTitleLogoSpacing) : 0); |
- if (ShouldAddDefaultCaptionButtons()) { |
- min_titlebar_width += |
- minimize_button_->GetMinimumSize().width() + |
- restore_button_->GetMinimumSize().width() + |
- close_button_->GetMinimumSize().width(); |
- } |
- min_size.set_width(std::max(min_size.width(), min_titlebar_width)); |
+ // Ensure that we can, at minimum, hold our window controls and avatar icon. |
+ min_size.set_width(std::max(min_size.width(), minimum_size_for_buttons_)); |
// Ensure that the minimum width is enough to hold a minimum width tab strip |
- // and avatar icon at their usual insets. |
+ // at its usual insets. |
if (delegate_->IsTabStripVisible()) { |
gfx::Size preferred_size = delegate_->GetTabstripPreferredSize(); |
const int min_tabstrip_width = preferred_size.width(); |
- const int min_tabstrip_area_width = |
- available_width - |
- GetBoundsForTabStripAndAvatarArea( |
- preferred_size, available_width).width() + |
- min_tabstrip_width + delegate_->GetOTRAvatarIcon().width() + |
- kAvatarLeftSpacing + kAvatarRightSpacing; |
- min_size.set_width(std::max(min_size.width(), min_tabstrip_area_width)); |
+ const int caption_spacing = delegate_->IsMaximized() ? |
+ kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing; |
+ min_size.Enlarge(min_tabstrip_width + caption_spacing, 0); |
} |
return min_size; |
@@ -229,35 +212,7 @@ int OpaqueBrowserFrameViewLayout::CaptionButtonY(bool restored) const { |
} |
gfx::Rect OpaqueBrowserFrameViewLayout::IconBounds() const { |
- int size = delegate_->GetIconSize(); |
- int frame_thickness = FrameBorderThickness(false); |
- int y; |
- if (delegate_->ShouldShowWindowIcon() || |
- delegate_->ShouldShowWindowTitle()) { |
- // Our frame border has a different "3D look" than Windows'. Theirs has a |
- // more complex gradient on the top that they push their icon/title below; |
- // then the maximized window cuts this off and the icon/title are centered |
- // in the remaining space. Because the apparent shape of our border is |
- // simpler, using the same positioning makes things look slightly uncentered |
- // with restored windows, so when the window is restored, instead of |
- // calculating the remaining space from below the frame border, we calculate |
- // from below the 3D edge. |
- int unavailable_px_at_top = delegate_->IsMaximized() ? |
- frame_thickness : kTitlebarTopAndBottomEdgeThickness; |
- // When the icon is shorter than the minimum space we reserve for the |
- // caption button, we vertically center it. We want to bias rounding to put |
- // extra space above the icon, since the 3D edge (+ client edge, for |
- // restored windows) below looks (to the eye) more like additional space |
- // than does the 3D edge (or nothing at all, for maximized windows) above; |
- // hence the +1. |
- y = unavailable_px_at_top + (NonClientTopBorderHeight(false) - |
- unavailable_px_at_top - size - TitlebarBottomThickness(false) + 1) / 2; |
- } else { |
- // For "browser mode" windows, we use the native positioning, which is just |
- // below the top frame border. |
- y = frame_thickness; |
- } |
- return gfx::Rect(frame_thickness + kIconLeftSpacing, y, size, size); |
+ return window_icon_bounds_; |
} |
gfx::Rect OpaqueBrowserFrameViewLayout::CalculateClientAreaBounds( |
@@ -276,65 +231,85 @@ gfx::Rect OpaqueBrowserFrameViewLayout::CalculateClientAreaBounds( |
void OpaqueBrowserFrameViewLayout::LayoutWindowControls(views::View* host) { |
if (!ShouldAddDefaultCaptionButtons()) |
return; |
- bool is_maximized = delegate_->IsMaximized(); |
- close_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
- views::ImageButton::ALIGN_BOTTOM); |
+ |
+ // Reset the visibility of the buttons. |
+ minimize_button_->SetVisible(false); |
sky
2013/09/05 15:54:32
Initially making hidden and then making visible ri
Elliot Glaysher
2013/09/05 19:35:48
While I can't have ConfigureButton() control this
|
+ restore_button_->SetVisible(false); |
+ maximize_button_->SetVisible(false); |
+ close_button_->SetVisible(false); |
+ |
+ // TODO(erg): Replace this with configurable calls in the next patch. |
int caption_y = CaptionButtonY(false); |
- // There should always be the same number of non-shadow pixels visible to the |
- // side of the caption buttons. In maximized mode we extend the rightmost |
- // button to the screen corner to obey Fitts' Law. |
- int right_extra_width = is_maximized ? |
- (kFrameBorderThickness - |
- views::NonClientFrameView::kFrameShadowThickness) : 0; |
- gfx::Size close_button_size = close_button_->GetPreferredSize(); |
- close_button_->SetBounds(host->width() - FrameBorderThickness(false) - |
- right_extra_width - close_button_size.width(), caption_y, |
- close_button_size.width() + right_extra_width, |
- close_button_size.height()); |
- |
- // When the window is restored, we show a maximized button; otherwise, we show |
- // a restore button. |
- bool is_restored = !is_maximized && !delegate_->IsMinimized(); |
- views::ImageButton* invisible_button = is_restored ? |
- restore_button_ : maximize_button_; |
- invisible_button->SetVisible(false); |
- |
- views::ImageButton* visible_button = is_restored ? |
- maximize_button_ : restore_button_; |
- visible_button->SetVisible(true); |
- visible_button->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
- views::ImageButton::ALIGN_BOTTOM); |
- gfx::Size visible_button_size = visible_button->GetPreferredSize(); |
- visible_button->SetBounds(close_button_->x() - visible_button_size.width(), |
- caption_y, visible_button_size.width(), |
- visible_button_size.height()); |
- |
- minimize_button_->SetVisible(true); |
- minimize_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
- views::ImageButton::ALIGN_BOTTOM); |
- gfx::Size minimize_button_size = minimize_button_->GetPreferredSize(); |
- minimize_button_->SetBounds( |
- visible_button->x() - minimize_button_size.width(), caption_y, |
- minimize_button_size.width(), |
- minimize_button_size.height()); |
+ ConfigureButton(host, BUTTON_CLOSE, ALIGN_RIGHT, caption_y); |
+ ConfigureButton(host, BUTTON_MAXIMIZE, ALIGN_RIGHT, caption_y); |
+ ConfigureButton(host, BUTTON_MINIMIZE, ALIGN_RIGHT, caption_y); |
} |
-void OpaqueBrowserFrameViewLayout::LayoutTitleBar() { |
- gfx::Rect icon_bounds(IconBounds()); |
- if (delegate_->ShouldShowWindowIcon() && window_icon_) |
- window_icon_->SetBoundsRect(icon_bounds); |
+void OpaqueBrowserFrameViewLayout::LayoutTitleBar(views::View* host) { |
+ bool use_hidden_icon_location = true; |
- if (window_title_) { |
- bool should_show = delegate_->ShouldShowWindowTitle(); |
- window_title_->SetVisible(should_show); |
+ int size = delegate_->GetIconSize(); |
+ int frame_thickness = FrameBorderThickness(false); |
+ bool should_show_icon = delegate_->ShouldShowWindowIcon(); |
+ bool should_show_title = delegate_->ShouldShowWindowTitle(); |
+ |
+ if (should_show_icon || should_show_title) { |
+ use_hidden_icon_location = false; |
+ |
+ // Our frame border has a different "3D look" than Windows'. Theirs has |
+ // a more complex gradient on the top that they push their icon/title |
+ // below; then the maximized window cuts this off and the icon/title are |
+ // centered in the remaining space. Because the apparent shape of our |
+ // border is simpler, using the same positioning makes things look |
+ // slightly uncentered with restored windows, so when the window is |
+ // restored, instead of calculating the remaining space from below the |
+ // frame border, we calculate from below the 3D edge. |
+ int unavailable_px_at_top = delegate_->IsMaximized() ? |
+ frame_thickness : kTitlebarTopAndBottomEdgeThickness; |
+ // When the icon is shorter than the minimum space we reserve for the |
+ // caption button, we vertically center it. We want to bias rounding to |
+ // put extra space above the icon, since the 3D edge (+ client edge, for |
+ // restored windows) below looks (to the eye) more like additional space |
+ // than does the 3D edge (or nothing at all, for maximized windows) |
+ // above; hence the +1. |
+ int y = unavailable_px_at_top + (NonClientTopBorderHeight(false) - |
+ unavailable_px_at_top - size - |
+ TitlebarBottomThickness(false) + 1) / 2; |
+ |
+ window_icon_bounds_ = gfx::Rect(left_button_start_ + kIconLeftSpacing, y, |
+ size, size); |
+ left_button_start_ += size + kIconLeftSpacing; |
+ minimum_size_for_buttons_ += size + kIconLeftSpacing; |
+ } |
+ |
+ if (should_show_icon) |
+ window_icon_->SetBoundsRect(window_icon_bounds_); |
- if (should_show) { |
+ if (window_title_) { |
+ window_title_->SetVisible(should_show_title); |
+ if (should_show_title) { |
window_title_->SetText(delegate_->GetWindowTitle()); |
- const int title_x = delegate_->ShouldShowWindowIcon() ? |
- icon_bounds.right() + kIconTitleSpacing : icon_bounds.x(); |
- window_title_->SetBounds(title_x, icon_bounds.y(), |
- std::max(0, minimize_button_->x() - kTitleLogoSpacing - title_x), |
- icon_bounds.height()); |
+ |
+ int text_width = std::max( |
+ 0, host->width() - right_button_start_ - kTitleLogoSpacing - |
+ left_button_start_ - kIconTitleSpacing); |
+ window_title_->SetBounds(left_button_start_ + kIconTitleSpacing, |
+ window_icon_bounds_.y(), |
+ text_width, window_icon_bounds_.height()); |
+ left_button_start_ += text_width + kIconTitleSpacing; |
+ } |
+ } |
+ |
+ if (use_hidden_icon_location) { |
+ if (has_left_buttons_) { |
+ // There are window button icons on the left. Don't size the hidden window |
+ // icon that people can double click on to close the window. |
+ window_icon_bounds_ = gfx::Rect(); |
+ } else { |
+ // We set the icon bounds to a small rectangle in the top left corner if |
+ // there are no icons on the left side. |
+ window_icon_bounds_ = gfx::Rect( |
+ frame_thickness + kIconLeftSpacing, frame_thickness, size, size); |
} |
} |
} |
@@ -351,11 +326,14 @@ void OpaqueBrowserFrameViewLayout::LayoutAvatar() { |
int avatar_y = delegate_->IsMaximized() ? |
(NonClientTopBorderHeight(false) + kTabstripTopShadowThickness) : |
avatar_restored_y; |
- avatar_bounds_.SetRect(NonClientBorderThickness() + kAvatarLeftSpacing, |
+ avatar_bounds_.SetRect(left_button_start_ + kAvatarLeftSpacing, |
avatar_y, incognito_icon.width(), |
delegate_->ShouldShowAvatar() ? (avatar_bottom - avatar_y) : 0); |
- if (avatar_button_) |
+ if (avatar_button_) { |
avatar_button_->SetBoundsRect(avatar_bounds_); |
+ left_button_start_ += kAvatarLeftSpacing + incognito_icon.width(); |
+ minimum_size_for_buttons_ += kAvatarLeftSpacing + incognito_icon.width(); |
+ } |
if (avatar_label_) { |
// Space between the bottom of the avatar and the bottom of the avatar |
@@ -365,11 +343,84 @@ void OpaqueBrowserFrameViewLayout::LayoutAvatar() { |
const int kAvatarLabelLeftSpacing = -1; |
gfx::Size label_size = avatar_label_->GetPreferredSize(); |
gfx::Rect label_bounds( |
- FrameBorderThickness(false) + kAvatarLabelLeftSpacing, |
+ left_button_start_ + kAvatarLabelLeftSpacing, |
avatar_bottom - kAvatarLabelBottomSpacing - label_size.height(), |
label_size.width(), |
delegate_->ShouldShowAvatar() ? label_size.height() : 0); |
avatar_label_->SetBoundsRect(label_bounds); |
+ left_button_start_ += kAvatarLabelLeftSpacing + label_size.width(); |
+ } |
+} |
+ |
+void OpaqueBrowserFrameViewLayout::ConfigureButton( |
+ views::View* host, |
+ ButtonID button_id, |
+ ButtonAlignment alignment, |
+ int caption_y) { |
+ if (button_id == BUTTON_MINIMIZE) { |
+ minimize_button_->SetVisible(true); |
+ SetBoundsForButton(host, minimize_button_, alignment, caption_y); |
+ } else if (button_id == BUTTON_MAXIMIZE) { |
+ // When the window is restored, we show a maximized button; otherwise, we |
+ // show a restore button. |
+ bool is_restored = !delegate_->IsMaximized() && !delegate_->IsMinimized(); |
+ views::ImageButton* invisible_button = is_restored ? |
+ restore_button_ : maximize_button_; |
+ invisible_button->SetVisible(false); |
+ |
+ views::ImageButton* visible_button = is_restored ? |
+ maximize_button_ : restore_button_; |
+ visible_button->SetVisible(true); |
+ SetBoundsForButton(host, visible_button, alignment, caption_y); |
+ } else if (button_id == BUTTON_CLOSE) { |
+ close_button_->SetVisible(true); |
+ SetBoundsForButton(host, close_button_, alignment, caption_y); |
+ } |
+} |
sky
2013/09/05 15:54:32
else NOTREACHED? Although I would likely just use
|
+ |
+void OpaqueBrowserFrameViewLayout::SetBoundsForButton( |
+ views::View* host, |
+ views::ImageButton* button, |
+ ButtonAlignment alignment, |
+ int caption_y) { |
+ gfx::Size button_size = button->GetPreferredSize(); |
+ |
+ button->SetImageAlignment( |
+ (alignment == ALIGN_LEFT) ? |
+ views::ImageButton::ALIGN_RIGHT : views::ImageButton::ALIGN_LEFT, |
+ views::ImageButton::ALIGN_BOTTOM); |
+ |
+ // There should always be the same number of non-shadow pixels visible to the |
+ // side of the caption buttons. In maximized mode we extend the rightmost |
+ // button to the screen corner to obey Fitts' Law. |
+ bool is_maximized = delegate_->IsMaximized(); |
+ |
+ if (alignment == ALIGN_LEFT) { |
+ button->SetBounds( |
+ left_button_start_, |
+ caption_y, |
+ button_size.width(), |
+ button_size.height()); |
Elliot Glaysher
2013/09/05 00:49:30
The whole left alignment case here does work, but
|
+ |
+ left_button_start_ += button_size.width(); |
+ minimum_size_for_buttons_ += button_size.width(); |
+ has_left_buttons_ = true; |
+ } else { |
+ // If we're the first button on the right and maximized, add with to the |
+ // right hand side of the screen. |
+ int extra_width = (is_maximized && !has_right_buttons_) ? |
+ (kFrameBorderThickness - |
+ views::NonClientFrameView::kFrameShadowThickness) : 0; |
+ |
+ button->SetBounds( |
+ host->width() - right_button_start_ - extra_width - button_size.width(), |
+ caption_y, |
+ button_size.width() + extra_width, |
+ button_size.height()); |
+ |
+ right_button_start_ += extra_width + button_size.width(); |
+ minimum_size_for_buttons_ += extra_width + button_size.width(); |
+ has_right_buttons_ = true; |
} |
} |
@@ -433,8 +484,22 @@ void OpaqueBrowserFrameViewLayout::SetView(int id, views::View* view) { |
// OpaqueBrowserFrameView, views::LayoutManager: |
void OpaqueBrowserFrameViewLayout::Layout(views::View* host) { |
+ // Reset all our data so that everything is invisible. |
+ int thickness = FrameBorderThickness(false); |
+ left_button_start_ = thickness; |
+ right_button_start_ = thickness; |
+ minimum_size_for_buttons_ = left_button_start_ + right_button_start_; |
+ has_left_buttons_ = false; |
+ has_right_buttons_ = false; |
+ |
LayoutWindowControls(host); |
- LayoutTitleBar(); |
+ LayoutTitleBar(host); |
+ |
+ // We now add a single pixel to the left spacing. We do this because the |
+ // avatar and tab strip start one pixel inward compared to where things start |
+ // on the right side. |
+ left_button_start_++; |
+ |
LayoutAvatar(); |
client_view_bounds_ = CalculateClientAreaBounds( |