15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_item_view.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/case_conversion.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/ui_resources.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_strings.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/accessibility/accessible_view_state.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/menu_model.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/common_theme.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/menu_button.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/image_view.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_config.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_controller.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/menu/menu_image_util.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/menu/menu_scroll_view_container.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_separator.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/submenu_view.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// EmptyMenuMenuItem ---------------------------------------------------------
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// EmptyMenuMenuItem is used when a menu has no menu items. EmptyMenuMenuItem
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is itself a MenuItemView, but it uses a different ID so that it isn't
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// identified as a MenuItemView.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EmptyMenuMenuItem : public MenuItemView {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit EmptyMenuMenuItem(MenuItemView* parent)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : MenuItemView(parent, 0, EMPTY) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set this so that we're not identified as a normal menu item.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_id(kEmptyMenuItemViewID);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetTitle(l10n_util::GetStringUTF16(IDS_APP_MENU_EMPTY_SUBMENU));
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetEnabled(false);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetTooltipText(const gfx::Point& p,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              string16* tooltip) const OVERRIDE {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Empty menu items shouldn't have a tooltip.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(EmptyMenuMenuItem);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Padding between child views.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kChildXPadding = 8;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuItemView ---------------------------------------------------------------
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int MenuItemView::kMenuItemViewID = 1001;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int MenuItemView::kEmptyMenuItemViewID =
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MenuItemView::kMenuItemViewID + 1;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MenuItemView::icon_area_width_ = 0;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MenuItemView::label_start_;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MenuItemView::item_right_margin_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MenuItemView::pref_menu_height_;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char MenuItemView::kViewClassName[] = "MenuItemView";
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView::MenuItemView(MenuDelegate* delegate)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : delegate_(delegate),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controller_(NULL),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      canceled_(false),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parent_menu_item_(NULL),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type_(SUBMENU),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      selected_(false),
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_(0),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      submenu_(NULL),
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_mnemonics_(false),
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      show_mnemonics_(false),
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_icons_(false),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon_view_(NULL),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      top_margin_(-1),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bottom_margin_(-1),
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      left_icon_margin_(0),
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      right_icon_margin_(0),
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requested_menu_position_(POSITION_BEST_FIT),
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      actual_menu_position_(requested_menu_position_),
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_right_margin_(true) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: don't check the delegate for NULL, UpdateMenuPartSizes() supplies a
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NULL delegate.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(NULL, 0, SUBMENU, delegate);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::ChildPreferredSizeChanged(View* child) {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalidate_dimensions();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PreferredSizeChanged();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MenuItemView::GetTooltipText(const gfx::Point& p,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  string16* tooltip) const {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *tooltip = tooltip_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tooltip->empty())
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetType() == SEPARATOR)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MenuController* controller = GetMenuController();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!controller || controller->exit_type() != MenuController::EXIT_NONE) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Either the menu has been closed or we're in the process of closing the
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // menu. Don't attempt to query the delegate as it may no longer be valid.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MenuItemView* root_menu_item = GetRootMenuItem();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (root_menu_item->canceled_) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(sky): if |canceled_| is true, controller->exit_type() should be
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // something other than EXIT_NONE, but crash reports seem to indicate
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // otherwise. Figure out why this is needed.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MenuDelegate* delegate = GetDelegate();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(delegate);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point location(p);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConvertPointToScreen(this, &location);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *tooltip = delegate->GetTooltipText(command_, location);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !tooltip->empty();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::GetAccessibleState(ui::AccessibleViewState* state) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state->role = ui::AccessibilityTypes::ROLE_MENUITEM;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 item_text;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsContainer()) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The first child is taking over, just use its accessible name instead of
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |title_|.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    View* child = child_at(0);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::AccessibleViewState state;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    child->GetAccessibleState(&state);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item_text = state.name;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item_text = title_;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  state->name = GetAccessibleNameForMenuItem(item_text, GetMinorText());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (GetType()) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SUBMENU:
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state->state |= ui::AccessibilityTypes::STATE_HASPOPUP;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CHECKBOX:
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RADIO:
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state->state |= GetDelegate()->IsItemChecked(GetCommand()) ?
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ui::AccessibilityTypes::STATE_CHECKED : 0;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NORMAL:
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SEPARATOR:
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EMPTY:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // No additional accessibility states currently for these menu states.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MenuItemView::IsBubble(MenuItemView::AnchorPosition anchor) {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return anchor == MenuItemView::BUBBLE_LEFT ||
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         anchor == MenuItemView::BUBBLE_RIGHT ||
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         anchor == MenuItemView::BUBBLE_ABOVE ||
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         anchor == MenuItemView::BUBBLE_BELOW;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 MenuItemView::GetAccessibleNameForMenuItem(
1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const string16& item_text, const string16& minor_text) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 accessible_name = item_text;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Filter out the "&" for accessibility clients.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t index = 0;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char16 amp = '&';
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while ((index = accessible_name.find(amp, index)) != string16::npos &&
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         index + 1 < accessible_name.length()) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    accessible_name.replace(index, accessible_name.length() - index,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            accessible_name.substr(index + 1));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Special case for "&&" (escaped for "&").
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (accessible_name[index] == '&')
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++index;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Append subtext.
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!minor_text.empty()) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    accessible_name.push_back(' ');
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    accessible_name.append(minor_text);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return accessible_name;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::Cancel() {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (controller_ && !canceled_) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canceled_ = true;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller_->Cancel(MenuController::EXIT_ALL);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* MenuItemView::AddMenuItemAt(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int item_id,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& label,
2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const string16& sublabel,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::ImageSkia& icon,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type type,
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::MenuSeparatorType separator_style) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(type, EMPTY);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(0, index);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!submenu_)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateSubmenu();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(submenu_->child_count(), index);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == SEPARATOR) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    submenu_->AddChildViewAt(new MenuSeparator(this, separator_style), index);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView* item = new MenuItemView(this, item_id, type);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (label.empty() && GetDelegate())
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->SetTitle(GetDelegate()->GetLabel(item_id));
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->SetTitle(label);
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  item->SetSubtitle(sublabel);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!icon.isNull())
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->SetIcon(icon);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == SUBMENU)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->CreateSubmenu();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  submenu_->AddChildViewAt(item, index);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return item;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::RemoveMenuItemAt(int index) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(submenu_);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(0, index);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(submenu_->child_count(), index);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  View* item = submenu_->child_at(index);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(item);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  submenu_->RemoveChildView(item);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RemoveChildView() does not delete the item, which is a good thing
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in case a submenu is being displayed while items are being removed.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deletion will be done by ChildrenChanged() or at destruction.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  removed_items_.push_back(item);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* MenuItemView::AppendMenuItem(int item_id,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const string16& label,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           Type type) {
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return AppendMenuItemImpl(item_id, label, string16(), gfx::ImageSkia(), type,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::NORMAL_SEPARATOR);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* MenuItemView::AppendSubMenu(int item_id,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const string16& label) {
2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return AppendMenuItemImpl(item_id, label, string16(), gfx::ImageSkia(),
2817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      SUBMENU, ui::NORMAL_SEPARATOR);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* MenuItemView::AppendSubMenuWithIcon(int item_id,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  const string16& label,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  const gfx::ImageSkia& icon) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AppendMenuItemImpl(
2887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      item_id, label, string16(), icon, SUBMENU, ui::NORMAL_SEPARATOR);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* MenuItemView::AppendMenuItemWithLabel(int item_id,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    const string16& label) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AppendMenuItem(item_id, label, NORMAL);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* MenuItemView::AppendDelegateMenuItem(int item_id) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AppendMenuItem(item_id, string16(), NORMAL);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::AppendSeparator() {
3017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  AppendMenuItemImpl(0, string16(), string16(), gfx::ImageSkia(), SEPARATOR,
3027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                     ui::NORMAL_SEPARATOR);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* MenuItemView::AppendMenuItemWithIcon(int item_id,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   const string16& label,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   const gfx::ImageSkia& icon) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AppendMenuItemImpl(
3097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      item_id, label, string16(), icon, NORMAL, ui::NORMAL_SEPARATOR);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* MenuItemView::AppendMenuItemFromModel(ui::MenuModel* model,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    int index,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    int id) {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image icon;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  model->GetIconAt(index, &icon);
3177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  string16 label, sublabel;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::MenuSeparatorType separator_style = ui::NORMAL_SEPARATOR;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView::Type type;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::MenuModel::ItemType menu_type = model->GetTypeAt(index);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (menu_type) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::MenuModel::TYPE_COMMAND:
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type = MenuItemView::NORMAL;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      label = model->GetLabelAt(index);
3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      sublabel = model->GetSublabelAt(index);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::MenuModel::TYPE_CHECK:
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type = MenuItemView::CHECKBOX;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      label = model->GetLabelAt(index);
3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      sublabel = model->GetSublabelAt(index);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::MenuModel::TYPE_RADIO:
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type = MenuItemView::RADIO;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      label = model->GetLabelAt(index);
3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      sublabel = model->GetSublabelAt(index);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::MenuModel::TYPE_SEPARATOR:
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      icon = gfx::Image();
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type = MenuItemView::SEPARATOR;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      separator_style = model->GetSeparatorTypeAt(index);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::MenuModel::TYPE_SUBMENU:
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type = MenuItemView::SUBMENU;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      label = model->GetLabelAt(index);
3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      sublabel = model->GetSublabelAt(index);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type = MenuItemView::NORMAL;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AppendMenuItemImpl(id,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      label,
3557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      sublabel,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon.IsEmpty() ? gfx::ImageSkia() : *icon.ToImageSkia(),
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      separator_style);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* MenuItemView::AppendMenuItemImpl(
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int item_id,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& label,
3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const string16& sublabel,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::ImageSkia& icon,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type type,
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::MenuSeparatorType separator_style) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int index = submenu_ ? submenu_->child_count() : 0;
3697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return AddMenuItemAt(index, item_id, label, sublabel, icon, type,
3707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                       separator_style);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SubmenuView* MenuItemView::CreateSubmenu() {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!submenu_)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    submenu_ = new SubmenuView(this);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return submenu_;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MenuItemView::HasSubmenu() const {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (submenu_ != NULL);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SubmenuView* MenuItemView::GetSubmenu() const {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return submenu_;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::SetTitle(const string16& title) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  title_ = title;
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalidate_dimensions();  // Triggers preferred size recalculation.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MenuItemView::SetSubtitle(const string16& subtitle) {
3937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  subtitle_ = subtitle;
3947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  invalidate_dimensions();  // Triggers preferred size recalculation.
3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::SetSelected(bool selected) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  selected_ = selected;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::SetTooltip(const string16& tooltip, int item_id) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView* item = GetMenuItemByID(item_id);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(item);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item->tooltip_ = tooltip;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::SetIcon(const gfx::ImageSkia& icon, int item_id) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView* item = GetMenuItemByID(item_id);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(item);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item->SetIcon(icon);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::SetIcon(const gfx::ImageSkia& icon) {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (icon.isNull()) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetIconView(NULL);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ImageView* icon_view = new ImageView();
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon_view->SetImage(&icon);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetIconView(icon_view);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::SetIconView(View* icon_view) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (icon_view_) {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveChildView(icon_view_);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete icon_view_;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon_view_ = NULL;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (icon_view) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddChildView(icon_view);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon_view_ = icon_view;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layout();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::OnPaint(gfx::Canvas* canvas) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PaintButton(canvas, PB_NORMAL);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size MenuItemView::GetPreferredSize() {
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const MenuItemDimensions& dimensions(GetDimensions());
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::Size(dimensions.standard_width + dimensions.children_width,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   dimensions.height);
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const MenuItemView::MenuItemDimensions& MenuItemView::GetDimensions() {
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!is_dimensions_valid())
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dimensions_ = CalculateDimensions();
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(is_dimensions_valid());
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dimensions_;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuController* MenuItemView::GetMenuController() {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetRootMenuItem()->controller_;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const MenuController* MenuItemView::GetMenuController() const {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetRootMenuItem()->controller_;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuDelegate* MenuItemView::GetDelegate() {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetRootMenuItem()->delegate_;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const MenuDelegate* MenuItemView::GetDelegate() const {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetRootMenuItem()->delegate_;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* MenuItemView::GetRootMenuItem() {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return const_cast<MenuItemView*>(
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<const MenuItemView*>(this)->GetRootMenuItem());
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const MenuItemView* MenuItemView::GetRootMenuItem() const {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MenuItemView* item = this;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (const MenuItemView* parent = GetParentMenuItem(); parent;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       parent = item->GetParentMenuItem())
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item = parent;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return item;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char16 MenuItemView::GetMnemonic() {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetRootMenuItem()->has_mnemonics_)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t index = 0;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    index = title_.find('&', index);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index != string16::npos) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (index + 1 != title_.size() && title_[index + 1] != '&') {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char16 char_array[] = { title_[index + 1], 0 };
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(jshin): What about Turkish locale? See http://crbug.com/81719.
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If the mnemonic is capital I and the UI language is Turkish,
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // lowercasing it results in 'small dotless i', which is different
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // from a 'dotted i'. Similar issues may exist for az and lt locales.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return base::i18n::ToLower(char_array)[0];
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      index++;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (index != string16::npos);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* MenuItemView::GetMenuItemByID(int id) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetCommand() == id)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HasSubmenu())
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < GetSubmenu()->child_count(); ++i) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    View* child = GetSubmenu()->child_at(i);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (child->id() == MenuItemView::kMenuItemViewID) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MenuItemView* result = static_cast<MenuItemView*>(child)->
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GetMenuItemByID(id);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return result;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::ChildrenChanged() {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuController* controller = GetMenuController();
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (controller) {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Handles the case where we were empty and are no longer empty.
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveEmptyMenus();
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Handles the case where we were not empty, but now are.
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddEmptyMenus();
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller->MenuChildrenChanged(this);
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (submenu_) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Force a paint and layout. This handles the case of the top
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // level window's size remaining the same, resulting in no
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // change to the submenu's size and no layout.
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      submenu_->Layout();
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      submenu_->SchedulePaint();
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Update the menu selection after layout.
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controller->UpdateSubmenuSelection(submenu_);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&removed_items_);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::Layout() {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_children())
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsContainer()) {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    View* child = child_at(0);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Size size = child->GetPreferredSize();
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    child->SetBounds(0, GetTopMargin(), size.width(), size.height());
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Child views are laid out right aligned and given the full height. To
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // right align start with the last view and progress to the first.
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int x = width() - (use_right_margin_ ? item_right_margin_ : 0);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = child_count() - 1; i >= 0; --i) {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      View* child = child_at(i);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (icon_view_ && (icon_view_ == child))
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int width = child->GetPreferredSize().width();
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      child->SetBounds(x - width, 0, width, height());
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      x -= width - kChildXPadding;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Position |icon_view|.
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const MenuConfig& config = GetMenuConfig();
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (icon_view_) {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon_view_->SizeToPreferredSize();
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Size size = icon_view_->GetPreferredSize();
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int x = config.item_left_margin + left_icon_margin_ +
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (icon_area_width_ - size.width()) / 2;
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (type_ == CHECKBOX || type_ == RADIO)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        x = label_start_;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int y =
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (height() + GetTopMargin() - GetBottomMargin() - size.height()) / 2;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon_view_->SetPosition(gfx::Point(x, y));
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::SetMargins(int top_margin, int bottom_margin) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_margin_ = top_margin;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bottom_margin_ = bottom_margin;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalidate_dimensions();
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const MenuConfig& MenuItemView::GetMenuConfig() const {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MenuController* controller = GetMenuController();
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (controller)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return controller->menu_config_;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return MenuConfig::instance(NULL);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView::MenuItemView(MenuItemView* parent,
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int command,
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           MenuItemView::Type type)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : delegate_(NULL),
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controller_(NULL),
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      canceled_(false),
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parent_menu_item_(parent),
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type_(type),
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      selected_(false),
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_(command),
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      submenu_(NULL),
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_mnemonics_(false),
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      show_mnemonics_(false),
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_icons_(false),
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon_view_(NULL),
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      top_margin_(-1),
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bottom_margin_(-1),
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      left_icon_margin_(0),
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      right_icon_margin_(0),
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requested_menu_position_(POSITION_BEST_FIT),
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      actual_menu_position_(requested_menu_position_),
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      use_right_margin_(true) {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(parent, command, type, NULL);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView::~MenuItemView() {
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete submenu_;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&removed_items_);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
629b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char* MenuItemView::GetClassName() const {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kViewClassName;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Calculates all sizes that we can from the OS.
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is invoked prior to Running a menu.
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::UpdateMenuPartSizes() {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MenuConfig& config = GetMenuConfig();
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item_right_margin_ = config.label_to_arrow_padding + config.arrow_width +
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       config.arrow_to_edge_padding;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon_area_width_ = config.check_width;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_icons_)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon_area_width_ = std::max(icon_area_width_, GetMaxIconViewWidth());
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  label_start_ = config.item_left_margin + icon_area_width_;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int padding = 0;
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (config.always_use_icon_to_label_padding) {
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    padding = config.icon_to_label_padding;
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (config.render_gutter) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    padding = config.item_left_margin;
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    padding = (has_icons_ || HasChecksOrRadioButtons()) ?
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        config.icon_to_label_padding : 0;
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  label_start_ += padding;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (config.render_gutter)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    label_start_ += config.gutter_width + config.gutter_to_label;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmptyMenuMenuItem menu_item(this);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  menu_item.set_controller(GetMenuController());
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pref_menu_height_ = menu_item.GetPreferredSize().height();
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::Init(MenuItemView* parent,
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int command,
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        MenuItemView::Type type,
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        MenuDelegate* delegate) {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_ = delegate;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller_ = NULL;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  canceled_ = false;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parent_menu_item_ = parent;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type_ = type;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  selected_ = false;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_ = command;
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  submenu_ = NULL;
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  show_mnemonics_ = false;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assign our ID, this allows SubmenuItemView to find MenuItemViews.
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_id(kMenuItemViewID);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_icons_ = false;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't request enabled status from the root menu item as it is just
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a container for real items.  EMPTY items will be disabled.
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuDelegate* root_delegate = GetDelegate();
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parent && type != EMPTY && root_delegate)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetEnabled(root_delegate->IsCommandEnabled(command));
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::PrepareForRun(bool is_first_menu,
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 bool has_mnemonics,
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 bool show_mnemonics) {
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Currently we only support showing the root.
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!parent_menu_item_);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Force us to have a submenu.
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateSubmenu();
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  actual_menu_position_ = requested_menu_position_;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  canceled_ = false;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_mnemonics_ = has_mnemonics;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  show_mnemonics_ = has_mnemonics && show_mnemonics;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddEmptyMenus();
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_first_menu) {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only update the menu size if there are no menus showing, otherwise
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // things may shift around.
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateMenuPartSizes();
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MenuItemView::GetDrawStringFlags() {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = 0;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::i18n::IsRTL())
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetRootMenuItem()->has_mnemonics_) {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (GetMenuConfig().show_mnemonics || GetRootMenuItem()->show_mnemonics_) {
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags |= gfx::Canvas::SHOW_PREFIX;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags |= gfx::Canvas::HIDE_PREFIX;
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return flags;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const gfx::Font& MenuItemView::GetFont() {
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MenuDelegate* delegate = GetDelegate();
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate) {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Font* font = delegate->GetLabelFont(GetCommand());
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (font)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return *font;
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetMenuConfig().font;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::AddEmptyMenus() {
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(HasSubmenu());
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!submenu_->has_children()) {
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    submenu_->AddChildViewAt(new EmptyMenuMenuItem(this), 0);
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0, item_count = submenu_->GetMenuItemCount(); i < item_count;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ++i) {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MenuItemView* child = submenu_->GetMenuItemAt(i);
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (child->HasSubmenu())
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        child->AddEmptyMenus();
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::RemoveEmptyMenus() {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(HasSubmenu());
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Iterate backwards as we may end up removing views, which alters the child
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // view count.
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = submenu_->child_count() - 1; i >= 0; --i) {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    View* child = submenu_->child_at(i);
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (child->id() == MenuItemView::kMenuItemViewID) {
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MenuItemView* menu_item = static_cast<MenuItemView*>(child);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (menu_item->HasSubmenu())
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        menu_item->RemoveEmptyMenus();
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (child->id() == EmptyMenuMenuItem::kEmptyMenuItemViewID) {
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      submenu_->RemoveChildView(child);
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete child;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      child = NULL;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::AdjustBoundsForRTLUI(gfx::Rect* rect) const {
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rect->set_x(GetMirroredXForRect(*rect));
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const MenuConfig& config = GetMenuConfig();
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool render_selection =
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (mode == PB_NORMAL && IsSelected() &&
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       parent_menu_item_->GetSubmenu()->GetShowSelection(this) &&
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       (NonIconChildViewsCount() == 0));
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int icon_x = config.item_left_margin + left_icon_margin_;
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int top_margin = GetTopMargin();
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int bottom_margin = GetBottomMargin();
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int icon_y = top_margin + (height() - config.item_top_margin -
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             bottom_margin - config.check_height) / 2;
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int icon_height = config.check_height;
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int available_height = height() - top_margin - bottom_margin;
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MenuDelegate *delegate = GetDelegate();
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Render the background. As MenuScrollViewContainer draws the background, we
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // only need the background when we want it to look different, as when we're
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // selected.
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::NativeTheme* native_theme = GetNativeTheme();
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkColor override_color;
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (delegate && delegate->GetBackgroundColor(GetCommand(),
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               render_selection,
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               &override_color)) {
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->DrawColor(override_color);
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (render_selection) {
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Rect item_bounds(0, 0, width(), height());
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    AdjustBoundsForRTLUI(&item_bounds);
802b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
803b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    native_theme->Paint(canvas->sk_canvas(),
804b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        ui::NativeTheme::kMenuItemBackground,
805b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        ui::NativeTheme::kHovered,
806b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        item_bounds,
807b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        ui::NativeTheme::ExtraParams());
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Render the check.
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (type_ == CHECKBOX && delegate->IsItemChecked(GetCommand())) {
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::ImageSkia* check = GetMenuCheckImage();
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Don't use config.check_width here as it's padded
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // to force more padding (AURA).
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect check_bounds(icon_x, icon_y, check->width(), icon_height);
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AdjustBoundsForRTLUI(&check_bounds);
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->DrawImageInt(*check, check_bounds.x(), check_bounds.y());
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (type_ == RADIO) {
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::ImageSkia* image =
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetRadioButtonImage(delegate->IsItemChecked(GetCommand()));
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect radio_bounds(icon_x,
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           top_margin +
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           (height() - top_margin - bottom_margin -
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            image->height()) / 2,
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           image->width(),
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           image->height());
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AdjustBoundsForRTLUI(&radio_bounds);
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->DrawImageInt(*image, radio_bounds.x(), radio_bounds.y());
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Render the foreground.
832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ui::NativeTheme::ColorId color_id =
833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ui::NativeTheme::kColorId_DisabledMenuItemForegroundColor;
834c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (enabled()) {
835c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    color_id = render_selection ?
836c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor:
837c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ui::NativeTheme::kColorId_EnabledMenuItemForegroundColor;
838c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
839c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SkColor fg_color = native_theme->GetSystemColor(color_id);
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkColor override_foreground_color;
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (delegate && delegate->GetForegroundColor(GetCommand(),
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               render_selection,
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               &override_foreground_color))
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    fg_color = override_foreground_color;
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Font& font = GetFont();
8477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int accel_width = parent_menu_item_->GetSubmenu()->max_minor_text_width();
848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int label_start = GetLabelStartForThisItem();
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int width = this->width() - label_start - accel_width -
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (!delegate ||
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       delegate->ShouldReserveSpaceForSubmenuIndicator() ?
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           item_right_margin_ : config.arrow_to_edge_padding);
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect text_bounds(label_start, top_margin, width, available_height);
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  text_bounds.set_x(GetMirroredXForRect(text_bounds));
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int flags = GetDrawStringFlags();
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mode == PB_FOR_DRAG)
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->DrawStringInt(title(), font, fg_color,
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        text_bounds.x(), text_bounds.y(), text_bounds.width(),
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        text_bounds.height(), flags);
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PaintMinorText(canvas, render_selection);
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Render the submenu indicator (arrow).
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (HasSubmenu()) {
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect arrow_bounds(this->width() - config.arrow_width -
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               config.arrow_to_edge_padding,
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           top_margin + (available_height -
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         config.arrow_width) / 2,
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           config.arrow_width, height());
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AdjustBoundsForRTLUI(&arrow_bounds);
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->DrawImageInt(*GetSubmenuArrowImage(),
8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         arrow_bounds.x(), arrow_bounds.y());
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MenuItemView::PaintMinorText(gfx::Canvas* canvas,
8797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                  bool render_selection) {
8807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  string16 minor_text = GetMinorText();
8817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (minor_text.empty())
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Font& font = GetFont();
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int available_height = height() - GetTopMargin() - GetBottomMargin();
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int max_accel_width =
8877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      parent_menu_item_->GetSubmenu()->max_minor_text_width();
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MenuConfig& config = GetMenuConfig();
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int accel_right_margin = config.align_arrow_and_shortcut ?
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           config.arrow_to_edge_padding :  item_right_margin_;
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect accel_bounds(width() - accel_right_margin - max_accel_width,
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetTopMargin(), max_accel_width, available_height);
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  accel_bounds.set_x(GetMirroredXForRect(accel_bounds));
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = GetDrawStringFlags();
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flags &= ~(gfx::Canvas::TEXT_ALIGN_RIGHT | gfx::Canvas::TEXT_ALIGN_LEFT);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::i18n::IsRTL())
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  canvas->DrawStringInt(
9017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      minor_text,
902c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      font,
903c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetNativeTheme()->GetSystemColor(render_selection ?
904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor :
90590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          ui::NativeTheme::kColorId_ButtonDisabledColor),
906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      accel_bounds.x(),
907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      accel_bounds.y(),
908c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      accel_bounds.width(),
909c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      accel_bounds.height(),
910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      flags);
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuItemView::DestroyAllMenuHosts() {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HasSubmenu())
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  submenu_->Close();
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0, item_count = submenu_->GetMenuItemCount(); i < item_count;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++i) {
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    submenu_->GetMenuItemAt(i)->DestroyAllMenuHosts();
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MenuItemView::GetTopMargin() {
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (top_margin_ >= 0)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return top_margin_;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView* root = GetRootMenuItem();
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return root && root->has_icons_
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ? GetMenuConfig().item_top_margin :
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetMenuConfig().item_no_icon_top_margin;
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MenuItemView::GetBottomMargin() {
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bottom_margin_ >= 0)
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return bottom_margin_;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView* root = GetRootMenuItem();
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return root && root->has_icons_
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ? GetMenuConfig().item_bottom_margin :
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetMenuConfig().item_no_icon_bottom_margin;
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size MenuItemView::GetChildPreferredSize() {
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_children())
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return gfx::Size();
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsContainer()) {
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    View* child = child_at(0);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return child->GetPreferredSize();
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = 0;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < child_count(); ++i) {
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    View* child = child_at(i);
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (icon_view_ && (icon_view_ == child))
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      width += kChildXPadding;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width += child->GetPreferredSize().width();
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int height = 0;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (icon_view_)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    height = icon_view_->GetPreferredSize().height();
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is no icon view it returns a height of 0 to indicate that
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we should use the title height instead.
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::Size(width, height);
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MenuItemView::MenuItemDimensions MenuItemView::CalculateDimensions() {
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size child_size = GetChildPreferredSize();
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemDimensions dimensions;
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the container height.
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dimensions.children_width = child_size.width();
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dimensions.height = child_size.height();
9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Adjust item content height if menu has both items with and without icons.
9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This way all menu items will have the same height.
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!icon_view_ && GetRootMenuItem()->has_icons()) {
9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dimensions.height = std::max(dimensions.height,
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 GetMenuConfig().check_height);
9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dimensions.height += GetBottomMargin() + GetTopMargin();
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In case of a container, only the container size needs to be filled.
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsContainer())
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dimensions;
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine the length of the label text.
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Font& font = GetFont();
9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Get Icon margin overrides for this particular item.
9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const MenuDelegate* delegate = GetDelegate();
9952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (delegate) {
9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delegate->GetHorizontalIconMargins(command_,
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       icon_area_width_,
9982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       &left_icon_margin_,
9992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       &right_icon_margin_);
10002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
10012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    left_icon_margin_ = 0;
10022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    right_icon_margin_ = 0;
10032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1004c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int label_start = GetLabelStartForThisItem();
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dimensions.standard_width = font.GetStringWidth(title_) + label_start +
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item_right_margin_;
10087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Determine the length of the right-side text.
10097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  string16 minor_text = GetMinorText();
10107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  dimensions.minor_text_width =
10117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      minor_text.empty() ? 0 : GetFont().GetStringWidth(minor_text);
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine the height to use.
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dimensions.height = std::max(dimensions.height,
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      font.GetHeight() + GetBottomMargin() + GetTopMargin());
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dimensions.height = std::max(dimensions.height,
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMenuConfig().item_min_height);
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dimensions;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1021c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int MenuItemView::GetLabelStartForThisItem() {
1022c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int label_start = label_start_ + left_icon_margin_ + right_icon_margin_;
1023c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if ((type_ == CHECKBOX || type_ == RADIO) && icon_view_) {
1024c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    label_start += icon_view_->size().width() +
1025c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GetMenuConfig().icon_to_label_padding;
1026c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1027c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return label_start;
1028c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1029c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstring16 MenuItemView::GetMinorText() {
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id() == kEmptyMenuItemViewID) {
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't query the delegate for menus that represent no children.
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return string16();
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::Accelerator accelerator;
10377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (GetMenuConfig().show_accelerators && GetDelegate() && GetCommand() &&
10387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          GetDelegate()->GetAccelerator(GetCommand(), &accelerator)) {
10397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return accelerator.GetShortcutText();
10407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
10417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
10427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return subtitle_;
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MenuItemView::IsContainer() const {
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Let the first child take over |this| when we only have one child and no
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // title.
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (NonIconChildViewsCount() == 1) && title_.empty();
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MenuItemView::NonIconChildViewsCount() const {
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that what child_count() returns is the number of children,
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not the number of menu items.
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return child_count() - (icon_view_ ? 1 : 0);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MenuItemView::GetMaxIconViewWidth() const {
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = 0;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < submenu_->GetMenuItemCount(); ++i) {
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MenuItemView* menu_item = submenu_->GetMenuItemAt(i);
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int temp_width = 0;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (menu_item->HasSubmenu()) {
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      temp_width = menu_item->GetMaxIconViewWidth();
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (menu_item->icon_view()) {
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      temp_width = menu_item->icon_view()->GetPreferredSize().width();
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width = std::max(width, temp_width);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return width;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MenuItemView::HasChecksOrRadioButtons() const {
10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < submenu_->GetMenuItemCount(); ++i) {
10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MenuItemView* menu_item = submenu_->GetMenuItemAt(i);
10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (menu_item->HasSubmenu()) {
10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (menu_item->HasChecksOrRadioButtons())
10772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return true;
10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const Type& type = menu_item->GetType();
10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (type == CHECKBOX || type == RADIO)
10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return true;
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace views
1088