OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 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 "base/basictypes.h" |
| 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "chrome/browser/ui/views/tab_icon_view.h" |
| 10 #include "chrome/browser/ui/views/tabs/tab.h" |
| 11 #include "ui/gfx/image/image_skia.h" |
| 12 #include "ui/gfx/image/image_skia_rep.h" |
| 13 #include "ui/gfx/text_constants.h" |
| 14 #include "ui/views/controls/button/image_button.h" |
| 15 #include "ui/views/controls/button/menu_button.h" |
| 16 #include "ui/views/controls/label.h" |
| 17 #include "ui/views/test/views_test_base.h" |
| 18 |
| 19 using views::Widget; |
| 20 |
| 21 namespace { |
| 22 |
| 23 const int kWidth = 500; |
| 24 |
| 25 class TestLayoutDelegate : public OpaqueBrowserFrameViewLayoutDelegate { |
| 26 public: |
| 27 enum WindowState { |
| 28 STATE_NORMAL, |
| 29 STATE_MAXIMIZED, |
| 30 STATE_MINIMIZED, |
| 31 STATE_FULLSCREEN |
| 32 }; |
| 33 |
| 34 TestLayoutDelegate() |
| 35 : show_avatar_(false), |
| 36 window_state_(STATE_NORMAL) { |
| 37 } |
| 38 |
| 39 virtual ~TestLayoutDelegate() {} |
| 40 |
| 41 void SetWindowTitle(const base::string16& title) { |
| 42 window_title_ = title; |
| 43 } |
| 44 |
| 45 void SetShouldShowAvatar(bool show_avatar) { |
| 46 show_avatar_ = show_avatar; |
| 47 } |
| 48 |
| 49 void SetWindowState(WindowState state) { |
| 50 window_state_ = state; |
| 51 } |
| 52 |
| 53 virtual bool ShouldShowWindowIcon() const OVERRIDE { |
| 54 return !window_title_.empty(); |
| 55 } |
| 56 |
| 57 virtual bool ShouldShowWindowTitle() const OVERRIDE { |
| 58 return !window_title_.empty(); |
| 59 } |
| 60 |
| 61 virtual base::string16 GetWindowTitle() const OVERRIDE { |
| 62 return window_title_; |
| 63 } |
| 64 |
| 65 virtual int GetIconSize() const OVERRIDE { |
| 66 // The value on linux_aura and non-aura windows. |
| 67 return 17; |
| 68 } |
| 69 |
| 70 virtual bool ShouldLeaveOffsetNearTopBorder() const OVERRIDE { |
| 71 return !IsMaximized(); |
| 72 } |
| 73 |
| 74 virtual gfx::Size GetBrowserViewMinimumSize() const OVERRIDE { |
| 75 // Taken from a calculation in BrowserViewLayout. |
| 76 return gfx::Size(168, 64); |
| 77 } |
| 78 |
| 79 virtual bool ShouldShowAvatar() const OVERRIDE { |
| 80 return show_avatar_; |
| 81 } |
| 82 |
| 83 virtual gfx::ImageSkia GetOTRAvatarIcon() const OVERRIDE { |
| 84 // The calculations depend on the size of the OTR resource, and chromeos |
| 85 // uses a different sized image, so hard code the size of the current |
| 86 // windows/linux one. |
| 87 gfx::ImageSkiaRep rep(gfx::Size(40, 29), ui::SCALE_FACTOR_100P); |
| 88 gfx::ImageSkia image(rep); |
| 89 return image; |
| 90 } |
| 91 |
| 92 virtual bool IsMaximized() const OVERRIDE { |
| 93 return window_state_ == STATE_MAXIMIZED; |
| 94 } |
| 95 |
| 96 virtual bool IsMinimized() const OVERRIDE { |
| 97 return window_state_ == STATE_MINIMIZED; |
| 98 } |
| 99 |
| 100 virtual bool IsFullscreen() const OVERRIDE { |
| 101 return window_state_ == STATE_FULLSCREEN; |
| 102 } |
| 103 |
| 104 virtual bool IsTabStripVisible() const OVERRIDE { |
| 105 return window_title_.empty(); |
| 106 } |
| 107 |
| 108 virtual int GetTabStripHeight() const OVERRIDE { |
| 109 return IsTabStripVisible() ? Tab::GetMinimumUnselectedSize().height() : 0; |
| 110 } |
| 111 |
| 112 virtual int GetAdditionalReservedSpaceInTabStrip() const OVERRIDE { |
| 113 return 0; |
| 114 } |
| 115 |
| 116 virtual gfx::Size GetTabstripPreferredSize() const OVERRIDE { |
| 117 // Measured from Tabstrip::GetPreferredSize(). |
| 118 return IsTabStripVisible() ? gfx::Size(78, 29) : gfx::Size(0, 0); |
| 119 } |
| 120 |
| 121 private: |
| 122 base::string16 window_title_; |
| 123 bool show_avatar_; |
| 124 WindowState window_state_; |
| 125 |
| 126 DISALLOW_COPY_AND_ASSIGN(TestLayoutDelegate); |
| 127 }; |
| 128 |
| 129 } // namespace |
| 130 |
| 131 class OpaqueBrowserFrameViewLayoutTest : public views::ViewsTestBase { |
| 132 public: |
| 133 OpaqueBrowserFrameViewLayoutTest() {} |
| 134 virtual ~OpaqueBrowserFrameViewLayoutTest() {} |
| 135 |
| 136 virtual void SetUp() OVERRIDE { |
| 137 views::ViewsTestBase::SetUp(); |
| 138 |
| 139 delegate_ = new TestLayoutDelegate; |
| 140 layout_manager_ = new OpaqueBrowserFrameViewLayout(delegate_); |
| 141 widget_ = new Widget; |
| 142 widget_->Init(CreateParams(Widget::InitParams::TYPE_POPUP)); |
| 143 root_view_ = widget_->GetRootView(); |
| 144 root_view_->SetSize(gfx::Size(kWidth, kWidth)); |
| 145 root_view_->SetLayoutManager(layout_manager_); |
| 146 |
| 147 // Add the caption buttons. We use fake images because we're modeling the |
| 148 // Windows assets here, while the linux version uses differently sized |
| 149 // assets. |
| 150 // |
| 151 // TODO(erg): In a follow up patch, separate these sizes out into virtual |
| 152 // accessors so we can test both the windows and linux behaviours once we |
| 153 // start modifying the code. |
| 154 minimize_button_ = InitWindowCaptionButton( |
| 155 VIEW_ID_MINIMIZE_BUTTON, gfx::Size(26, 18)); |
| 156 maximize_button_ = InitWindowCaptionButton( |
| 157 VIEW_ID_MAXIMIZE_BUTTON, gfx::Size(25, 18)); |
| 158 restore_button_ = InitWindowCaptionButton( |
| 159 VIEW_ID_RESTORE_BUTTON, gfx::Size(25, 18)); |
| 160 close_button_ = InitWindowCaptionButton( |
| 161 VIEW_ID_CLOSE_BUTTON, gfx::Size(43, 18)); |
| 162 } |
| 163 |
| 164 virtual void TearDown() OVERRIDE { |
| 165 widget_->CloseNow(); |
| 166 |
| 167 views::ViewsTestBase::TearDown(); |
| 168 } |
| 169 |
| 170 protected: |
| 171 views::ImageButton* InitWindowCaptionButton(ViewID view_id, |
| 172 const gfx::Size& size) { |
| 173 views::ImageButton* button = new views::ImageButton(NULL); |
| 174 gfx::ImageSkiaRep rep(size, ui::SCALE_FACTOR_100P); |
| 175 gfx::ImageSkia image(rep); |
| 176 button->SetImage(views::CustomButton::STATE_NORMAL, &image); |
| 177 button->set_id(view_id); |
| 178 root_view_->AddChildView(button); |
| 179 return button; |
| 180 } |
| 181 |
| 182 void AddWindowTitleIcons() { |
| 183 tab_icon_view_ = new TabIconView(NULL); |
| 184 tab_icon_view_->set_is_light(true); |
| 185 tab_icon_view_->set_id(VIEW_ID_WINDOW_ICON); |
| 186 root_view_->AddChildView(tab_icon_view_); |
| 187 |
| 188 window_title_ = new views::Label(delegate_->GetWindowTitle(), |
| 189 default_font_); |
| 190 window_title_->SetVisible(delegate_->ShouldShowWindowTitle()); |
| 191 window_title_->SetEnabledColor(SK_ColorWHITE); |
| 192 window_title_->SetBackgroundColor(0x00000000); |
| 193 window_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 194 window_title_->set_id(VIEW_ID_WINDOW_TITLE); |
| 195 root_view_->AddChildView(window_title_); |
| 196 } |
| 197 |
| 198 void AddAvatarButton() { |
| 199 menu_button_ = new views::MenuButton(NULL, string16(), NULL, false); |
| 200 menu_button_->set_id(VIEW_ID_AVATAR_BUTTON); |
| 201 delegate_->SetShouldShowAvatar(true); |
| 202 root_view_->AddChildView(menu_button_); |
| 203 } |
| 204 |
| 205 void ExpectBasicWindowBounds() { |
| 206 EXPECT_EQ("428,1 25x18", maximize_button_->bounds().ToString()); |
| 207 EXPECT_EQ("402,1 26x18", minimize_button_->bounds().ToString()); |
| 208 EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString()); |
| 209 EXPECT_EQ("453,1 43x18", close_button_->bounds().ToString()); |
| 210 } |
| 211 |
| 212 gfx::Font default_font_; |
| 213 |
| 214 Widget* widget_; |
| 215 views::View* root_view_; |
| 216 OpaqueBrowserFrameViewLayout* layout_manager_; |
| 217 TestLayoutDelegate* delegate_; |
| 218 |
| 219 // Widgets: |
| 220 views::ImageButton* minimize_button_; |
| 221 views::ImageButton* maximize_button_; |
| 222 views::ImageButton* restore_button_; |
| 223 views::ImageButton* close_button_; |
| 224 |
| 225 TabIconView* tab_icon_view_; |
| 226 views::Label* window_title_; |
| 227 |
| 228 views::MenuButton* menu_button_; |
| 229 |
| 230 DISALLOW_COPY_AND_ASSIGN(OpaqueBrowserFrameViewLayoutTest); |
| 231 }; |
| 232 |
| 233 TEST_F(OpaqueBrowserFrameViewLayoutTest, BasicWindow) { |
| 234 // Tests the layout of a default chrome window with no avatars, no window |
| 235 // titles, and a tabstrip. |
| 236 root_view_->Layout(); |
| 237 |
| 238 ExpectBasicWindowBounds(); |
| 239 |
| 240 // After some visual inspection, it really does look like the tabstrip is |
| 241 // initally positioned out of our view. |
| 242 EXPECT_EQ("-1,13 398x29", |
| 243 layout_manager_->GetBoundsForTabStrip( |
| 244 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); |
| 245 EXPECT_EQ("226x73", layout_manager_->GetMinimumSize(kWidth).ToString()); |
| 246 |
| 247 // A normal window with no window icon still produces icon bounds for |
| 248 // Windows, which has a hidden icon that a user can double click on to close |
| 249 // the window. |
| 250 EXPECT_EQ("6,4 17x17", layout_manager_->IconBounds().ToString()); |
| 251 } |
| 252 |
| 253 TEST_F(OpaqueBrowserFrameViewLayoutTest, BasicWindowMaximized) { |
| 254 // Tests the layout of a default chrome window with no avatars, no window |
| 255 // titles, and a tabstrip, but maximized this time. |
| 256 delegate_->SetWindowState(TestLayoutDelegate::STATE_MAXIMIZED); |
| 257 root_view_->Layout(); |
| 258 |
| 259 // Note how the bonds start at the exact top of the window while maximized |
| 260 // while they start 1 pixel below when unmaximized. |
| 261 EXPECT_EQ("0,0 0x0", maximize_button_->bounds().ToString()); |
| 262 EXPECT_EQ("403,0 26x18", minimize_button_->bounds().ToString()); |
| 263 EXPECT_EQ("429,0 25x18", restore_button_->bounds().ToString()); |
| 264 EXPECT_EQ("454,0 46x18", close_button_->bounds().ToString()); |
| 265 |
| 266 EXPECT_EQ("-6,-3 393x29", |
| 267 layout_manager_->GetBoundsForTabStrip( |
| 268 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); |
| 269 EXPECT_EQ("231x61", layout_manager_->GetMinimumSize(kWidth).ToString()); |
| 270 |
| 271 // In the maximized case, OpaqueBrowserFrameView::NonClientHitTest() uses |
| 272 // this rect, extended to the top left corner of the window. |
| 273 EXPECT_EQ("2,0 17x17", layout_manager_->IconBounds().ToString()); |
| 274 } |
| 275 |
| 276 TEST_F(OpaqueBrowserFrameViewLayoutTest, WithWindowTitleAndIcon) { |
| 277 // Tests the layout of pop up windows. |
| 278 delegate_->SetWindowTitle(ASCIIToUTF16("Window Title")); |
| 279 AddWindowTitleIcons(); |
| 280 root_view_->Layout(); |
| 281 |
| 282 // We should have the right hand side should match the BasicWindow case. |
| 283 ExpectBasicWindowBounds(); |
| 284 |
| 285 // Check the location of the tab icon and window title. |
| 286 EXPECT_EQ("6,3 17x17", tab_icon_view_->bounds().ToString()); |
| 287 EXPECT_EQ("27,3 370x17", window_title_->bounds().ToString()); |
| 288 } |
| 289 |
| 290 TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithAvatar) { |
| 291 // Tests a normal tabstrip window with an avatar icon. |
| 292 AddAvatarButton(); |
| 293 root_view_->Layout(); |
| 294 |
| 295 ExpectBasicWindowBounds(); |
| 296 |
| 297 // Check the location of the avatar |
| 298 EXPECT_EQ("7,11 40x29", menu_button_->bounds().ToString()); |
| 299 EXPECT_EQ("45,13 352x29", |
| 300 layout_manager_->GetBoundsForTabStrip( |
| 301 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); |
| 302 EXPECT_EQ("226x73", layout_manager_->GetMinimumSize(kWidth).ToString()); |
| 303 } |
OLD | NEW |