blob: bfe6c20e1212422a0b1abfc25d45c8b1b5801e10 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEWS_SECTION_H_
#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEWS_SECTION_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "ash/public/cpp/holding_space/holding_space_controller.h"
#include "ash/public/cpp/holding_space/holding_space_controller_observer.h"
#include "ash/public/cpp/holding_space/holding_space_item.h"
#include "ash/public/cpp/holding_space/holding_space_model.h"
#include "ash/public/cpp/holding_space/holding_space_model_observer.h"
#include "base/optional.h"
#include "base/scoped_observation.h"
#include "ui/views/view.h"
namespace ui {
class CallbackLayerAnimationObserver;
class LayerAnimationObserver;
} // namespace ui
namespace ash {
class HoldingSpaceItemView;
class HoldingSpaceItemViewDelegate;
// A section of holding space item views in a `HoldingSpaceTrayChildBubble`.
class HoldingSpaceItemViewsSection : public views::View,
public HoldingSpaceControllerObserver,
public HoldingSpaceModelObserver {
public:
HoldingSpaceItemViewsSection(
HoldingSpaceItemViewDelegate* delegate,
std::vector<HoldingSpaceItem::Type> supported_types,
const base::Optional<size_t>& max_count);
HoldingSpaceItemViewsSection(const HoldingSpaceItemViewsSection& other) =
delete;
HoldingSpaceItemViewsSection& operator=(
const HoldingSpaceItemViewsSection& other) = delete;
~HoldingSpaceItemViewsSection() override;
// Initializes the section.
void Init();
// Resets the section. Called when the tray bubble starts closing to stop
// observing the holding space controller/model to ensure that no new items
// are created while the bubble widget is being asynchronously closed.
void Reset();
// views::View:
void ChildPreferredSizeChanged(views::View* child) override;
void ChildVisibilityChanged(views::View* child) override;
void ViewHierarchyChanged(const views::ViewHierarchyChangedDetails&) override;
// HoldingSpaceControllerObserver:
void OnHoldingSpaceModelAttached(HoldingSpaceModel* model) override;
void OnHoldingSpaceModelDetached(HoldingSpaceModel* model) override;
// HoldingSpaceModelObserver:
void OnHoldingSpaceItemsAdded(
const std::vector<const HoldingSpaceItem*>& items) override;
void OnHoldingSpaceItemsRemoved(
const std::vector<const HoldingSpaceItem*>& items) override;
void OnHoldingSpaceItemFinalized(const HoldingSpaceItem* item) override;
protected:
// Invoked to create the `header_` for this section.
virtual std::unique_ptr<views::View> CreateHeader() = 0;
// Invoked to create the `container_` for this section which parents its
// holding space item views.
virtual std::unique_ptr<views::View> CreateContainer() = 0;
// Invoked to create the view for the specified holding space `item`. Note
// that the created view will be parented by `container_`.
virtual std::unique_ptr<HoldingSpaceItemView> CreateView(
const HoldingSpaceItem* item) = 0;
// Invoked to create the `placeholder_` for this section which shows when
// `container_` is empty. The `placeholder_` can be destroyed via call to
// `DestroyPlaceholder()` if it is no longer needed to exist.
virtual std::unique_ptr<views::View> CreatePlaceholder();
// Invoked to destroy `placeholder_`.
void DestroyPlaceholder();
HoldingSpaceItemViewDelegate* delegate() { return delegate_; }
private:
enum AnimationState : uint32_t {
kNotAnimating = 0,
kAnimatingIn = 1 << 1,
kAnimatingOut = 1 << 2,
};
// Invoke to start animating in the contents of this section. No-ops if
// animate in is already in progress.
void MaybeAnimateIn();
// Invoke to start animating out the contents of this section. No-ops if
// animate out is already in progress.
void MaybeAnimateOut();
// Invoked to animate in the contents of this section. Any created animation
// sequences must be observed by `observer`.
void AnimateIn(ui::LayerAnimationObserver* observer);
// Invoked to animate out the contents of this section. Any created animation
// sequences must be observed by `observer`.
void AnimateOut(ui::LayerAnimationObserver* observer);
// Invoked when an animate in/out of the contents of this section has been
// completed. Note that the provided observer will be deleted after returning.
void OnAnimateInCompleted(const ui::CallbackLayerAnimationObserver&);
void OnAnimateOutCompleted(const ui::CallbackLayerAnimationObserver&);
HoldingSpaceItemViewDelegate* const delegate_;
const std::vector<HoldingSpaceItem::Type> supported_types_;
const base::Optional<size_t> max_count_;
// Owned by view hierarchy.
views::View* header_ = nullptr;
views::View* container_ = nullptr;
views::View* placeholder_ = nullptr;
std::map<std::string, HoldingSpaceItemView*> views_by_item_id_;
// Bit flag representation of current `AnimationState`. Note that it is
// briefly possible to be both `kAnimatingIn` and `kAnimatingOut` when one
// animation is preempting another.
uint32_t animation_state_ = AnimationState::kNotAnimating;
// Whether or not animations are disabled. Animations are only disabled during
// initialization as holding space child bubbles are animated in instead.
bool disable_animations_ = false;
base::ScopedObservation<HoldingSpaceController,
HoldingSpaceControllerObserver>
controller_observer_{this};
base::ScopedObservation<HoldingSpaceModel, HoldingSpaceModelObserver>
model_observer_{this};
base::WeakPtrFactory<HoldingSpaceItemViewsSection> weak_factory_{this};
};
} // namespace ash
#endif // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEWS_SECTION_H_