Commit af6570ea authored by David Black's avatar David Black Committed by Chromium LUCI CQ

Implement animate in/out of holding space child bubbles.

Holding space child bubbles animate out when their sections no longer
have finalized items to display. They animate in when at least one of
their sections becomes populated.

Bug: 1154998
Change-Id: I2d4bc1dc27346aa085c7d12e373d5618639926a1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2606667
Commit-Queue: David Black <dmblack@google.com>
Reviewed-by: default avatarToni Baržić <tbarzic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#839711}
parent 0e7d7a98
...@@ -27,6 +27,10 @@ void HoldingSpaceModel::AddItems( ...@@ -27,6 +27,10 @@ void HoldingSpaceModel::AddItems(
std::vector<const HoldingSpaceItem*> item_ptrs; std::vector<const HoldingSpaceItem*> item_ptrs;
for (std::unique_ptr<HoldingSpaceItem>& item : items) { for (std::unique_ptr<HoldingSpaceItem>& item : items) {
DCHECK(!GetItem(item->id())); DCHECK(!GetItem(item->id()));
if (item->IsFinalized())
++finalized_item_counts_by_type_[item->type()];
item_ptrs.push_back(item.get()); item_ptrs.push_back(item.get());
items_.push_back(std::move(item)); items_.push_back(std::move(item));
} }
...@@ -64,6 +68,8 @@ void HoldingSpaceModel::FinalizeOrRemoveItem(const std::string& id, ...@@ -64,6 +68,8 @@ void HoldingSpaceModel::FinalizeOrRemoveItem(const std::string& id,
DCHECK(!item->IsFinalized()); DCHECK(!item->IsFinalized());
item->Finalize(file_system_url); item->Finalize(file_system_url);
++finalized_item_counts_by_type_[item->type()];
for (auto& observer : observers_) for (auto& observer : observers_)
observer.OnHoldingSpaceItemFinalized(item); observer.OnHoldingSpaceItemFinalized(item);
} }
...@@ -99,6 +105,9 @@ void HoldingSpaceModel::RemoveIf(Predicate predicate) { ...@@ -99,6 +105,9 @@ void HoldingSpaceModel::RemoveIf(Predicate predicate) {
item_ptrs.push_back(item.get()); item_ptrs.push_back(item.get());
items.push_back(std::move(item)); items.push_back(std::move(item));
items_.erase(items_.begin() + i); items_.erase(items_.begin() + i);
if (item_ptrs.back()->IsFinalized())
--finalized_item_counts_by_type_[item_ptrs.back()->type()];
} }
} }
...@@ -116,6 +125,8 @@ void HoldingSpaceModel::RemoveAll() { ...@@ -116,6 +125,8 @@ void HoldingSpaceModel::RemoveAll() {
ItemList items; ItemList items;
items.swap(items_); items.swap(items_);
finalized_item_counts_by_type_.clear();
std::vector<const HoldingSpaceItem*> item_ptrs; std::vector<const HoldingSpaceItem*> item_ptrs;
for (auto& item : items) for (auto& item : items)
item_ptrs.push_back(item.get()); item_ptrs.push_back(item.get());
...@@ -156,6 +167,12 @@ bool HoldingSpaceModel::ContainsItem(HoldingSpaceItem::Type type, ...@@ -156,6 +167,12 @@ bool HoldingSpaceModel::ContainsItem(HoldingSpaceItem::Type type,
return GetItem(type, file_path) != nullptr; return GetItem(type, file_path) != nullptr;
} }
bool HoldingSpaceModel::ContainsFinalizedItemOfType(
HoldingSpaceItem::Type type) const {
auto it = finalized_item_counts_by_type_.find(type);
return it != finalized_item_counts_by_type_.end() && it->second > 0u;
}
void HoldingSpaceModel::AddObserver(HoldingSpaceModelObserver* observer) { void HoldingSpaceModel::AddObserver(HoldingSpaceModelObserver* observer) {
observers_.AddObserver(observer); observers_.AddObserver(observer);
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef ASH_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_MODEL_H_ #ifndef ASH_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_MODEL_H_
#define ASH_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_MODEL_H_ #define ASH_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_MODEL_H_
#include <map>
#include <memory> #include <memory>
#include <set> #include <set>
#include <string> #include <string>
...@@ -85,6 +86,10 @@ class ASH_PUBLIC_EXPORT HoldingSpaceModel { ...@@ -85,6 +86,10 @@ class ASH_PUBLIC_EXPORT HoldingSpaceModel {
bool ContainsItem(HoldingSpaceItem::Type type, bool ContainsItem(HoldingSpaceItem::Type type,
const base::FilePath& file_path) const; const base::FilePath& file_path) const;
// Returns true if the model contains any finalized items of the specified
// `type`, false otherwise.
bool ContainsFinalizedItemOfType(HoldingSpaceItem::Type type) const;
const ItemList& items() const { return items_; } const ItemList& items() const { return items_; }
void AddObserver(HoldingSpaceModelObserver* observer); void AddObserver(HoldingSpaceModelObserver* observer);
...@@ -95,6 +100,11 @@ class ASH_PUBLIC_EXPORT HoldingSpaceModel { ...@@ -95,6 +100,11 @@ class ASH_PUBLIC_EXPORT HoldingSpaceModel {
// the model. // the model.
ItemList items_; ItemList items_;
// Caches the count of finalized items in the model for each holding space
// item type. Used to quickly look up whether the model contains any finalized
// items of a given type.
std::map<HoldingSpaceItem::Type, size_t> finalized_item_counts_by_type_;
base::ObserverList<HoldingSpaceModelObserver> observers_; base::ObserverList<HoldingSpaceModelObserver> observers_;
}; };
......
...@@ -9,11 +9,10 @@ ...@@ -9,11 +9,10 @@
#include "ash/public/cpp/holding_space/holding_space_model.h" #include "ash/public/cpp/holding_space/holding_space_model.h"
#include "ash/system/holding_space/holding_space_item_view.h" #include "ash/system/holding_space/holding_space_item_view.h"
#include "ash/system/holding_space/holding_space_item_view_delegate.h" #include "ash/system/holding_space/holding_space_item_view_delegate.h"
#include "ash/system/holding_space/holding_space_util.h"
#include "base/auto_reset.h" #include "base/auto_reset.h"
#include "ui/compositor/callback_layer_animation_observer.h" #include "ui/compositor/callback_layer_animation_observer.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h" #include "ui/compositor/layer_animator.h"
#include "ui/views/controls/scroll_view.h" #include "ui/views/controls/scroll_view.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout.h"
...@@ -39,61 +38,6 @@ void InitLayerForAnimations(views::View* view) { ...@@ -39,61 +38,6 @@ void InitLayerForAnimations(views::View* view) {
ui::LayerAnimator::PreemptionStrategy::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); ui::LayerAnimator::PreemptionStrategy::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
} }
// Creates a `ui::LayerAnimationSequence` for the specified `element` with
// optional `delay`, observed by the specified `observer`.
std::unique_ptr<ui::LayerAnimationSequence> CreateObservedSequence(
std::unique_ptr<ui::LayerAnimationElement> element,
base::TimeDelta delay,
ui::LayerAnimationObserver* observer) {
auto sequence = std::make_unique<ui::LayerAnimationSequence>();
if (!delay.is_zero()) {
sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement(
element->properties(), delay));
}
sequence->AddElement(std::move(element));
sequence->AddObserver(observer);
return sequence;
}
// Animates the specified `view` to a target `opacity` with the specified
// `duration` and optional `delay`, associating `observer` with the created
// animation sequences.
void DoAnimateTo(views::View* view,
float opacity,
base::TimeDelta duration,
base::TimeDelta delay,
ui::LayerAnimationObserver* observer) {
// Opacity animation.
auto opacity_element =
ui::LayerAnimationElement::CreateOpacityElement(opacity, duration);
opacity_element->set_tween_type(gfx::Tween::Type::LINEAR);
// Note that the `ui::LayerAnimator` takes ownership of any animation
// sequences so they need to be released.
view->layer()->GetAnimator()->StartAnimation(
CreateObservedSequence(std::move(opacity_element), delay, observer)
.release());
}
// Animates in the specified `view` with the specified `duration` and optional
// `delay`, associating `observer` with the created animation sequences.
void DoAnimateIn(views::View* view,
base::TimeDelta duration,
base::TimeDelta delay,
ui::LayerAnimationObserver* observer) {
view->layer()->SetOpacity(0.f);
DoAnimateTo(view, /*opacity=*/1.f, duration, delay, observer);
}
// Animates out the specified `view` with the specified `duration, associating
// `observer` with the created animation sequences.
void DoAnimateOut(views::View* view,
base::TimeDelta duration,
ui::LayerAnimationObserver* observer) {
DoAnimateTo(view, /*opacity=*/0.f, duration, /*delay=*/base::TimeDelta(),
observer);
}
// Returns a callback which deletes the associated animation observer after // Returns a callback which deletes the associated animation observer after
// running another `callback`. // running another `callback`.
using AnimationCompletedCallback = using AnimationCompletedCallback =
...@@ -173,7 +117,7 @@ class HoldingSpaceScrollView : public views::ScrollView, ...@@ -173,7 +117,7 @@ class HoldingSpaceScrollView : public views::ScrollView,
HoldingSpaceItemViewsSection::HoldingSpaceItemViewsSection( HoldingSpaceItemViewsSection::HoldingSpaceItemViewsSection(
HoldingSpaceItemViewDelegate* delegate, HoldingSpaceItemViewDelegate* delegate,
std::vector<HoldingSpaceItem::Type> supported_types, std::set<HoldingSpaceItem::Type> supported_types,
const base::Optional<size_t>& max_count) const base::Optional<size_t>& max_count)
: delegate_(delegate), : delegate_(delegate),
supported_types_(std::move(supported_types)), supported_types_(std::move(supported_types)),
...@@ -231,11 +175,15 @@ void HoldingSpaceItemViewsSection::Init() { ...@@ -231,11 +175,15 @@ void HoldingSpaceItemViewsSection::Init() {
// Views. // Views.
HoldingSpaceModel* model = HoldingSpaceController::Get()->model(); HoldingSpaceModel* model = HoldingSpaceController::Get()->model();
if (model) { if (model && !model->items().empty()) {
std::vector<const HoldingSpaceItem*> item_ptrs;
for (const auto& item : model->items())
item_ptrs.push_back(item.get());
// Sections are not animated during initialization as their respective // Sections are not animated during initialization as their respective
// bubbles will be animated in instead. // bubbles will be animated in instead.
base::AutoReset<bool> scoped_disable_animations(&disable_animations_, true); base::AutoReset<bool> scoped_disable_animations(&disable_animations_, true);
OnHoldingSpaceModelAttached(model); OnHoldingSpaceItemsAdded(item_ptrs);
} }
// Re-enable propagation of `PreferredSizeChanged()` after initializing. // Re-enable propagation of `PreferredSizeChanged()` after initializing.
...@@ -304,22 +252,6 @@ void HoldingSpaceItemViewsSection::ViewHierarchyChanged( ...@@ -304,22 +252,6 @@ void HoldingSpaceItemViewsSection::ViewHierarchyChanged(
PreferredSizeChanged(); PreferredSizeChanged();
} }
void HoldingSpaceItemViewsSection::OnHoldingSpaceModelAttached(
HoldingSpaceModel* model) {
std::vector<const HoldingSpaceItem*> item_ptrs;
for (const auto& item : model->items())
item_ptrs.push_back(item.get());
if (!item_ptrs.empty())
OnHoldingSpaceItemsAdded(item_ptrs);
}
void HoldingSpaceItemViewsSection::OnHoldingSpaceModelDetached(
HoldingSpaceModel* model) {
if (!container_->children().empty())
MaybeAnimateOut();
}
void HoldingSpaceItemViewsSection::OnHoldingSpaceItemsAdded( void HoldingSpaceItemViewsSection::OnHoldingSpaceItemsAdded(
const std::vector<const HoldingSpaceItem*>& items) { const std::vector<const HoldingSpaceItem*>& items) {
const bool needs_update = std::any_of( const bool needs_update = std::any_of(
...@@ -347,6 +279,15 @@ void HoldingSpaceItemViewsSection::OnHoldingSpaceItemFinalized( ...@@ -347,6 +279,15 @@ void HoldingSpaceItemViewsSection::OnHoldingSpaceItemFinalized(
MaybeAnimateOut(); MaybeAnimateOut();
} }
void HoldingSpaceItemViewsSection::RemoveAllHoldingSpaceItemViews() {
// Holding space item views should only be removed when the `container_` is
// not visible to the user.
DCHECK(!IsDrawn() || !container_->IsDrawn() ||
container_->layer()->opacity() == 0.f);
container_->RemoveAllChildViews(/*delete_children=*/true);
views_by_item_id_.clear();
}
std::unique_ptr<views::View> HoldingSpaceItemViewsSection::CreatePlaceholder() { std::unique_ptr<views::View> HoldingSpaceItemViewsSection::CreatePlaceholder() {
return nullptr; return nullptr;
} }
...@@ -420,15 +361,19 @@ void HoldingSpaceItemViewsSection::AnimateIn( ...@@ -420,15 +361,19 @@ void HoldingSpaceItemViewsSection::AnimateIn(
// If the `header_` is not opaque, this section was not previously visible // If the `header_` is not opaque, this section was not previously visible
// to the user so the `header_` needs to be animated in alongside any content. // to the user so the `header_` needs to be animated in alongside any content.
const bool animate_in_header = header_->layer()->GetTargetOpacity() != 1.f; const bool animate_in_header = header_->layer()->GetTargetOpacity() != 1.f;
if (animate_in_header) if (animate_in_header) {
DoAnimateIn(header_, animation_duration, animation_delay, observer); holding_space_util::AnimateIn(header_, animation_duration, animation_delay,
observer);
}
if (views_by_item_id_.empty() && placeholder_) { if (views_by_item_id_.empty() && placeholder_) {
DoAnimateIn(placeholder_, animation_duration, animation_delay, observer); holding_space_util::AnimateIn(placeholder_, animation_duration,
animation_delay, observer);
return; return;
} }
DoAnimateIn(container_, animation_duration, animation_delay, observer); holding_space_util::AnimateIn(container_, animation_duration, animation_delay,
observer);
} }
void HoldingSpaceItemViewsSection::AnimateOut( void HoldingSpaceItemViewsSection::AnimateOut(
...@@ -446,25 +391,24 @@ void HoldingSpaceItemViewsSection::AnimateOut( ...@@ -446,25 +391,24 @@ void HoldingSpaceItemViewsSection::AnimateOut(
if (animate_out_header) { if (animate_out_header) {
HoldingSpaceModel* model = HoldingSpaceController::Get()->model(); HoldingSpaceModel* model = HoldingSpaceController::Get()->model();
if (model) { if (model) {
animate_out_header = animate_out_header = std::none_of(
std::none_of(model->items().begin(), model->items().end(), supported_types_.begin(), supported_types_.end(),
[this](const auto& item) { [&model](HoldingSpaceItem::Type supported_type) {
return item->IsFinalized() && return model->ContainsFinalizedItemOfType(supported_type);
base::Contains(supported_types_, item->type()); });
});
} }
} }
if (animate_out_header) if (animate_out_header)
DoAnimateOut(header_, animation_duration, observer); holding_space_util::AnimateOut(header_, animation_duration, observer);
if (placeholder_ && placeholder_->GetVisible()) { if (placeholder_ && placeholder_->GetVisible()) {
DCHECK(views_by_item_id_.empty()); DCHECK(views_by_item_id_.empty());
DoAnimateOut(placeholder_, animation_duration, observer); holding_space_util::AnimateOut(placeholder_, animation_duration, observer);
return; return;
} }
DoAnimateOut(container_, animation_duration, observer); holding_space_util::AnimateOut(container_, animation_duration, observer);
} }
void HoldingSpaceItemViewsSection::OnAnimateInCompleted( void HoldingSpaceItemViewsSection::OnAnimateInCompleted(
...@@ -514,11 +458,7 @@ void HoldingSpaceItemViewsSection::OnAnimateOutCompleted( ...@@ -514,11 +458,7 @@ void HoldingSpaceItemViewsSection::OnAnimateOutCompleted(
}, },
base::Unretained(this))); base::Unretained(this)));
if (!container_->children().empty()) { RemoveAllHoldingSpaceItemViews();
container_->RemoveAllChildViews(/*delete_children=*/true);
views_by_item_id_.clear();
}
DCHECK(views_by_item_id_.empty()); DCHECK(views_by_item_id_.empty());
HoldingSpaceModel* model = HoldingSpaceController::Get()->model(); HoldingSpaceModel* model = HoldingSpaceController::Get()->model();
......
...@@ -27,15 +27,13 @@ namespace ash { ...@@ -27,15 +27,13 @@ namespace ash {
class HoldingSpaceItemView; class HoldingSpaceItemView;
class HoldingSpaceItemViewDelegate; class HoldingSpaceItemViewDelegate;
class HoldingSpaceModel;
// A section of holding space item views in a `HoldingSpaceTrayChildBubble`. // A section of holding space item views in a `HoldingSpaceTrayChildBubble`.
class HoldingSpaceItemViewsSection : public views::View { class HoldingSpaceItemViewsSection : public views::View {
public: public:
HoldingSpaceItemViewsSection( HoldingSpaceItemViewsSection(HoldingSpaceItemViewDelegate* delegate,
HoldingSpaceItemViewDelegate* delegate, std::set<HoldingSpaceItem::Type> supported_types,
std::vector<HoldingSpaceItem::Type> supported_types, const base::Optional<size_t>& max_count);
const base::Optional<size_t>& max_count);
HoldingSpaceItemViewsSection(const HoldingSpaceItemViewsSection& other) = HoldingSpaceItemViewsSection(const HoldingSpaceItemViewsSection& other) =
delete; delete;
HoldingSpaceItemViewsSection& operator=( HoldingSpaceItemViewsSection& operator=(
...@@ -56,15 +54,29 @@ class HoldingSpaceItemViewsSection : public views::View { ...@@ -56,15 +54,29 @@ class HoldingSpaceItemViewsSection : public views::View {
void PreferredSizeChanged() override; void PreferredSizeChanged() override;
void ViewHierarchyChanged(const views::ViewHierarchyChangedDetails&) override; void ViewHierarchyChanged(const views::ViewHierarchyChangedDetails&) override;
// `HoldingSpaceControllerObserver` and `HoldingSpaceModelObserver` events // `HoldingSpaceModelObserver` events forwarded from the parent
// forwarded from the parent `HoldingSpaceTrayChildBubble`. Events may be // `HoldingSpaceTrayChildBubble`. Note that events may be withheld from this
// withheld from this view if, for example, its parent is animating out. // view if, for example, its parent is animating out.
void OnHoldingSpaceModelAttached(HoldingSpaceModel* model);
void OnHoldingSpaceModelDetached(HoldingSpaceModel* model);
void OnHoldingSpaceItemsAdded(const std::vector<const HoldingSpaceItem*>&); void OnHoldingSpaceItemsAdded(const std::vector<const HoldingSpaceItem*>&);
void OnHoldingSpaceItemsRemoved(const std::vector<const HoldingSpaceItem*>&); void OnHoldingSpaceItemsRemoved(const std::vector<const HoldingSpaceItem*>&);
void OnHoldingSpaceItemFinalized(const HoldingSpaceItem* item); void OnHoldingSpaceItemFinalized(const HoldingSpaceItem* item);
// Removes all holding space item views from this section. This method is
// expected to only be called:
// * from the parent `HoldingSpaceTrayChildBubble` when this view is hidden.
// * internally after having animated out the `container_` just prior to
// swapping in new contents.
void RemoveAllHoldingSpaceItemViews();
// Returns whether this section has a placeholder to show in lieu of item
// views when the model contains no finalized items of supported types.
bool has_placeholder() const { return !!placeholder_; }
// Returns the types of holding space items supported by this section.
const std::set<HoldingSpaceItem::Type>& supported_types() const {
return supported_types_;
}
protected: protected:
// Invoked to create the `header_` for this section. // Invoked to create the `header_` for this section.
virtual std::unique_ptr<views::View> CreateHeader() = 0; virtual std::unique_ptr<views::View> CreateHeader() = 0;
...@@ -117,7 +129,7 @@ class HoldingSpaceItemViewsSection : public views::View { ...@@ -117,7 +129,7 @@ class HoldingSpaceItemViewsSection : public views::View {
void OnAnimateOutCompleted(const ui::CallbackLayerAnimationObserver&); void OnAnimateOutCompleted(const ui::CallbackLayerAnimationObserver&);
HoldingSpaceItemViewDelegate* const delegate_; HoldingSpaceItemViewDelegate* const delegate_;
const std::vector<HoldingSpaceItem::Type> supported_types_; const std::set<HoldingSpaceItem::Type> supported_types_;
const base::Optional<size_t> max_count_; const base::Optional<size_t> max_count_;
// Owned by view hierarchy. // Owned by view hierarchy.
......
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
#include "base/scoped_observation.h" #include "base/scoped_observation.h"
#include "ui/views/view.h" #include "ui/views/view.h"
namespace ui {
class LayerAnimationObserver;
} // namespace ui
namespace ash { namespace ash {
class HoldingSpaceItemViewDelegate; class HoldingSpaceItemViewDelegate;
...@@ -64,17 +68,37 @@ class HoldingSpaceTrayChildBubble : public views::View, ...@@ -64,17 +68,37 @@ class HoldingSpaceTrayChildBubble : public views::View,
void ChildPreferredSizeChanged(views::View* child) override; void ChildPreferredSizeChanged(views::View* child) override;
void ChildVisibilityChanged(views::View* child) override; void ChildVisibilityChanged(views::View* child) override;
// Invoked to animate in/out this view if necessary.
void MaybeAnimateIn();
void MaybeAnimateOut();
// Invoked to animate in/out this view. These methods should only be called
// from `MaybeAnimateIn()`/`MaybeAnimateOut()` respectively as those methods
// contain gating criteria for when these methods may be invoked.
void AnimateIn(ui::LayerAnimationObserver* observer);
void AnimateOut(ui::LayerAnimationObserver* observer);
// Invoked when an in/out animation has completed. If `aborted` is true,
// the animation was cancelled and did not animation to target end values.
void OnAnimateInCompleted(bool aborted);
void OnAnimateOutCompleted(bool aborted);
HoldingSpaceItemViewDelegate* const delegate_; HoldingSpaceItemViewDelegate* const delegate_;
// Views owned by view hierarchy. // Views owned by view hierarchy.
std::vector<HoldingSpaceItemViewsSection*> sections_; std::vector<HoldingSpaceItemViewsSection*> sections_;
// Whether or not this view is currently being animated out.
bool is_animating_out_ = false;
base::ScopedObservation<HoldingSpaceController, base::ScopedObservation<HoldingSpaceController,
HoldingSpaceControllerObserver> HoldingSpaceControllerObserver>
controller_observer_{this}; controller_observer_{this};
base::ScopedObservation<HoldingSpaceModel, HoldingSpaceModelObserver> base::ScopedObservation<HoldingSpaceModel, HoldingSpaceModelObserver>
model_observer_{this}; model_observer_{this};
base::WeakPtrFactory<HoldingSpaceTrayChildBubble> weak_factory_{this};
}; };
} // namespace ash } // namespace ash
......
...@@ -5,11 +5,76 @@ ...@@ -5,11 +5,76 @@
#include "ash/system/holding_space/holding_space_util.h" #include "ash/system/holding_space/holding_space_util.h"
#include "ash/style/ash_color_provider.h" #include "ash/style/ash_color_provider.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
#include "ui/views/controls/label.h" #include "ui/views/controls/label.h"
namespace ash { namespace ash {
namespace holding_space_util { namespace holding_space_util {
namespace {
// Helpers ---------------------------------------------------------------------
// Creates a `ui::LayerAnimationSequence` for the specified `element` with
// optional `delay`, observed by the specified `observer`.
std::unique_ptr<ui::LayerAnimationSequence> CreateObservedSequence(
std::unique_ptr<ui::LayerAnimationElement> element,
base::TimeDelta delay,
ui::LayerAnimationObserver* observer) {
auto sequence = std::make_unique<ui::LayerAnimationSequence>();
if (!delay.is_zero()) {
sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement(
element->properties(), delay));
}
sequence->AddElement(std::move(element));
sequence->AddObserver(observer);
return sequence;
}
// Animates the specified `view` to a target `opacity` with the specified
// `duration` and optional `delay`, associating `observer` with the created
// animation sequences.
void AnimateTo(views::View* view,
float opacity,
base::TimeDelta duration,
base::TimeDelta delay,
ui::LayerAnimationObserver* observer) {
// Opacity animation.
auto opacity_element =
ui::LayerAnimationElement::CreateOpacityElement(opacity, duration);
opacity_element->set_tween_type(gfx::Tween::Type::LINEAR);
// Note that the `ui::LayerAnimator` takes ownership of any animation
// sequences so they need to be released.
view->layer()->GetAnimator()->StartAnimation(
CreateObservedSequence(std::move(opacity_element), delay, observer)
.release());
}
} // namespace
// Animates in the specified `view` with the specified `duration` and optional
// `delay`, associating `observer` with the created animation sequences.
void AnimateIn(views::View* view,
base::TimeDelta duration,
base::TimeDelta delay,
ui::LayerAnimationObserver* observer) {
view->layer()->SetOpacity(0.f);
AnimateTo(view, /*opacity=*/1.f, duration, delay, observer);
}
// Animates out the specified `view` with the specified `duration, associating
// `observer` with the created animation sequences.
void AnimateOut(views::View* view,
base::TimeDelta duration,
ui::LayerAnimationObserver* observer) {
AnimateTo(view, /*opacity=*/0.f, duration, /*delay=*/base::TimeDelta(),
observer);
}
std::unique_ptr<views::Label> CreateLabel(LabelStyle style, std::unique_ptr<views::Label> CreateLabel(LabelStyle style,
const base::string16& text) { const base::string16& text) {
auto label = std::make_unique<views::Label>(text); auto label = std::make_unique<views::Label>(text);
......
...@@ -6,14 +6,33 @@ ...@@ -6,14 +6,33 @@
#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_UTIL_H_ #define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_UTIL_H_
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/time/time.h"
namespace ui {
class LayerAnimationObserver;
} // namespace ui
namespace views { namespace views {
class Label; class Label;
class View;
} // namespace views } // namespace views
namespace ash { namespace ash {
namespace holding_space_util { namespace holding_space_util {
// Animates in the specified `view` with the specified `duration` and optional
// `delay`, associating `observer` with the created animation sequences.
void AnimateIn(views::View* view,
base::TimeDelta duration,
base::TimeDelta delay,
ui::LayerAnimationObserver* observer);
// Animates out the specified `view` with the specified `duration, associating
// `observer` with the created animation sequences.
void AnimateOut(views::View* view,
base::TimeDelta duration,
ui::LayerAnimationObserver* observer);
// Enumeration of supported label styles. // Enumeration of supported label styles.
enum class LabelStyle { enum class LabelStyle {
kBadge, kBadge,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment