holding_space_view_delegate.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Copyright 2020 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. #ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_VIEW_DELEGATE_H_
  5. #define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_VIEW_DELEGATE_H_
  6. #include <memory>
  7. #include <string>
  8. #include <vector>
  9. #include "ash/ash_export.h"
  10. #include "ash/public/cpp/tablet_mode.h"
  11. #include "ash/public/cpp/tablet_mode_observer.h"
  12. #include "base/callback_list.h"
  13. #include "base/scoped_observation.h"
  14. #include "third_party/abseil-cpp/absl/types/optional.h"
  15. #include "ui/base/models/simple_menu_model.h"
  16. #include "ui/views/context_menu_controller.h"
  17. #include "ui/views/drag_controller.h"
  18. #include "ui/views/view.h"
  19. namespace ui {
  20. class GestureEvent;
  21. class KeyEvent;
  22. class MouseEvent;
  23. } // namespace ui
  24. namespace views {
  25. class MenuRunner;
  26. } // namespace views
  27. namespace ash {
  28. class HoldingSpaceItemView;
  29. class HoldingSpaceTrayBubble;
  30. // A delegate for holding space views which implements context menu,
  31. // drag-and-drop, and selection functionality. Only a single delegate instance
  32. // exists at a time and is shared by all existing holding space views in order
  33. // to support multiselection which requires a shared state.
  34. class ASH_EXPORT HoldingSpaceViewDelegate
  35. : public views::ContextMenuController,
  36. public views::DragController,
  37. public ui::SimpleMenuModel::Delegate,
  38. public TabletModeObserver {
  39. public:
  40. // A class which caches the current selection of holding space item views on
  41. // creation and restores that selection on destruction.
  42. class ScopedSelectionRestore {
  43. public:
  44. explicit ScopedSelectionRestore(HoldingSpaceViewDelegate* delegate);
  45. ScopedSelectionRestore(const ScopedSelectionRestore&) = delete;
  46. ScopedSelectionRestore& operator=(const ScopedSelectionRestore&) = delete;
  47. ~ScopedSelectionRestore();
  48. private:
  49. HoldingSpaceViewDelegate* const delegate_;
  50. std::vector<std::string> selected_item_ids_;
  51. absl::optional<std::string> selected_range_start_item_id_;
  52. absl::optional<std::string> selected_range_end_item_id_;
  53. };
  54. explicit HoldingSpaceViewDelegate(HoldingSpaceTrayBubble* bubble);
  55. HoldingSpaceViewDelegate(const HoldingSpaceViewDelegate&) = delete;
  56. HoldingSpaceViewDelegate& operator=(const HoldingSpaceViewDelegate&) = delete;
  57. ~HoldingSpaceViewDelegate() override;
  58. // Invoked when `view` has been created.
  59. void OnHoldingSpaceItemViewCreated(HoldingSpaceItemView* view);
  60. // Invoked when `view` is being destroyed.
  61. void OnHoldingSpaceItemViewDestroying(HoldingSpaceItemView* view);
  62. // Invoked when `view` should perform an accessible action. Returns true if
  63. // the action is handled, otherwise false.
  64. bool OnHoldingSpaceItemViewAccessibleAction(
  65. HoldingSpaceItemView* view,
  66. const ui::AXActionData& action_data);
  67. // Invoked when `view` receives the specified gesture `event`. If `true` is
  68. // returned, the `event` was fully handled and should stop propagating.
  69. bool OnHoldingSpaceItemViewGestureEvent(HoldingSpaceItemView* view,
  70. const ui::GestureEvent& event);
  71. // Invoked when `view` receives the specified key pressed `event`.
  72. bool OnHoldingSpaceItemViewKeyPressed(HoldingSpaceItemView* view,
  73. const ui::KeyEvent& event);
  74. // Invoked when `view` receives the specified mouse pressed `event`.
  75. bool OnHoldingSpaceItemViewMousePressed(HoldingSpaceItemView* view,
  76. const ui::MouseEvent& event);
  77. // Invoked when `view` receives the specified mouse released `event`.
  78. void OnHoldingSpaceItemViewMouseReleased(HoldingSpaceItemView* view,
  79. const ui::MouseEvent& event);
  80. // Invoked when the primary action for `view` is pressed.
  81. void OnHoldingSpaceItemViewPrimaryActionPressed(HoldingSpaceItemView* view);
  82. // Invoked when the secondary action for `view` is pressed.
  83. void OnHoldingSpaceItemViewSecondaryActionPressed(HoldingSpaceItemView* view);
  84. // Invoked when `view` has changed selected state.
  85. void OnHoldingSpaceItemViewSelectedChanged(HoldingSpaceItemView* view);
  86. // Invoked when the tray bubble receives the specified key pressed `event`.
  87. bool OnHoldingSpaceTrayBubbleKeyPressed(const ui::KeyEvent& event);
  88. // Invoked when a tray child bubble receives the specified gesture `event`.
  89. void OnHoldingSpaceTrayChildBubbleGestureEvent(const ui::GestureEvent& event);
  90. // Invoked when a tray child bubble receives the given mouse pressed `event`.
  91. void OnHoldingSpaceTrayChildBubbleMousePressed(const ui::MouseEvent& event);
  92. // Enumeration of possible selection UI's.
  93. enum class SelectionUi {
  94. kSingleSelect, // UI should reflect single selection.
  95. kMultiSelect, // UI should reflect multiple selection.
  96. };
  97. // Returns the current `selection_ui_` which dictates how UI should represent
  98. // holding space item views' selected states to the user.
  99. SelectionUi selection_ui() const { return selection_ui_; }
  100. // Registers a `callback` to be notified of changes to `selection_ui_`. To
  101. // unregister, destroy the returned subscription.
  102. base::RepeatingClosureList::Subscription AddSelectionUiChangedCallback(
  103. base::RepeatingClosureList::CallbackType callback);
  104. // Instructs the associated holding space tray to update its visibility. Note
  105. // that this may or may not result in a visibility change depending on state.
  106. void UpdateTrayVisibility();
  107. private:
  108. // views::ContextMenuController:
  109. void ShowContextMenuForViewImpl(views::View* source,
  110. const gfx::Point& point,
  111. ui::MenuSourceType source_type) override;
  112. // views::DragController:
  113. bool CanStartDragForView(views::View* sender,
  114. const gfx::Point& press_pt,
  115. const gfx::Point& current_pt) override;
  116. int GetDragOperationsForView(views::View* sender,
  117. const gfx::Point& press_pt) override;
  118. void WriteDragDataForView(views::View* sender,
  119. const gfx::Point& press_pt,
  120. ui::OSExchangeData* data) override;
  121. // SimpleMenuModel::Delegate:
  122. void ExecuteCommand(int command_id, int event_flags) override;
  123. // TabletModeObserver:
  124. void OnTabletModeStarted() override;
  125. void OnTabletModeEnded() override;
  126. // Builds and returns a raw pointer to `context_menu_model_`.
  127. ui::SimpleMenuModel* BuildMenuModel();
  128. // Returns the subset of views which are currently selected. Views are
  129. // returned in top-to-bottom, left-to-right order (or mirrored for RTL).
  130. std::vector<const HoldingSpaceItemView*> GetSelection();
  131. // Marks all views as unselected.
  132. void ClearSelection();
  133. // Marks `view` as selected. All other views are marked unselected.
  134. void SetSelection(HoldingSpaceItemView* view);
  135. // Marks any views whose associated holding space items are contained in
  136. // `item_ids` as selected. All other views are marked unselected.
  137. void SetSelection(const std::vector<std::string>& item_ids);
  138. // Marks any views between the specified `start` and `end` points (inclusive)
  139. // as selected. Any views in a previously selected range, as tracked by
  140. // `selected_range_start_` and `selected_range_end_`, will be marked as
  141. // unselected. Any views outside of these ranges will not be affected.
  142. void SetSelectedRange(HoldingSpaceItemView* start, HoldingSpaceItemView* end);
  143. // Updates `selection_ui_` based on device state and `selection_size_`.
  144. void UpdateSelectionUi();
  145. HoldingSpaceTrayBubble* const bubble_;
  146. std::unique_ptr<ui::SimpleMenuModel> context_menu_model_;
  147. std::unique_ptr<views::MenuRunner> context_menu_runner_;
  148. // Caches a view for which mouse released events should be temporarily
  149. // ignored. This is to prevent us from selecting a view on mouse pressed but
  150. // then unselecting that same view on mouse released.
  151. HoldingSpaceItemView* ignore_mouse_released_ = nullptr;
  152. // Caches views from which range-based selections should start and end. This
  153. // is used when determining the range for selection performed via shift-click.
  154. HoldingSpaceItemView* selected_range_start_ = nullptr;
  155. HoldingSpaceItemView* selected_range_end_ = nullptr;
  156. // Dictates how UI should represent holding space item views' selected states
  157. // to the user based on device state and `selection_size_`.
  158. SelectionUi selection_ui_;
  159. // List of callbacks to be run on changes to `selection_ui_`.
  160. base::RepeatingClosureList selection_ui_changed_callbacks_;
  161. // Cached size of the selection of holding space item views.
  162. size_t selection_size_ = 0u;
  163. base::ScopedObservation<TabletMode, TabletModeObserver> tablet_mode_observer_{
  164. this};
  165. };
  166. } // namespace ash
  167. #endif // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_VIEW_DELEGATE_H_