1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef UI_VIEWS_CONTROLS_BUTTON_MENU_BUTTON_H_ 6#define UI_VIEWS_CONTROLS_BUTTON_MENU_BUTTON_H_ 7 8#include <string> 9 10#include "base/memory/weak_ptr.h" 11#include "base/strings/string16.h" 12#include "base/time/time.h" 13#include "ui/views/background.h" 14#include "ui/views/controls/button/label_button.h" 15 16namespace views { 17 18class MenuButtonListener; 19 20//////////////////////////////////////////////////////////////////////////////// 21// 22// MenuButton 23// 24// A button that shows a menu when the left mouse button is pushed 25// 26//////////////////////////////////////////////////////////////////////////////// 27class VIEWS_EXPORT MenuButton : public LabelButton { 28 public: 29 // A scoped lock for keeping the MenuButton in STATE_PRESSED e.g., while a 30 // menu is running. These are cumulative. 31 class VIEWS_EXPORT PressedLock { 32 public: 33 explicit PressedLock(MenuButton* menu_button); 34 ~PressedLock(); 35 36 private: 37 base::WeakPtr<MenuButton> menu_button_; 38 39 DISALLOW_COPY_AND_ASSIGN(PressedLock); 40 }; 41 42 static const char kViewClassName[]; 43 44 // How much padding to put on the left and right of the menu marker. 45 static const int kMenuMarkerPaddingLeft; 46 static const int kMenuMarkerPaddingRight; 47 48 // Create a Button. 49 MenuButton(ButtonListener* listener, 50 const base::string16& text, 51 MenuButtonListener* menu_button_listener, 52 bool show_menu_marker); 53 virtual ~MenuButton(); 54 55 bool show_menu_marker() const { return show_menu_marker_; } 56 void set_menu_marker(const gfx::ImageSkia* menu_marker) { 57 menu_marker_ = menu_marker; 58 } 59 const gfx::ImageSkia* menu_marker() const { return menu_marker_; } 60 61 const gfx::Point& menu_offset() const { return menu_offset_; } 62 void set_menu_offset(int x, int y) { menu_offset_.SetPoint(x, y); } 63 64 // Activate the button (called when the button is pressed). 65 virtual bool Activate(); 66 67 // Overridden from View: 68 virtual gfx::Size GetPreferredSize() const OVERRIDE; 69 virtual const char* GetClassName() const OVERRIDE; 70 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 71 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; 72 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; 73 virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; 74 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; 75 virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE; 76 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; 77 virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE; 78 virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE; 79 virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE; 80 81 protected: 82 // Paint the menu marker image. 83 void PaintMenuMarker(gfx::Canvas* canvas); 84 85 // Overridden from LabelButton: 86 virtual gfx::Rect GetChildAreaBounds() OVERRIDE; 87 88 // Offset of the associated menu position. 89 gfx::Point menu_offset_; 90 91 private: 92 friend class PressedLock; 93 94 // Increment/decrement the number of "pressed" locks this button has, and 95 // set the state accordingly. 96 void IncrementPressedLocked(); 97 void DecrementPressedLocked(); 98 99 // Compute the maximum X coordinate for the current screen. MenuButtons 100 // use this to make sure a menu is never shown off screen. 101 int GetMaximumScreenXCoordinate(); 102 103 // We use a time object in order to keep track of when the menu was closed. 104 // The time is used for simulating menu behavior for the menu button; that 105 // is, if the menu is shown and the button is pressed, we need to close the 106 // menu. There is no clean way to get the second click event because the 107 // menu is displayed using a modal loop and, unlike regular menus in Windows, 108 // the button is not part of the displayed menu. 109 base::TimeTicks menu_closed_time_; 110 111 // Our listener. Not owned. 112 MenuButtonListener* listener_; 113 114 // Whether or not we're showing a drop marker. 115 bool show_menu_marker_; 116 117 // The down arrow used to differentiate the menu button from normal buttons. 118 const gfx::ImageSkia* menu_marker_; 119 120 // If non-null the destuctor sets this to true. This is set while the menu is 121 // showing and used to detect if the menu was deleted while running. 122 bool* destroyed_flag_; 123 124 // The current number of "pressed" locks this button has. 125 int pressed_lock_count_; 126 127 base::WeakPtrFactory<MenuButton> weak_factory_; 128 129 DISALLOW_COPY_AND_ASSIGN(MenuButton); 130}; 131 132} // namespace views 133 134#endif // UI_VIEWS_CONTROLS_BUTTON_MENU_BUTTON_H_ 135