Commit 25fd04e6 authored by Alex Newcomer's avatar Alex Newcomer Committed by Commit Bot

cros: Fade in HTML render when it is ready

Bug: 1112441
Change-Id: If5ea1d536313885fde79f407346db8715789c6ae
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2406681Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Xiyuan Xia <xiyuan@chromium.org>
Auto-Submit: Alex Newcomer <newcomer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#807109}
parent 0bf08388
......@@ -130,7 +130,7 @@ views::MenuItemView* ClipboardHistoryMenuModelAdapter::AppendMenuItem(
std::unique_ptr<ClipboardHistoryItemView> item_view =
ClipboardHistoryItemView::CreateFromClipboardHistoryItem(
GetItemFromCommandId(command_id), *resource_manager_, container);
GetItemFromCommandId(command_id), resource_manager_, container);
item_view->Init();
container->AddChildView(std::move(item_view));
......
......@@ -160,6 +160,14 @@ base::string16 ClipboardHistoryResourceManager::GetLabel(
}
}
void ClipboardHistoryResourceManager::AddObserver(Observer* observer) const {
observers_.AddObserver(observer);
}
void ClipboardHistoryResourceManager::RemoveObserver(Observer* observer) const {
observers_.RemoveObserver(observer);
}
ClipboardHistoryResourceManager::CachedImageModel::CachedImageModel() = default;
ClipboardHistoryResourceManager::CachedImageModel::CachedImageModel(
......@@ -177,8 +185,15 @@ void ClipboardHistoryResourceManager::CacheImageModel(
ui::ImageModel image_model) {
auto cached_image_model = base::ConstCastIterator(
cached_image_models_, FindCachedImageModelForId(id));
if (cached_image_model != cached_image_models_.end())
cached_image_model->image_model = std::move(image_model);
if (cached_image_model == cached_image_models_.end())
return;
cached_image_model->image_model = std::move(image_model);
for (auto& observer : observers_) {
observer.OnCachedImageModelUpdated(
cached_image_model->clipboard_history_item_ids);
}
}
std::vector<ClipboardHistoryResourceManager::CachedImageModel>::const_iterator
......
......@@ -10,6 +10,8 @@
#include "ash/ash_export.h"
#include "ash/clipboard/clipboard_history.h"
#include "ash/clipboard/clipboard_history_item.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/strings/string16.h"
#include "base/unguessable_token.h"
#include "ui/base/models/image_model.h"
......@@ -19,6 +21,14 @@ namespace ash {
class ASH_EXPORT ClipboardHistoryResourceManager
: public ClipboardHistory::Observer {
public:
class Observer : public base::CheckedObserver {
public:
// Called when the CachedImageModel that corresponds with 'menu_item_ids'
// has been updated.
virtual void OnCachedImageModelUpdated(
const std::vector<base::UnguessableToken>& menu_item_ids) = 0;
};
explicit ClipboardHistoryResourceManager(
const ClipboardHistory* clipboard_history);
ClipboardHistoryResourceManager(const ClipboardHistoryResourceManager&) =
......@@ -33,10 +43,8 @@ class ASH_EXPORT ClipboardHistoryResourceManager
// Returns the label to display for the specified clipboard history |item|.
base::string16 GetLabel(const ClipboardHistoryItem& item) const;
// Returns the main format of the specified clipboard history |item|. Note
// that one `ClipboardHistoryItem` instance may own multiple formats.
ui::ClipboardInternalFormat CalculateMainFormat(
const ClipboardHistoryItem& item) const;
void AddObserver(Observer* observer) const;
void RemoveObserver(Observer* observer) const;
private:
struct CachedImageModel {
......@@ -80,6 +88,10 @@ class ASH_EXPORT ClipboardHistoryResourceManager
// Image used when the cached ImageModel has not yet been generated.
ui::ImageModel placeholder_image_model_;
// Mutable to allow adding/removing from |observers_| through a const
// ClipboardHistoryResourceManager.
mutable base::ObserverList<Observer> observers_;
base::WeakPtrFactory<ClipboardHistoryResourceManager> weak_factory_{this};
};
......
......@@ -5,13 +5,21 @@
#include "ash/clipboard/views/clipboard_history_bitmap_item_view.h"
#include "ash/clipboard/clipboard_history_item.h"
#include "ash/clipboard/clipboard_history_resource_manager.h"
#include "ash/clipboard/clipboard_history_util.h"
#include "base/time/time.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view_class_properties.h"
namespace ash {
namespace {
// The preferred height for the bitmap.
......@@ -20,9 +28,108 @@ constexpr int kBitmapHeight = 64;
// The margins of the delete button.
constexpr gfx::Insets kDeleteButtonMargins =
gfx::Insets(/*top=*/4, /*left=*/0, /*bottom=*/0, /*right=*/4);
} // namespace
namespace ash {
// The duration of the fade out animation for transitioning the placeholder
// image to rendered HTML.
constexpr base::TimeDelta kFadeOutDurationMs =
base::TimeDelta::FromMilliseconds(60);
// The duration of the fade in animation for transitioning the placeholder image
// to rendered HTML.
constexpr base::TimeDelta kFadeInDurationMs =
base::TimeDelta::FromMilliseconds(200);
////////////////////////////////////////////////////////////////////////////////
// FadeImageView
// An ImageView which reacts to updates from ClipboardHistoryResourceManager by
// fading out the old image, and fading in the new image. Used when HTML is done
// rendering. Only expected to transition once in its lifetime.
class FadeImageView : public views::ImageView,
public ui::ImplicitAnimationObserver,
public ClipboardHistoryResourceManager::Observer {
public:
FadeImageView(const ClipboardHistoryItem& clipboard_history_item,
const ClipboardHistoryResourceManager* resource_manager)
: views::ImageView(),
resource_manager_(resource_manager),
clipboard_history_item_(clipboard_history_item) {
resource_manager_->AddObserver(this);
SetImage(*(resource_manager_->GetImageModel(clipboard_history_item_)
.GetImage()
.ToImageSkia()));
}
FadeImageView(const FadeImageView& rhs) = delete;
FadeImageView& operator=(const FadeImageView& rhs) = delete;
~FadeImageView() override {
StopObservingImplicitAnimations();
resource_manager_->RemoveObserver(this);
}
// ClipboardHistoryResourceManager::Observer:
void OnCachedImageModelUpdated(
const std::vector<base::UnguessableToken>& item_ids) override {
if (!base::Contains(item_ids, clipboard_history_item_.id()))
return;
// Fade the old image out, then swap in the new image.
DCHECK_EQ(FadeAnimationState::kNoFadeAnimation, animation_state_);
SetPaintToLayer();
animation_state_ = FadeAnimationState::kFadeOut;
ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
settings.SetTransitionDuration(kFadeOutDurationMs);
settings.AddObserver(this);
layer()->SetOpacity(0.0f);
}
// ui::ImplicitAnimationObserver:
void OnImplicitAnimationsCompleted() override {
switch (animation_state_) {
case FadeAnimationState::kNoFadeAnimation:
NOTREACHED();
return;
case FadeAnimationState::kFadeOut:
DCHECK_EQ(0.0f, layer()->opacity());
animation_state_ = FadeAnimationState::kFadeIn;
SetImage(*(resource_manager_->GetImageModel(clipboard_history_item_)
.GetImage()
.ToImageSkia()));
{
ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
settings.AddObserver(this);
settings.SetTransitionDuration(kFadeInDurationMs);
layer()->SetOpacity(1.0f);
}
return;
case FadeAnimationState::kFadeIn:
DestroyLayer();
animation_state_ = FadeAnimationState::kNoFadeAnimation;
return;
}
}
// The different animation states possible when transitioning from one
// gfx::ImageSkia to the next.
enum class FadeAnimationState {
kNoFadeAnimation,
kFadeOut,
kFadeIn,
};
// The current animation state.
FadeAnimationState animation_state_ = FadeAnimationState::kNoFadeAnimation;
// The resource manager, owned by ClipboardHistoryController.
const ClipboardHistoryResourceManager* const resource_manager_;
// The ClipboardHistoryItem represented by this class.
const ClipboardHistoryItem clipboard_history_item_;
};
} // namespace
////////////////////////////////////////////////////////////////////////////////
// ClipboardHistoryBitmapItemView::BitmapContentsView
......@@ -62,9 +169,12 @@ class ClipboardHistoryBitmapItemView::BitmapContentsView
// ClipboardHistoryBitmapItemView
ClipboardHistoryBitmapItemView::ClipboardHistoryBitmapItemView(
const gfx::ImageSkia& image_skia,
const ClipboardHistoryItem& clipboard_history_item,
const ClipboardHistoryResourceManager* resource_manager,
views::MenuItemView* container)
: ClipboardHistoryItemView(container), original_image_(image_skia) {}
: ClipboardHistoryItemView(container),
resource_manager_(resource_manager),
clipboard_history_item_(clipboard_history_item) {}
ClipboardHistoryBitmapItemView::~ClipboardHistoryBitmapItemView() = default;
......@@ -77,11 +187,9 @@ ClipboardHistoryBitmapItemView::CreateContentsView() {
auto contents_view = std::make_unique<BitmapContentsView>(this);
contents_view->SetLayoutManager(std::make_unique<views::FillLayout>());
auto image_view = std::make_unique<views::ImageView>();
image_view->SetImage(original_image_);
auto image_view = BuildImageView();
image_view->SetPreferredSize(gfx::Size(INT_MAX, kBitmapHeight));
image_view_ = contents_view->AddChildView(std::move(image_view));
contents_view->InstallDeleteButton();
return contents_view;
}
......@@ -91,6 +199,26 @@ void ClipboardHistoryBitmapItemView::OnBoundsChanged(
image_view_->SetImageSize(CalculateTargetImageSize());
}
std::unique_ptr<views::ImageView>
ClipboardHistoryBitmapItemView::BuildImageView() {
switch (
ClipboardHistoryUtil::CalculateMainFormat(clipboard_history_item_.data())
.value()) {
case ui::ClipboardInternalFormat::kHtml:
return std::make_unique<FadeImageView>(clipboard_history_item_,
resource_manager_);
case ui::ClipboardInternalFormat::kBitmap: {
auto image_view = std::make_unique<views::ImageView>();
image_view->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(
clipboard_history_item_.data().bitmap()));
return image_view;
}
default:
NOTREACHED();
return std::make_unique<views::ImageView>();
}
}
gfx::Size ClipboardHistoryBitmapItemView::CalculateTargetImageSize() const {
const gfx::Size image_size = image_view_->GetImage().size();
const double width_ratio = image_size.width() / double(width());
......
......@@ -5,23 +5,24 @@
#ifndef ASH_CLIPBOARD_VIEWS_CLIPBOARD_HISTORY_BITMAP_ITEM_VIEW_H_
#define ASH_CLIPBOARD_VIEWS_CLIPBOARD_HISTORY_BITMAP_ITEM_VIEW_H_
#include "ash/clipboard/clipboard_history_item.h"
#include "ash/clipboard/views/clipboard_history_item_view.h"
namespace gfx {
class ImageSkia;
} // namespace gfx
#include "ui/base/clipboard/clipboard_data.h"
namespace views {
class ImageView;
} // namespace views
namespace ash {
class ClipboardHistoryResourceManager;
// The menu item showing the bitmap.
// The menu item showing a bitmap.
class ClipboardHistoryBitmapItemView : public ClipboardHistoryItemView {
public:
ClipboardHistoryBitmapItemView(const gfx::ImageSkia& image_skia,
views::MenuItemView* container);
ClipboardHistoryBitmapItemView(
const ClipboardHistoryItem& clipboard_history_item,
const ClipboardHistoryResourceManager* resource_manager,
views::MenuItemView* container);
ClipboardHistoryBitmapItemView(const ClipboardHistoryBitmapItemView& rhs) =
delete;
ClipboardHistoryBitmapItemView& operator=(
......@@ -36,14 +37,20 @@ class ClipboardHistoryBitmapItemView : public ClipboardHistoryItemView {
std::unique_ptr<ContentsView> CreateContentsView() override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
// Builds `image_view_`.
std::unique_ptr<views::ImageView> BuildImageView();
// Calculates the target size of the image to show.
gfx::Size CalculateTargetImageSize() const;
// The image from the bitmap which is stored in the clipboard data.
const gfx::ImageSkia original_image_;
// Owned by view hierarchy.
views::ImageView* image_view_ = nullptr;
// Owned by ClipboardHistoryController.
const ClipboardHistoryResourceManager* const resource_manager_;
// The ClipboardHistoryItem represented by this view.
const ClipboardHistoryItem clipboard_history_item_;
};
} // namespace ash
......
......@@ -138,16 +138,13 @@ const char* ClipboardHistoryItemView::DeleteButton::GetClassName() const {
std::unique_ptr<ClipboardHistoryItemView>
ClipboardHistoryItemView::CreateFromClipboardHistoryItem(
const ClipboardHistoryItem& item,
const ClipboardHistoryResourceManager& resource_manager,
const ClipboardHistoryResourceManager* resource_manager,
views::MenuItemView* container) {
switch (ClipboardHistoryUtil::CalculateMainFormat(item.data()).value()) {
case ui::ClipboardInternalFormat::kBitmap:
return std::make_unique<ClipboardHistoryBitmapItemView>(
gfx::ImageSkia::CreateFrom1xBitmap(item.data().bitmap()), container);
case ui::ClipboardInternalFormat::kHtml:
return std::make_unique<ClipboardHistoryBitmapItemView>(
*(resource_manager.GetImageModel(item).GetImage().ToImageSkia()),
container);
item, resource_manager, container);
case ui::ClipboardInternalFormat::kText:
case ui::ClipboardInternalFormat::kSvg:
case ui::ClipboardInternalFormat::kRtf:
......
......@@ -23,7 +23,7 @@ class ClipboardHistoryItemView : public views::View,
static std::unique_ptr<ClipboardHistoryItemView>
CreateFromClipboardHistoryItem(
const ClipboardHistoryItem& item,
const ClipboardHistoryResourceManager& resource_manager,
const ClipboardHistoryResourceManager* resource_manager,
views::MenuItemView* container);
ClipboardHistoryItemView(const ClipboardHistoryItemView& rhs) = delete;
......
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