Commit d3db848c authored by Elly Fong-Jones's avatar Elly Fong-Jones Committed by Commit Bot

views: remove AnimatedImageView

As far as I can tell this class has never had a user in chromium.

This change also removes the ImageViewBase abstraction layer, which
was added to support AnimatedImageView.

Bug: None
Change-Id: I9af55bfb0ef1b7a07a2d5a1db234b5e998a66c07
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1842037Reviewed-by: default avatarRobert Liao <robliao@chromium.org>
Commit-Queue: Elly Fong-Jones <ellyjones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#703416}
parent 280f7621
......@@ -101,7 +101,6 @@ jumbo_component("views") {
"color_chooser/color_chooser_listener.h",
"color_chooser/color_chooser_view.h",
"context_menu_controller.h",
"controls/animated_image_view.h",
"controls/button/button.h",
"controls/button/button_controller.h",
"controls/button/button_controller_delegate.h",
......@@ -126,7 +125,6 @@ jumbo_component("views") {
"controls/focusable_border.h",
"controls/highlight_path_generator.h",
"controls/image_view.h",
"controls/image_view_base.h",
"controls/label.h",
"controls/link.h",
"controls/link_listener.h",
......@@ -325,7 +323,6 @@ jumbo_component("views") {
"button_drag_utils.cc",
"color_chooser/color_chooser_view.cc",
"context_menu_controller.cc",
"controls/animated_image_view.cc",
"controls/button/button.cc",
"controls/button/button_controller.cc",
"controls/button/checkbox.cc",
......@@ -345,7 +342,6 @@ jumbo_component("views") {
"controls/focusable_border.cc",
"controls/highlight_path_generator.cc",
"controls/image_view.cc",
"controls/image_view_base.cc",
"controls/label.cc",
"controls/link.cc",
"controls/menu/menu_closure_animation_mac.mm",
......
// Copyright 2018 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.
#include "ui/views/controls/animated_image_view.h"
#include <utility>
#include "base/logging.h"
#include "cc/paint/skottie_wrapper.h"
#include "ui/gfx/canvas.h"
#include "ui/views/widget/widget.h"
namespace views {
namespace {
bool AreAnimatedImagesEqual(const gfx::SkiaVectorAnimation& animation_1,
const gfx::SkiaVectorAnimation& animation_2) {
// In rare cases this may return false, even if the animated images are backed
// by the same resource file.
return animation_1.skottie() == animation_2.skottie();
}
} // namespace
AnimatedImageView::AnimatedImageView() = default;
AnimatedImageView::~AnimatedImageView() = default;
void AnimatedImageView::SetAnimatedImage(
std::unique_ptr<gfx::SkiaVectorAnimation> animated_image) {
if (animated_image_ &&
AreAnimatedImagesEqual(*animated_image, *animated_image_)) {
Stop();
return;
}
gfx::Size preferred_size(GetPreferredSize());
animated_image_ = std::move(animated_image);
// Stop the animation to reset it.
Stop();
if (preferred_size != GetPreferredSize())
PreferredSizeChanged();
SchedulePaint();
}
void AnimatedImageView::Play() {
DCHECK(animated_image_);
DCHECK_EQ(state_, State::kStopped);
state_ = State::kPlaying;
SetCompositorFromWidget();
animated_image_->Start();
}
void AnimatedImageView::Stop() {
if (state_ == State::kStopped)
return;
DCHECK(animated_image_);
ClearCurrentCompositor();
animated_image_->Stop();
state_ = State::kStopped;
}
gfx::Size AnimatedImageView::GetImageSize() const {
return image_size_.value_or(
animated_image_ ? animated_image_->GetOriginalSize() : gfx::Size());
}
void AnimatedImageView::OnPaint(gfx::Canvas* canvas) {
View::OnPaint(canvas);
if (!animated_image_)
return;
canvas->Save();
canvas->Translate(GetImageBounds().origin().OffsetFromOrigin());
// OnPaint may be called before clock tick was received; in that case just
// paint the first frame.
if (!previous_timestamp_.is_null() && state_ != State::kStopped)
animated_image_->Paint(canvas, previous_timestamp_, GetImageSize());
else
animated_image_->PaintFrame(canvas, 0, GetImageSize());
canvas->Restore();
}
void AnimatedImageView::NativeViewHierarchyChanged() {
ui::Compositor* compositor = GetWidget()->GetCompositor();
DCHECK(compositor);
if (compositor_ != compositor) {
ClearCurrentCompositor();
// Restore the Play() state with the new compositor.
if (state_ == State::kPlaying)
SetCompositorFromWidget();
}
}
void AnimatedImageView::RemovedFromWidget() {
if (compositor_) {
Stop();
ClearCurrentCompositor();
}
}
void AnimatedImageView::OnAnimationStep(base::TimeTicks timestamp) {
previous_timestamp_ = timestamp;
SchedulePaint();
}
void AnimatedImageView::OnCompositingShuttingDown(ui::Compositor* compositor) {
if (compositor_ == compositor) {
Stop();
ClearCurrentCompositor();
}
}
void AnimatedImageView::SetCompositorFromWidget() {
DCHECK(!compositor_);
auto* widget = GetWidget();
DCHECK(widget);
compositor_ = widget->GetCompositor();
DCHECK(!compositor_->HasAnimationObserver(this));
compositor_->AddAnimationObserver(this);
}
void AnimatedImageView::ClearCurrentCompositor() {
if (compositor_) {
DCHECK(compositor_->HasAnimationObserver(this));
compositor_->RemoveAnimationObserver(this);
compositor_ = nullptr;
}
}
BEGIN_METADATA(AnimatedImageView)
METADATA_PARENT_CLASS(ImageViewBase)
END_METADATA()
} // namespace views
// Copyright 2018 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 UI_VIEWS_CONTROLS_ANIMATED_IMAGE_VIEW_H_
#define UI_VIEWS_CONTROLS_ANIMATED_IMAGE_VIEW_H_
#include <memory>
#include "base/macros.h"
#include "ui/gfx/skia_vector_animation.h"
#include "ui/views/controls/image_view_base.h"
namespace gfx {
class SkiaVectorAnimation;
class Canvas;
} // namespace gfx
namespace ui {
class Compositor;
}
namespace views {
/////////////////////////////////////////////////////////////////////////////
//
// AnimatedImageView class.
//
// An AnimatedImageView can display a skia vector animation. The animation paint
// size can be set via SetImageSize. The animation is stopped by default.
// Use this over AnimatedIconView if you want to play a skottie animation file.
//
/////////////////////////////////////////////////////////////////////////////
class VIEWS_EXPORT AnimatedImageView : public ImageViewBase,
public ui::CompositorAnimationObserver {
public:
METADATA_HEADER(AnimatedImageView);
enum class State {
kPlaying, // The animation is currently playing.
kStopped // The animation is stopped and paint will raster the first
// frame.
};
AnimatedImageView();
~AnimatedImageView() override;
// Set the animated image that should be displayed. Setting an animated image
// will result in stopping the current animation.
void SetAnimatedImage(
std::unique_ptr<gfx::SkiaVectorAnimation> animated_image);
// Plays the animation in loop and must only be called when this view has
// access to a widget.
void Play();
// Stops any animation and resets it to the start frame.
void Stop();
private:
friend class AnimatedImageViewTest;
// Overridden from View:
void OnPaint(gfx::Canvas* canvas) override;
void NativeViewHierarchyChanged() override;
void RemovedFromWidget() override;
// Overridden from ui::CompositorAnimationObserver:
void OnAnimationStep(base::TimeTicks timestamp) override;
void OnCompositingShuttingDown(ui::Compositor* compositor) override;
void SetCompositorFromWidget();
void ClearCurrentCompositor();
// Overridden from ImageViewBase:
gfx::Size GetImageSize() const override;
// The current state of the animation.
State state_ = State::kStopped;
// The compositor associated with the widget of this view.
ui::Compositor* compositor_ = nullptr;
// The most recent timestamp at which a paint was scheduled for this view.
base::TimeTicks previous_timestamp_;
// The underlying skia vector animation.
std::unique_ptr<gfx::SkiaVectorAnimation> animated_image_;
DISALLOW_COPY_AND_ASSIGN(AnimatedImageView);
};
} // namespace views
#endif // UI_VIEWS_CONTROLS_ANIMATED_IMAGE_VIEW_H_
......@@ -9,6 +9,8 @@
#include "base/logging.h"
#include "cc/paint/paint_flags.h"
#include "skia/ext/image_operations.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/gfx/canvas.h"
namespace views {
......@@ -49,10 +51,60 @@ void ImageView::SetImage(const gfx::ImageSkia* image_skia) {
}
}
void ImageView::SetImageSize(const gfx::Size& image_size) {
image_size_ = image_size;
PreferredSizeChanged();
}
void ImageView::ResetImageSize() {
image_size_.reset();
PreferredSizeChanged();
}
gfx::Rect ImageView::GetImageBounds() const {
return gfx::Rect(image_origin_, GetImageSize());
}
const gfx::ImageSkia& ImageView::GetImage() const {
return image_;
}
void ImageView::SetHorizontalAlignment(Alignment alignment) {
if (alignment != horizontal_alignment_) {
horizontal_alignment_ = alignment;
UpdateImageOrigin();
OnPropertyChanged(&horizontal_alignment_, kPropertyEffectsPaint);
}
}
ImageView::Alignment ImageView::GetHorizontalAlignment() const {
return horizontal_alignment_;
}
void ImageView::SetVerticalAlignment(Alignment alignment) {
if (alignment != vertical_alignment_) {
vertical_alignment_ = alignment;
UpdateImageOrigin();
OnPropertyChanged(&horizontal_alignment_, kPropertyEffectsPaint);
}
}
ImageView::Alignment ImageView::GetVerticalAlignment() const {
return vertical_alignment_;
}
void ImageView::SetAccessibleName(const base::string16& accessible_name) {
if (accessible_name_ == accessible_name)
return;
accessible_name_ = accessible_name;
OnPropertyChanged(&accessible_name_, kPropertyEffectsNone);
}
const base::string16& ImageView::GetAccessibleName() const {
return accessible_name_.empty() ? tooltip_text_ : accessible_name_;
}
bool ImageView::IsImageEqual(const gfx::ImageSkia& img) const {
// Even though we copy ImageSkia in SetImage() the backing store
// (ImageSkiaStorage) is not copied and may have changed since the last call
......@@ -64,6 +116,49 @@ bool ImageView::IsImageEqual(const gfx::ImageSkia& img) const {
last_painted_bitmap_pixels_ == GetBitmapPixels(img, last_paint_scale_);
}
void ImageView::UpdateImageOrigin() {
gfx::Size image_size = GetImageSize();
gfx::Insets insets = GetInsets();
int x = 0;
// In order to properly handle alignment of images in RTL locales, we need
// to flip the meaning of trailing and leading. For example, if the
// horizontal alignment is set to trailing, then we'll use left alignment for
// the image instead of right alignment if the UI layout is RTL.
Alignment actual_horizontal_alignment = horizontal_alignment_;
if (base::i18n::IsRTL() && (horizontal_alignment_ != Alignment::kCenter)) {
actual_horizontal_alignment = (horizontal_alignment_ == Alignment::kLeading)
? Alignment::kTrailing
: Alignment::kLeading;
}
switch (actual_horizontal_alignment) {
case Alignment::kLeading:
x = insets.left();
break;
case Alignment::kTrailing:
x = width() - insets.right() - image_size.width();
break;
case Alignment::kCenter:
x = (width() - insets.width() - image_size.width()) / 2 + insets.left();
break;
}
int y = 0;
switch (vertical_alignment_) {
case Alignment::kLeading:
y = insets.top();
break;
case Alignment::kTrailing:
y = height() - insets.bottom() - image_size.height();
break;
case Alignment::kCenter:
y = (height() - insets.height() - image_size.height()) / 2 + insets.top();
break;
}
image_origin_ = gfx::Point(x, y);
}
gfx::Size ImageView::GetImageSize() const {
return image_size_.value_or(image_.size());
}
......@@ -73,6 +168,49 @@ void ImageView::OnPaint(gfx::Canvas* canvas) {
OnPaintImage(canvas);
}
void ImageView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
const base::string16& name = GetAccessibleName();
if (name.empty()) {
node_data->role = ax::mojom::Role::kIgnored;
return;
}
node_data->role = ax::mojom::Role::kImage;
node_data->SetName(name);
}
base::string16 ImageView::GetTooltipText(const gfx::Point& p) const {
return tooltip_text_;
}
gfx::Size ImageView::CalculatePreferredSize() const {
gfx::Size size = GetImageSize();
size.Enlarge(GetInsets().width(), GetInsets().height());
return size;
}
views::PaintInfo::ScaleType ImageView::GetPaintScaleType() const {
// ImageViewBase contains an image which is rastered at the device scale
// factor. By default, the paint commands are recorded at a scale factor
// slightly different from the device scale factor. Re-rastering the image at
// this paint recording scale will result in a distorted image. Paint
// recording scale might also not be uniform along the x & y axis, thus
// resulting in further distortion in the aspect ratio of the final image.
// |kUniformScaling| ensures that the paint recording scale is uniform along
// the x & y axis and keeps the scale equal to the device scale factor.
// See http://crbug.com/754010 for more details.
return views::PaintInfo::ScaleType::kUniformScaling;
}
void ImageView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
UpdateImageOrigin();
}
void ImageView::PreferredSizeChanged() {
View::PreferredSizeChanged();
UpdateImageOrigin();
}
void ImageView::OnPaintImage(gfx::Canvas* canvas) {
last_paint_scale_ = canvas->image_scale();
last_painted_bitmap_pixels_ = nullptr;
......@@ -123,8 +261,17 @@ gfx::ImageSkia ImageView::GetPaintImage(float scale) {
return scaled_image_;
}
DEFINE_ENUM_CONVERTERS(
ImageView::Alignment,
{ImageView::Alignment::kLeading, base::ASCIIToUTF16("kLeading")},
{ImageView::Alignment::kCenter, base::ASCIIToUTF16("kCenter")},
{ImageView::Alignment::kTrailing, base::ASCIIToUTF16("kTrailing")})
BEGIN_METADATA(ImageView)
METADATA_PARENT_CLASS(ImageViewBase)
METADATA_PARENT_CLASS(View)
ADD_PROPERTY_METADATA(ImageView, Alignment, HorizontalAlignment)
ADD_PROPERTY_METADATA(ImageView, Alignment, VerticalAlignment)
ADD_PROPERTY_METADATA(ImageView, base::string16, AccessibleName)
END_METADATA()
} // namespace views
......@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/image_view_base.h"
#include "ui/views/view.h"
namespace gfx {
class Canvas;
......@@ -25,10 +25,12 @@ namespace views {
// provided image size.
//
/////////////////////////////////////////////////////////////////////////////
class VIEWS_EXPORT ImageView : public ImageViewBase {
class VIEWS_EXPORT ImageView : public View {
public:
METADATA_HEADER(ImageView);
enum class Alignment { kLeading, kCenter, kTrailing };
ImageView();
~ImageView() override;
......@@ -40,16 +42,46 @@ class VIEWS_EXPORT ImageView : public ImageViewBase {
// image.
void SetImage(const gfx::ImageSkia* image_skia);
// Sets the desired size of the image to be displayed.
void SetImageSize(const gfx::Size& size);
// Reset the image size to the current image dimensions.
void ResetImageSize();
// Returns the actual bounds of the visible image inside the view.
gfx::Rect GetImageBounds() const;
// Returns the image currently displayed, which can be empty if not set.
// The returned image is still owned by the ImageView.
const gfx::ImageSkia& GetImage() const;
// Set / Get the horizontal alignment.
void SetHorizontalAlignment(Alignment ha);
Alignment GetHorizontalAlignment() const;
// Set / Get the vertical alignment.
void SetVerticalAlignment(Alignment va);
Alignment GetVerticalAlignment() const;
// Set / Get the accessible name text.
void SetAccessibleName(const base::string16& name);
const base::string16& GetAccessibleName() const;
// Set the tooltip text.
void set_tooltip_text(const base::string16& tooltip) {
tooltip_text_ = tooltip;
}
// Overridden from View:
void OnPaint(gfx::Canvas* canvas) override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
base::string16 GetTooltipText(const gfx::Point& p) const override;
gfx::Size CalculatePreferredSize() const override;
views::PaintInfo::ScaleType GetPaintScaleType() const override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
void PreferredSizeChanged() override;
protected:
// Overridden from ImageViewBase:
gfx::Size GetImageSize() const override;
private:
friend class ImageViewTest;
......@@ -64,6 +96,26 @@ class VIEWS_EXPORT ImageView : public ImageViewBase {
// for this to return false even though the images are in fact equal.
bool IsImageEqual(const gfx::ImageSkia& img) const;
// Recomputes and updates the |image_origin_|.
void UpdateImageOrigin();
gfx::Size GetImageSize() const;
// The origin of the image.
gfx::Point image_origin_;
// The current tooltip text.
base::string16 tooltip_text_;
// The current accessible name text.
base::string16 accessible_name_;
// Horizontal alignment.
Alignment horizontal_alignment_ = Alignment::kCenter;
// Vertical alignment.
Alignment vertical_alignment_ = Alignment::kCenter;
// The underlying image.
gfx::ImageSkia image_;
......@@ -77,6 +129,9 @@ class VIEWS_EXPORT ImageView : public ImageViewBase {
// safe to cache.
void* last_painted_bitmap_pixels_ = nullptr;
// The requested image size.
base::Optional<gfx::Size> image_size_;
DISALLOW_COPY_AND_ASSIGN(ImageView);
};
......
// Copyright 2018 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.
#include "ui/views/controls/image_view_base.h"
#include <utility>
#include "base/logging.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
ImageViewBase::ImageViewBase() = default;
ImageViewBase::~ImageViewBase() = default;
void ImageViewBase::SetImageSize(const gfx::Size& image_size) {
image_size_ = image_size;
PreferredSizeChanged();
}
gfx::Rect ImageViewBase::GetImageBounds() const {
return gfx::Rect(image_origin_, GetImageSize());
}
void ImageViewBase::ResetImageSize() {
image_size_.reset();
PreferredSizeChanged();
}
void ImageViewBase::GetAccessibleNodeData(ui::AXNodeData* node_data) {
const base::string16& name = GetAccessibleName();
if (name.empty()) {
node_data->role = ax::mojom::Role::kIgnored;
return;
}
node_data->role = ax::mojom::Role::kImage;
node_data->SetName(name);
}
void ImageViewBase::SetHorizontalAlignment(Alignment alignment) {
if (alignment != horizontal_alignment_) {
horizontal_alignment_ = alignment;
UpdateImageOrigin();
OnPropertyChanged(&horizontal_alignment_, kPropertyEffectsPaint);
}
}
ImageViewBase::Alignment ImageViewBase::GetHorizontalAlignment() const {
return horizontal_alignment_;
}
void ImageViewBase::SetVerticalAlignment(Alignment alignment) {
if (alignment != vertical_alignment_) {
vertical_alignment_ = alignment;
UpdateImageOrigin();
OnPropertyChanged(&horizontal_alignment_, kPropertyEffectsPaint);
}
}
ImageViewBase::Alignment ImageViewBase::GetVerticalAlignment() const {
return vertical_alignment_;
}
void ImageViewBase::SetAccessibleName(const base::string16& accessible_name) {
if (accessible_name_ == accessible_name)
return;
accessible_name_ = accessible_name;
OnPropertyChanged(&accessible_name_, kPropertyEffectsNone);
}
const base::string16& ImageViewBase::GetAccessibleName() const {
return accessible_name_.empty() ? tooltip_text_ : accessible_name_;
}
base::string16 ImageViewBase::GetTooltipText(const gfx::Point& p) const {
return tooltip_text_;
}
gfx::Size ImageViewBase::CalculatePreferredSize() const {
gfx::Size size = GetImageSize();
size.Enlarge(GetInsets().width(), GetInsets().height());
return size;
}
views::PaintInfo::ScaleType ImageViewBase::GetPaintScaleType() const {
// ImageViewBase contains an image which is rastered at the device scale
// factor. By default, the paint commands are recorded at a scale factor
// slightly different from the device scale factor. Re-rastering the image at
// this paint recording scale will result in a distorted image. Paint
// recording scale might also not be uniform along the x & y axis, thus
// resulting in further distortion in the aspect ratio of the final image.
// |kUniformScaling| ensures that the paint recording scale is uniform along
// the x & y axis and keeps the scale equal to the device scale factor.
// See http://crbug.com/754010 for more details.
return views::PaintInfo::ScaleType::kUniformScaling;
}
void ImageViewBase::OnBoundsChanged(const gfx::Rect& previous_bounds) {
UpdateImageOrigin();
}
void ImageViewBase::UpdateImageOrigin() {
gfx::Size image_size = GetImageSize();
gfx::Insets insets = GetInsets();
int x = 0;
// In order to properly handle alignment of images in RTL locales, we need
// to flip the meaning of trailing and leading. For example, if the
// horizontal alignment is set to trailing, then we'll use left alignment for
// the image instead of right alignment if the UI layout is RTL.
Alignment actual_horizontal_alignment = horizontal_alignment_;
if (base::i18n::IsRTL() && (horizontal_alignment_ != Alignment::kCenter)) {
actual_horizontal_alignment = (horizontal_alignment_ == Alignment::kLeading)
? Alignment::kTrailing
: Alignment::kLeading;
}
switch (actual_horizontal_alignment) {
case Alignment::kLeading:
x = insets.left();
break;
case Alignment::kTrailing:
x = width() - insets.right() - image_size.width();
break;
case Alignment::kCenter:
x = (width() - insets.width() - image_size.width()) / 2 + insets.left();
break;
}
int y = 0;
switch (vertical_alignment_) {
case Alignment::kLeading:
y = insets.top();
break;
case Alignment::kTrailing:
y = height() - insets.bottom() - image_size.height();
break;
case Alignment::kCenter:
y = (height() - insets.height() - image_size.height()) / 2 + insets.top();
break;
}
image_origin_ = gfx::Point(x, y);
}
void ImageViewBase::PreferredSizeChanged() {
View::PreferredSizeChanged();
UpdateImageOrigin();
}
DEFINE_ENUM_CONVERTERS(
ImageViewBase::Alignment,
{ImageViewBase::Alignment::kLeading, base::ASCIIToUTF16("kLeading")},
{ImageViewBase::Alignment::kCenter, base::ASCIIToUTF16("kCenter")},
{ImageViewBase::Alignment::kTrailing, base::ASCIIToUTF16("kTrailing")})
BEGIN_METADATA(ImageViewBase)
METADATA_PARENT_CLASS(View)
ADD_PROPERTY_METADATA(ImageViewBase, Alignment, HorizontalAlignment)
ADD_PROPERTY_METADATA(ImageViewBase, Alignment, VerticalAlignment)
ADD_PROPERTY_METADATA(ImageViewBase, base::string16, AccessibleName)
END_METADATA()
} // namespace views
// Copyright 2018 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 UI_VIEWS_CONTROLS_IMAGE_VIEW_BASE_H_
#define UI_VIEWS_CONTROLS_IMAGE_VIEW_BASE_H_
#include "base/macros.h"
#include "base/optional.h"
#include "ui/views/view.h"
namespace gfx {
class Canvas;
}
namespace views {
class VIEWS_EXPORT ImageViewBase : public View {
public:
METADATA_HEADER(ImageViewBase);
enum class Alignment { kLeading, kCenter, kTrailing };
ImageViewBase();
~ImageViewBase() override;
// Set the desired image size for the receiving ImageView.
void SetImageSize(const gfx::Size& image_size);
// Returns the actual bounds of the visible image inside the view.
gfx::Rect GetImageBounds() const;
// Reset the image size to the current image dimensions.
void ResetImageSize();
// Set / Get the horizontal alignment.
void SetHorizontalAlignment(Alignment ha);
Alignment GetHorizontalAlignment() const;
// Set / Get the vertical alignment.
void SetVerticalAlignment(Alignment va);
Alignment GetVerticalAlignment() const;
// Set the tooltip text.
void set_tooltip_text(const base::string16& tooltip) {
tooltip_text_ = tooltip;
}
// Set / Get the accessible name text.
void SetAccessibleName(const base::string16& name);
const base::string16& GetAccessibleName() const;
// Overridden from View:
void OnPaint(gfx::Canvas* canvas) override = 0;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
base::string16 GetTooltipText(const gfx::Point& p) const override;
gfx::Size CalculatePreferredSize() const override;
views::PaintInfo::ScaleType GetPaintScaleType() const override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
void PreferredSizeChanged() override;
protected:
// Returns the size the image will be painted.
virtual gfx::Size GetImageSize() const = 0;
// The requested image size.
base::Optional<gfx::Size> image_size_;
private:
friend class ImageViewTest;
// Recomputes and updates the |image_origin_|.
void UpdateImageOrigin();
// The origin of the image.
gfx::Point image_origin_;
// Horizontal alignment.
Alignment horizontal_alignment_ = Alignment::kCenter;
// Vertical alignment.
Alignment vertical_alignment_ = Alignment::kCenter;
// The current tooltip text.
base::string16 tooltip_text_;
// The current accessible name text.
base::string16 accessible_name_;
DISALLOW_COPY_AND_ASSIGN(ImageViewBase);
};
} // namespace views
#endif // UI_VIEWS_CONTROLS_IMAGE_VIEW_BASE_H_
......@@ -9,8 +9,6 @@ jumbo_component("views_examples_lib") {
testonly = true
sources = [
"animated_image_view_example.cc",
"animated_image_view_example.h",
"box_layout_example.cc",
"box_layout_example.h",
"bubble_example.cc",
......
// Copyright 2018 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.
#include "ui/views/examples/animated_image_view_example.h"
#include <memory>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "cc/paint/skottie_wrapper.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/border.h"
#include "ui/views/controls/animated_image_view.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view.h"
namespace views {
namespace examples {
namespace {
// This class can load a skottie(and lottie) animation file from disk and play
// it in a view as AnimatedImageView.
// See https://skia.org/user/modules/skottie for more info on skottie.
class AnimationGallery : public View,
public TextfieldController,
public ButtonListener {
public:
AnimationGallery() {
auto image_view_container = std::make_unique<views::View>();
animated_image_view_ = image_view_container->AddChildView(
std::make_unique<AnimatedImageView>());
image_view_container->SetLayoutManager(std::make_unique<FillLayout>());
animated_image_view_->SetBorder(
CreateSolidSidedBorder(1, 1, 1, 1, SK_ColorBLACK));
image_view_container_ = AddChildView(std::move(image_view_container));
BoxLayout* box = SetLayoutManager(std::make_unique<BoxLayout>(
BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
box->SetFlexForView(image_view_container_, 1);
auto file_chooser = std::make_unique<Textfield>();
file_chooser->SetPlaceholderText(
base::ASCIIToUTF16("Enter path to lottie JSON file"));
auto file_container = std::make_unique<View>();
BoxLayout* file_box =
file_container->SetLayoutManager(std::make_unique<BoxLayout>(
BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
file_chooser_ = file_container->AddChildView(std::move(file_chooser));
file_go_button_ = file_container->AddChildView(
MdTextButton::Create(this, base::ASCIIToUTF16("Render")));
file_box->SetFlexForView(file_chooser_, 1);
AddChildView(std::move(file_container));
size_input_->SetPlaceholderText(
base::ASCIIToUTF16("Size in dip (Empty for default)"));
size_input_->set_controller(this);
}
~AnimationGallery() override = default;
// TextfieldController:
void ContentsChanged(Textfield* sender,
const base::string16& new_contents) override {
if (sender == size_input_) {
if (!base::StringToInt(new_contents, &size_) && (size_ > 0)) {
size_ = 0;
size_input_->SetText(base::string16());
}
Update();
}
}
// ButtonListener:
void ButtonPressed(Button* sender, const ui::Event& event) override {
DCHECK_EQ(file_go_button_, sender);
std::string json;
base::ScopedAllowBlockingForTesting allow_blocking;
#if defined(OS_POSIX)
base::FilePath path(base::UTF16ToUTF8(file_chooser_->GetText()));
#else
base::FilePath path(file_chooser_->GetText());
#endif // defined(OS_POSIX)
base::ReadFileToString(path, &json);
auto skottie = base::MakeRefCounted<cc::SkottieWrapper>(
base::RefCountedString::TakeString(&json));
animated_image_view_->SetAnimatedImage(
std::make_unique<gfx::SkiaVectorAnimation>(skottie));
animated_image_view_->Play();
Update();
}
private:
void Update() {
if (size_ > 24)
animated_image_view_->SetImageSize(gfx::Size(size_, size_));
else
animated_image_view_->ResetImageSize();
InvalidateLayout();
}
AnimatedImageView* animated_image_view_;
View* image_view_container_;
Textfield* size_input_ = AddChildView(std::make_unique<Textfield>());
Textfield* file_chooser_;
Button* file_go_button_;
int size_ = 0;
DISALLOW_COPY_AND_ASSIGN(AnimationGallery);
};
} // namespace
AnimatedImageViewExample::AnimatedImageViewExample()
: ExampleBase("Animated Image View") {}
AnimatedImageViewExample::~AnimatedImageViewExample() = default;
void AnimatedImageViewExample::CreateExampleView(View* container) {
container->SetLayoutManager(std::make_unique<FillLayout>());
container->AddChildView(std::make_unique<AnimationGallery>());
}
} // namespace examples
} // namespace views
// Copyright 2018 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 UI_VIEWS_EXAMPLES_ANIMATED_IMAGE_VIEW_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_ANIMATED_IMAGE_VIEW_EXAMPLE_H_
#include "base/macros.h"
#include "ui/views/examples/example_base.h"
namespace views {
namespace examples {
class VIEWS_EXAMPLES_EXPORT AnimatedImageViewExample : public ExampleBase {
public:
AnimatedImageViewExample();
~AnimatedImageViewExample() override;
// ExampleBase:
void CreateExampleView(View* container) override;
private:
DISALLOW_COPY_AND_ASSIGN(AnimatedImageViewExample);
};
} // namespace examples
} // namespace views
#endif // UI_VIEWS_EXAMPLES_ANIMATED_IMAGE_VIEW_EXAMPLE_H_
......@@ -19,7 +19,6 @@
#include "ui/views/background.h"
#include "ui/views/controls/combobox/combobox.h"
#include "ui/views/controls/label.h"
#include "ui/views/examples/animated_image_view_example.h"
#include "ui/views/examples/box_layout_example.h"
#include "ui/views/examples/bubble_example.h"
#include "ui/views/examples/button_example.h"
......@@ -62,7 +61,6 @@ namespace {
// Creates the default set of examples.
ExampleVector CreateExamples() {
ExampleVector examples;
examples.push_back(std::make_unique<AnimatedImageViewExample>());
examples.push_back(std::make_unique<BoxLayoutExample>());
examples.push_back(std::make_unique<BubbleExample>());
examples.push_back(std::make_unique<ButtonExample>());
......
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