blob: 5d6908f96fd04b0fdc31c3e0523b86e4efe6d0be [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 CHROME_BROWSER_UI_VIEWS_FLYING_INDICATOR_H_
#define CHROME_BROWSER_UI_VIEWS_FLYING_INDICATOR_H_
#include "base/callback.h"
#include "base/scoped_observation.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/multi_animation.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
namespace gfx {
struct VectorIcon;
}
namespace views {
class View;
}
// Shows a flying indicator with an icon that takes a curved path from a
// starting position to a target view. This can be used to indicate a link
// opening in the background, an item flying to the downloads tray, etc.
//
// The indicator is a bubble with a fixed trajectory curve that fades in, cannot
// be interacted with, flies to the target, and fades out.
class FlyingIndicator : public views::WidgetObserver,
public gfx::AnimationDelegate {
public:
~FlyingIndicator() override;
// Play a flying indicator with |icon| from |start| position to the center of
// view |target|. When the indicator is finished flying (and has started
// fading out), or if the flying indicator is destroyed for any reason (e.g.
// the target view has disappeared), |done_callback| is called.
//
// Note that the flying indicator will still be fading out for a small period
// of time after |done_callback| is called, so do not immediately destroy the
// indicator object.
//
// If the returned object is freed, destroying the flying indicator
// externally, the indicator disappears immediately and |done_callback| is
// *not* called.
static std::unique_ptr<FlyingIndicator> StartFlyingIndicator(
const gfx::VectorIcon& icon,
const gfx::Point& start,
views::View* target,
base::OnceClosure done_callback);
bool is_flying() const {
return animation_.is_animating() && animation_.current_part_index() <= 1U;
}
private:
FlyingIndicator(const gfx::VectorIcon& icon,
const gfx::Point& start,
views::View* target,
base::OnceClosure done_callback);
// gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override;
void AnimationEnded(const gfx::Animation* animation) override;
// views::WidgetObserver:
void OnWidgetDestroyed(views::Widget* widget) override;
const gfx::Point start_;
const views::View* const target_;
gfx::Size bubble_size_;
gfx::MultiAnimation animation_;
base::OnceClosure done_callback_;
views::Widget* widget_ = nullptr;
base::ScopedObservation<views::Widget, views::WidgetObserver>
scoped_observation_{this};
};
#endif // CHROME_BROWSER_UI_VIEWS_FLYING_INDICATOR_H_