// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_STYLE_TAB_SLIDER_H_
#define ASH_STYLE_TAB_SLIDER_H_
#include <cstddef>
#include <utility>
#include "ash/ash_export.h"
#include "base/memory/raw_ptr.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/layout/table_layout_view.h"
namespace ash {
class TabSliderButton;
// A tab slider has multiple slider buttons placed horizontally in a button
// container. At any time, only one of the buttons can be selected. Selecting a
// button will deselect all the other buttons. A selector painted with a fully
// rounded rectangle shows behind the selected button. When another button is
// selected, the selector will move from the position of previously selected
// button to the position of currently selected button.
class ASH_EXPORT TabSlider : public views::TableLayoutView {
METADATA_HEADER(TabSlider, views::TableLayoutView)
public:
// The init parameters used to initialize the layout, appearance, and behavior
// of the tab slider.
struct InitParams {
int internal_border_padding;
int between_buttons_spacing;
// Indicates whether there is a fully rounded rect background for the tab
// slider.
bool has_background;
// Indicates whether an animation should be shown when the selector moves
// between buttons.
bool has_selector_animation;
// Indicates whether the extra space should be distributed evenly between
// buttons.
bool distribute_space_evenly;
};
static constexpr InitParams kDefaultParams = {2, 0, true, true, true};
// `max_tab_num` is the maximum number of tabs in the slider.
explicit TabSlider(size_t max_tab_num,
const InitParams& params = kDefaultParams);
TabSlider(const TabSlider&) = delete;
TabSlider& operator=(const TabSlider&) = delete;
~TabSlider() override;
views::View* GetSelectorView();
TabSliderButton* GetButtonAtIndex(size_t index);
// Add a button with the button's unique pointer. For example
// AddButton(std::make_unique<SliderButtonType>(...)).
template <typename T>
T* AddButton(std::unique_ptr<T> button) {
T* button_ptr = button.get();
AddButtonInternal(button.release());
return button_ptr;
}
// Add a button with the button's ctor arguments. For example
// AddButton<SliderButtonType>(arg1, arg2, ...).
template <typename T, typename... Args>
T* AddButton(Args&&... args) {
auto button = std::make_unique<T>(std::forward<Args>(args)...);
return AddButton(std::move(button));
}
// Called when a button is selected.
void OnButtonSelected(TabSliderButton* button);
// views::View:
void Layout(PassKey) override;
private:
// The view of the selector.
class SelectorView;
// Initialize the layout according to the total number of tabs and init
// parameters.
void Init();
// Adds the button as a child of the button container and inserts it into the
// 'buttons_' list.
void AddButtonInternal(TabSliderButton* button);
// Called when the enabled state is changed.
void OnEnabledStateChanged();
const size_t max_tab_num_;
const InitParams params_;
// Owned by view hierarchy.
raw_ptr<SelectorView> selector_view_;
std::vector<raw_ptr<TabSliderButton, VectorExperimental>> buttons_;
base::CallbackListSubscription enabled_changed_subscription_;
};
} // namespace ash
#endif // ASH_STYLE_TAB_SLIDER_H_