chromium/ash/game_dashboard/game_dashboard_button.h

// 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 ASH_GAME_DASHBOARD_GAME_DASHBOARD_BUTTON_H_
#define ASH_GAME_DASHBOARD_GAME_DASHBOARD_BUTTON_H_

#include "base/memory/raw_ptr.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/controls/button/button.h"

namespace views {
class ImageView;
class InkDropContainerView;
class Label;
class View;
}  // namespace views

namespace ash {

// The main button for the Game Dashboard, which acts as an entry point for
// features in GameDashboardMainMenuView.
//
// The button looks like:
// +-----------+-------+-----------+
// | icon_view | label | icon_view |
// +-----------+-------+-----------+
//
// There are 2 states: Default and Recording
//
// The 'Default' button indicates an idle Game Dashboard menu. Clicking on
// the button will toggle the `GameDashboardMainMenuView`, where the Recording
// Game tile is in the default state.
//
// The 'Recording' button state indicates that the game window is being
// recorded, which is shown after a user has initiated a game window recording.
// The label view is updated to show a count up timer, representing the
// duration, and "Recording" as its status. Clicking on the button will toggle
// the `GameDashboardMainMenuView`, where the Recording Game tile allows the
// user to stop the recording.
//
// The first "icon_view" always shows the gamepad icon.
// The second "icon_view" shows an up or down arrow. Calling `SetToggled()` with
// true will replace the second "icon_view" with an the up arrow. Called with
// false, it will show the down arrow.
class GameDashboardButton : public views::Button {
  METADATA_HEADER(GameDashboardButton, views::Button)

 public:
  explicit GameDashboardButton(PressedCallback callback);
  GameDashboardButton(const GameDashboardButton&) = delete;
  GameDashboardButton& operator=(const GameDashboardButton&) = delete;
  ~GameDashboardButton() override;

  bool is_recording() const { return is_recording_; }

  bool toggled() const { return toggled_; }

  // Updates the `toggled_` state of the button.
  void SetToggled(bool toggled);

  // Called when the game window recording has started.
  void OnRecordingStarted();

  // Called when the game window recording has ended.
  void OnRecordingEnded();

  // Updates `title_view_`'s text with `duration`.
  void UpdateRecordingDuration(const std::u16string& duration);

  // views::View:
  void AddedToWidget() override;
  void ChildPreferredSizeChanged(views::View* child) override;
  void OnThemeChanged() override;
  void AddLayerToRegion(ui::Layer* new_layer,
                        views::LayerRegion region) override;
  void RemoveLayerFromRegions(ui::Layer* old_layer) override;

  // views::Button:
  void StateChanged(ButtonState old_state) override;

 private:
  friend class GameDashboardContextTestApi;

  // Updates the icon in `arrow_icon_view_`. If `toggled_` is true, it'll show
  // the up arrow, otherwise the down arrow.
  void UpdateArrowIcon();

  // Updates `is_recording_` with `is_recording`, then updates all the views.
  void UpdateRecordingState(bool is_recording);

  // Updates all the views in the button. If `is_recording_` is true, the
  // UI is updated to show the 'Recording' button, indicating that there's an
  // active video recording session. Otherwise, it will show the 'Default'
  // button. Make sure this is called after this view is added to a widget.
  void UpdateViews();

  // Sets the `title_view` and the tooltip text to `title_text`.
  void SetTitle(const std::u16string& title_text);

  // Owned by views hierarchy.
  raw_ptr<views::ImageView> gamepad_icon_view_;
  raw_ptr<views::Label> title_view_;
  raw_ptr<views::ImageView> arrow_icon_view_;
  // Ensures the ink drop is painted above the button's background.
  raw_ptr<views::InkDropContainerView> ink_drop_container_ = nullptr;

  // If true, the game window is being recorded, otherwise false.
  bool is_recording_ = false;

  // The button toggle state.
  bool toggled_ = false;
};

}  // namespace ash

#endif  // ASH_GAME_DASHBOARD_GAME_DASHBOARD_BUTTON_H_