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

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, 6 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 29 matching lines...) Expand all
55 56
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
66 //static
67 gfx::ImageSkia MenuItemView::empty_icon_;
68
69 // static
70 int MenuItemView::icon_width_ = 0;
Aaron Boodman 2012/06/21 08:15:30 Having this stuff be static is really weird, but I
71
65 // static 72 // static
66 int MenuItemView::label_start_; 73 int MenuItemView::label_start_;
67 74
68 // static 75 // static
69 int MenuItemView::item_right_margin_; 76 int MenuItemView::item_right_margin_;
70 77
71 // static 78 // static
72 int MenuItemView::pref_menu_height_; 79 int MenuItemView::pref_menu_height_;
73 80
74 // static 81 // static
75 const char MenuItemView::kViewClassName[] = "views/MenuItemView"; 82 const char MenuItemView::kViewClassName[] = "views/MenuItemView";
76 83
77 MenuItemView::MenuItemView(MenuDelegate* delegate) 84 MenuItemView::MenuItemView(MenuDelegate* delegate)
78 : delegate_(delegate), 85 : delegate_(delegate),
79 controller_(NULL), 86 controller_(NULL),
80 canceled_(false), 87 canceled_(false),
81 parent_menu_item_(NULL), 88 parent_menu_item_(NULL),
82 type_(SUBMENU), 89 type_(SUBMENU),
83 selected_(false), 90 selected_(false),
84 command_(0), 91 command_(0),
85 submenu_(NULL), 92 submenu_(NULL),
86 has_mnemonics_(false), 93 has_mnemonics_(false),
87 show_mnemonics_(false), 94 show_mnemonics_(false),
88 has_icons_(false), 95 has_icons_(false),
96 icon_view_type_(NONE),
89 top_margin_(-1), 97 top_margin_(-1),
90 bottom_margin_(-1), 98 bottom_margin_(-1),
91 requested_menu_position_(POSITION_BEST_FIT), 99 requested_menu_position_(POSITION_BEST_FIT),
92 actual_menu_position_(requested_menu_position_), 100 actual_menu_position_(requested_menu_position_),
93 use_right_margin_(true) { 101 use_right_margin_(true) {
94 // NOTE: don't check the delegate for NULL, UpdateMenuPartSizes supplies a 102 // NOTE: don't check the delegate for NULL, UpdateMenuPartSizes supplies a
95 // NULL delegate. 103 // NULL delegate.
96 Init(NULL, 0, SUBMENU, delegate); 104 Init(NULL, 0, SUBMENU, delegate);
97 } 105 }
98 106
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 DCHECK_GE(submenu_->child_count(), index); 220 DCHECK_GE(submenu_->child_count(), index);
213 if (type == SEPARATOR) { 221 if (type == SEPARATOR) {
214 submenu_->AddChildViewAt(new MenuSeparator(), index); 222 submenu_->AddChildViewAt(new MenuSeparator(), index);
215 return NULL; 223 return NULL;
216 } 224 }
217 MenuItemView* item = new MenuItemView(this, item_id, type); 225 MenuItemView* item = new MenuItemView(this, item_id, type);
218 if (label.empty() && GetDelegate()) 226 if (label.empty() && GetDelegate())
219 item->SetTitle(GetDelegate()->GetLabel(item_id)); 227 item->SetTitle(GetDelegate()->GetLabel(item_id));
220 else 228 else
221 item->SetTitle(label); 229 item->SetTitle(label);
222 item->SetIcon(icon); 230 if (!icon.empty())
231 item->SetIcon(icon);
223 if (type == SUBMENU) 232 if (type == SUBMENU)
224 item->CreateSubmenu(); 233 item->CreateSubmenu();
225 submenu_->AddChildViewAt(item, index); 234 submenu_->AddChildViewAt(item, index);
226 return item; 235 return item;
227 } 236 }
228 237
229 void MenuItemView::RemoveMenuItemAt(int index) { 238 void MenuItemView::RemoveMenuItemAt(int index) {
230 DCHECK(submenu_); 239 DCHECK(submenu_);
231 DCHECK_LE(0, index); 240 DCHECK_LE(0, index);
232 DCHECK_GT(submenu_->child_count(), index); 241 DCHECK_GT(submenu_->child_count(), index);
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 item->tooltip_ = tooltip; 362 item->tooltip_ = tooltip;
354 } 363 }
355 364
356 void MenuItemView::SetIcon(const gfx::ImageSkia& icon, int item_id) { 365 void MenuItemView::SetIcon(const gfx::ImageSkia& icon, int item_id) {
357 MenuItemView* item = GetMenuItemByID(item_id); 366 MenuItemView* item = GetMenuItemByID(item_id);
358 DCHECK(item); 367 DCHECK(item);
359 item->SetIcon(icon); 368 item->SetIcon(icon);
360 } 369 }
361 370
362 void MenuItemView::SetIcon(const gfx::ImageSkia& icon) { 371 void MenuItemView::SetIcon(const gfx::ImageSkia& icon) {
363 icon_ = icon; 372 if (icon_view_type_ == IMAGE_VIEW) {
373 View* view = GetIconView();
374 static_cast<ImageView*>(view)->SetImage(&icon);
375 return;
376 }
377
378 ImageView* icon_view = new ImageView();
379 icon_view->SetImage(&icon);
380 SetIconView(icon_view);
381 icon_view_type_ = IMAGE_VIEW;
382 }
383
384 const gfx::ImageSkia& MenuItemView::GetIcon() {
385 if (icon_view_type_ != IMAGE_VIEW)
386 return empty_icon_;
387
388 View* view = GetIconView();
389 return static_cast<ImageView*>(view)->GetImage();
390 }
391
392 void MenuItemView::SetIconView(View* icon_view) {
393 DCHECK(icon_view);
394 View* child_view = GetIconView();
395 if (child_view) {
396 RemoveChildView(child_view);
397 delete child_view;
398 }
399 AddChildViewAt(icon_view, 0);
400 icon_view_type_ = SOME_VIEW;
364 SchedulePaint(); 401 SchedulePaint();
365 } 402 }
366 403
404 View* MenuItemView::GetIconView() {
405 if (icon_view_type_ == NONE)
406 return NULL;
407
408 return child_at(0);
409 }
410
367 void MenuItemView::OnPaint(gfx::Canvas* canvas) { 411 void MenuItemView::OnPaint(gfx::Canvas* canvas) {
368 PaintButton(canvas, PB_NORMAL); 412 PaintButton(canvas, PB_NORMAL);
369 } 413 }
370 414
371 gfx::Size MenuItemView::GetPreferredSize() { 415 gfx::Size MenuItemView::GetPreferredSize() {
372 if (pref_size_.IsEmpty()) 416 if (pref_size_.IsEmpty())
373 pref_size_ = CalculatePreferredSize(); 417 pref_size_ = CalculatePreferredSize();
374 return pref_size_; 418 return pref_size_;
375 } 419 }
376 420
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 return; 516 return;
473 517
474 if (IsContainer()) { 518 if (IsContainer()) {
475 View* child = child_at(0); 519 View* child = child_at(0);
476 gfx::Size size = child->GetPreferredSize(); 520 gfx::Size size = child->GetPreferredSize();
477 child->SetBounds(0, GetTopMargin(), size.width(), size.height()); 521 child->SetBounds(0, GetTopMargin(), size.width(), size.height());
478 } else { 522 } else {
479 // Child views are laid out right aligned and given the full height. To 523 // 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. 524 // right align start with the last view and progress to the first.
481 int x = width() - (use_right_margin_ ? item_right_margin_ : 0); 525 int x = width() - (use_right_margin_ ? item_right_margin_ : 0);
482 for (int i = child_count() - 1; i >= 0; --i) { 526 int first_non_icon_view = (icon_view_type_ != NONE) ? 1 : 0;
Aaron Boodman 2012/06/21 08:15:30 If you have an icon_view_ member, you can remove t
yefimt 2012/06/22 22:14:40 Done.
527 for (int i = child_count() - 1; i >= first_non_icon_view; --i) {
483 View* child = child_at(i); 528 View* child = child_at(i);
484 int width = child->GetPreferredSize().width(); 529 int width = child->GetPreferredSize().width();
485 child->SetBounds(x - width, 0, width, height()); 530 child->SetBounds(x - width, 0, width, height());
486 x -= width - kChildXPadding; 531 x -= width - kChildXPadding;
487 } 532 }
533 // Position icon_view
534 const MenuConfig& config = MenuConfig::instance();
535 if (icon_view_type_ != NONE) {
536 View* child = child_at(0);
537 child->SizeToPreferredSize();
538 gfx::Size size = child->GetPreferredSize();
539 int x = config.item_left_margin + (icon_width_ - size.width()) / 2;
540 int y = (height() + GetTopMargin() - GetBottomMargin() -
541 size.height()) / 2;
542 child->SetPosition(gfx::Point(x, y));
543 }
488 } 544 }
489 } 545 }
490 546
491 int MenuItemView::GetAcceleratorTextWidth() { 547 int MenuItemView::GetAcceleratorTextWidth() {
492 string16 text = GetAcceleratorText(); 548 string16 text = GetAcceleratorText();
493 return text.empty() ? 0 : GetFont().GetStringWidth(text); 549 return text.empty() ? 0 : GetFont().GetStringWidth(text);
494 } 550 }
495 551
496 void MenuItemView::SetMargins(int top_margin, int bottom_margin) { 552 void MenuItemView::SetMargins(int top_margin, int bottom_margin) {
497 top_margin_ = top_margin; 553 top_margin_ = top_margin;
498 bottom_margin_ = bottom_margin; 554 bottom_margin_ = bottom_margin;
499 555
500 // invalidate GetPreferredSize() cache 556 // invalidate GetPreferredSize() cache
501 pref_size_.SetSize(0,0); 557 pref_size_.SetSize(0,0);
502 } 558 }
503 559
560 Border* MenuItemView::GetMenuBorder() {
561 return Border::CreateEmptyBorder(
562 MenuConfig::instance().submenu_vertical_margin_size,
563 MenuConfig::instance().submenu_horizontal_margin_size,
564 MenuConfig::instance().submenu_vertical_margin_size,
565 MenuConfig::instance().submenu_horizontal_margin_size);
566 }
567
568 Background* MenuItemView::GetMenuBackground() {
569 return NULL;
570 }
571
504 MenuItemView::MenuItemView(MenuItemView* parent, 572 MenuItemView::MenuItemView(MenuItemView* parent,
505 int command, 573 int command,
506 MenuItemView::Type type) 574 MenuItemView::Type type)
507 : delegate_(NULL), 575 : delegate_(NULL),
508 controller_(NULL), 576 controller_(NULL),
509 canceled_(false), 577 canceled_(false),
510 parent_menu_item_(parent), 578 parent_menu_item_(parent),
511 type_(type), 579 type_(type),
512 selected_(false), 580 selected_(false),
513 command_(command), 581 command_(command),
514 submenu_(NULL), 582 submenu_(NULL),
515 has_mnemonics_(false), 583 has_mnemonics_(false),
516 show_mnemonics_(false), 584 show_mnemonics_(false),
517 has_icons_(false), 585 has_icons_(false),
586 icon_view_type_(NONE),
518 top_margin_(-1), 587 top_margin_(-1),
519 bottom_margin_(-1), 588 bottom_margin_(-1),
520 requested_menu_position_(POSITION_BEST_FIT), 589 requested_menu_position_(POSITION_BEST_FIT),
521 actual_menu_position_(requested_menu_position_) { 590 actual_menu_position_(requested_menu_position_) {
522 Init(parent, command, type, NULL); 591 Init(parent, command, type, NULL);
523 } 592 }
524 593
525 MenuItemView::~MenuItemView() { 594 MenuItemView::~MenuItemView() {
526 delete submenu_; 595 delete submenu_;
527 STLDeleteElements(&removed_items_); 596 STLDeleteElements(&removed_items_);
528 } 597 }
529 598
530 std::string MenuItemView::GetClassName() const { 599 std::string MenuItemView::GetClassName() const {
531 return kViewClassName; 600 return kViewClassName;
532 } 601 }
533 602
534 // Calculates all sizes that we can from the OS. 603 // Calculates all sizes that we can from the OS.
535 // 604 //
536 // This is invoked prior to Running a menu. 605 // This is invoked prior to Running a menu.
537 void MenuItemView::UpdateMenuPartSizes(bool has_icons) { 606 void MenuItemView::UpdateMenuPartSizes() {
538 MenuConfig::Reset(); 607 MenuConfig::Reset();
539 const MenuConfig& config = MenuConfig::instance(); 608 const MenuConfig& config = MenuConfig::instance();
540 609
541 item_right_margin_ = config.label_to_arrow_padding + config.arrow_width + 610 item_right_margin_ = config.label_to_arrow_padding + config.arrow_width +
542 config.arrow_to_edge_padding; 611 config.arrow_to_edge_padding;
612 icon_width_ = config.check_width;
613 if (has_icons_) {
614 for (int i = 0; i < submenu_->GetMenuItemCount(); ++i) {
615 MenuItemView* menu_item = submenu_->GetMenuItemAt(i);
616 if (menu_item->icon_view_type_ != NONE)
617 icon_width_ = std::max(icon_width_,
618 menu_item->child_at(0)->GetPreferredSize().width());
619 }
620 }
543 621
544 if (config.always_use_icon_to_label_padding) 622 if (config.always_use_icon_to_label_padding)
545 label_start_ = config.item_left_margin + config.check_width + 623 label_start_ = config.item_left_margin + icon_width_ +
546 config.icon_to_label_padding; 624 config.icon_to_label_padding;
547 else 625 else
548 // If there are no icons don't pad by the icon to label padding. This 626 // If there are no icons don't pad by the icon to label padding. This
549 // makes us look close to system menus. 627 // makes us look close to system menus.
550 label_start_ = config.item_left_margin + config.check_width + 628 label_start_ = config.item_left_margin + icon_width_ +
551 (has_icons ? config.icon_to_label_padding : 0); 629 (has_icons_ ? config.icon_to_label_padding : 0);
552 630
553 if (config.render_gutter) 631 if (config.render_gutter)
554 label_start_ += config.gutter_width + config.gutter_to_label; 632 label_start_ += config.gutter_width + config.gutter_to_label;
555 633
556 MenuItemView menu_item(NULL); 634 MenuItemView menu_item(NULL);
557 menu_item.SetTitle(ASCIIToUTF16("blah")); // Text doesn't matter here. 635 menu_item.SetTitle(ASCIIToUTF16("blah")); // Text doesn't matter here.
558 pref_menu_height_ = menu_item.GetPreferredSize().height(); 636 pref_menu_height_ = menu_item.GetPreferredSize().height();
559 } 637 }
560 638
561 void MenuItemView::Init(MenuItemView* parent, 639 void MenuItemView::Init(MenuItemView* parent,
(...skipping 30 matching lines...) Expand all
592 canceled_ = false; 670 canceled_ = false;
593 671
594 has_mnemonics_ = has_mnemonics; 672 has_mnemonics_ = has_mnemonics;
595 show_mnemonics_ = has_mnemonics && show_mnemonics; 673 show_mnemonics_ = has_mnemonics && show_mnemonics;
596 674
597 AddEmptyMenus(); 675 AddEmptyMenus();
598 676
599 if (!MenuController::GetActiveInstance()) { 677 if (!MenuController::GetActiveInstance()) {
600 // Only update the menu size if there are no menus showing, otherwise 678 // Only update the menu size if there are no menus showing, otherwise
601 // things may shift around. 679 // things may shift around.
602 UpdateMenuPartSizes(has_icons_); 680 UpdateMenuPartSizes();
603 } 681 }
604 } 682 }
605 683
606 int MenuItemView::GetDrawStringFlags() { 684 int MenuItemView::GetDrawStringFlags() {
607 int flags = 0; 685 int flags = 0;
608 if (base::i18n::IsRTL()) 686 if (base::i18n::IsRTL())
609 flags |= gfx::Canvas::TEXT_ALIGN_RIGHT; 687 flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
610 else 688 else
611 flags |= gfx::Canvas::TEXT_ALIGN_LEFT; 689 flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
612 690
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 gfx::Size MenuItemView::GetChildPreferredSize() { 805 gfx::Size MenuItemView::GetChildPreferredSize() {
728 if (!has_children()) 806 if (!has_children())
729 return gfx::Size(); 807 return gfx::Size();
730 808
731 if (IsContainer()) { 809 if (IsContainer()) {
732 View* child = child_at(0); 810 View* child = child_at(0);
733 return child->GetPreferredSize(); 811 return child->GetPreferredSize();
734 } 812 }
735 813
736 int width = 0; 814 int width = 0;
737 for (int i = 0; i < child_count(); ++i) { 815 int i = (icon_view_type_ != NONE) ? 1 : 0;
816 for (; i < child_count(); ++i) {
738 if (i) 817 if (i)
739 width += kChildXPadding; 818 width += kChildXPadding;
740 width += child_at(i)->GetPreferredSize().width(); 819 gfx::Size size = child_at(i)->GetPreferredSize();
820 width += size.width();
741 } 821 }
822 int height = 0;
823 if (icon_view_type_ != NONE)
824 height = child_at(0)->GetPreferredSize().height();
825
742 // Return a height of 0 to indicate that we should use the title height 826 // Return a height of 0 to indicate that we should use the title height
743 // instead. 827 // instead.
744 return gfx::Size(width, 0); 828 return gfx::Size(width, height);
745 } 829 }
746 830
747 gfx::Size MenuItemView::CalculatePreferredSize() { 831 gfx::Size MenuItemView::CalculatePreferredSize() {
748 gfx::Size child_size = GetChildPreferredSize(); 832 gfx::Size child_size = GetChildPreferredSize();
749 if (IsContainer()) { 833 if (IsContainer()) {
750 return gfx::Size( 834 return gfx::Size(
751 child_size.width(), 835 child_size.width(),
752 child_size.height() + GetBottomMargin() + GetTopMargin()); 836 child_size.height() + GetBottomMargin() + GetTopMargin());
753 } 837 }
754 838
(...skipping 21 matching lines...) Expand all
776 accelerator.GetShortcutText() : string16(); 860 accelerator.GetShortcutText() : string16();
777 } 861 }
778 862
779 bool MenuItemView::IsContainer() const { 863 bool MenuItemView::IsContainer() const {
780 // Let the first child take over |this| when we only have one child and no 864 // 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, 865 // title. Note that what child_count() returns is the number of children,
782 // not the number of menu items. 866 // not the number of menu items.
783 return child_count() == 1 && title_.empty(); 867 return child_count() == 1 && title_.empty();
784 } 868 }
785 869
870 bool MenuItemView::HasNonIconChildViews() {
871 return child_count() > ((icon_view_type_ != NONE) ? 1 : 0);
872 }
873
786 } // namespace views 874 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698