1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_VIEWS_CONTROLS_BUTTON_MENU_BUTTON_CONTROLLER_H_
#define UI_VIEWS_CONTROLS_BUTTON_MENU_BUTTON_CONTROLLER_H_
#include <memory>
#include <utility>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "ui/views/controls/button/button_controller.h"
namespace views {
class ButtonControllerDelegate;
class MenuButton;
// A controller that contains the logic for showing a menu when the left mouse
// is pushed.
class VIEWS_EXPORT MenuButtonController : public ButtonController {
public:
// A scoped lock for keeping the MenuButton in STATE_PRESSED e.g., while a
// menu is running. These are cumulative.
class VIEWS_EXPORT PressedLock {
public:
explicit PressedLock(MenuButtonController* menu_button_controller);
// |event| is the event that caused the button to be pressed. May be null.
PressedLock(MenuButtonController* menu_button_controller,
bool is_sibling_menu_show,
const ui::LocatedEvent* event);
PressedLock(const PressedLock&) = delete;
PressedLock& operator=(const PressedLock&) = delete;
~PressedLock();
private:
base::WeakPtr<MenuButtonController> menu_button_controller_;
};
MenuButtonController(Button* button,
Button::PressedCallback callback,
std::unique_ptr<ButtonControllerDelegate> delegate);
MenuButtonController(const MenuButtonController&) = delete;
MenuButtonController& operator=(const MenuButtonController&) = delete;
~MenuButtonController() override;
// view::ButtonController
bool OnMousePressed(const ui::MouseEvent& event) override;
void OnMouseReleased(const ui::MouseEvent& event) override;
void OnMouseMoved(const ui::MouseEvent& event) override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
bool OnKeyPressed(const ui::KeyEvent& event) override;
bool OnKeyReleased(const ui::KeyEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
void UpdateButtonAccessibleDefaultActionVerb() override;
bool IsTriggerableEvent(const ui::Event& event) override;
void NotifyClick() override;
// Calls TakeLock with is_sibling_menu_show as false and a nullptr to the
// event.
std::unique_ptr<PressedLock> TakeLock();
// Convenience method to increment the lock count on a button to keep the
// button in a PRESSED state when a menu is showing.
std::unique_ptr<PressedLock> TakeLock(bool is_sibling_menu_show,
const ui::LocatedEvent* event);
// Activate the button (called when the button is pressed). |event| is the
// event triggering the activation, if any.
bool Activate(const ui::Event* event);
// Returns true if the event is of the proper type to potentially trigger an
// action. Since MenuButtons have properties other than event type (like
// last menu open time) to determine if an event is valid to activate the
// menu, this is distinct from IsTriggerableEvent().
bool IsTriggerableEventType(const ui::Event& event);
void SetCallback(Button::PressedCallback callback) {
callback_ = std::move(callback);
}
private:
// Increment/decrement the number of "pressed" locks this button has, and
// set the state accordingly. The ink drop is snapped to the final ACTIVATED
// state if |snap_ink_drop_to_activated| is true, otherwise the ink drop
// will be animated to the ACTIVATED node_data. The ink drop is animated at
// the location of |event| if non-null, otherwise at the default location.
void IncrementPressedLocked(bool snap_ink_drop_to_activated,
const ui::LocatedEvent* event);
void DecrementPressedLocked();
// Called if the button state changes while pressed lock is engaged.
void OnButtonStateChangedWhilePressedLocked();
// Our callback.
Button::PressedCallback callback_;
// We use a time object in order to keep track of when the menu was closed.
// The time is used for simulating menu behavior for the menu button; that
// is, if the menu is shown and the button is pressed, we need to close the
// menu. There is no clean way to get the second click event because the
// menu is displayed using a modal loop and, unlike regular menus in
// Windows, the button is not part of the displayed menu.
base::TimeTicks menu_closed_time_;
// Tracks if the current triggering event should open a menu.
bool is_intentional_menu_trigger_ = true;
// The current number of "pressed" locks this button has.
int pressed_lock_count_ = 0;
// Used to let Activate() know if IncrementPressedLocked() was called.
raw_ptr<bool> increment_pressed_lock_called_ = nullptr;
// True if the button was in a disabled state when a menu was run, and
// should return to it once the press is complete. This can happen if, e.g.,
// we programmatically show a menu on a disabled button.
bool should_disable_after_press_ = false;
// Subscribes to state changes on the button while pressed lock is engaged.
base::CallbackListSubscription state_changed_subscription_;
base::WeakPtrFactory<MenuButtonController> weak_factory_{this};
};
} // namespace views
#endif // UI_VIEWS_CONTROLS_BUTTON_MENU_BUTTON_CONTROLLER_H_
|