blob: 3b380b56363ef7f268fb4b81e58b0e3ac373fd14 [file]
// Copyright 2025 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_TABS_VERTICAL_TAB_COLLECTION_NODE_H_
#define CHROME_BROWSER_UI_VIEWS_TABS_VERTICAL_TAB_COLLECTION_NODE_H_
#include <memory>
#include <string>
#include <vector>
#include "base/callback_list.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/types/pass_key.h"
#include "components/tabs/public/tab_collection.h"
#include "components/tabs/public/tab_collection_types.h"
#include "ui/gfx/geometry/rect.h"
namespace views {
class View;
}
class VerticalTabStripController;
// The individual collection node of the view model. The root
// node also inherits from this class. It provides extensibility hooks for the
// views to use to implement things like animations.
class TabCollectionNode {
public:
// Keep the same as TabCollection::Type with a tab.
// LINT.IfChange(TYPE)
enum class Type { TABSTRIP, PINNED, UNPINNED, GROUP, SPLIT, TAB };
// LINT.ThenChange(components/tabs/public/tab_collection.h:TYPE)
// Helper type for creating CustomAddChildViewCallbacks with
// base::BindRepeating.
typedef views::View* (views::View::*CustomAddChildView)(
std::unique_ptr<views::View>);
typedef base::RepeatingCallback<views::View*(std::unique_ptr<views::View>)>
CustomAddChildViewCallback;
typedef base::RepeatingCallback<void(views::View* view_to_remove)>
CustomRemoveChildViewCallback;
typedef base::RepeatingCallback<void(std::unique_ptr<views::View>,
const gfx::Rect&)>
CustomAttachChildViewCallback;
typedef base::RepeatingCallback<std::unique_ptr<views::View>(views::View*)>
CustomDetachChildViewCallback;
typedef std::vector<std::unique_ptr<TabCollectionNode>> NodeChildren;
explicit TabCollectionNode(tabs::ConstChildPtr node_data);
virtual ~TabCollectionNode();
// Creates the view for this node. Then, for each child container in children,
// creates a TabCollectionNode, calls Initialize on it, and then adds the node
// as a child of this.
std::unique_ptr<views::View> Initialize();
// Deinitializes all the child nodes in a recursive manner.
void Deinitialize();
// Gets the collection under this subtree that has the associated handle.
// Returns nullptr if no such node exists.
TabCollectionNode* GetNodeForHandle(
const tabs::TabCollectionNodeHandle& handle);
const TabCollectionNode* GetNodeForHandle(
const tabs::TabCollectionNodeHandle& handle) const;
TabCollectionNode* GetParentNodeForHandle(
const tabs::TabCollectionNodeHandle& handle);
const TabCollectionNode* GetParentNodeForHandle(
const tabs::TabCollectionNodeHandle& handle) const;
// Gets the first direct child of this node that has the associated type.
// Returns nullptr if no such node exists.
TabCollectionNode* GetChildNodeOfType(const Type type);
// Creates a new child and adds it at model_index. If |perform_initialization|
// is true, then the entire subtree of the node data will be constructed as
// well, if not, then only the view for the child is constructed and added.
void AddNewChild(base::PassKey<TabCollectionNode> pass_key,
tabs::ConstChildPtr node_data,
size_t model_index,
bool perform_initialization);
// Removes the child and removes and destroys the view.
void RemoveChild(base::PassKey<TabCollectionNode> pass_key,
const tabs::TabCollectionNodeHandle& handle,
bool perform_deinitialization);
// Moves the node to the new index within the same parent. Also updates the
// z-order of the moved child to the highest to ensure it shows over other
// tabs when animating.
void MoveChild(base::PassKey<TabCollectionNode> pass_key,
const tabs::TabCollectionNodeHandle& handle,
int new_index);
// Moves the node to the new index across different parent nodes.
static void MoveChild(base::PassKey<TabCollectionNode> pass_key,
const tabs::TabCollectionNodeHandle& handle,
int new_index,
TabCollectionNode* src_parent_node,
TabCollectionNode* dst_parent_node);
tabs::ConstChildPtr GetNodeData() const { return node_data_; }
tabs::TabCollectionNodeHandle GetHandle() const;
Type type() const { return type_; }
const NodeChildren& children() const { return children_; }
views::View* view() const { return node_view_; }
std::vector<views::View*> GetDirectChildren() const;
void set_add_child_to_node(CustomAddChildViewCallback add_child_to_node) {
add_child_to_node_ = std::move(add_child_to_node);
}
void set_remove_child_from_node(
CustomRemoveChildViewCallback remove_child_from_node) {
remove_child_from_node_ = std::move(remove_child_from_node);
}
void set_attach_child_to_node(
CustomAttachChildViewCallback attach_child_to_node) {
attach_child_to_node_ = std::move(attach_child_to_node);
}
void set_detach_child_from_node(
CustomDetachChildViewCallback detach_child_from_node) {
detach_child_from_node_ = std::move(detach_child_from_node);
}
base::CallbackListSubscription RegisterWillDestroyCallback(
base::OnceClosure callback);
base::CallbackListSubscription RegisterDataChangedCallback(
base::RepeatingClosure callback);
void NotifyDataChanged();
void SetController(VerticalTabStripController* controller);
VerticalTabStripController* GetController() { return tab_strip_controller_; }
const VerticalTabStripController* GetController() const {
return tab_strip_controller_;
}
protected:
// Returns the pass key to be used by derived classes so that methods such as
// SetData may only be performed by a `TabCollectionNode`.
base::PassKey<TabCollectionNode> GetPassKey() const {
return base::PassKey<TabCollectionNode>();
}
static std::unique_ptr<views::View> CreateViewForNode(
TabCollectionNode* node_for_view);
// Adds `child_node` to `children_`.
void AddChildNode(std::unique_ptr<TabCollectionNode> child_node,
size_t model_index);
// Creates node_view_, then returns the unique_ptr to the view.
std::unique_ptr<views::View> CreateAndSetView();
// Updates the focus order of the child view at the specified `child_index`.
// This ensures that follows the logical order of the tab collection by
// re-linking the view's focus neighbors based on its current position in the
// children list.
void EnsureFocusOrder(size_t child_index);
base::OnceClosureList on_will_destroy_callback_list_;
base::RepeatingClosureList on_data_changed_callback_list_;
const Type type_;
const tabs::TabCollectionNodeHandle handle_;
tabs::ConstChildPtr node_data_;
// 1:1 mapping of the collections children.
NodeChildren children_;
// add_child_to_node_ must be assigned when constructing the node_view in
// Initialize so that the children that are created know how to be added to
// the View Hierarchy. Used when the default AddChildView behavior needs to be
// overridden.
CustomAddChildViewCallback add_child_to_node_;
// Custom callback to remove a child view, used when the default
// RemoveChildViewT behavior needs to be overridden if the view hierarchy does
// not match the view model hierarchy.
CustomRemoveChildViewCallback remove_child_from_node_;
// Custom callback invoked when reparent an existing view as child to another
// container. Used when the default AddChildView behavior needs to be
// overridden.
CustomAttachChildViewCallback attach_child_to_node_;
// Custom callback invoked when reparent an existing view as child to another
// container. Used when the default RemoveChildViewT behavior needs to be
// overridden.
CustomDetachChildViewCallback detach_child_from_node_;
// The view created for this node. (for tab:tabview, for unpinned: the
// unpinned_container_view).
raw_ptr<views::View> node_view_ = nullptr;
// Allows views to create the Tab Context Menu.
raw_ptr<VerticalTabStripController> tab_strip_controller_ = nullptr;
};
#endif // CHROME_BROWSER_UI_VIEWS_TABS_VERTICAL_TAB_COLLECTION_NODE_H_