| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_PINNED_TOOLBAR_ACTIONS_CONTAINER_H_ |
| #define CHROME_BROWSER_UI_VIEWS_TOOLBAR_PINNED_TOOLBAR_ACTIONS_CONTAINER_H_ |
| |
| #include <memory> |
| #include <optional> |
| #include <set> |
| #include <vector> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "chrome/browser/ui/toolbar/pinned_toolbar/pinned_toolbar_actions_model.h" |
| #include "chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.h" |
| #include "chrome/browser/ui/views/toolbar/toolbar_controller.h" |
| #include "chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h" |
| #include "ui/actions/action_id.h" |
| #include "ui/actions/actions.h" |
| #include "ui/base/metadata/metadata_header_macros.h" |
| #include "ui/views/drag_controller.h" |
| |
| class BrowserView; |
| class ToolbarButtonProvider; |
| |
| namespace views { |
| class ActionViewController; |
| } |
| |
| // Container for pinned and epheremeral actions shown in the toolbar. |
| // Pinned actions are tracked by `pinned_buttons_`. Ephemeral actions are |
| // tracked by `popped_out_buttons_`. Pinned actions are determined by listening |
| // to PinnedToolbarActionsModel. Ephemeral actions are determined by external |
| // callers via the methods UpdateActionState() and UpdateEphemeralAction(). |
| class PinnedToolbarActionsContainer |
| : public ToolbarIconContainerView, |
| public PinnedToolbarActionsModel::Observer, |
| public views::DragController, |
| public ToolbarController::PinnedActionsDelegate { |
| METADATA_HEADER(PinnedToolbarActionsContainer, ToolbarIconContainerView) |
| |
| public: |
| explicit PinnedToolbarActionsContainer( |
| BrowserView* browser_view, |
| ToolbarButtonProvider* button_provider); |
| PinnedToolbarActionsContainer(const PinnedToolbarActionsContainer&) = delete; |
| PinnedToolbarActionsContainer& operator=( |
| const PinnedToolbarActionsContainer&) = delete; |
| ~PinnedToolbarActionsContainer() override; |
| |
| // TODO(https://crbug.com/363743077): This method is almost but not quite |
| // identical to ShowActionEphemerallyInToolbar(). This doesn't make sense and |
| // one should be removed. |
| void UpdateActionState(actions::ActionId id, bool is_active); |
| // Updates whether the button is shown ephemerally in the toolbar (in the |
| // popped out region unless also pinned) regardless of whether it is active. |
| void ShowActionEphemerallyInToolbar(actions::ActionId id, bool show); |
| void UpdatePinnedStateAndAnnounce(actions::ActionId id, bool pin); |
| |
| void MovePinnedActionBy(actions::ActionId action_id, int delta); |
| |
| // ToolbarIconContainerView: |
| void UpdateAllIcons() override; |
| |
| // views::View: |
| void OnThemeChanged() override; |
| void AddedToWidget() override; |
| bool GetDropFormats(int* formats, |
| std::set<ui::ClipboardFormatType>* format_types) override; |
| bool AreDropTypesRequired() override; |
| bool CanDrop(const ui::OSExchangeData& data) override; |
| void OnDragEntered(const ui::DropTargetEvent& event) override; |
| int OnDragUpdated(const ui::DropTargetEvent& event) override; |
| void OnDragExited() override; |
| views::View::DropCallback GetDropCallback( |
| const ui::DropTargetEvent& event) override; |
| |
| // PinnedToolbarActionsModel::Observer: |
| void OnActionAddedLocally(actions::ActionId id) override; |
| void OnActionRemovedLocally(actions::ActionId id) override; |
| void OnActionsChanged() override; |
| |
| // views::DragController: |
| void WriteDragDataForView(View* sender, |
| const gfx::Point& press_pt, |
| ui::OSExchangeData* data) override; |
| int GetDragOperationsForView(View* sender, const gfx::Point& p) override; |
| bool CanStartDragForView(View* sender, |
| const gfx::Point& press_pt, |
| const gfx::Point& p) override; |
| |
| // ToolbarController::PinnedActionsDelegate: |
| actions::ActionItem* GetActionItemFor(actions::ActionId id) override; |
| bool IsOverflowed(actions::ActionId id) override; |
| views::View* GetContainerView() override; |
| bool ShouldAnyButtonsOverflow(gfx::Size available_size) const override; |
| |
| bool IsActionPinned(actions::ActionId id); |
| bool IsActionPoppedOut(actions::ActionId id); |
| bool IsActionPinnedOrPoppedOut(actions::ActionId id); |
| |
| // Returns the button associated with `id`. This does not return permanent |
| // buttons which are currently invisible, an accessor for these can be |
| // obtained on creation via `CreatePermanentButtonFor`. |
| PinnedActionToolbarButton* GetButtonFor(actions::ActionId id); |
| |
| // Removes the popped out button if it should no longer remain in the toolbar. |
| void MaybeRemovePoppedOutButtonFor(actions::ActionId id); |
| |
| // Ensures that if `id` is unpinned, the associated button object will not |
| // get destroyed. This is useful for features which need to maintain a |
| // persistent reference to the button. |
| PinnedActionToolbarButton* CreatePermanentButtonFor(actions::ActionId id); |
| |
| gfx::Size GetDefaultButtonSize() const; |
| |
| const std::vector<actions::ActionId>& PinnedActionIds() const override; |
| |
| base::WeakPtr<PinnedToolbarActionsContainer> GetWeakPtrForTesting() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| private: |
| friend class PinnedSidePanelInteractiveTest; |
| friend class PinnedToolbarActionsContainerTest; |
| |
| // A struct representing the position and action being dragged. |
| struct DropInfo; |
| class BrowserObserver; |
| |
| PinnedActionToolbarButton* AddPoppedOutButtonFor(actions::ActionId id); |
| void AddPinnedActionButtonFor(actions::ActionId id); |
| void RemovePinnedActionButtonFor(actions::ActionId id); |
| PinnedActionToolbarButton* GetPinnedButtonFor(actions::ActionId id); |
| PinnedActionToolbarButton* GetPoppedOutButtonFor(actions::ActionId id); |
| bool ShouldRemainPoppedOutInToolbar(PinnedActionToolbarButton* button); |
| // Returns the size based on the layout manager's default flex specification. |
| gfx::Size DefaultFlexRule(const views::SizeBounds& size_bounds); |
| // Returns the total width of the `popped_out_buttons_` including margins |
| // between them. |
| int CalculatePoppedOutButtonsWidth(); |
| |
| // Sorts child views to display them in the correct order. |
| void ReorderViews(); |
| |
| // Updates the container view to match the current state of the model. |
| void UpdateViews(); |
| |
| void RemoveButton(PinnedActionToolbarButton* button); |
| void SetActionButtonIconVisibility(actions::ActionId id, bool visible); |
| |
| // Moves the dragged action `action_id`. |
| void MovePinnedAction( |
| actions::ActionId action_id, |
| size_t index, |
| base::ScopedClosureRunner cleanup, |
| const ui::DropTargetEvent& event, |
| ui::mojom::DragOperation& output_drag_op, |
| std::unique_ptr<ui::LayerTreeOwner> drag_image_layer_owner); |
| |
| std::unique_ptr<PinnedActionToolbarButton> CreateOrGetButtonForAction( |
| actions::ActionId id); |
| |
| // Performs clean up after dragging. |
| void DragDropCleanup(actions::ActionId dragged_action_id); |
| |
| // Utility function for going from width to icon counts. |
| size_t WidthToIconCount(int x_offset); |
| |
| const std::unique_ptr<BrowserObserver> browser_observer_; |
| raw_ptr<BrowserView> browser_view_; |
| raw_ptr<ToolbarButtonProvider> button_provider_; |
| |
| std::unique_ptr<views::ActionViewController> action_view_controller_; |
| std::vector<raw_ptr<PinnedActionToolbarButton, VectorExperimental>> |
| pinned_buttons_; |
| std::vector<raw_ptr<PinnedActionToolbarButton, VectorExperimental>> |
| popped_out_buttons_; |
| std::vector<std::unique_ptr<PinnedActionToolbarButton>> permanent_buttons_; |
| raw_ptr<views::View> toolbar_divider_; |
| raw_ptr<PinnedToolbarActionsModel> model_; |
| |
| base::ScopedObservation<PinnedToolbarActionsModel, |
| PinnedToolbarActionsModel::Observer> |
| model_observation_{this}; |
| |
| // The DropInfo for the current drag-and-drop operation, or a null pointer if |
| // there is none. |
| std::unique_ptr<DropInfo> drop_info_; |
| |
| base::WeakPtrFactory<PinnedToolbarActionsContainer> weak_ptr_factory_{this}; |
| |
| base::WeakPtrFactory<PinnedToolbarActionsContainer> drop_weak_ptr_factory_{ |
| this}; |
| }; |
| |
| #endif // CHROME_BROWSER_UI_VIEWS_TOOLBAR_PINNED_TOOLBAR_ACTIONS_CONTAINER_H_ |