blob: 81504534ec0a01d8213c32c6a5df2641ed6a6dcb [file] [log] [blame]
// Copyright 2024 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_GLIC_BUTTON_H_
#define CHROME_BROWSER_UI_VIEWS_TABS_GLIC_BUTTON_H_
#include "base/memory/raw_ptr.h"
#include "chrome/browser/glic/browser_ui/glic_button_controller_delegate.h"
#include "chrome/browser/ui/views/tabs/tab_strip_controller.h"
#include "chrome/browser/ui/views/tabs/tab_strip_nudge_button.h"
#include "chrome/common/buildflags.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/vector_icon_types.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#if BUILDFLAG(ENABLE_GLIC)
#include "chrome/browser/glic/fre/glic_fre.mojom.h"
#endif // BUILDFLAG(ENABLE_GLIC)
class BrowserWindowInterface;
class PrefService;
namespace glic {
// GlicButton should leverage the look and feel of the existing
// TabSearchButton for sizing and appropriate theming.
class GlicButton : public TabStripNudgeButton,
public views::ContextMenuController,
public ui::SimpleMenuModel::Delegate {
METADATA_HEADER(GlicButton, TabStripNudgeButton)
public:
explicit GlicButton(TabStripController* tab_strip_controller,
PressedCallback pressed_callback,
PressedCallback close_pressed_callback,
base::RepeatingClosure hovered_callback,
base::RepeatingClosure mouse_down_callback,
base::RepeatingClosure expansion_animation_done_callback,
const std::u16string& tooltip);
GlicButton(const GlicButton&) = delete;
GlicButton& operator=(const GlicButton&) = delete;
~GlicButton() override;
static GlicButton* FromBrowser(BrowserWindowInterface* browser);
void SetNudgeLabel(std::string label);
void RestoreDefaultLabel();
void SetGlicPanelIsOpen(bool open);
// Update button for glic attachment state.
void SetGlicDetached(bool detached);
// TabStripNudgeButton:
void SetIsShowingNudge(bool is_showing) override;
void SetDropToAttachIndicator(bool indicate);
// GetBoundsInScreen() gives a rect with some padding that extends beyond the
// visible edges of the button. This function returns a rect without that
// padding.
gfx::Rect GetBoundsWithInset() const;
// TabStripControlButton:
gfx::Size CalculatePreferredSize(
const views::SizeBounds& available_size) const override;
void StateChanged(ButtonState old_state) override;
void AddedToWidget() override;
// views::ContextMenuController:
void ShowContextMenuForViewImpl(
View* source,
const gfx::Point& point,
ui::mojom::MenuSourceType source_type) override;
// ui::SimpleMenuModel::Delegate:
void ExecuteCommand(int command_id, int event_flags) override;
// views::View:
// Note that this is an optimization for fetching zero-state suggestions so
// that we can load the suggestions in the UI as quickly as possible.
bool OnMousePressed(const ui::MouseEvent& event) override;
// gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override;
void AnimationEnded(const gfx::Animation* animation) override;
void AnimationCanceled(const gfx::Animation* animation) override;
bool IsContextMenuShowingForTest();
// Sets the button back to its default colors.
void SetDefaultColors();
// Called when the slide animation finishes.
void OnAnimationEnded();
gfx::SlideAnimation* GetExpansionAnimationForTesting() override;
bool GetLabelEnabledForTesting() const;
private:
// views::LabelButton:
void SetText(std::u16string_view text) override;
// Creates the model for the context menu.
std::unique_ptr<ui::SimpleMenuModel> CreateMenuModel();
// Callback when the context menu closes.
void OnMenuClosed();
// Called every time the contextual cue is shown to make a screen reader
// announcement.
void AnnounceNudgeShown();
PrefService* profile_prefs() {
return tab_strip_controller_->GetProfile()->GetPrefs();
}
void UpdateTextAndBackgroundColors();
void UpdateIcon();
bool IsHighlightVisible() const;
void CreateIconAndLabelContainer();
void SetCloseButtonVisible(bool visible);
void StartShowAnimation();
void StartHideAnimation();
void ApplyTextAndFadeIn(std::optional<std::u16string> text,
base::TimeDelta delay,
base::TimeDelta duration);
void MaybeFadeHighlightOnHover(float final_opacity);
void StartExpansionAnimations(bool show,
base::TimeDelta overall_duration,
base::TimeDelta close_button_fade_start,
base::TimeDelta close_button_fade_duration);
int CalculateExpandedWidth();
#if BUILDFLAG(ENABLE_GLIC)
void PanelStateChanged(bool active);
void OnFreWebUiStateChanged(mojom::FreWebUiState new_state);
// Used to update the tooltip text when the showing states of the Glic
// window/FRE change.
void UpdateTooltipText();
// Callback subscription for listening to changes to the Glic window
// activation changes.
base::CallbackListSubscription glic_window_activation_subscription_;
// Callback subscription for listening to changes to the FRE WebUI state.
base::CallbackListSubscription fre_subscription_;
#endif // BUILDFLAG(ENABLE_GLIC)
// The model adapter for the context menu.
std::unique_ptr<views::MenuModelAdapter> menu_model_adapter_;
// Model for the context menu.
std::unique_ptr<ui::MenuModel> menu_model_;
// Used to ensure the button remains highlighted while the menu is active.
std::optional<Button::ScopedAnchorHighlight> menu_anchor_higlight_;
// Menu runner for the context menu.
std::unique_ptr<views::MenuRunner> menu_runner_;
// Tab strip that contains this button.
raw_ptr<TabStripController> tab_strip_controller_;
// Callback which is invoked when the button is hovered (i.e., the user is
// more likely to interact with it soon).
base::RepeatingClosure hovered_callback_;
// Callback which is invoked when there is a mouse down event on the button
// (i.e., the user is very likely to interact with it soon).
base::RepeatingClosure mouse_down_callback_;
// Invoked when the button hide animation finishes.
base::RepeatingClosure expansion_animation_done_callback_;
// Cached widths for animating label changes.
int initial_width_ = 0;
int expanded_width_ = 0;
// View to be drawn behind the icon and label with a background color.
raw_ptr<View> highlight_view_ = nullptr;
// Container view for the icon and label, and the highlight drawn behind them.
raw_ptr<View> icon_label_highlight_view_ = nullptr;
// If GlicEntrypointVariations is enabled, this animation is responsible for
// changing the button width when the nudge is shown.
std::unique_ptr<gfx::SlideAnimation> expansion_animation_;
// Holds the incoming nudge text until the point in the animation when it can
// be applied.
std::optional<std::u16string> pending_text_;
const ui::ImageModel normal_icon_;
const ui::ImageModel icon_for_highlight_;
bool glic_panel_is_open_ = false;
base::WeakPtrFactory<GlicButton> weak_ptr_factory_{this};
};
} // namespace glic
#endif // CHROME_BROWSER_UI_VIEWS_TABS_GLIC_BUTTON_H_