blob: ba8ab48ab9d6bce0cd4081cb602f5d0add79c4eb [file] [log] [blame]
// 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 <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.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/lottie/animation.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_view.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 BoxLayoutView, public TextfieldController {
public:
AnimationGallery() {
View* image_view_container = nullptr;
BoxLayoutView* file_container = nullptr;
Builder<BoxLayoutView>(this)
.SetOrientation(BoxLayout::Orientation::kVertical)
.SetInsideBorderInsets(gfx::Insets(10))
.SetBetweenChildSpacing(10)
.AddChildren(
Builder<Textfield>()
.CopyAddressTo(&size_input_)
.SetPlaceholderText(u"Size in dip (Empty for default)")
.SetController(this),
Builder<View>()
.CopyAddressTo(&image_view_container)
.SetUseDefaultFillLayout(true)
.AddChild(Builder<AnimatedImageView>()
.CopyAddressTo(&animated_image_view_)
.SetBorder(CreateSolidSidedBorder(
1, 1, 1, 1, SK_ColorBLACK))),
Builder<BoxLayoutView>()
.CopyAddressTo(&file_container)
.SetInsideBorderInsets(gfx::Insets(10))
.SetBetweenChildSpacing(10)
.AddChildren(
Builder<Textfield>()
.CopyAddressTo(&file_chooser_)
.SetPlaceholderText(u"Enter path to lottie JSON file"),
Builder<MdTextButton>()
.SetCallback(base::BindRepeating(
&AnimationGallery::ButtonPressed,
base::Unretained(this)))
.SetText(u"Render")))
.BuildChildren();
SetFlexForView(image_view_container, 1);
file_container->SetFlexForView(file_chooser_, 1);
}
AnimationGallery(const AnimationGallery&) = delete;
AnimationGallery& operator=(const AnimationGallery&) = delete;
~AnimationGallery() override = default;
// TextfieldController:
void ContentsChanged(Textfield* sender,
const std::u16string& new_contents) override {
if (sender == size_input_) {
if (!base::StringToInt(new_contents, &size_) && (size_ > 0)) {
size_ = 0;
size_input_->SetText(std::u16string());
}
Update();
}
}
void ButtonPressed(const ui::Event& event) {
std::string json;
base::ScopedAllowBlockingForTesting allow_blocking;
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
base::FilePath path(base::UTF16ToUTF8(file_chooser_->GetText()));
#else
base::FilePath path(base::UTF16ToWide(file_chooser_->GetText()));
#endif // defined(OS_POSIX)
if (base::ReadFileToString(path, &json)) {
auto skottie = cc::SkottieWrapper::CreateSerializable(
std::vector<uint8_t>(json.begin(), json.end()));
animated_image_view_->SetAnimatedImage(
std::make_unique<lottie::Animation>(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_ = nullptr;
Textfield* size_input_ = nullptr;
Textfield* file_chooser_ = nullptr;
int size_ = 0;
};
} // namespace
AnimatedImageViewExample::AnimatedImageViewExample()
: ExampleBase("Animated Image View") {}
AnimatedImageViewExample::~AnimatedImageViewExample() = default;
void AnimatedImageViewExample::CreateExampleView(View* container) {
container->SetUseDefaultFillLayout(true);
container->AddChildView(std::make_unique<AnimationGallery>());
}
} // namespace examples
} // namespace views