From d86a71f79afe0e4dac768f61d6bff690567aca5b Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 24 May 2020 01:40:02 +0800 Subject: ... --- include/cru/ui/render/BorderRenderObject.hpp | 102 ++++++++++++++++++ include/cru/ui/render/CanvasRenderObject.hpp | 39 +++++++ include/cru/ui/render/FlexLayoutRenderObject.hpp | 42 ++++++++ include/cru/ui/render/LayoutRenderObject.hpp | 88 +++++++++++++++ include/cru/ui/render/LayoutUtility.hpp | 7 ++ include/cru/ui/render/RenderObject.hpp | 118 +++++++++++++++++++++ include/cru/ui/render/ScrollRenderObject.hpp | 30 ++++++ include/cru/ui/render/StackLayoutRenderObject.hpp | 17 +++ include/cru/ui/render/TextRenderObject.hpp | 85 +++++++++++++++ include/cru/ui/render/WindowRenderObject.hpp | 30 ++++++ include/cru/ui/render/base.hpp | 2 +- include/cru/ui/render/border_render_object.hpp | 102 ------------------ include/cru/ui/render/canvas_render_object.hpp | 39 ------- .../cru/ui/render/flex_layout_render_object.hpp | 42 -------- include/cru/ui/render/layout_render_object.hpp | 88 --------------- include/cru/ui/render/layout_utility.hpp | 7 -- include/cru/ui/render/render_object.hpp | 118 --------------------- include/cru/ui/render/scroll_render_object.hpp | 30 ------ .../cru/ui/render/stack_layout_render_object.hpp | 17 --- include/cru/ui/render/text_render_object.hpp | 85 --------------- include/cru/ui/render/window_render_object.hpp | 30 ------ 21 files changed, 559 insertions(+), 559 deletions(-) create mode 100644 include/cru/ui/render/BorderRenderObject.hpp create mode 100644 include/cru/ui/render/CanvasRenderObject.hpp create mode 100644 include/cru/ui/render/FlexLayoutRenderObject.hpp create mode 100644 include/cru/ui/render/LayoutRenderObject.hpp create mode 100644 include/cru/ui/render/LayoutUtility.hpp create mode 100644 include/cru/ui/render/RenderObject.hpp create mode 100644 include/cru/ui/render/ScrollRenderObject.hpp create mode 100644 include/cru/ui/render/StackLayoutRenderObject.hpp create mode 100644 include/cru/ui/render/TextRenderObject.hpp create mode 100644 include/cru/ui/render/WindowRenderObject.hpp delete mode 100644 include/cru/ui/render/border_render_object.hpp delete mode 100644 include/cru/ui/render/canvas_render_object.hpp delete mode 100644 include/cru/ui/render/flex_layout_render_object.hpp delete mode 100644 include/cru/ui/render/layout_render_object.hpp delete mode 100644 include/cru/ui/render/layout_utility.hpp delete mode 100644 include/cru/ui/render/render_object.hpp delete mode 100644 include/cru/ui/render/scroll_render_object.hpp delete mode 100644 include/cru/ui/render/stack_layout_render_object.hpp delete mode 100644 include/cru/ui/render/text_render_object.hpp delete mode 100644 include/cru/ui/render/window_render_object.hpp (limited to 'include/cru/ui/render') diff --git a/include/cru/ui/render/BorderRenderObject.hpp b/include/cru/ui/render/BorderRenderObject.hpp new file mode 100644 index 00000000..c3031f59 --- /dev/null +++ b/include/cru/ui/render/BorderRenderObject.hpp @@ -0,0 +1,102 @@ +#pragma once +#include "RenderObject.hpp" + +namespace cru::ui::render { +class BorderRenderObject : public RenderObject { + public: + BorderRenderObject(); + BorderRenderObject(const BorderRenderObject& other) = delete; + BorderRenderObject(BorderRenderObject&& other) = delete; + BorderRenderObject& operator=(const BorderRenderObject& other) = delete; + BorderRenderObject& operator=(BorderRenderObject&& other) = delete; + ~BorderRenderObject() override; + + bool IsBorderEnabled() const { return is_border_enabled_; } + void SetBorderEnabled(bool enabled) { is_border_enabled_ = enabled; } + + std::shared_ptr GetBorderBrush() { + return border_brush_; + } + + void SetBorderBrush(std::shared_ptr brush) { + if (brush == border_brush_) return; + border_brush_ = std::move(brush); + InvalidatePaint(); + } + + Thickness GetBorderThickness() { return border_thickness_; } + + void SetBorderThickness(const Thickness thickness) { + if (thickness == border_thickness_) return; + border_thickness_ = thickness; + InvalidateLayout(); + } + + CornerRadius GetBorderRadius() { return border_radius_; } + + void SetBorderRadius(const CornerRadius radius) { + if (radius == border_radius_) return; + border_radius_ = radius; + RecreateGeometry(); + } + + std::shared_ptr GetForegroundBrush() { + return foreground_brush_; + } + + void SetForegroundBrush(std::shared_ptr brush) { + if (brush == foreground_brush_) return; + foreground_brush_ = std::move(brush); + InvalidatePaint(); + } + + std::shared_ptr GetBackgroundBrush() { + return background_brush_; + } + + void SetBackgroundBrush(std::shared_ptr brush) { + if (brush == background_brush_) return; + background_brush_ = std::move(brush); + InvalidatePaint(); + } + + void SetBorderStyle(const BorderStyle& style); + + void Draw(platform::graph::IPainter* painter) override; + + RenderObject* HitTest(const Point& point) override; + + protected: + void OnMeasureCore(const Size& available_size) override; + void OnLayoutCore(const Rect& rect) override; + Size OnMeasureContent(const Size& available_size) override; + void OnLayoutContent(const Rect& content_rect) override; + + void OnAfterLayout() override; + + private: + RenderObject* GetChild() const { + return GetChildren().empty() ? nullptr : GetChildren()[0]; + } + + void RecreateGeometry(); + + private: + bool is_border_enabled_ = false; + + std::shared_ptr border_brush_; + platform::Thickness border_thickness_; + CornerRadius border_radius_; + + std::shared_ptr foreground_brush_; + std::shared_ptr background_brush_; + + // The ring. Used for painting. + std::unique_ptr geometry_; + // Area including inner area of the border. Used for painting foreground and + // background. + std::unique_ptr border_inner_geometry_; + // Area including border ring and inner area. Used for hit test. + std::unique_ptr border_outer_geometry_; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/CanvasRenderObject.hpp b/include/cru/ui/render/CanvasRenderObject.hpp new file mode 100644 index 00000000..ba50a985 --- /dev/null +++ b/include/cru/ui/render/CanvasRenderObject.hpp @@ -0,0 +1,39 @@ +#pragma once +#include "RenderObject.hpp" + +namespace cru::ui::render { +// The measure logic for `CanvasRenderObject` is that you set a desired size by +// `SetDesiredSize` (not `SetPreferredSize`) and it will compare desired size +// and available size and use the smaller one (by `Min`). +class CanvasRenderObject : public RenderObject { + public: + CanvasRenderObject(); + + CRU_DELETE_COPY(CanvasRenderObject) + CRU_DELETE_MOVE(CanvasRenderObject) + + ~CanvasRenderObject(); + + public: + void Draw(platform::graph::IPainter* painter) override; + + RenderObject* HitTest(const Point& point) override; + + Size GetDesiredSize() const { return desired_size_; } + + // Set the desired size. This is the content size excluding padding and + // margin. + void SetDesiredSize(const Size& new_size) { desired_size_ = new_size; } + + IEvent* PaintEvent() { return &paint_event_; } + + protected: + Size OnMeasureContent(const Size& available_size) override; + void OnLayoutContent(const Rect& content_rect) override; + + private: + Size desired_size_{}; + + Event paint_event_; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/FlexLayoutRenderObject.hpp b/include/cru/ui/render/FlexLayoutRenderObject.hpp new file mode 100644 index 00000000..bc43141d --- /dev/null +++ b/include/cru/ui/render/FlexLayoutRenderObject.hpp @@ -0,0 +1,42 @@ +#pragma once +#include "LayoutRenderObject.hpp" + +namespace cru::ui::render { +class FlexLayoutRenderObject : public LayoutRenderObject { + public: + FlexLayoutRenderObject() = default; + FlexLayoutRenderObject(const FlexLayoutRenderObject& other) = delete; + FlexLayoutRenderObject& operator=(const FlexLayoutRenderObject& other) = + delete; + FlexLayoutRenderObject(FlexLayoutRenderObject&& other) = delete; + FlexLayoutRenderObject& operator=(FlexLayoutRenderObject&& other) = delete; + ~FlexLayoutRenderObject() override = default; + + FlexDirection GetFlexDirection() const { return direction_; } + void SetFlexDirection(FlexDirection direction) { + direction_ = direction; + InvalidateLayout(); + } + + FlexMainAlignment GetContentMainAlign() const { return content_main_align_; } + void SetContentMainAlign(FlexMainAlignment align) { + content_main_align_ = align; + InvalidateLayout(); + } + + FlexCrossAlignment GetItemCrossAlign() const { return item_cross_align_; } + void SetItemCrossAlign(FlexCrossAlignment align) { + item_cross_align_ = align; + InvalidateLayout(); + } + + protected: + Size OnMeasureContent(const Size& available_size) override; + void OnLayoutContent(const Rect& content_rect) override; + + private: + FlexDirection direction_ = FlexDirection::Horizontal; + FlexMainAlignment content_main_align_ = FlexMainAlignment::Start; + FlexCrossAlignment item_cross_align_ = FlexCrossAlignment::Center; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/LayoutRenderObject.hpp b/include/cru/ui/render/LayoutRenderObject.hpp new file mode 100644 index 00000000..e6ca9dc0 --- /dev/null +++ b/include/cru/ui/render/LayoutRenderObject.hpp @@ -0,0 +1,88 @@ +#pragma once +#include "RenderObject.hpp" + +#include "cru/platform/graph/util/Painter.hpp" + +namespace cru::ui::render { +template +class LayoutRenderObject : public RenderObject { + public: + using ChildLayoutData = TChildLayoutData; + + protected: + LayoutRenderObject() : RenderObject(ChildMode::Multiple) {} + + public: + CRU_DELETE_COPY(LayoutRenderObject) + CRU_DELETE_MOVE(LayoutRenderObject) + + ~LayoutRenderObject() override = default; + + ChildLayoutData* GetChildLayoutData(Index position) { + Expects(position >= 0 && + position < static_cast(child_layout_data_.size())); + return &child_layout_data_[position]; + } + + void Draw(platform::graph::IPainter* painter) override; + + RenderObject* HitTest(const Point& point) override; + + protected: + void OnAddChild(RenderObject* new_child, Index position) override; + void OnRemoveChild(RenderObject* removed_child, Index position) override; + + private: + std::vector child_layout_data_{}; +}; + +template +void LayoutRenderObject::Draw( + platform::graph::IPainter* painter) { + for (const auto child : GetChildren()) { + auto offset = child->GetOffset(); + platform::graph::util::WithTransform( + painter, platform::Matrix::Translation(offset.x, offset.y), + [child](auto p) { child->Draw(p); }); + } +} + +template +RenderObject* LayoutRenderObject::HitTest( + const Point& point) { + const auto& children = GetChildren(); + for (auto i = children.crbegin(); i != children.crend(); ++i) { + auto offset = (*i)->GetOffset(); + Point p{point.x - offset.x, point.y - offset.y}; + const auto result = (*i)->HitTest(p); + if (result != nullptr) { + return result; + } + } + + const auto margin = GetMargin(); + const auto size = GetSize(); + return Rect{margin.left, margin.top, + std::max(size.width - margin.GetHorizontalTotal(), 0.0f), + std::max(size.height - margin.GetVerticalTotal(), 0.0f)} + .IsPointInside(point) + ? this + : nullptr; +} // namespace cru::ui::render + +template +void LayoutRenderObject::OnAddChild(RenderObject* new_child, + const Index position) { + CRU_UNUSED(new_child) + + child_layout_data_.emplace(child_layout_data_.cbegin() + position); +} + +template +void LayoutRenderObject::OnRemoveChild( + RenderObject* removed_child, const Index position) { + CRU_UNUSED(removed_child) + + child_layout_data_.erase(child_layout_data_.cbegin() + position); +} +} // namespace cru::ui::render diff --git a/include/cru/ui/render/LayoutUtility.hpp b/include/cru/ui/render/LayoutUtility.hpp new file mode 100644 index 00000000..63d13fd3 --- /dev/null +++ b/include/cru/ui/render/LayoutUtility.hpp @@ -0,0 +1,7 @@ +#pragma once +#include "Base.hpp" + +namespace cru::ui::render { +Size Min(const Size& left, const Size& right); +Size Max(const Size& left, const Size& right); +} // namespace cru::ui::render diff --git a/include/cru/ui/render/RenderObject.hpp b/include/cru/ui/render/RenderObject.hpp new file mode 100644 index 00000000..7cfa3883 --- /dev/null +++ b/include/cru/ui/render/RenderObject.hpp @@ -0,0 +1,118 @@ +#pragma once +#include "Base.hpp" + +#include "cru/common/Event.hpp" + +namespace cru::ui::render { +// Render object will not destroy its children when destroyed. Control must +// manage lifecycle of its render objects. Since control will destroy its +// children when destroyed, render objects will be destroyed along with it. +class RenderObject : public Object { + friend WindowRenderObject; + + protected: + enum class ChildMode { + None, + Single, + Multiple, + }; + + RenderObject() = default; + RenderObject(ChildMode child_mode) : RenderObject() { + SetChildMode(child_mode); + } + + public: + RenderObject(const RenderObject& other) = delete; + RenderObject(RenderObject&& other) = delete; + RenderObject& operator=(const RenderObject& other) = delete; + RenderObject& operator=(RenderObject&& other) = delete; + ~RenderObject() override = default; + + Control* GetAttachedControl() const { return control_; } + void SetAttachedControl(Control* new_control) { control_ = new_control; } + + UiHost* GetUiHost() const { return ui_host_; } + + RenderObject* GetParent() const { return parent_; } + + const std::vector& GetChildren() const { return children_; } + Index GetChildCount() const { return static_cast(children_.size()); } + void AddChild(RenderObject* render_object, Index position); + void RemoveChild(Index position); + + Point GetOffset() const { return offset_; } + void SetOffset(const Point& offset) { offset_ = offset; } + Point GetTotalOffset() const; + Point FromRootToContent(const Point& point) const; + Size GetSize() const { return size_; } + void SetSize(const Size& size) { size_ = size; } + + Thickness GetMargin() const { return margin_; } + void SetMargin(const Thickness& margin) { margin_ = margin; } + + Thickness GetPadding() const { return padding_; } + void SetPadding(const Thickness& padding) { padding_ = padding; } + + Size GetPreferredSize() const { return preferred_size_; } + void SetPreferredSize(const Size& preferred_size) { + preferred_size_ = preferred_size; + } + + void Measure(const Size& available_size); + void Layout(const Rect& rect); + + virtual void Draw(platform::graph::IPainter* painter) = 0; + + virtual RenderObject* HitTest(const Point& point) = 0; + + public: + void InvalidateLayout(); + void InvalidatePaint(); + + protected: + void SetChildMode(ChildMode mode) { child_mode_ = mode; } + + protected: + virtual void OnParentChanged(RenderObject* old_parent, + RenderObject* new_parent); + + // default is to invalidate both layout and paint + virtual void OnAddChild(RenderObject* new_child, Index position); + // default is to invalidate both layout and paint + virtual void OnRemoveChild(RenderObject* removed_child, Index position); + + virtual void OnMeasureCore(const Size& available_size); + virtual void OnLayoutCore(const Rect& rect); + virtual Size OnMeasureContent(const Size& available_size) = 0; + virtual void OnLayoutContent(const Rect& content_rect) = 0; + + virtual void OnAfterLayout(); + static void NotifyAfterLayoutRecursive(RenderObject* render_object); + + Rect GetPaddingRect() const; + Rect GetContentRect() const; + + private: + void SetParent(RenderObject* new_parent); + + void SetRenderHostRecursive(UiHost* host); + + private: + Control* control_ = nullptr; + UiHost* ui_host_ = nullptr; + + RenderObject* parent_ = nullptr; + std::vector children_{}; + + ChildMode child_mode_ = ChildMode::None; + + Point offset_{}; + Size size_{}; + + Thickness margin_{}; + Thickness padding_{}; + + Size preferred_size_{}; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/ScrollRenderObject.hpp b/include/cru/ui/render/ScrollRenderObject.hpp new file mode 100644 index 00000000..dcf6dae6 --- /dev/null +++ b/include/cru/ui/render/ScrollRenderObject.hpp @@ -0,0 +1,30 @@ +#pragma once +#include "RenderObject.hpp" + +#include "cru/platform/graph/util/Painter.hpp" + +namespace cru::ui::render { +class ScrollRenderObject : public RenderObject { + public: + ScrollRenderObject() : RenderObject(ChildMode::Single) {} + + CRU_DELETE_COPY(ScrollRenderObject) + CRU_DELETE_MOVE(ScrollRenderObject) + + ~ScrollRenderObject() override = default; + + void Draw(platform::graph::IPainter* painter) override; + + RenderObject* HitTest(const Point& point) override; + + Point GetScrollOffset() { return scroll_offset_; } + void SetScrollOffset(const Point& offset); + + protected: + void OnAddChild(RenderObject* new_child, Index position) override; + void OnRemoveChild(RenderObject* removed_child, Index position) override; + + private: + Point scroll_offset_; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/StackLayoutRenderObject.hpp b/include/cru/ui/render/StackLayoutRenderObject.hpp new file mode 100644 index 00000000..a5bf9335 --- /dev/null +++ b/include/cru/ui/render/StackLayoutRenderObject.hpp @@ -0,0 +1,17 @@ +#pragma once +#include "LayoutRenderObject.hpp" + +namespace cru::ui::render { +class StackLayoutRenderObject + : public LayoutRenderObject { + public: + StackLayoutRenderObject() = default; + CRU_DELETE_COPY(StackLayoutRenderObject) + CRU_DELETE_MOVE(StackLayoutRenderObject) + ~StackLayoutRenderObject() = default; + + protected: + Size OnMeasureContent(const Size& available_size) override; + void OnLayoutContent(const Rect& content_rect) override; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/TextRenderObject.hpp b/include/cru/ui/render/TextRenderObject.hpp new file mode 100644 index 00000000..7a81ba51 --- /dev/null +++ b/include/cru/ui/render/TextRenderObject.hpp @@ -0,0 +1,85 @@ +#pragma once +#include "RenderObject.hpp" + +#include + +namespace cru::ui::render { +class TextRenderObject : public RenderObject { + public: + constexpr static float default_caret_width = 2; + + public: + TextRenderObject(std::shared_ptr brush, + std::shared_ptr font, + std::shared_ptr selection_brush, + std::shared_ptr caret_brush); + TextRenderObject(const TextRenderObject& other) = delete; + TextRenderObject(TextRenderObject&& other) = delete; + TextRenderObject& operator=(const TextRenderObject& other) = delete; + TextRenderObject& operator=(TextRenderObject&& other) = delete; + ~TextRenderObject() override; + + std::string GetText() const; + void SetText(std::string new_text); + + std::shared_ptr GetBrush() const { return brush_; } + void SetBrush(std::shared_ptr new_brush); + + std::shared_ptr GetFont() const; + void SetFont(std::shared_ptr font); + + std::vector TextRangeRect(const TextRange& text_range); + Point TextSinglePoint(gsl::index position, bool trailing); + platform::graph::TextHitTestResult TextHitTest(const Point& point); + + std::optional GetSelectionRange() const { + return selection_range_; + } + void SetSelectionRange(std::optional new_range); + + std::shared_ptr GetSelectionBrush() const { + return selection_brush_; + } + void SetSelectionBrush(std::shared_ptr new_brush); + + bool IsDrawCaret() const { return draw_caret_; } + void SetDrawCaret(bool draw_caret); + void ToggleDrawCaret() { SetDrawCaret(!IsDrawCaret()); } + + // Caret position can be any value. When it is negative, 0 is used. When it + // exceeds the size of the string, the size of the string is used. + gsl::index GetCaretPosition() const { return caret_position_; } + void SetCaretPosition(gsl::index position); + + std::shared_ptr GetCaretBrush() const { + return caret_brush_; + } + void GetCaretBrush(std::shared_ptr brush); + + float GetCaretWidth() const { return caret_width_; } + void SetCaretWidth(float width); + + void Draw(platform::graph::IPainter* painter) override; + + RenderObject* HitTest(const Point& point) override; + + protected: + Size OnMeasureContent(const Size& available_size) override; + void OnLayoutContent(const Rect& content_rect) override; + + void OnAfterLayout() override; + + private: + std::shared_ptr brush_; + std::shared_ptr font_; + std::unique_ptr text_layout_; + + std::optional selection_range_ = std::nullopt; + std::shared_ptr selection_brush_; + + bool draw_caret_ = false; + gsl::index caret_position_ = 0; + std::shared_ptr caret_brush_; + float caret_width_ = default_caret_width; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/WindowRenderObject.hpp b/include/cru/ui/render/WindowRenderObject.hpp new file mode 100644 index 00000000..00bce29b --- /dev/null +++ b/include/cru/ui/render/WindowRenderObject.hpp @@ -0,0 +1,30 @@ +#pragma once +#include "RenderObject.hpp" + +namespace cru::ui::render { +class WindowRenderObject : public RenderObject { + public: + WindowRenderObject(UiHost* host); + WindowRenderObject(const WindowRenderObject& other) = delete; + WindowRenderObject(WindowRenderObject&& other) = delete; + WindowRenderObject& operator=(const WindowRenderObject& other) = delete; + WindowRenderObject& operator=(WindowRenderObject&& other) = delete; + ~WindowRenderObject() override = default; + + void Draw(platform::graph::IPainter* painter) override; + + RenderObject* HitTest(const Point& point) override; + + protected: + Size OnMeasureContent(const Size& available_size) override; + void OnLayoutContent(const Rect& content_rect) override; + + private: + RenderObject* GetChild() const { + return GetChildren().empty() ? nullptr : GetChildren()[0]; + } + + private: + EventRevokerGuard after_layout_event_guard_; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/base.hpp b/include/cru/ui/render/base.hpp index f9d936e0..c2af5e99 100644 --- a/include/cru/ui/render/base.hpp +++ b/include/cru/ui/render/base.hpp @@ -1,5 +1,5 @@ #pragma once -#include "../base.hpp" +#include "../Base.hpp" namespace cru::ui::render { class RenderObject; diff --git a/include/cru/ui/render/border_render_object.hpp b/include/cru/ui/render/border_render_object.hpp deleted file mode 100644 index 02672309..00000000 --- a/include/cru/ui/render/border_render_object.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once -#include "render_object.hpp" - -namespace cru::ui::render { -class BorderRenderObject : public RenderObject { - public: - BorderRenderObject(); - BorderRenderObject(const BorderRenderObject& other) = delete; - BorderRenderObject(BorderRenderObject&& other) = delete; - BorderRenderObject& operator=(const BorderRenderObject& other) = delete; - BorderRenderObject& operator=(BorderRenderObject&& other) = delete; - ~BorderRenderObject() override; - - bool IsBorderEnabled() const { return is_border_enabled_; } - void SetBorderEnabled(bool enabled) { is_border_enabled_ = enabled; } - - std::shared_ptr GetBorderBrush() { - return border_brush_; - } - - void SetBorderBrush(std::shared_ptr brush) { - if (brush == border_brush_) return; - border_brush_ = std::move(brush); - InvalidatePaint(); - } - - Thickness GetBorderThickness() { return border_thickness_; } - - void SetBorderThickness(const Thickness thickness) { - if (thickness == border_thickness_) return; - border_thickness_ = thickness; - InvalidateLayout(); - } - - CornerRadius GetBorderRadius() { return border_radius_; } - - void SetBorderRadius(const CornerRadius radius) { - if (radius == border_radius_) return; - border_radius_ = radius; - RecreateGeometry(); - } - - std::shared_ptr GetForegroundBrush() { - return foreground_brush_; - } - - void SetForegroundBrush(std::shared_ptr brush) { - if (brush == foreground_brush_) return; - foreground_brush_ = std::move(brush); - InvalidatePaint(); - } - - std::shared_ptr GetBackgroundBrush() { - return background_brush_; - } - - void SetBackgroundBrush(std::shared_ptr brush) { - if (brush == background_brush_) return; - background_brush_ = std::move(brush); - InvalidatePaint(); - } - - void SetBorderStyle(const BorderStyle& style); - - void Draw(platform::graph::IPainter* painter) override; - - RenderObject* HitTest(const Point& point) override; - - protected: - void OnMeasureCore(const Size& available_size) override; - void OnLayoutCore(const Rect& rect) override; - Size OnMeasureContent(const Size& available_size) override; - void OnLayoutContent(const Rect& content_rect) override; - - void OnAfterLayout() override; - - private: - RenderObject* GetChild() const { - return GetChildren().empty() ? nullptr : GetChildren()[0]; - } - - void RecreateGeometry(); - - private: - bool is_border_enabled_ = false; - - std::shared_ptr border_brush_; - platform::Thickness border_thickness_; - CornerRadius border_radius_; - - std::shared_ptr foreground_brush_; - std::shared_ptr background_brush_; - - // The ring. Used for painting. - std::unique_ptr geometry_; - // Area including inner area of the border. Used for painting foreground and - // background. - std::unique_ptr border_inner_geometry_; - // Area including border ring and inner area. Used for hit test. - std::unique_ptr border_outer_geometry_; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/canvas_render_object.hpp b/include/cru/ui/render/canvas_render_object.hpp deleted file mode 100644 index cb3828b6..00000000 --- a/include/cru/ui/render/canvas_render_object.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "render_object.hpp" - -namespace cru::ui::render { -// The measure logic for `CanvasRenderObject` is that you set a desired size by -// `SetDesiredSize` (not `SetPreferredSize`) and it will compare desired size -// and available size and use the smaller one (by `Min`). -class CanvasRenderObject : public RenderObject { - public: - CanvasRenderObject(); - - CRU_DELETE_COPY(CanvasRenderObject) - CRU_DELETE_MOVE(CanvasRenderObject) - - ~CanvasRenderObject(); - - public: - void Draw(platform::graph::IPainter* painter) override; - - RenderObject* HitTest(const Point& point) override; - - Size GetDesiredSize() const { return desired_size_; } - - // Set the desired size. This is the content size excluding padding and - // margin. - void SetDesiredSize(const Size& new_size) { desired_size_ = new_size; } - - IEvent* PaintEvent() { return &paint_event_; } - - protected: - Size OnMeasureContent(const Size& available_size) override; - void OnLayoutContent(const Rect& content_rect) override; - - private: - Size desired_size_{}; - - Event paint_event_; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/flex_layout_render_object.hpp b/include/cru/ui/render/flex_layout_render_object.hpp deleted file mode 100644 index 849c1a0d..00000000 --- a/include/cru/ui/render/flex_layout_render_object.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include "layout_render_object.hpp" - -namespace cru::ui::render { -class FlexLayoutRenderObject : public LayoutRenderObject { - public: - FlexLayoutRenderObject() = default; - FlexLayoutRenderObject(const FlexLayoutRenderObject& other) = delete; - FlexLayoutRenderObject& operator=(const FlexLayoutRenderObject& other) = - delete; - FlexLayoutRenderObject(FlexLayoutRenderObject&& other) = delete; - FlexLayoutRenderObject& operator=(FlexLayoutRenderObject&& other) = delete; - ~FlexLayoutRenderObject() override = default; - - FlexDirection GetFlexDirection() const { return direction_; } - void SetFlexDirection(FlexDirection direction) { - direction_ = direction; - InvalidateLayout(); - } - - FlexMainAlignment GetContentMainAlign() const { return content_main_align_; } - void SetContentMainAlign(FlexMainAlignment align) { - content_main_align_ = align; - InvalidateLayout(); - } - - FlexCrossAlignment GetItemCrossAlign() const { return item_cross_align_; } - void SetItemCrossAlign(FlexCrossAlignment align) { - item_cross_align_ = align; - InvalidateLayout(); - } - - protected: - Size OnMeasureContent(const Size& available_size) override; - void OnLayoutContent(const Rect& content_rect) override; - - private: - FlexDirection direction_ = FlexDirection::Horizontal; - FlexMainAlignment content_main_align_ = FlexMainAlignment::Start; - FlexCrossAlignment item_cross_align_ = FlexCrossAlignment::Center; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/layout_render_object.hpp b/include/cru/ui/render/layout_render_object.hpp deleted file mode 100644 index 5c4c9c5c..00000000 --- a/include/cru/ui/render/layout_render_object.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once -#include "render_object.hpp" - -#include "cru/platform/graph/util/painter.hpp" - -namespace cru::ui::render { -template -class LayoutRenderObject : public RenderObject { - public: - using ChildLayoutData = TChildLayoutData; - - protected: - LayoutRenderObject() : RenderObject(ChildMode::Multiple) {} - - public: - CRU_DELETE_COPY(LayoutRenderObject) - CRU_DELETE_MOVE(LayoutRenderObject) - - ~LayoutRenderObject() override = default; - - ChildLayoutData* GetChildLayoutData(Index position) { - Expects(position >= 0 && - position < static_cast(child_layout_data_.size())); - return &child_layout_data_[position]; - } - - void Draw(platform::graph::IPainter* painter) override; - - RenderObject* HitTest(const Point& point) override; - - protected: - void OnAddChild(RenderObject* new_child, Index position) override; - void OnRemoveChild(RenderObject* removed_child, Index position) override; - - private: - std::vector child_layout_data_{}; -}; - -template -void LayoutRenderObject::Draw( - platform::graph::IPainter* painter) { - for (const auto child : GetChildren()) { - auto offset = child->GetOffset(); - platform::graph::util::WithTransform( - painter, platform::Matrix::Translation(offset.x, offset.y), - [child](auto p) { child->Draw(p); }); - } -} - -template -RenderObject* LayoutRenderObject::HitTest( - const Point& point) { - const auto& children = GetChildren(); - for (auto i = children.crbegin(); i != children.crend(); ++i) { - auto offset = (*i)->GetOffset(); - Point p{point.x - offset.x, point.y - offset.y}; - const auto result = (*i)->HitTest(p); - if (result != nullptr) { - return result; - } - } - - const auto margin = GetMargin(); - const auto size = GetSize(); - return Rect{margin.left, margin.top, - std::max(size.width - margin.GetHorizontalTotal(), 0.0f), - std::max(size.height - margin.GetVerticalTotal(), 0.0f)} - .IsPointInside(point) - ? this - : nullptr; -} // namespace cru::ui::render - -template -void LayoutRenderObject::OnAddChild(RenderObject* new_child, - const Index position) { - CRU_UNUSED(new_child) - - child_layout_data_.emplace(child_layout_data_.cbegin() + position); -} - -template -void LayoutRenderObject::OnRemoveChild( - RenderObject* removed_child, const Index position) { - CRU_UNUSED(removed_child) - - child_layout_data_.erase(child_layout_data_.cbegin() + position); -} -} // namespace cru::ui::render diff --git a/include/cru/ui/render/layout_utility.hpp b/include/cru/ui/render/layout_utility.hpp deleted file mode 100644 index 16a15d87..00000000 --- a/include/cru/ui/render/layout_utility.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include "base.hpp" - -namespace cru::ui::render { -Size Min(const Size& left, const Size& right); -Size Max(const Size& left, const Size& right); -} // namespace cru::ui::render diff --git a/include/cru/ui/render/render_object.hpp b/include/cru/ui/render/render_object.hpp deleted file mode 100644 index 6a8db52f..00000000 --- a/include/cru/ui/render/render_object.hpp +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once -#include "base.hpp" - -#include "cru/common/event.hpp" - -namespace cru::ui::render { -// Render object will not destroy its children when destroyed. Control must -// manage lifecycle of its render objects. Since control will destroy its -// children when destroyed, render objects will be destroyed along with it. -class RenderObject : public Object { - friend WindowRenderObject; - - protected: - enum class ChildMode { - None, - Single, - Multiple, - }; - - RenderObject() = default; - RenderObject(ChildMode child_mode) : RenderObject() { - SetChildMode(child_mode); - } - - public: - RenderObject(const RenderObject& other) = delete; - RenderObject(RenderObject&& other) = delete; - RenderObject& operator=(const RenderObject& other) = delete; - RenderObject& operator=(RenderObject&& other) = delete; - ~RenderObject() override = default; - - Control* GetAttachedControl() const { return control_; } - void SetAttachedControl(Control* new_control) { control_ = new_control; } - - UiHost* GetUiHost() const { return ui_host_; } - - RenderObject* GetParent() const { return parent_; } - - const std::vector& GetChildren() const { return children_; } - Index GetChildCount() const { return static_cast(children_.size()); } - void AddChild(RenderObject* render_object, Index position); - void RemoveChild(Index position); - - Point GetOffset() const { return offset_; } - void SetOffset(const Point& offset) { offset_ = offset; } - Point GetTotalOffset() const; - Point FromRootToContent(const Point& point) const; - Size GetSize() const { return size_; } - void SetSize(const Size& size) { size_ = size; } - - Thickness GetMargin() const { return margin_; } - void SetMargin(const Thickness& margin) { margin_ = margin; } - - Thickness GetPadding() const { return padding_; } - void SetPadding(const Thickness& padding) { padding_ = padding; } - - Size GetPreferredSize() const { return preferred_size_; } - void SetPreferredSize(const Size& preferred_size) { - preferred_size_ = preferred_size; - } - - void Measure(const Size& available_size); - void Layout(const Rect& rect); - - virtual void Draw(platform::graph::IPainter* painter) = 0; - - virtual RenderObject* HitTest(const Point& point) = 0; - - public: - void InvalidateLayout(); - void InvalidatePaint(); - - protected: - void SetChildMode(ChildMode mode) { child_mode_ = mode; } - - protected: - virtual void OnParentChanged(RenderObject* old_parent, - RenderObject* new_parent); - - // default is to invalidate both layout and paint - virtual void OnAddChild(RenderObject* new_child, Index position); - // default is to invalidate both layout and paint - virtual void OnRemoveChild(RenderObject* removed_child, Index position); - - virtual void OnMeasureCore(const Size& available_size); - virtual void OnLayoutCore(const Rect& rect); - virtual Size OnMeasureContent(const Size& available_size) = 0; - virtual void OnLayoutContent(const Rect& content_rect) = 0; - - virtual void OnAfterLayout(); - static void NotifyAfterLayoutRecursive(RenderObject* render_object); - - Rect GetPaddingRect() const; - Rect GetContentRect() const; - - private: - void SetParent(RenderObject* new_parent); - - void SetRenderHostRecursive(UiHost* host); - - private: - Control* control_ = nullptr; - UiHost* ui_host_ = nullptr; - - RenderObject* parent_ = nullptr; - std::vector children_{}; - - ChildMode child_mode_ = ChildMode::None; - - Point offset_{}; - Size size_{}; - - Thickness margin_{}; - Thickness padding_{}; - - Size preferred_size_{}; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/scroll_render_object.hpp b/include/cru/ui/render/scroll_render_object.hpp deleted file mode 100644 index 1527db6c..00000000 --- a/include/cru/ui/render/scroll_render_object.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -#include "render_object.hpp" - -#include "cru/platform/graph/util/painter.hpp" - -namespace cru::ui::render { -class ScrollRenderObject : public RenderObject { - public: - ScrollRenderObject() : RenderObject(ChildMode::Single) {} - - CRU_DELETE_COPY(ScrollRenderObject) - CRU_DELETE_MOVE(ScrollRenderObject) - - ~ScrollRenderObject() override = default; - - void Draw(platform::graph::IPainter* painter) override; - - RenderObject* HitTest(const Point& point) override; - - Point GetScrollOffset() { return scroll_offset_; } - void SetScrollOffset(const Point& offset); - - protected: - void OnAddChild(RenderObject* new_child, Index position) override; - void OnRemoveChild(RenderObject* removed_child, Index position) override; - - private: - Point scroll_offset_; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/stack_layout_render_object.hpp b/include/cru/ui/render/stack_layout_render_object.hpp deleted file mode 100644 index c259b98d..00000000 --- a/include/cru/ui/render/stack_layout_render_object.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "layout_render_object.hpp" - -namespace cru::ui::render { -class StackLayoutRenderObject - : public LayoutRenderObject { - public: - StackLayoutRenderObject() = default; - CRU_DELETE_COPY(StackLayoutRenderObject) - CRU_DELETE_MOVE(StackLayoutRenderObject) - ~StackLayoutRenderObject() = default; - - protected: - Size OnMeasureContent(const Size& available_size) override; - void OnLayoutContent(const Rect& content_rect) override; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/text_render_object.hpp b/include/cru/ui/render/text_render_object.hpp deleted file mode 100644 index 4b1e91e0..00000000 --- a/include/cru/ui/render/text_render_object.hpp +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once -#include "render_object.hpp" - -#include - -namespace cru::ui::render { -class TextRenderObject : public RenderObject { - public: - constexpr static float default_caret_width = 2; - - public: - TextRenderObject(std::shared_ptr brush, - std::shared_ptr font, - std::shared_ptr selection_brush, - std::shared_ptr caret_brush); - TextRenderObject(const TextRenderObject& other) = delete; - TextRenderObject(TextRenderObject&& other) = delete; - TextRenderObject& operator=(const TextRenderObject& other) = delete; - TextRenderObject& operator=(TextRenderObject&& other) = delete; - ~TextRenderObject() override; - - std::string GetText() const; - void SetText(std::string new_text); - - std::shared_ptr GetBrush() const { return brush_; } - void SetBrush(std::shared_ptr new_brush); - - std::shared_ptr GetFont() const; - void SetFont(std::shared_ptr font); - - std::vector TextRangeRect(const TextRange& text_range); - Point TextSinglePoint(gsl::index position, bool trailing); - platform::graph::TextHitTestResult TextHitTest(const Point& point); - - std::optional GetSelectionRange() const { - return selection_range_; - } - void SetSelectionRange(std::optional new_range); - - std::shared_ptr GetSelectionBrush() const { - return selection_brush_; - } - void SetSelectionBrush(std::shared_ptr new_brush); - - bool IsDrawCaret() const { return draw_caret_; } - void SetDrawCaret(bool draw_caret); - void ToggleDrawCaret() { SetDrawCaret(!IsDrawCaret()); } - - // Caret position can be any value. When it is negative, 0 is used. When it - // exceeds the size of the string, the size of the string is used. - gsl::index GetCaretPosition() const { return caret_position_; } - void SetCaretPosition(gsl::index position); - - std::shared_ptr GetCaretBrush() const { - return caret_brush_; - } - void GetCaretBrush(std::shared_ptr brush); - - float GetCaretWidth() const { return caret_width_; } - void SetCaretWidth(float width); - - void Draw(platform::graph::IPainter* painter) override; - - RenderObject* HitTest(const Point& point) override; - - protected: - Size OnMeasureContent(const Size& available_size) override; - void OnLayoutContent(const Rect& content_rect) override; - - void OnAfterLayout() override; - - private: - std::shared_ptr brush_; - std::shared_ptr font_; - std::unique_ptr text_layout_; - - std::optional selection_range_ = std::nullopt; - std::shared_ptr selection_brush_; - - bool draw_caret_ = false; - gsl::index caret_position_ = 0; - std::shared_ptr caret_brush_; - float caret_width_ = default_caret_width; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/window_render_object.hpp b/include/cru/ui/render/window_render_object.hpp deleted file mode 100644 index 76b17b82..00000000 --- a/include/cru/ui/render/window_render_object.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -#include "render_object.hpp" - -namespace cru::ui::render { -class WindowRenderObject : public RenderObject { - public: - WindowRenderObject(UiHost* host); - WindowRenderObject(const WindowRenderObject& other) = delete; - WindowRenderObject(WindowRenderObject&& other) = delete; - WindowRenderObject& operator=(const WindowRenderObject& other) = delete; - WindowRenderObject& operator=(WindowRenderObject&& other) = delete; - ~WindowRenderObject() override = default; - - void Draw(platform::graph::IPainter* painter) override; - - RenderObject* HitTest(const Point& point) override; - - protected: - Size OnMeasureContent(const Size& available_size) override; - void OnLayoutContent(const Rect& content_rect) override; - - private: - RenderObject* GetChild() const { - return GetChildren().empty() ? nullptr : GetChildren()[0]; - } - - private: - EventRevokerGuard after_layout_event_guard_; -}; -} // namespace cru::ui::render -- cgit v1.2.3