aboutsummaryrefslogtreecommitdiff
path: root/include/cru/ui/render
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-06-22 01:09:24 +0800
committercrupest <crupest@outlook.com>2020-06-22 01:09:24 +0800
commit4f0a2f32c273780c32cc3937615c2a8bbd993aab (patch)
tree6e1f45447854a40fe2d16ef9bec79f3c0fef030a /include/cru/ui/render
parentd86a71f79afe0e4dac768f61d6bff690567aca5b (diff)
downloadcru-4f0a2f32c273780c32cc3937615c2a8bbd993aab.tar.gz
cru-4f0a2f32c273780c32cc3937615c2a8bbd993aab.tar.bz2
cru-4f0a2f32c273780c32cc3937615c2a8bbd993aab.zip
...
Diffstat (limited to 'include/cru/ui/render')
-rw-r--r--include/cru/ui/render/BorderRenderObject.hpp8
-rw-r--r--include/cru/ui/render/CanvasRenderObject.hpp2
-rw-r--r--include/cru/ui/render/FlexLayoutRenderObject.hpp2
-rw-r--r--include/cru/ui/render/MeasureRequirement.hpp79
-rw-r--r--include/cru/ui/render/RenderObject.hpp48
-rw-r--r--include/cru/ui/render/ScrollRenderObject.hpp8
-rw-r--r--include/cru/ui/render/StackLayoutRenderObject.hpp2
-rw-r--r--include/cru/ui/render/TextRenderObject.hpp2
-rw-r--r--include/cru/ui/render/WindowRenderObject.hpp2
9 files changed, 130 insertions, 23 deletions
diff --git a/include/cru/ui/render/BorderRenderObject.hpp b/include/cru/ui/render/BorderRenderObject.hpp
index c3031f59..45df89f9 100644
--- a/include/cru/ui/render/BorderRenderObject.hpp
+++ b/include/cru/ui/render/BorderRenderObject.hpp
@@ -67,9 +67,9 @@ class BorderRenderObject : public RenderObject {
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;
+ Size OnMeasureCore(const MeasureRequirement& requirement) override;
+ void OnLayoutCore(const Size& size) override;
+ Size OnMeasureContent(const MeasureRequirement& requirement) override;
void OnLayoutContent(const Rect& content_rect) override;
void OnAfterLayout() override;
@@ -85,7 +85,7 @@ class BorderRenderObject : public RenderObject {
bool is_border_enabled_ = false;
std::shared_ptr<platform::graph::IBrush> border_brush_;
- platform::Thickness border_thickness_;
+ Thickness border_thickness_;
CornerRadius border_radius_;
std::shared_ptr<platform::graph::IBrush> foreground_brush_;
diff --git a/include/cru/ui/render/CanvasRenderObject.hpp b/include/cru/ui/render/CanvasRenderObject.hpp
index ba50a985..402302cb 100644
--- a/include/cru/ui/render/CanvasRenderObject.hpp
+++ b/include/cru/ui/render/CanvasRenderObject.hpp
@@ -28,7 +28,7 @@ class CanvasRenderObject : public RenderObject {
IEvent<CanvasPaintEventArgs>* PaintEvent() { return &paint_event_; }
protected:
- Size OnMeasureContent(const Size& available_size) override;
+ Size OnMeasureContent(const MeasureRequirement& requirement) override;
void OnLayoutContent(const Rect& content_rect) override;
private:
diff --git a/include/cru/ui/render/FlexLayoutRenderObject.hpp b/include/cru/ui/render/FlexLayoutRenderObject.hpp
index bc43141d..217ca6cb 100644
--- a/include/cru/ui/render/FlexLayoutRenderObject.hpp
+++ b/include/cru/ui/render/FlexLayoutRenderObject.hpp
@@ -31,7 +31,7 @@ class FlexLayoutRenderObject : public LayoutRenderObject<FlexChildLayoutData> {
}
protected:
- Size OnMeasureContent(const Size& available_size) override;
+ Size OnMeasureContent(const MeasureRequirement& requirement) override;
void OnLayoutContent(const Rect& content_rect) override;
private:
diff --git a/include/cru/ui/render/MeasureRequirement.hpp b/include/cru/ui/render/MeasureRequirement.hpp
new file mode 100644
index 00000000..83de255d
--- /dev/null
+++ b/include/cru/ui/render/MeasureRequirement.hpp
@@ -0,0 +1,79 @@
+#pragma once
+#include "Base.hpp"
+
+#include <limits>
+
+namespace cru::ui::render {
+class MeasureLength {
+ public:
+ struct tag_infinate_t {};
+ constexpr static tag_infinate_t tag_infinate{};
+
+ constexpr MeasureLength() : MeasureLength(0) {}
+ constexpr MeasureLength(tag_infinate_t) : length_(-1) {}
+ constexpr MeasureLength(float length) : length_(length) {
+ Expects(length >= 0);
+ }
+
+ MeasureLength(const MeasureLength& other) = default;
+ MeasureLength& operator=(const MeasureLength& other) = default;
+ MeasureLength& operator=(float length) {
+ Expects(length >= 0);
+ length_ = length;
+ return *this;
+ }
+
+ ~MeasureLength() = default;
+
+ constexpr static MeasureLength Infinate() {
+ return MeasureLength{tag_infinate};
+ }
+
+ constexpr bool IsInfinate() const { return length_ < 0; }
+ constexpr float GetLength() const {
+ return length_ < 0 ? std::numeric_limits<float>::max() : length_;
+ }
+
+ constexpr bool operator==(MeasureLength other) const {
+ return (length_ < 0 && other.length_ < 0) || length_ == other.length_;
+ }
+
+ constexpr bool operator!=(MeasureLength other) const {
+ return !operator==(other);
+ }
+
+ private:
+ // -1 for infinate
+ float length_;
+};
+
+struct MeasureRequirement {
+ MeasureLength max_width;
+ MeasureLength max_height;
+
+ constexpr MeasureRequirement() = default;
+ constexpr MeasureRequirement(MeasureLength max_width,
+ MeasureLength max_height)
+ : max_width(max_width), max_height(max_height) {}
+
+ constexpr MeasureRequirement(const Size& max_size)
+ : max_width(max_size.width), max_height(max_size.height) {}
+
+ constexpr bool Satisfy(const Size& size) const {
+ if (!max_width.IsInfinate() && max_width.GetLength() < size.width)
+ return false;
+ if (!max_height.IsInfinate() && max_height.GetLength() < size.height)
+ return false;
+ return true;
+ }
+
+ constexpr Size GetMaxSize() const {
+ return Size{max_width.GetLength(), max_height.GetLength()};
+ }
+
+ constexpr static MeasureRequirement Infinate() {
+ return MeasureRequirement{MeasureLength::Infinate(),
+ MeasureLength::Infinate()};
+ }
+};
+} // namespace cru::ui::render
diff --git a/include/cru/ui/render/RenderObject.hpp b/include/cru/ui/render/RenderObject.hpp
index 7cfa3883..9de2cc27 100644
--- a/include/cru/ui/render/RenderObject.hpp
+++ b/include/cru/ui/render/RenderObject.hpp
@@ -1,12 +1,22 @@
#pragma once
#include "Base.hpp"
+#include "MeasureRequirement.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.
+//
+// To write a custom RenderObject, override following methods:
+// public:
+// void Draw(platform::graph::IPainter* painter) override;
+// RenderObject* HitTest(const Point& point) override;
+// protected:
+// Size OnMeasureContent(const MeasureRequirement& requirement) override;
+// void OnLayoutContent(const Rect& content_rect) override;
class RenderObject : public Object {
friend WindowRenderObject;
@@ -41,12 +51,12 @@ class RenderObject : public Object {
void AddChild(RenderObject* render_object, Index position);
void RemoveChild(Index position);
+ // Offset from parent's lefttop to lefttop of this render object. Margin is
+ // accounted for.
Point GetOffset() const { return offset_; }
- void SetOffset(const Point& offset) { offset_ = offset; }
+ Size GetSize() const { return size_; }
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; }
@@ -54,16 +64,16 @@ class RenderObject : public Object {
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;
- }
+ Size GetMeasuredSize() const { return measured_size_; }
- void Measure(const Size& available_size);
+ void Measure(const MeasureRequirement& requirement);
+ // Size of rect must not be negative.
void Layout(const Rect& rect);
virtual void Draw(platform::graph::IPainter* painter) = 0;
+ // Param point must be relative the lefttop of render object including margin.
+ // Add offset before pass point to children.
virtual RenderObject* HitTest(const Point& point) = 0;
public:
@@ -82,9 +92,23 @@ class RenderObject : public Object {
// 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;
+ // Size measure including margin and padding. Please reduce margin and padding
+ // or other custom things and pass the result content measure requirement to
+ // OnMeasureContent.
+ // Return value must not be negative and not bigger than requirement.
+ virtual Size OnMeasureCore(const MeasureRequirement& requirement);
+
+ // Size including margin and padding. Please reduce margin and padding or
+ // other custom things and pass the result content rect to OnLayoutContent.
+ // Parameter size are never negative.
+ virtual void OnLayoutCore(const Size& size);
+
+ // Do not consider margin or padding in this method because they are already
+ // considered in OnMeasureCore. Returned size should never be bigger than
+ // requirement.
+ virtual Size OnMeasureContent(const MeasureRequirement& requirement) = 0;
+
+ // Lefttop of content_rect should be added when calculated children's offset.
virtual void OnLayoutContent(const Rect& content_rect) = 0;
virtual void OnAfterLayout();
@@ -113,6 +137,6 @@ class RenderObject : public Object {
Thickness margin_{};
Thickness padding_{};
- Size preferred_size_{};
+ Size measured_size_{};
};
} // namespace cru::ui::render
diff --git a/include/cru/ui/render/ScrollRenderObject.hpp b/include/cru/ui/render/ScrollRenderObject.hpp
index dcf6dae6..924b8ca6 100644
--- a/include/cru/ui/render/ScrollRenderObject.hpp
+++ b/include/cru/ui/render/ScrollRenderObject.hpp
@@ -21,8 +21,12 @@ class ScrollRenderObject : public RenderObject {
void SetScrollOffset(const Point& offset);
protected:
- void OnAddChild(RenderObject* new_child, Index position) override;
- void OnRemoveChild(RenderObject* removed_child, Index position) override;
+ // Logic:
+ // If available size is bigger than child's preferred size, then child's
+ // preferred size is taken.
+ // If not, all available size is taken while forming a scroll area.
+ Size OnMeasureContent(const MeasureRequirement& requirement) override;
+ void OnLayoutContent(const Rect& content_rect) override;
private:
Point scroll_offset_;
diff --git a/include/cru/ui/render/StackLayoutRenderObject.hpp b/include/cru/ui/render/StackLayoutRenderObject.hpp
index a5bf9335..2320e1ca 100644
--- a/include/cru/ui/render/StackLayoutRenderObject.hpp
+++ b/include/cru/ui/render/StackLayoutRenderObject.hpp
@@ -11,7 +11,7 @@ class StackLayoutRenderObject
~StackLayoutRenderObject() = default;
protected:
- Size OnMeasureContent(const Size& available_size) override;
+ Size OnMeasureContent(const MeasureRequirement& requirement) 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
index 7a81ba51..96bb5997 100644
--- a/include/cru/ui/render/TextRenderObject.hpp
+++ b/include/cru/ui/render/TextRenderObject.hpp
@@ -64,7 +64,7 @@ class TextRenderObject : public RenderObject {
RenderObject* HitTest(const Point& point) override;
protected:
- Size OnMeasureContent(const Size& available_size) override;
+ Size OnMeasureContent(const MeasureRequirement& requirement) override;
void OnLayoutContent(const Rect& content_rect) override;
void OnAfterLayout() override;
diff --git a/include/cru/ui/render/WindowRenderObject.hpp b/include/cru/ui/render/WindowRenderObject.hpp
index 00bce29b..d993dc58 100644
--- a/include/cru/ui/render/WindowRenderObject.hpp
+++ b/include/cru/ui/render/WindowRenderObject.hpp
@@ -16,7 +16,7 @@ class WindowRenderObject : public RenderObject {
RenderObject* HitTest(const Point& point) override;
protected:
- Size OnMeasureContent(const Size& available_size) override;
+ Size OnMeasureContent(const MeasureRequirement& requirement) override;
void OnLayoutContent(const Rect& content_rect) override;
private: