// 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 ASH_WM_OVERVIEW_BIRCH_BIRCH_BAR_CONTROLLER_H_
#define ASH_WM_OVERVIEW_BIRCH_BIRCH_BAR_CONTROLLER_H_
#include <vector>
#include "ash/ash_export.h"
#include "ash/birch/birch_model.h"
#include "ash/wm/overview/birch/birch_bar_constants.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "components/prefs/pref_change_registrar.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/point.h"
class PrefRegistrySimple;
namespace ash {
class BirchBarMenuModelAdapter;
class BirchBarView;
class BirchChipButton;
class BirchItem;
// The controller used to manage the birch bar in every `OverviewGrid`. It will
// fetch data from `BirchModel` and distribute the data to birch bars.
class ASH_EXPORT BirchBarController : public BirchModel::Observer,
public ui::SimpleMenuModel::Delegate {
public:
explicit BirchBarController(bool from_pine_service);
BirchBarController(const BirchBarController&) = delete;
BirchBarController& operator=(const BirchBarController&) = delete;
~BirchBarController() override;
// Gets the instance of the controller. It can be nullptr when the Overview
// session is shutting down.
static BirchBarController* Get();
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
// TODO(http://b/361326120): Temporary getter for the first bar view before
// the menu ownership is defined.
BirchBarView* primary_birch_bar_view() { return bar_views_.front(); }
// Register a bar view.
void RegisterBar(BirchBarView* bar_view);
// Called if the given `bar_view` is being destroyed.
void OnBarDestroying(BirchBarView* bar_view);
// Show a context menu for the chip which is right clicked by the user.
void ShowChipContextMenu(BirchChipButton* chip,
BirchSuggestionType chip_type,
const gfx::Point& point,
ui::MenuSourceType source_type);
// Called if a suggestion is hidden by user from context menu.
void OnItemHiddenByUser(BirchItem* item);
// Called if the user shows/hides the suggestions from context menu.
void SetShowBirchSuggestions(bool show);
// Gets if the user allows the suggestions to show.
bool GetShowBirchSuggestions() const;
// Called if the user shows/hides the given type of suggestions.
void SetShowSuggestionType(BirchSuggestionType type, bool show);
// Gets if the user allows to show the given type of suggestions.
bool GetShowSuggestionType(BirchSuggestionType type) const;
// Gets if the suggestion data loading is in progress.
bool IsDataLoading() const;
// Toggles temperature units for weather chip between F and C.
void ToggleTemperatureUnits();
// Executes the commands from bar and chip context menus. `from_chip` will be
// true if the command is from a chip context menu.
// Please note that most of the bar menu commands should be executed by the
// switch button and checkboxes, see `BirchBarMenuModelAdapter` for details.
// However, due to the way how `MenuController` processes gesture events, the
// submenu may close on touch such that switch button and checkbox callbacks
// are not triggered. To solve the issue, we make `SimpleMenuModel::Delegate`
// to execute the commands for switch button and checkboxes on touch event.
// This is not a normal usage. For more details, please see the bug comment in
// http://b/360072119.
void ExecuteMenuCommand(int command_id, bool from_chip);
// ui::SimpleMenuModel::Delegate:
void ExecuteCommand(int command_id, int event_flags) override;
BirchBarMenuModelAdapter* chip_menu_model_adapter_for_testing() {
return chip_menu_model_adapter_.get();
}
private:
friend class BirchBarMenuTest;
// Fetches data from birch model if there is no fetching in progress.
void MaybeFetchDataFromModel();
// Called when birch items are fetched from model or the fetching process
// timed out.
void OnItemsFetchedFromModel();
// initialize the given `bar_view` with the `items`.
void InitBarWithItems(BirchBarView* bar_view,
const std::vector<std::unique_ptr<BirchItem>>& items);
// Remove the chips corresponding to the given `item` from the bars and fill
// in the chips if there are extra items to show. Note that the `item` is not
// removed from `items_` list in this method.
void RemoveItemChips(BirchItem* item);
// Called when the context menu is closed.
void OnChipContextMenuClosed();
// BirchModel::Observer:
void OnBirchClientSet() override;
// Called when the show suggestions pref changes.
void OnShowSuggestionsPrefChanged();
// Called when the customize suggestion prefs change.
void OnCustomizeSuggestionsPrefChanged();
// Called when recevice a lost media item.
void OnLostMediaItemReceived();
// Called when the lost media is removed.
void OnLostMediaItemRemoved();
// Called when the lost media item is updated with the `updated_item`.
void OnLostMediaItemUpdated(std::unique_ptr<BirchItem> updated_item);
// Birch items fetched from model.
std::vector<std::unique_ptr<BirchItem>> items_;
std::unique_ptr<BirchBarMenuModelAdapter> chip_menu_model_adapter_;
std::vector<raw_ptr<BirchBarView>> bar_views_;
// Indicates if the data fetching is in progress.
bool data_fetch_in_progress_ = false;
// True if the overview session is an informed restore session.
const bool is_informed_restore_;
// Show/hide suggestions pref change registrar.
PrefChangeRegistrar show_suggestions_pref_registrar_;
// Customize suggestions pref change registrar.
PrefChangeRegistrar customize_suggestions_pref_registrar_;
// To avoid sending multiple data requests when reset suggestions, the
// variable is used as an indicator to block the data request from
// `OnCustomizeSuggestionsPrefChanged`.
bool hold_data_request_on_suggestion_pref_change_ = false;
base::ScopedObservation<BirchModel, BirchModel::Observer>
birch_model_observer_{this};
base::WeakPtrFactory<BirchBarController> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_WM_OVERVIEW_BIRCH_BIRCH_BAR_CONTROLLER_H_