From e0e1b978603d8504f8b1b68d53f32a8c325da00b Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sat, 27 Feb 2021 16:38:58 +0300 Subject: [PATCH] Add ui::image_view element --- libs/ui/include/psemek/ui/image_view.hpp | 45 ++++++++++++ libs/ui/source/image_view.cpp | 87 ++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 libs/ui/include/psemek/ui/image_view.hpp create mode 100644 libs/ui/source/image_view.cpp diff --git a/libs/ui/include/psemek/ui/image_view.hpp b/libs/ui/include/psemek/ui/image_view.hpp new file mode 100644 index 00000000..cfc860a1 --- /dev/null +++ b/libs/ui/include/psemek/ui/image_view.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + +#include + +namespace psemek::ui +{ + + struct image_view + : element + { + virtual bool upscale() const { return upscale_; } + virtual void set_upscale(bool value); + + virtual bool downscale() const { return downscale_; } + virtual void set_downscale(bool value); + + virtual bool keep_aspect_ratio() const { return keep_aspect_ratio_; } + virtual void set_keep_aspect_ratio(bool value); + + virtual std::shared_ptr image() const { return image_; } + virtual void set_image(std::shared_ptr image); + + virtual gfx::color_rgba const & color() const { return color_; } + virtual void set_color(gfx::color_rgba const & c) { color_ = c; } + + struct shape const & shape() const override { return shape_; } + void reshape(geom::box const & bbox) override { shape_.box = bbox; } + + geom::box size_constraints() const override; + + void draw(painter & p) const override; + + private: + bool upscale_ = true; + bool downscale_ = true; + bool keep_aspect_ratio_ = true; + std::shared_ptr image_; + gfx::color_rgba color_{0, 0, 0, 0}; + box_shape shape_; + }; + +} diff --git a/libs/ui/source/image_view.cpp b/libs/ui/source/image_view.cpp new file mode 100644 index 00000000..0e5b8269 --- /dev/null +++ b/libs/ui/source/image_view.cpp @@ -0,0 +1,87 @@ +#include + +namespace psemek::ui +{ + + void image_view::set_upscale(bool value) + { + upscale_ = value; + post_reshape(); + } + + void image_view::set_downscale(bool value) + { + downscale_ = value; + post_reshape(); + } + + void image_view::set_keep_aspect_ratio(bool value) + { + keep_aspect_ratio_ = value; + post_reshape(); + } + + void image_view::set_image(std::shared_ptr image) + { + image_ = std::move(image); + post_reshape(); + } + + geom::box image_view::size_constraints() const + { + auto r = element::size_constraints(); + + if (image_) + { + auto const size = image_->size(); + + if (!downscale_) + { + r[0].min = size[0]; + r[1].min = size[1]; + } + + if (!upscale_) + { + r[0].max = size[0]; + r[1].max = size[1]; + } + } + + return r; + } + + void image_view::draw(painter & p) const + { + if (!image_) return; + + auto const size = image_->size(); + + auto box = shape_.box; + + if (!upscale_) + { + if (size[0] < box[0].length()) + box[0] = geom::shrink(box[0], (box[0].length() - size[0]) / 2.f); + if (size[1] < box[1].length()) + box[1] = geom::shrink(box[1], (box[1].length() - size[1]) / 2.f); + } + + if (keep_aspect_ratio_ && size[0] > 0.f && size[1] > 0.f) + { + if (size[0] * box[1].length() < box[0].length() * size[1]) + { + float const width = box[1].length() * size[0] / size[1]; + box[0] = geom::shrink(box[0], (box[0].length() - width) / 2.f); + } + else + { + float const height = box[0].length() * size[1] / size[0]; + box[1] = geom::shrink(box[1], (box[1].length() - height) / 2.f); + } + } + + p.draw_image(box, *image_, color_); + } + +}