menu_controller.h revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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)#ifndef UI_VIEWS_CONTROLS_MENU_MENU_CONTROLLER_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UI_VIEWS_CONTROLS_MENU_MENU_CONTROLLER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event_constants.h"
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/platform/platform_event_dispatcher.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_delegate.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_item_view.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/widget/widget_observer.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
234ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochnamespace base {
244ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochclass MessagePumpDispatcher;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Screen;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
294ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochnamespace ui {
304ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochclass NativeTheme;
314ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochclass OSExchangeData;
32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass ScopedEventDispatcher;
334ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MenuButton;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MenuHostRootView;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MouseEvent;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SubmenuView;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class View;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MenuControllerDelegate;
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass MenuEventDispatcher;
454ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochclass MenuMessagePumpDispatcher;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MenuRunnerImpl;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuController -------------------------------------------------------------
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuController is used internally by the various menu classes to manage
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// showing, selecting and drag/drop for menus. All relevant events are
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// forwarded to the MenuController from SubmenuView and MenuHost.
544ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochclass VIEWS_EXPORT MenuController : public WidgetObserver {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enumeration of how the menu should exit.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum ExitType {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't exit.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXIT_NONE,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // All menus, including nested, should be exited.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXIT_ALL,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only the outermost menu should be exited.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXIT_OUTERMOST,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is set if the menu is being closed as the result of one of the menus
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // being destroyed.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXIT_DESTROYED
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If a menu is currently active, this returns the controller for it.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static MenuController* GetActiveInstance();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Runs the menu at the specified location. If the menu was configured to
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // block, the selected item is returned. If the menu does not block this
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns NULL immediately.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView* Run(Widget* parent,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    MenuButton* button,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    MenuItemView* root,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const gfx::Rect& bounds,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    MenuItemView::AnchorPosition position,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    bool context_menu,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    int* event_flags);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether or not Run blocks.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsBlockingRun() const { return blocking_run_; }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether or not drag operation is in progress.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool drag_in_progress() const { return drag_in_progress_; }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Get the anchor position wich is used to show this menu.
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MenuItemView::AnchorPosition GetAnchorPosition() { return state_.anchor; }
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancels the current Run. See ExitType for a description of what happens
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with the various parameters.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Cancel(ExitType type);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An alternative to Cancel(EXIT_ALL) that can be used with a OneShotTimer.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CancelAll() { Cancel(EXIT_ALL); }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the current exit type. This returns a value other than EXIT_NONE if
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the menu is being canceled.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExitType exit_type() const { return exit_type_; }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns the time from the event which closed the menu - or 0.
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta closing_event_time() const { return closing_event_time_; }
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void set_is_combobox(bool is_combobox) { is_combobox_ = is_combobox; }
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Various events, forwarded from the submenu.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: the coordinates of the events are in that of the
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MenuScrollViewContainer.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnMousePressed(SubmenuView* source, const ui::MouseEvent& event);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnMouseDragged(SubmenuView* source, const ui::MouseEvent& event);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnMouseReleased(SubmenuView* source, const ui::MouseEvent& event);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnMouseMoved(SubmenuView* source, const ui::MouseEvent& event);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnMouseEntered(SubmenuView* source, const ui::MouseEvent& event);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool OnMouseWheel(SubmenuView* source, const ui::MouseWheelEvent& event);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnGestureEvent(SubmenuView* source, ui::GestureEvent* event);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetDropFormats(
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SubmenuView* source,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int* formats,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::set<ui::OSExchangeData::CustomFormat>* custom_formats);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool AreDropTypesRequired(SubmenuView* source);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool CanDrop(SubmenuView* source, const ui::OSExchangeData& data);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDragEntered(SubmenuView* source, const ui::DropTargetEvent& event);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int OnDragUpdated(SubmenuView* source, const ui::DropTargetEvent& event);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDragExited(SubmenuView* source);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int OnPerformDrop(SubmenuView* source, const ui::DropTargetEvent& event);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoked from the scroll buttons of the MenuScrollViewContainer.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDragEnteredScrollButton(SubmenuView* source, bool is_up);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDragExitedScrollButton(SubmenuView* source);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the submenu's selection based on the current mouse location
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateSubmenuSelection(SubmenuView* source);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // WidgetObserver overrides:
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnWidgetDestroying(Widget* widget) OVERRIDE;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Only used for testing.
145424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  static void TurnOffMenuSelectionHoldForTest();
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  friend class internal::MenuEventDispatcher;
1494ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  friend class internal::MenuMessagePumpDispatcher;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class internal::MenuRunnerImpl;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class MenuHostRootView;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class MenuItemView;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class SubmenuView;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class MenuScrollTask;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct SelectByCharDetails;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Values supplied to SetSelection.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum SetSelectionTypes {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SELECTION_DEFAULT               = 0,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If set submenus are opened immediately, otherwise submenus are only
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // openned after a timer fires.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SELECTION_UPDATE_IMMEDIATELY    = 1 << 0,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If set and the menu_item has a submenu, the submenu is shown.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SELECTION_OPEN_SUBMENU          = 1 << 1,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SetSelection is being invoked as the result exiting or cancelling the
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // menu. This is used for debugging.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SELECTION_EXIT                  = 1 << 2,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Result type for SendAcceleratorToHotTrackedView
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum SendAcceleratorResultType {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Accelerator is not sent because of no hot tracked views.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACCELERATOR_NOT_PROCESSED,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Accelerator is sent to the hot tracked views.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACCELERATOR_PROCESSED,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Same as above and the accelerator causes the exit of the menu.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACCELERATOR_PROCESSED_EXIT
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tracks selection information.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct State {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~State();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The selected menu item.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MenuItemView* item;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If item has a submenu this indicates if the submenu is showing.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool submenu_open;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Bounds passed to the run menu. Used for positioning the first menu.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect initial_bounds;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Position of the initial menu.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MenuItemView::AnchorPosition anchor;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The direction child menus have opened in.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::list<bool> open_leading;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Bounds for the monitor we're showing on.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect monitor_bounds;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Is the current menu a context menu.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool context_menu;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used by GetMenuPart to indicate the menu part at a particular location.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct MenuPart {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Type of part.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum Type {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NONE,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MENU_ITEM,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SCROLL_UP,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SCROLL_DOWN
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MenuPart() : type(NONE), menu(NULL), parent(NULL), submenu(NULL) {}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Convenience for testing type == SCROLL_DOWN or type == SCROLL_UP.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_scroll() const { return type == SCROLL_DOWN || type == SCROLL_UP; }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Type of part.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type type;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If type is MENU_ITEM, this is the menu item the mouse is over, otherwise
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this is NULL.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NOTE: if type is MENU_ITEM and the mouse is not over a valid menu item
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //       but is over a menu (for example, the mouse is over a separator or
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //       empty menu), this is NULL and parent is the menu the mouse was
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //       clicked on.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MenuItemView* menu;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If type is MENU_ITEM but the mouse is not over a menu item this is the
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // parent of the menu item the user clicked on. Otherwise this is NULL.
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MenuItemView* parent;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is the submenu the mouse is over.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SubmenuView* submenu;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sets the selection to |menu_item|. A value of NULL unselects
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // everything. |types| is a bitmask of |SetSelectionTypes|.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Internally this updates pending_state_ immediatley. state_ is only updated
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // immediately if SELECTION_UPDATE_IMMEDIATELY is set. If
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SELECTION_UPDATE_IMMEDIATELY is not set CommitPendingSelection is invoked
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to show/hide submenus and update state_.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetSelection(MenuItemView* menu_item, int types);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetSelectionOnPointerDown(SubmenuView* source,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const ui::LocatedEvent& event);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartDrag(SubmenuView* source, const gfx::Point& location);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Key processing. The return value of this is returned from Dispatch.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In other words, if this returns false (which happens if escape was
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pressed, or a matching mnemonic was found) the message loop returns.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool OnKeyDown(ui::KeyboardCode key_code);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a MenuController. If |blocking| is true a nested message loop is
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // started in |Run|.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuController(ui::NativeTheme* theme,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 bool blocking,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 internal::MenuControllerDelegate* delegate);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MenuController();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Runs the platform specific bits of the message loop. If |nested_menu| is
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // true we're being asked to run a menu from within a menu (eg a context
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // menu).
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RunMessageLoop(bool nested_menu);
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AcceleratorPressed is invoked on the hot tracked view if it exists.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendAcceleratorResultType SendAcceleratorToHotTrackedView();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateInitialLocation(const gfx::Rect& bounds,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             MenuItemView::AnchorPosition position,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             bool context_menu);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoked when the user accepts the selected item. This is only used
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // when blocking. This schedules the loop to quit.
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Accept(MenuItemView* item, int event_flags);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ShowSiblingMenu(SubmenuView* source, const gfx::Point& mouse_location);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shows a context menu for |menu_item| as a result of a located event if
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // appropriate. This is invoked on long press and releasing the right mouse
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // button. Returns whether a context menu was shown.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ShowContextMenu(MenuItemView* menu_item,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       SubmenuView* source,
2977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       const ui::LocatedEvent& event,
2987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       ui::MenuSourceType source_type);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Closes all menus, including any menus of nested invocations of Run.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CloseAllNestedMenus();
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets the enabled menu item at the specified location.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If over_any_menu is non-null it is set to indicate whether the location
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is over any menu. It is possible for this to return NULL, but
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // over_any_menu to be true. For example, the user clicked on a separator.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView* GetMenuItemAt(View* menu, int x, int y);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is an empty menu item at the specified location, it is returned.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView* GetEmptyMenuItemAt(View* source, int x, int y);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the coordinate is over the scroll buttons of the
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SubmenuView's MenuScrollViewContainer. If true is returned, part is set to
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // indicate which scroll button the coordinate is.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsScrollButtonAt(SubmenuView* source,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int x,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int y,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        MenuPart::Type* part);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the target for the mouse event. The coordinates are in terms of
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // source's scroll view container.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuPart GetMenuPart(SubmenuView* source, const gfx::Point& source_loc);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the target for mouse events. The search is done through |item| and
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // all its parents.
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuPart GetMenuPartByScreenCoordinateUsingMenu(MenuItemView* item,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  const gfx::Point& screen_loc);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implementation of GetMenuPartByScreenCoordinate for a single menu. Returns
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true if the supplied SubmenuView contains the location in terms of the
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // screen. If it does, part is set appropriately and true is returned.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetMenuPartByScreenCoordinateImpl(SubmenuView* menu,
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const gfx::Point& screen_loc,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         MenuPart* part);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the SubmenuView contains the specified location. This does
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOT included the scroll buttons, only the submenu view.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool DoesSubmenuContainLocation(SubmenuView* submenu,
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const gfx::Point& screen_loc);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Opens/Closes the necessary menus such that state_ matches that of
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending_state_. This is invoked if submenus are not opened immediately,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but after a delay.
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CommitPendingSelection();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If item has a submenu, it is closed. This does NOT update the selection
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in anyway.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CloseMenu(MenuItemView* item);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If item has a submenu, it is opened. This does NOT update the selection
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in anyway.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OpenMenu(MenuItemView* item);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implementation of OpenMenu. If |show| is true, this invokes show on the
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // menu, otherwise Reposition is invoked.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OpenMenuImpl(MenuItemView* item, bool show);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoked when the children of a menu change and the menu is showing.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This closes any submenus and resizes the submenu.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void MenuChildrenChanged(MenuItemView* item);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Builds the paths of the two menu items into the two paths, and
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sets first_diff_at to the location of the first difference between the
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // two paths.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildPathsAndCalculateDiff(MenuItemView* old_item,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  MenuItemView* new_item,
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  std::vector<MenuItemView*>* old_path,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  std::vector<MenuItemView*>* new_path,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  size_t* first_diff_at);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Builds the path for the specified item.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildMenuItemPath(MenuItemView* item, std::vector<MenuItemView*>* path);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starts/stops the timer that commits the pending state to state
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (opens/closes submenus).
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartShowTimer();
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopShowTimer();
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starts/stops the timer cancel the menu. This is used during drag and
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // drop when the drop enters/exits the menu.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartCancelAllTimer();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopCancelAllTimer();
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calculates the bounds of the menu to show. is_leading is set to match the
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // direction the menu opened in.
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect CalculateMenuBounds(MenuItemView* item,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bool prefer_leading,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bool* is_leading);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calculates the bubble bounds of the menu to show. is_leading is set to
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // match the direction the menu opened in.
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect CalculateBubbleMenuBounds(MenuItemView* item,
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      bool prefer_leading,
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      bool* is_leading);
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the depth of the menu.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int MenuDepth(MenuItemView* item);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Selects the next/previous menu item.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void IncrementSelection(int delta);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the next selectable child menu item of |parent| starting at |index|
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and incrementing index by |delta|. If there are no more selected menu items
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NULL is returned.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView* FindNextSelectableMenuItem(MenuItemView* parent,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           int index,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           int delta);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the selected item has a submenu and it isn't currently open, the
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the selection is changed such that the menu opens immediately.
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OpenSubmenuChangeSelectionIfCan();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If possible, closes the submenu.
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CloseSubmenu();
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns details about which menu items match the mnemonic |key|.
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |match_function| is used to determine which menus match.
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectByCharDetails FindChildForMnemonic(
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MenuItemView* parent,
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::char16 key,
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool (*match_function)(MenuItemView* menu, base::char16 mnemonic));
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Selects or accepts the appropriate menu item based on |details|. Returns
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true if |Accept| was invoked (which happens if there aren't multiple item
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with the same mnemonic and the item to select does not have a submenu).
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool AcceptOrSelect(MenuItemView* parent, const SelectByCharDetails& details);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Selects by mnemonic, and if that doesn't work tries the first character of
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the title. Returns true if a match was selected and the menu should exit.
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool SelectByChar(base::char16 key);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For Windows and Aura we repost an event for some events that dismiss
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the context menu. The event is then reprocessed to cause its result
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if the context menu had not been present.
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // On non-aura Windows, a new mouse event is generated and posted to
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the window (if there is one) at the location of the event. On
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // aura, the event is reposted on the RootWindow.
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RepostEvent(SubmenuView* source, const ui::LocatedEvent& event);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets the drop target to new_item.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetDropMenuItem(MenuItemView* new_item,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       MenuDelegate::DropPosition position);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starts/stops scrolling as appropriate. part gives the part the mouse is
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // over.
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateScrolling(const MenuPart& part);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stops scrolling.
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopScrolling();
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
451424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Updates active mouse view from the location of the event and sends it
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the appropriate events. This is used to send mouse events to child views so
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that they react to click-drag-release as if the user clicked on the view
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // itself.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateActiveMouseView(SubmenuView* event_source,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const ui::MouseEvent& event,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             View* target_menu);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
459424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Sends a mouse release event to the current active mouse view and sets
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it to null.
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SendMouseReleaseToActiveView(SubmenuView* event_source,
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const ui::MouseEvent& event);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
464424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Sends a mouse capture lost event to the current active mouse view and sets
465424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // it to null.
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SendMouseCaptureLostToActiveView();
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
468424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Sets/gets the active mouse view. See UpdateActiveMouseView() for details.
469424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  void SetActiveMouseView(View* view);
470424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  View* GetActiveMouseView();
471424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets exit type.
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetExitType(ExitType type);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true if SetExitType() should quit the message loop.
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ShouldQuitNow() const;
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handles the mouse location event on the submenu |source|.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleMouseLocation(SubmenuView* source,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const gfx::Point& mouse_location);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retrieve an appropriate Screen.
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Screen* GetScreen();
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The active instance.
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static MenuController* active_instance_;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If true, Run blocks. If false, Run doesn't block and this is used for
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // drag and drop. Note that the semantics for drag and drop are slightly
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // different: cancel timer is kicked off any time the drag moves outside the
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // menu, mouse events do nothing...
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool blocking_run_;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If true, we're showing.
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool showing_;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicates what to exit.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExitType exit_type_;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether we did a capture. We do a capture only if we're blocking and
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the mouse was down when Run.
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_capture_;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As the user drags the mouse around pending_state_ changes immediately.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the user stops moving/dragging the mouse (or clicks the mouse)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending_state_ is committed to state_, potentially resulting in
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // opening or closing submenus. This gives a slight delayed effect to
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // submenus as the user moves the mouse around. This is done so that as the
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // user moves the mouse all submenus don't immediately pop.
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State pending_state_;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State state_;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the user accepted the selection, this is the result.
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView* result_;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The event flags when the user selected the menu.
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int accept_event_flags_;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If not empty, it means we're nested. When Run is invoked from within
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run, the current state (state_) is pushed onto menu_stack_. This allows
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MenuController to restore the state when the nested run returns.
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::list<State> menu_stack_;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As the mouse moves around submenus are not opened immediately. Instead
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // they open after this timer fires.
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::OneShotTimer<MenuController> show_timer_;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used to invoke CancelAll(). This is used during drag and drop to hide the
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // menu after the mouse moves out of the of the menu. This is necessitated by
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the lack of an ability to detect when the drag has completed from the drop
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // side.
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::OneShotTimer<MenuController> cancel_all_timer_;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Drop target.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuItemView* drop_target_;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuDelegate::DropPosition drop_position_;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Owner of child windows.
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WARNING: this may be NULL.
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Widget* owner_;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicates a possible drag operation.
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool possible_drag_;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True when drag operation is in progress.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool drag_in_progress_;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Location the mouse was pressed at. Used to detect d&d.
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point press_pt_;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We get a slew of drag updated messages as the mouse is over us. To avoid
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // continually processing whether we can drop, we cache the coordinates.
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool valid_drop_coordinates_;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point drop_pt_;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int last_drop_operation_;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If true, we're in the middle of invoking ShowAt on a submenu.
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool showing_submenu_;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Task for scrolling the menu. If non-null indicates a scroll is currently
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // underway.
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MenuScrollTask> scroll_task_;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuButton* menu_button_;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
566424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // ViewStorage id used to store the view mouse drag events are forwarded to.
567424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // See UpdateActiveMouseView() for details.
568424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int active_mouse_view_id_;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal::MenuControllerDelegate* delegate_;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // How deep we are in nested message loops. This should be at most 2 (when
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // showing a context menu from a menu).
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int message_loop_depth_;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::MenuConfig menu_config_;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The timestamp of the event which closed the menu - or 0 otherwise.
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta closing_event_time_;
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Time when the menu is first shown.
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeTicks menu_start_time_;
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
584424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // If a mouse press triggered this menu, this will have its location (in
585424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // screen coordinates). Otherwise this will be (0, 0).
586424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  gfx::Point menu_start_mouse_press_loc_;
587424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
588a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Controls behavior differences between a combobox and other types of menu
589a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (like a context menu).
590a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool is_combobox_;
5914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
592a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Set to true if the menu item was selected by touch.
593a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool item_selected_by_touch_;
594a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
595c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<ui::ScopedEventDispatcher> nested_dispatcher_;
596c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MenuController);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace views
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // UI_VIEWS_CONTROLS_MENU_MENU_CONTROLLER_H_
603