Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: ui/views/controls/menu/menu_item_view.cc

Issue 10532171: Added support for icon views (view used instead of icon in a menu item). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added support for icon views (view used instead of icon in a menu item). Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "ui/views/controls/menu/menu_item_view.h" 5 #include "ui/views/controls/menu/menu_item_view.h"
6 6
7 #include "base/i18n/case_conversion.h" 7 #include "base/i18n/case_conversion.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "base/utf_string_conversions.h" 9 #include "base/utf_string_conversions.h"
10 #include "grit/ui_strings.h" 10 #include "grit/ui_strings.h"
11 #include "ui/base/accessibility/accessible_view_state.h" 11 #include "ui/base/accessibility/accessible_view_state.h"
12 #include "ui/base/l10n/l10n_util.h" 12 #include "ui/base/l10n/l10n_util.h"
13 #include "ui/base/models/menu_model.h" 13 #include "ui/base/models/menu_model.h"
14 #include "ui/gfx/canvas.h" 14 #include "ui/gfx/canvas.h"
15 #include "ui/views/controls/button/menu_button.h" 15 #include "ui/views/controls/button/menu_button.h"
16 #include "ui/views/controls/image_view.h"
16 #include "ui/views/controls/menu/menu_config.h" 17 #include "ui/views/controls/menu/menu_config.h"
17 #include "ui/views/controls/menu/menu_controller.h" 18 #include "ui/views/controls/menu/menu_controller.h"
18 #include "ui/views/controls/menu/menu_separator.h" 19 #include "ui/views/controls/menu/menu_separator.h"
19 #include "ui/views/controls/menu/submenu_view.h" 20 #include "ui/views/controls/menu/submenu_view.h"
20 21
21 namespace views { 22 namespace views {
22 23
23 namespace { 24 namespace {
24 25
25 // EmptyMenuMenuItem --------------------------------------------------------- 26 // EmptyMenuMenuItem ---------------------------------------------------------
(...skipping 30 matching lines...) Expand all
56 // MenuItemView --------------------------------------------------------------- 57 // MenuItemView ---------------------------------------------------------------
57 58
58 // static 59 // static
59 const int MenuItemView::kMenuItemViewID = 1001; 60 const int MenuItemView::kMenuItemViewID = 1001;
60 61
61 // static 62 // static
62 const int MenuItemView::kEmptyMenuItemViewID = 63 const int MenuItemView::kEmptyMenuItemViewID =
63 MenuItemView::kMenuItemViewID + 1; 64 MenuItemView::kMenuItemViewID + 1;
64 65
65 // static 66 // static
67 int MenuItemView::icon_area_width_ = 0;
68
69 // static
66 int MenuItemView::label_start_; 70 int MenuItemView::label_start_;
67 71
68 // static 72 // static
69 int MenuItemView::item_right_margin_; 73 int MenuItemView::item_right_margin_;
70 74
71 // static 75 // static
72 int MenuItemView::pref_menu_height_; 76 int MenuItemView::pref_menu_height_;
73 77
74 // static 78 // static
75 const char MenuItemView::kViewClassName[] = "views/MenuItemView"; 79 const char MenuItemView::kViewClassName[] = "views/MenuItemView";
76 80
77 MenuItemView::MenuItemView(MenuDelegate* delegate) 81 MenuItemView::MenuItemView(MenuDelegate* delegate)
78 : delegate_(delegate), 82 : delegate_(delegate),
79 controller_(NULL), 83 controller_(NULL),
80 canceled_(false), 84 canceled_(false),
81 parent_menu_item_(NULL), 85 parent_menu_item_(NULL),
82 type_(SUBMENU), 86 type_(SUBMENU),
83 selected_(false), 87 selected_(false),
84 command_(0), 88 command_(0),
85 submenu_(NULL), 89 submenu_(NULL),
86 has_mnemonics_(false), 90 has_mnemonics_(false),
87 show_mnemonics_(false), 91 show_mnemonics_(false),
88 has_icons_(false), 92 has_icons_(false),
93 icon_view_(NULL),
89 top_margin_(-1), 94 top_margin_(-1),
90 bottom_margin_(-1), 95 bottom_margin_(-1),
91 requested_menu_position_(POSITION_BEST_FIT), 96 requested_menu_position_(POSITION_BEST_FIT),
92 actual_menu_position_(requested_menu_position_), 97 actual_menu_position_(requested_menu_position_),
93 use_right_margin_(true) { 98 use_right_margin_(true) {
94 // NOTE: don't check the delegate for NULL, UpdateMenuPartSizes supplies a 99 // NOTE: don't check the delegate for NULL, UpdateMenuPartSizes supplies a
95 // NULL delegate. 100 // NULL delegate.
96 Init(NULL, 0, SUBMENU, delegate); 101 Init(NULL, 0, SUBMENU, delegate);
97 } 102 }
98 103
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 DCHECK_GE(submenu_->child_count(), index); 217 DCHECK_GE(submenu_->child_count(), index);
213 if (type == SEPARATOR) { 218 if (type == SEPARATOR) {
214 submenu_->AddChildViewAt(new MenuSeparator(), index); 219 submenu_->AddChildViewAt(new MenuSeparator(), index);
215 return NULL; 220 return NULL;
216 } 221 }
217 MenuItemView* item = new MenuItemView(this, item_id, type); 222 MenuItemView* item = new MenuItemView(this, item_id, type);
218 if (label.empty() && GetDelegate()) 223 if (label.empty() && GetDelegate())
219 item->SetTitle(GetDelegate()->GetLabel(item_id)); 224 item->SetTitle(GetDelegate()->GetLabel(item_id));
220 else 225 else
221 item->SetTitle(label); 226 item->SetTitle(label);
222 item->SetIcon(icon); 227 if (!icon.empty())
228 item->SetIcon(icon);
223 if (type == SUBMENU) 229 if (type == SUBMENU)
224 item->CreateSubmenu(); 230 item->CreateSubmenu();
225 submenu_->AddChildViewAt(item, index); 231 submenu_->AddChildViewAt(item, index);
226 return item; 232 return item;
227 } 233 }
228 234
229 void MenuItemView::RemoveMenuItemAt(int index) { 235 void MenuItemView::RemoveMenuItemAt(int index) {
230 DCHECK(submenu_); 236 DCHECK(submenu_);
231 DCHECK_LE(0, index); 237 DCHECK_LE(0, index);
232 DCHECK_GT(submenu_->child_count(), index); 238 DCHECK_GT(submenu_->child_count(), index);
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 item->tooltip_ = tooltip; 359 item->tooltip_ = tooltip;
354 } 360 }
355 361
356 void MenuItemView::SetIcon(const gfx::ImageSkia& icon, int item_id) { 362 void MenuItemView::SetIcon(const gfx::ImageSkia& icon, int item_id) {
357 MenuItemView* item = GetMenuItemByID(item_id); 363 MenuItemView* item = GetMenuItemByID(item_id);
358 DCHECK(item); 364 DCHECK(item);
359 item->SetIcon(icon); 365 item->SetIcon(icon);
360 } 366 }
361 367
362 void MenuItemView::SetIcon(const gfx::ImageSkia& icon) { 368 void MenuItemView::SetIcon(const gfx::ImageSkia& icon) {
363 icon_ = icon; 369 if (icon.empty()) {
370 SetIconView(NULL);
371 return;
372 }
373
374 ImageView* icon_view = new ImageView();
375 icon_view->SetImage(&icon);
376 SetIconView(icon_view);
377 }
378
379 void MenuItemView::SetIconView(View* icon_view) {
380 if (icon_view_) {
381 RemoveChildView(icon_view_);
382 delete icon_view_;
383 icon_view_ = NULL;
384 }
385 if (icon_view) {
386 AddChildView(icon_view);
387 icon_view_ = icon_view;
388 }
364 SchedulePaint(); 389 SchedulePaint();
365 } 390 }
366 391
367 void MenuItemView::OnPaint(gfx::Canvas* canvas) { 392 void MenuItemView::OnPaint(gfx::Canvas* canvas) {
368 PaintButton(canvas, PB_NORMAL); 393 PaintButton(canvas, PB_NORMAL);
369 } 394 }
370 395
371 gfx::Size MenuItemView::GetPreferredSize() { 396 gfx::Size MenuItemView::GetPreferredSize() {
372 if (pref_size_.IsEmpty()) 397 if (pref_size_.IsEmpty())
373 pref_size_ = CalculatePreferredSize(); 398 pref_size_ = CalculatePreferredSize();
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 if (IsContainer()) { 499 if (IsContainer()) {
475 View* child = child_at(0); 500 View* child = child_at(0);
476 gfx::Size size = child->GetPreferredSize(); 501 gfx::Size size = child->GetPreferredSize();
477 child->SetBounds(0, GetTopMargin(), size.width(), size.height()); 502 child->SetBounds(0, GetTopMargin(), size.width(), size.height());
478 } else { 503 } else {
479 // Child views are laid out right aligned and given the full height. To 504 // Child views are laid out right aligned and given the full height. To
480 // right align start with the last view and progress to the first. 505 // right align start with the last view and progress to the first.
481 int x = width() - (use_right_margin_ ? item_right_margin_ : 0); 506 int x = width() - (use_right_margin_ ? item_right_margin_ : 0);
482 for (int i = child_count() - 1; i >= 0; --i) { 507 for (int i = child_count() - 1; i >= 0; --i) {
483 View* child = child_at(i); 508 View* child = child_at(i);
509 if (icon_view_ && (icon_view_ == child))
510 continue;
484 int width = child->GetPreferredSize().width(); 511 int width = child->GetPreferredSize().width();
485 child->SetBounds(x - width, 0, width, height()); 512 child->SetBounds(x - width, 0, width, height());
486 x -= width - kChildXPadding; 513 x -= width - kChildXPadding;
487 } 514 }
515 // Position icon_view
msw 2012/06/28 01:56:38 nit: vertical bars around "|icon_view|", add punct
yefimt 2012/06/28 16:53:34 Done.
516 const MenuConfig& config = MenuConfig::instance();
517 if (icon_view_) {
518 icon_view_->SizeToPreferredSize();
519 gfx::Size size = icon_view_->GetPreferredSize();
520 int x = config.item_left_margin + (icon_area_width_ - size.width()) / 2;
521 int y = (height() + GetTopMargin() - GetBottomMargin() -
msw 2012/06/28 01:56:38 nit: I'd move the entire value calculation to the
yefimt 2012/06/28 16:53:34 Done.
522 size.height()) / 2;
523 icon_view_->SetPosition(gfx::Point(x, y));
524 }
488 } 525 }
489 } 526 }
490 527
491 int MenuItemView::GetAcceleratorTextWidth() { 528 int MenuItemView::GetAcceleratorTextWidth() {
492 string16 text = GetAcceleratorText(); 529 string16 text = GetAcceleratorText();
493 return text.empty() ? 0 : GetFont().GetStringWidth(text); 530 return text.empty() ? 0 : GetFont().GetStringWidth(text);
494 } 531 }
495 532
496 void MenuItemView::SetMargins(int top_margin, int bottom_margin) { 533 void MenuItemView::SetMargins(int top_margin, int bottom_margin) {
497 top_margin_ = top_margin; 534 top_margin_ = top_margin;
(...skipping 10 matching lines...) Expand all
508 controller_(NULL), 545 controller_(NULL),
509 canceled_(false), 546 canceled_(false),
510 parent_menu_item_(parent), 547 parent_menu_item_(parent),
511 type_(type), 548 type_(type),
512 selected_(false), 549 selected_(false),
513 command_(command), 550 command_(command),
514 submenu_(NULL), 551 submenu_(NULL),
515 has_mnemonics_(false), 552 has_mnemonics_(false),
516 show_mnemonics_(false), 553 show_mnemonics_(false),
517 has_icons_(false), 554 has_icons_(false),
555 icon_view_(NULL),
518 top_margin_(-1), 556 top_margin_(-1),
519 bottom_margin_(-1), 557 bottom_margin_(-1),
520 requested_menu_position_(POSITION_BEST_FIT), 558 requested_menu_position_(POSITION_BEST_FIT),
521 actual_menu_position_(requested_menu_position_) { 559 actual_menu_position_(requested_menu_position_) {
522 Init(parent, command, type, NULL); 560 Init(parent, command, type, NULL);
523 } 561 }
524 562
525 MenuItemView::~MenuItemView() { 563 MenuItemView::~MenuItemView() {
526 delete submenu_; 564 delete submenu_;
527 STLDeleteElements(&removed_items_); 565 STLDeleteElements(&removed_items_);
528 } 566 }
529 567
530 std::string MenuItemView::GetClassName() const { 568 std::string MenuItemView::GetClassName() const {
531 return kViewClassName; 569 return kViewClassName;
532 } 570 }
533 571
534 // Calculates all sizes that we can from the OS. 572 // Calculates all sizes that we can from the OS.
535 // 573 //
536 // This is invoked prior to Running a menu. 574 // This is invoked prior to Running a menu.
537 void MenuItemView::UpdateMenuPartSizes(bool has_icons) { 575 void MenuItemView::UpdateMenuPartSizes() {
538 MenuConfig::Reset(); 576 MenuConfig::Reset();
539 const MenuConfig& config = MenuConfig::instance(); 577 const MenuConfig& config = MenuConfig::instance();
540 578
541 item_right_margin_ = config.label_to_arrow_padding + config.arrow_width + 579 item_right_margin_ = config.label_to_arrow_padding + config.arrow_width +
542 config.arrow_to_edge_padding; 580 config.arrow_to_edge_padding;
581 icon_area_width_ = config.check_width;
582 if (has_icons_)
583 icon_area_width_ = std::max(icon_area_width_, GetMaxIconViewWidth());
543 584
544 if (config.always_use_icon_to_label_padding) 585 if (config.always_use_icon_to_label_padding)
545 label_start_ = config.item_left_margin + config.check_width + 586 label_start_ = config.item_left_margin + icon_area_width_ +
546 config.icon_to_label_padding; 587 config.icon_to_label_padding;
547 else 588 else
548 // If there are no icons don't pad by the icon to label padding. This 589 // If there are no icons don't pad by the icon to label padding. This
549 // makes us look close to system menus. 590 // makes us look close to system menus.
550 label_start_ = config.item_left_margin + config.check_width + 591 label_start_ = config.item_left_margin + icon_area_width_ +
551 (has_icons ? config.icon_to_label_padding : 0); 592 (has_icons_ ? config.icon_to_label_padding : 0);
552 593
553 if (config.render_gutter) 594 if (config.render_gutter)
554 label_start_ += config.gutter_width + config.gutter_to_label; 595 label_start_ += config.gutter_width + config.gutter_to_label;
555 596
556 MenuItemView menu_item(NULL); 597 MenuItemView menu_item(NULL);
557 menu_item.SetTitle(ASCIIToUTF16("blah")); // Text doesn't matter here. 598 menu_item.SetTitle(ASCIIToUTF16("blah")); // Text doesn't matter here.
558 pref_menu_height_ = menu_item.GetPreferredSize().height(); 599 pref_menu_height_ = menu_item.GetPreferredSize().height();
559 } 600 }
560 601
561 void MenuItemView::Init(MenuItemView* parent, 602 void MenuItemView::Init(MenuItemView* parent,
(...skipping 30 matching lines...) Expand all
592 canceled_ = false; 633 canceled_ = false;
593 634
594 has_mnemonics_ = has_mnemonics; 635 has_mnemonics_ = has_mnemonics;
595 show_mnemonics_ = has_mnemonics && show_mnemonics; 636 show_mnemonics_ = has_mnemonics && show_mnemonics;
596 637
597 AddEmptyMenus(); 638 AddEmptyMenus();
598 639
599 if (!MenuController::GetActiveInstance()) { 640 if (!MenuController::GetActiveInstance()) {
600 // Only update the menu size if there are no menus showing, otherwise 641 // Only update the menu size if there are no menus showing, otherwise
601 // things may shift around. 642 // things may shift around.
602 UpdateMenuPartSizes(has_icons_); 643 UpdateMenuPartSizes();
603 } 644 }
604 } 645 }
605 646
606 int MenuItemView::GetDrawStringFlags() { 647 int MenuItemView::GetDrawStringFlags() {
607 int flags = 0; 648 int flags = 0;
608 if (base::i18n::IsRTL()) 649 if (base::i18n::IsRTL())
609 flags |= gfx::Canvas::TEXT_ALIGN_RIGHT; 650 flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
610 else 651 else
611 flags |= gfx::Canvas::TEXT_ALIGN_LEFT; 652 flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
612 653
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 if (!has_children()) 769 if (!has_children())
729 return gfx::Size(); 770 return gfx::Size();
730 771
731 if (IsContainer()) { 772 if (IsContainer()) {
732 View* child = child_at(0); 773 View* child = child_at(0);
733 return child->GetPreferredSize(); 774 return child->GetPreferredSize();
734 } 775 }
735 776
736 int width = 0; 777 int width = 0;
737 for (int i = 0; i < child_count(); ++i) { 778 for (int i = 0; i < child_count(); ++i) {
779 View* child = child_at(i);
780 if (icon_view_ && (icon_view_ == child))
781 continue;
738 if (i) 782 if (i)
739 width += kChildXPadding; 783 width += kChildXPadding;
740 width += child_at(i)->GetPreferredSize().width(); 784 width += child->GetPreferredSize().width();
741 } 785 }
742 // Return a height of 0 to indicate that we should use the title height 786 int height = 0;
743 // instead. 787 if (icon_view_)
744 return gfx::Size(width, 0); 788 height = icon_view_->GetPreferredSize().height();
789
790 // If there is no icon view it returns a height of 0 to indicate that
791 // we should use the title height instead.
792 return gfx::Size(width, height);
745 } 793 }
746 794
747 gfx::Size MenuItemView::CalculatePreferredSize() { 795 gfx::Size MenuItemView::CalculatePreferredSize() {
748 gfx::Size child_size = GetChildPreferredSize(); 796 gfx::Size child_size = GetChildPreferredSize();
749 if (IsContainer()) { 797 if (IsContainer()) {
750 return gfx::Size( 798 return gfx::Size(
751 child_size.width(), 799 child_size.width(),
752 child_size.height() + GetBottomMargin() + GetTopMargin()); 800 child_size.height() + GetBottomMargin() + GetTopMargin());
753 } 801 }
754 802
(...skipping 16 matching lines...) Expand all
771 return string16(); 819 return string16();
772 820
773 ui::Accelerator accelerator; 821 ui::Accelerator accelerator;
774 return (GetDelegate() && 822 return (GetDelegate() &&
775 GetDelegate()->GetAccelerator(GetCommand(), &accelerator)) ? 823 GetDelegate()->GetAccelerator(GetCommand(), &accelerator)) ?
776 accelerator.GetShortcutText() : string16(); 824 accelerator.GetShortcutText() : string16();
777 } 825 }
778 826
779 bool MenuItemView::IsContainer() const { 827 bool MenuItemView::IsContainer() const {
780 // Let the first child take over |this| when we only have one child and no 828 // Let the first child take over |this| when we only have one child and no
781 // title. Note that what child_count() returns is the number of children, 829 // title.
830 return NonIconChildViewsCount() == 1 && title_.empty();
msw 2012/06/28 01:56:38 nit: add parens around the first conditional.
yefimt 2012/06/28 16:53:34 Done.
831 }
832
833 int MenuItemView::NonIconChildViewsCount() const {
834 // Note that what child_count() returns is the number of children,
782 // not the number of menu items. 835 // not the number of menu items.
783 return child_count() == 1 && title_.empty(); 836 return child_count() - (icon_view_ ? 1 : 0);
837 }
838
839 int MenuItemView::GetMaxIconViewWidth() const {
840 int width = 0;
841 for (int i = 0; i < submenu_->GetMenuItemCount(); ++i) {
842 MenuItemView* menu_item = submenu_->GetMenuItemAt(i);
843 int temp_width = 0;
844 if (menu_item->HasSubmenu()) {
845 temp_width = menu_item->GetMaxIconViewWidth();
846 } else if (menu_item->icon_view()) {
847 temp_width = menu_item->icon_view()->GetPreferredSize().width();
848 }
849 width = std::max(width, temp_width);
850 }
851 return width;
784 } 852 }
785 853
786 } // namespace views 854 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698