OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/views/chrome_menu.h" | 5 #include "chrome/views/chrome_menu.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <uxtheme.h> | 8 #include <uxtheme.h> |
9 #include <Vssym32.h> | 9 #include <Vssym32.h> |
10 | 10 |
11 #include "base/base_drag_source.h" | 11 #include "base/base_drag_source.h" |
12 #include "base/gfx/native_theme.h" | 12 #include "base/gfx/native_theme.h" |
13 #include "base/gfx/skia_utils.h" | 13 #include "base/gfx/skia_utils.h" |
14 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
15 #include "base/task.h" | 15 #include "base/task.h" |
16 #include "base/timer.h" | 16 #include "base/timer.h" |
17 #include "base/win_util.h" | 17 #include "base/win_util.h" |
18 #include "chrome/browser/drag_utils.h" | 18 #include "chrome/browser/drag_utils.h" |
19 #include "chrome/common/gfx/chrome_canvas.h" | 19 #include "chrome/common/gfx/chrome_canvas.h" |
20 #include "chrome/common/gfx/color_utils.h" | 20 #include "chrome/common/gfx/color_utils.h" |
21 #include "chrome/common/l10n_util.h" | 21 #include "chrome/common/l10n_util.h" |
22 #include "chrome/common/os_exchange_data.h" | 22 #include "chrome/common/os_exchange_data.h" |
23 #include "chrome/views/border.h" | 23 #include "chrome/views/border.h" |
24 #include "chrome/views/hwnd_view_container.h" | 24 #include "chrome/views/hwnd_view_container.h" |
25 #include "chrome/views/root_view.h" | 25 #include "chrome/views/root_view.h" |
26 #include "generated_resources.h" | 26 #include "generated_resources.h" |
27 | 27 |
| 28 #undef min |
| 29 #undef max |
| 30 |
28 // Margins between the top of the item and the label. | 31 // Margins between the top of the item and the label. |
29 static const int kItemTopMargin = 3; | 32 static const int kItemTopMargin = 3; |
30 | 33 |
31 // Margins between the bottom of the item and the label. | 34 // Margins between the bottom of the item and the label. |
32 static const int kItemBottomMargin = 4; | 35 static const int kItemBottomMargin = 4; |
33 | 36 |
34 // Margins between the left of the item and the icon. | 37 // Margins between the left of the item and the icon. |
35 static const int kItemLeftMargin = 4; | 38 static const int kItemLeftMargin = 4; |
36 | 39 |
37 // Padding between the label and submenu arrow. | 40 // Padding between the label and submenu arrow. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 | 91 |
89 // Color of the drop indicator. | 92 // Color of the drop indicator. |
90 static const SkColor kDropIndicatorColor = SK_ColorBLACK; | 93 static const SkColor kDropIndicatorColor = SK_ColorBLACK; |
91 | 94 |
92 // Whether or not the gutter should be rendered. The gutter is specific to | 95 // Whether or not the gutter should be rendered. The gutter is specific to |
93 // Vista. | 96 // Vista. |
94 static bool render_gutter = false; | 97 static bool render_gutter = false; |
95 | 98 |
96 // Max width of a menu. There does not appear to be an OS value for this, yet | 99 // Max width of a menu. There does not appear to be an OS value for this, yet |
97 // both IE and FF restrict the max width of a menu. | 100 // both IE and FF restrict the max width of a menu. |
98 static const LONG kMaxMenuWidth = 400; | 101 static const int kMaxMenuWidth = 400; |
99 | 102 |
100 // Period of the scroll timer (in milliseconds). | 103 // Period of the scroll timer (in milliseconds). |
101 static const int kScrollTimerMS = 30; | 104 static const int kScrollTimerMS = 30; |
102 | 105 |
103 // Preferred height of menu items. Reset every time a menu is run. | 106 // Preferred height of menu items. Reset every time a menu is run. |
104 static int pref_menu_height; | 107 static int pref_menu_height; |
105 | 108 |
106 // Are mnemonics shown? This is updated before the menus are shown. | 109 // Are mnemonics shown? This is updated before the menus are shown. |
107 static bool show_mnemonics; | 110 static bool show_mnemonics; |
108 | 111 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 } | 163 } |
161 | 164 |
162 item_right_margin = kLabelToArrowPadding + arrow_width + kArrowToEdgePadding; | 165 item_right_margin = kLabelToArrowPadding + arrow_width + kArrowToEdgePadding; |
163 | 166 |
164 label_start = kItemLeftMargin + check_width + kIconToLabelPadding; | 167 label_start = kItemLeftMargin + check_width + kIconToLabelPadding; |
165 if (render_gutter) | 168 if (render_gutter) |
166 label_start += gutter_width + kGutterToLabel; | 169 label_start += gutter_width + kGutterToLabel; |
167 | 170 |
168 ReleaseDC(NULL, dc); | 171 ReleaseDC(NULL, dc); |
169 | 172 |
170 CSize pref; | |
171 MenuItemView menu_item(NULL); | 173 MenuItemView menu_item(NULL); |
172 menu_item.SetTitle(L"blah"); // Text doesn't matter here. | 174 menu_item.SetTitle(L"blah"); // Text doesn't matter here. |
173 menu_item.GetPreferredSize(&pref); | 175 pref_menu_height = menu_item.GetPreferredSize().height(); |
174 pref_menu_height = pref.cy; | |
175 } | 176 } |
176 | 177 |
177 namespace { | 178 namespace { |
178 | 179 |
179 // Convenience for scrolling the view such that the origin is visible. | 180 // Convenience for scrolling the view such that the origin is visible. |
180 static void ScrollToVisible(View* view) { | 181 static void ScrollToVisible(View* view) { |
181 view->ScrollRectToVisible(0, 0, view->width(), view->height()); | 182 view->ScrollRectToVisible(0, 0, view->width(), view->height()); |
182 } | 183 } |
183 | 184 |
184 // MenuScrollTask -------------------------------------------------------------- | 185 // MenuScrollTask -------------------------------------------------------------- |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 | 273 |
273 class MenuScrollButton : public View { | 274 class MenuScrollButton : public View { |
274 public: | 275 public: |
275 explicit MenuScrollButton(SubmenuView* host, bool is_up) | 276 explicit MenuScrollButton(SubmenuView* host, bool is_up) |
276 : host_(host), | 277 : host_(host), |
277 is_up_(is_up), | 278 is_up_(is_up), |
278 // Make our height the same as that of other MenuItemViews. | 279 // Make our height the same as that of other MenuItemViews. |
279 pref_height_(pref_menu_height) { | 280 pref_height_(pref_menu_height) { |
280 } | 281 } |
281 | 282 |
282 virtual void GetPreferredSize(CSize* out) { | 283 virtual gfx::Size GetPreferredSize() { |
283 out->cx = kScrollArrowHeight * 2 - 1; | 284 return gfx::Size(kScrollArrowHeight * 2 - 1, pref_height_); |
284 out->cy = pref_height_; | |
285 } | 285 } |
286 | 286 |
287 virtual bool CanDrop(const OSExchangeData& data) { | 287 virtual bool CanDrop(const OSExchangeData& data) { |
288 DCHECK(host_->GetMenuItem()->GetMenuController()); | 288 DCHECK(host_->GetMenuItem()->GetMenuController()); |
289 return true; // Always return true so that drop events are targeted to us. | 289 return true; // Always return true so that drop events are targeted to us. |
290 } | 290 } |
291 | 291 |
292 virtual void OnDragEntered(const DropTargetEvent& event) { | 292 virtual void OnDragEntered(const DropTargetEvent& event) { |
293 DCHECK(host_->GetMenuItem()->GetMenuController()); | 293 DCHECK(host_->GetMenuItem()->GetMenuController()); |
294 host_->GetMenuItem()->GetMenuController()->OnDragEnteredScrollButton( | 294 host_->GetMenuItem()->GetMenuController()->OnDragEnteredScrollButton( |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 explicit MenuScrollView(View* child) { | 360 explicit MenuScrollView(View* child) { |
361 AddChildView(child); | 361 AddChildView(child); |
362 } | 362 } |
363 | 363 |
364 virtual void ScrollRectToVisible(int x, int y, int width, int height) { | 364 virtual void ScrollRectToVisible(int x, int y, int width, int height) { |
365 // NOTE: this assumes we only want to scroll in the y direction. | 365 // NOTE: this assumes we only want to scroll in the y direction. |
366 | 366 |
367 View* child = GetContents(); | 367 View* child = GetContents(); |
368 // Convert y to view's coordinates. | 368 // Convert y to view's coordinates. |
369 y -= child->y(); | 369 y -= child->y(); |
370 CSize pref; | 370 gfx::Size pref = child->GetPreferredSize(); |
371 child->GetPreferredSize(&pref); | |
372 // Constrain y to make sure we don't show past the bottom of the view. | 371 // Constrain y to make sure we don't show past the bottom of the view. |
373 y = std::max(0, std::min(static_cast<int>(pref.cy) - this->height(), y)); | 372 y = std::max(0, std::min(pref.height() - this->height(), y)); |
374 child->SetY(-y); | 373 child->SetY(-y); |
375 } | 374 } |
376 | 375 |
377 // Returns the contents, which is the SubmenuView. | 376 // Returns the contents, which is the SubmenuView. |
378 View* GetContents() { | 377 View* GetContents() { |
379 return GetChildViewAt(0); | 378 return GetChildViewAt(0); |
380 } | 379 } |
381 | 380 |
382 private: | 381 private: |
383 DISALLOW_EVIL_CONSTRUCTORS(MenuScrollView); | 382 DISALLOW_EVIL_CONSTRUCTORS(MenuScrollView); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 int x = insets.left(); | 420 int x = insets.left(); |
422 int y = insets.top(); | 421 int y = insets.top(); |
423 int width = View::width() - insets.width(); | 422 int width = View::width() - insets.width(); |
424 int content_height = height() - insets.height(); | 423 int content_height = height() - insets.height(); |
425 if (!scroll_up_button_->IsVisible()) { | 424 if (!scroll_up_button_->IsVisible()) { |
426 scroll_view_->SetBounds(x, y, width, content_height); | 425 scroll_view_->SetBounds(x, y, width, content_height); |
427 scroll_view_->Layout(); | 426 scroll_view_->Layout(); |
428 return; | 427 return; |
429 } | 428 } |
430 | 429 |
431 CSize pref; | 430 gfx::Size pref = scroll_up_button_->GetPreferredSize(); |
432 scroll_up_button_->GetPreferredSize(&pref); | 431 scroll_up_button_->SetBounds(x, y, width, pref.height()); |
433 scroll_up_button_->SetBounds(x, y, width, pref.cy); | 432 content_height -= pref.height(); |
434 content_height -= pref.cy; | |
435 | 433 |
436 const int scroll_view_y = y + pref.cy; | 434 const int scroll_view_y = y + pref.height(); |
437 | 435 |
438 scroll_down_button_->GetPreferredSize(&pref); | 436 pref = scroll_down_button_->GetPreferredSize(); |
439 scroll_down_button_->SetBounds(x, height() - pref.cy - insets.top(), | 437 scroll_down_button_->SetBounds(x, height() - pref.height() - insets.top(), |
440 width, pref.cy); | 438 width, pref.height()); |
441 content_height -= pref.cy; | 439 content_height -= pref.height(); |
442 | 440 |
443 scroll_view_->SetBounds(x, scroll_view_y, width, content_height); | 441 scroll_view_->SetBounds(x, scroll_view_y, width, content_height); |
444 scroll_view_->Layout(); | 442 scroll_view_->Layout(); |
445 } | 443 } |
446 | 444 |
447 virtual void DidChangeBounds(const CRect& previous, const CRect& current) { | 445 virtual void DidChangeBounds(const CRect& previous, const CRect& current) { |
448 CSize content_pref; | 446 gfx::Size content_pref = scroll_view_->GetContents()->GetPreferredSize(); |
449 scroll_view_->GetContents()->GetPreferredSize(&content_pref); | 447 scroll_up_button_->SetVisible(content_pref.height() > height()); |
450 scroll_up_button_->SetVisible(content_pref.cy > height()); | 448 scroll_down_button_->SetVisible(content_pref.height() > height()); |
451 scroll_down_button_->SetVisible(content_pref.cy > height()); | |
452 } | 449 } |
453 | 450 |
454 virtual void GetPreferredSize(CSize* out) { | 451 virtual gfx::Size GetPreferredSize() { |
455 scroll_view_->GetContents()->GetPreferredSize(out); | 452 gfx::Size prefsize = scroll_view_->GetContents()->GetPreferredSize(); |
456 gfx::Insets insets = GetInsets(); | 453 gfx::Insets insets = GetInsets(); |
457 out->cx += insets.width(); | 454 prefsize.Enlarge(insets.width(), insets.height()); |
458 out->cy += insets.height(); | 455 return prefsize; |
459 } | 456 } |
460 | 457 |
461 private: | 458 private: |
462 // The scroll buttons. | 459 // The scroll buttons. |
463 View* scroll_up_button_; | 460 View* scroll_up_button_; |
464 View* scroll_down_button_; | 461 View* scroll_down_button_; |
465 | 462 |
466 // The scroll view. | 463 // The scroll view. |
467 MenuScrollView* scroll_view_; | 464 MenuScrollView* scroll_view_; |
468 | 465 |
(...skipping 24 matching lines...) Expand all Loading... |
493 &gutter_bounds); | 490 &gutter_bounds); |
494 start_x = gutter_bounds.left + gutter_width; | 491 start_x = gutter_bounds.left + gutter_width; |
495 start_y = 0; | 492 start_y = 0; |
496 } | 493 } |
497 RECT separator_bounds = { start_x, start_y, width(), height() }; | 494 RECT separator_bounds = { start_x, start_y, width(), height() }; |
498 NativeTheme::instance()->PaintMenuSeparator(dc, MENU_POPUPSEPARATOR, | 495 NativeTheme::instance()->PaintMenuSeparator(dc, MENU_POPUPSEPARATOR, |
499 MPI_NORMAL, &separator_bounds); | 496 MPI_NORMAL, &separator_bounds); |
500 canvas->endPlatformPaint(); | 497 canvas->endPlatformPaint(); |
501 } | 498 } |
502 | 499 |
503 void GetPreferredSize(CSize* out) { | 500 gfx::Size GetPreferredSize() { |
504 out->cx = 10; // Just in case we're the only item in a menu. | 501 return gfx::Size(10, // Just in case we're the only item in a menu. |
505 out->cy = separator_height; | 502 separator_height); |
506 } | 503 } |
507 | 504 |
508 private: | 505 private: |
509 DISALLOW_EVIL_CONSTRUCTORS(MenuSeparator); | 506 DISALLOW_EVIL_CONSTRUCTORS(MenuSeparator); |
510 }; | 507 }; |
511 | 508 |
512 // MenuHostRootView ---------------------------------------------------------- | 509 // MenuHostRootView ---------------------------------------------------------- |
513 | 510 |
514 // MenuHostRootView is the RootView of the window showing the menu. | 511 // MenuHostRootView is the RootView of the window showing the menu. |
515 // SubmenuView's scroll view is added as a child of MenuHostRootView. | 512 // SubmenuView's scroll view is added as a child of MenuHostRootView. |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 } | 792 } |
796 NOTREACHED(); | 793 NOTREACHED(); |
797 return NULL; | 794 return NULL; |
798 } | 795 } |
799 | 796 |
800 void SubmenuView::Layout() { | 797 void SubmenuView::Layout() { |
801 // We're in a ScrollView, and need to set our width/height ourselves. | 798 // We're in a ScrollView, and need to set our width/height ourselves. |
802 View* parent = GetParent(); | 799 View* parent = GetParent(); |
803 if (!parent) | 800 if (!parent) |
804 return; | 801 return; |
805 CSize pref; | 802 SetBounds(x(), y(), parent->width(), GetPreferredSize().height()); |
806 GetPreferredSize(&pref); | |
807 SetBounds(x(), y(), parent->width(), pref.cy); | |
808 | 803 |
809 gfx::Insets insets = GetInsets(); | 804 gfx::Insets insets = GetInsets(); |
810 int x = insets.left(); | 805 int x = insets.left(); |
811 int y = insets.top(); | 806 int y = insets.top(); |
812 int menu_item_width = width() - insets.width(); | 807 int menu_item_width = width() - insets.width(); |
813 for (int i = 0; i < GetChildViewCount(); ++i) { | 808 for (int i = 0; i < GetChildViewCount(); ++i) { |
814 View* child = GetChildViewAt(i); | 809 View* child = GetChildViewAt(i); |
815 CSize child_pref_size; | 810 gfx::Size child_pref_size = child->GetPreferredSize(); |
816 child->GetPreferredSize(&child_pref_size); | 811 child->SetBounds(x, y, menu_item_width, child_pref_size.height()); |
817 child->SetBounds(x, y, menu_item_width, child_pref_size.cy); | 812 y += child_pref_size.height(); |
818 y += child_pref_size.cy; | |
819 } | 813 } |
820 } | 814 } |
821 | 815 |
822 void SubmenuView::GetPreferredSize(CSize* out) { | 816 gfx::Size SubmenuView::GetPreferredSize() { |
823 if (GetChildViewCount() == 0) { | 817 if (GetChildViewCount() == 0) |
824 out->SetSize(0, 0); | 818 return gfx::Size(); |
825 return; | |
826 } | |
827 | 819 |
828 int max_width = 0; | 820 int max_width = 0; |
829 int height = 0; | 821 int height = 0; |
830 for (int i = 0; i < GetChildViewCount(); ++i) { | 822 for (int i = 0; i < GetChildViewCount(); ++i) { |
831 View* child = GetChildViewAt(i); | 823 View* child = GetChildViewAt(i); |
832 CSize child_pref_size; | 824 gfx::Size child_pref_size = child->GetPreferredSize(); |
833 child->GetPreferredSize(&child_pref_size); | 825 max_width = std::max(max_width, child_pref_size.width()); |
834 max_width = std::max(max_width, static_cast<int>(child_pref_size.cx)); | 826 height += child_pref_size.height(); |
835 height += child_pref_size.cy; | |
836 } | 827 } |
837 gfx::Insets insets = GetInsets(); | 828 gfx::Insets insets = GetInsets(); |
838 out->SetSize(max_width + insets.width(), height + insets.height()); | 829 return gfx::Size(max_width + insets.width(), height + insets.height()); |
839 } | 830 } |
840 | 831 |
841 void SubmenuView::DidChangeBounds(const CRect& previous, const CRect& current) { | 832 void SubmenuView::DidChangeBounds(const CRect& previous, const CRect& current) { |
842 SchedulePaint(); | 833 SchedulePaint(); |
843 } | 834 } |
844 | 835 |
845 void SubmenuView::PaintChildren(ChromeCanvas* canvas) { | 836 void SubmenuView::PaintChildren(ChromeCanvas* canvas) { |
846 View::PaintChildren(canvas); | 837 View::PaintChildren(canvas); |
847 | 838 |
848 if (drop_item_ && drop_position_ != MenuDelegate::DROP_ON) | 839 if (drop_item_ && drop_position_ != MenuDelegate::DROP_ON) |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 | 1149 |
1159 void MenuItemView::SetIcon(const SkBitmap& icon) { | 1150 void MenuItemView::SetIcon(const SkBitmap& icon) { |
1160 icon_ = icon; | 1151 icon_ = icon; |
1161 SchedulePaint(); | 1152 SchedulePaint(); |
1162 } | 1153 } |
1163 | 1154 |
1164 void MenuItemView::Paint(ChromeCanvas* canvas) { | 1155 void MenuItemView::Paint(ChromeCanvas* canvas) { |
1165 Paint(canvas, false); | 1156 Paint(canvas, false); |
1166 } | 1157 } |
1167 | 1158 |
1168 void MenuItemView::GetPreferredSize(CSize* out) { | 1159 gfx::Size MenuItemView::GetPreferredSize() { |
1169 out->cx = font_.GetStringWidth(title_) + label_start + item_right_margin; | 1160 return gfx::Size( |
1170 out->cy = font_.height() + kItemBottomMargin + kItemTopMargin; | 1161 font_.GetStringWidth(title_) + label_start + item_right_margin, |
| 1162 font_.height() + kItemBottomMargin + kItemTopMargin); |
1171 } | 1163 } |
1172 | 1164 |
1173 MenuController* MenuItemView::GetMenuController() { | 1165 MenuController* MenuItemView::GetMenuController() { |
1174 return GetRootMenuItem()->controller_; | 1166 return GetRootMenuItem()->controller_; |
1175 } | 1167 } |
1176 | 1168 |
1177 MenuDelegate* MenuItemView::GetDelegate() { | 1169 MenuDelegate* MenuItemView::GetDelegate() { |
1178 return GetRootMenuItem()->delegate_; | 1170 return GetRootMenuItem()->delegate_; |
1179 } | 1171 } |
1180 | 1172 |
(...skipping 1227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2408 } | 2400 } |
2409 | 2401 |
2410 gfx::Rect MenuController::CalculateMenuBounds(MenuItemView* item, | 2402 gfx::Rect MenuController::CalculateMenuBounds(MenuItemView* item, |
2411 bool prefer_leading, | 2403 bool prefer_leading, |
2412 bool* is_leading) { | 2404 bool* is_leading) { |
2413 DCHECK(item); | 2405 DCHECK(item); |
2414 | 2406 |
2415 SubmenuView* submenu = item->GetSubmenu(); | 2407 SubmenuView* submenu = item->GetSubmenu(); |
2416 DCHECK(submenu); | 2408 DCHECK(submenu); |
2417 | 2409 |
2418 CSize pref; | 2410 gfx::Size pref = submenu->GetScrollViewContainer()->GetPreferredSize(); |
2419 submenu->GetScrollViewContainer()->GetPreferredSize(&pref); | |
2420 | 2411 |
2421 // Don't let the menu go to wide. This is some where between what IE and FF | 2412 // Don't let the menu go to wide. This is some where between what IE and FF |
2422 // do. | 2413 // do. |
2423 pref.cx = std::min(pref.cx, kMaxMenuWidth); | 2414 pref.set_width(std::min(pref.width(), kMaxMenuWidth)); |
2424 if (!state_.monitor_bounds.IsEmpty()) | 2415 if (!state_.monitor_bounds.IsEmpty()) |
2425 pref.cx = std::min(pref.cx, | 2416 pref.set_width(std::min(pref.width(), state_.monitor_bounds.width())); |
2426 static_cast<LONG>(state_.monitor_bounds.width())); | |
2427 | 2417 |
2428 // Assume we can honor prefer_leading. | 2418 // Assume we can honor prefer_leading. |
2429 *is_leading = prefer_leading; | 2419 *is_leading = prefer_leading; |
2430 | 2420 |
2431 int x, y; | 2421 int x, y; |
2432 | 2422 |
2433 if (!item->GetParentMenuItem()) { | 2423 if (!item->GetParentMenuItem()) { |
2434 // First item, position relative to initial location. | 2424 // First item, position relative to initial location. |
2435 x = state_.initial_bounds.x(); | 2425 x = state_.initial_bounds.x(); |
2436 y = state_.initial_bounds.bottom(); | 2426 y = state_.initial_bounds.bottom(); |
2437 if (state_.anchor == MenuItemView::TOPRIGHT) | 2427 if (state_.anchor == MenuItemView::TOPRIGHT) |
2438 x = x + state_.initial_bounds.width() - pref.cx; | 2428 x = x + state_.initial_bounds.width() - pref.width(); |
2439 if (!state_.monitor_bounds.IsEmpty() && | 2429 if (!state_.monitor_bounds.IsEmpty() && |
2440 y + pref.cy > state_.monitor_bounds.bottom()) { | 2430 y + pref.height() > state_.monitor_bounds.bottom()) { |
2441 // The menu doesn't fit on screen. If the first location is above the | 2431 // The menu doesn't fit on screen. If the first location is above the |
2442 // half way point, show from the mouse location to bottom of screen. | 2432 // half way point, show from the mouse location to bottom of screen. |
2443 // Otherwise show from the top of the screen to the location of the mouse. | 2433 // Otherwise show from the top of the screen to the location of the mouse. |
2444 // While odd, this behavior matches IE. | 2434 // While odd, this behavior matches IE. |
2445 if (y < (state_.monitor_bounds.y() + | 2435 if (y < (state_.monitor_bounds.y() + |
2446 state_.monitor_bounds.height() / 2)) { | 2436 state_.monitor_bounds.height() / 2)) { |
2447 pref.cy = std::min(pref.cy, | 2437 pref.set_height(std::min(pref.height(), |
2448 static_cast<LONG>(state_.monitor_bounds.bottom() - y)); | 2438 state_.monitor_bounds.bottom() - y)); |
2449 } else { | 2439 } else { |
2450 pref.cy = std::min(pref.cy, static_cast<LONG>( | 2440 pref.set_height(std::min(pref.height(), |
2451 state_.initial_bounds.y() - state_.monitor_bounds.y())); | 2441 state_.initial_bounds.y() - state_.monitor_bounds.y())); |
2452 y = state_.initial_bounds.y() - pref.cy; | 2442 y = state_.initial_bounds.y() - pref.height(); |
2453 } | 2443 } |
2454 } | 2444 } |
2455 } else { | 2445 } else { |
2456 // Not the first menu; position it relative to the bounds of the menu | 2446 // Not the first menu; position it relative to the bounds of the menu |
2457 // item. | 2447 // item. |
2458 gfx::Point item_loc; | 2448 gfx::Point item_loc; |
2459 View::ConvertPointToScreen(item, &item_loc); | 2449 View::ConvertPointToScreen(item, &item_loc); |
2460 | 2450 |
2461 // We must make sure we take into account the UI layout. If the layout is | 2451 // We must make sure we take into account the UI layout. If the layout is |
2462 // RTL, then a 'leading' menu is positioned to the left of the parent menu | 2452 // RTL, then a 'leading' menu is positioned to the left of the parent menu |
2463 // item and not to the right. | 2453 // item and not to the right. |
2464 bool layout_is_rtl = item->UILayoutIsRightToLeft(); | 2454 bool layout_is_rtl = item->UILayoutIsRightToLeft(); |
2465 bool create_on_the_right = (prefer_leading && !layout_is_rtl) || | 2455 bool create_on_the_right = (prefer_leading && !layout_is_rtl) || |
2466 (!prefer_leading && layout_is_rtl); | 2456 (!prefer_leading && layout_is_rtl); |
2467 | 2457 |
2468 if (create_on_the_right) { | 2458 if (create_on_the_right) { |
2469 x = item_loc.x() + item->width() - kSubmenuHorizontalInset; | 2459 x = item_loc.x() + item->width() - kSubmenuHorizontalInset; |
2470 if (state_.monitor_bounds.width() != 0 && | 2460 if (state_.monitor_bounds.width() != 0 && |
2471 x + pref.cx > state_.monitor_bounds.right()) { | 2461 x + pref.width() > state_.monitor_bounds.right()) { |
2472 if (layout_is_rtl) | 2462 if (layout_is_rtl) |
2473 *is_leading = true; | 2463 *is_leading = true; |
2474 else | 2464 else |
2475 *is_leading = false; | 2465 *is_leading = false; |
2476 x = item_loc.x() - pref.cx + kSubmenuHorizontalInset; | 2466 x = item_loc.x() - pref.width() + kSubmenuHorizontalInset; |
2477 } | 2467 } |
2478 } else { | 2468 } else { |
2479 x = item_loc.x() - pref.cx + kSubmenuHorizontalInset; | 2469 x = item_loc.x() - pref.width() + kSubmenuHorizontalInset; |
2480 if (state_.monitor_bounds.width() != 0 && x < state_.monitor_bounds.x()) { | 2470 if (state_.monitor_bounds.width() != 0 && x < state_.monitor_bounds.x()) { |
2481 if (layout_is_rtl) | 2471 if (layout_is_rtl) |
2482 *is_leading = false; | 2472 *is_leading = false; |
2483 else | 2473 else |
2484 *is_leading = true; | 2474 *is_leading = true; |
2485 x = item_loc.x() + item->width() - kSubmenuHorizontalInset; | 2475 x = item_loc.x() + item->width() - kSubmenuHorizontalInset; |
2486 } | 2476 } |
2487 } | 2477 } |
2488 y = item_loc.y() - kSubmenuBorderSize; | 2478 y = item_loc.y() - kSubmenuBorderSize; |
2489 if (state_.monitor_bounds.width() != 0) { | 2479 if (state_.monitor_bounds.width() != 0) { |
2490 pref.cy = std::min(pref.cy, | 2480 pref.set_height(std::min(pref.height(), state_.monitor_bounds.height())); |
2491 static_cast<LONG>(state_.monitor_bounds.height())); | 2481 if (y + pref.height() > state_.monitor_bounds.bottom()) |
2492 if (y + pref.cy > state_.monitor_bounds.bottom()) | 2482 y = state_.monitor_bounds.bottom() - pref.height(); |
2493 y = state_.monitor_bounds.bottom() - pref.cy; | |
2494 if (y < state_.monitor_bounds.y()) | 2483 if (y < state_.monitor_bounds.y()) |
2495 y = state_.monitor_bounds.y(); | 2484 y = state_.monitor_bounds.y(); |
2496 } | 2485 } |
2497 } | 2486 } |
2498 | 2487 |
2499 if (state_.monitor_bounds.width() != 0) { | 2488 if (state_.monitor_bounds.width() != 0) { |
2500 if (x + pref.cx > state_.monitor_bounds.right()) | 2489 if (x + pref.width() > state_.monitor_bounds.right()) |
2501 x = state_.monitor_bounds.right() - pref.cx; | 2490 x = state_.monitor_bounds.right() - pref.width(); |
2502 if (x < state_.monitor_bounds.x()) | 2491 if (x < state_.monitor_bounds.x()) |
2503 x = state_.monitor_bounds.x(); | 2492 x = state_.monitor_bounds.x(); |
2504 } | 2493 } |
2505 return gfx::Rect(x, y, pref.cx, pref.cy); | 2494 return gfx::Rect(x, y, pref.width(), pref.height()); |
2506 } | 2495 } |
2507 | 2496 |
2508 // static | 2497 // static |
2509 int MenuController::MenuDepth(MenuItemView* item) { | 2498 int MenuController::MenuDepth(MenuItemView* item) { |
2510 if (!item) | 2499 if (!item) |
2511 return 0; | 2500 return 0; |
2512 return MenuDepth(item->GetParentMenuItem()) + 1; | 2501 return MenuDepth(item->GetParentMenuItem()) + 1; |
2513 } | 2502 } |
2514 | 2503 |
2515 void MenuController::IncrementSelection(int delta) { | 2504 void MenuController::IncrementSelection(int delta) { |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2723 scroll_task_.reset(new MenuScrollTask()); | 2712 scroll_task_.reset(new MenuScrollTask()); |
2724 scroll_task_->Update(part); | 2713 scroll_task_->Update(part); |
2725 } | 2714 } |
2726 | 2715 |
2727 void MenuController::StopScrolling() { | 2716 void MenuController::StopScrolling() { |
2728 scroll_task_.reset(NULL); | 2717 scroll_task_.reset(NULL); |
2729 } | 2718 } |
2730 | 2719 |
2731 } // namespace ChromeViews | 2720 } // namespace ChromeViews |
2732 | 2721 |
OLD | NEW |