aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/ui/Base.hpp8
-rw-r--r--include/cru/ui/render/BorderRenderObject.hpp4
-rw-r--r--include/cru/ui/render/CanvasRenderObject.hpp4
-rw-r--r--include/cru/ui/render/LayoutRenderObject.hpp13
-rw-r--r--include/cru/ui/render/RenderObject.hpp13
-rw-r--r--include/cru/ui/render/ScrollRenderObject.hpp7
-rw-r--r--include/cru/ui/render/TextRenderObject.hpp4
-rw-r--r--include/cru/ui/render/WindowRenderObject.hpp2
-rw-r--r--src/ui/UiHost.cpp1
-rw-r--r--src/ui/render/BorderRenderObject.cpp43
-rw-r--r--src/ui/render/CanvasRenderObject.cpp12
-rw-r--r--src/ui/render/RenderObject.cpp31
-rw-r--r--src/ui/render/ScrollRenderObject.cpp23
-rw-r--r--src/ui/render/TextRenderObject.cpp68
-rw-r--r--src/ui/render/WindowRenderObject.cpp10
15 files changed, 128 insertions, 115 deletions
diff --git a/include/cru/ui/Base.hpp b/include/cru/ui/Base.hpp
index b9ce0c88..c59d1b60 100644
--- a/include/cru/ui/Base.hpp
+++ b/include/cru/ui/Base.hpp
@@ -243,18 +243,18 @@ struct BorderStyle {
class CanvasPaintEventArgs {
public:
CanvasPaintEventArgs(platform::graph::IPainter* painter,
- const Rect& paint_rect)
- : painter_(painter), paint_rect_(paint_rect) {}
+ const Size& paint_size)
+ : painter_(painter), paint_size_(paint_size) {}
CRU_DEFAULT_COPY(CanvasPaintEventArgs)
CRU_DEFAULT_MOVE(CanvasPaintEventArgs)
~CanvasPaintEventArgs() = default;
platform::graph::IPainter* GetPainter() const { return painter_; }
- Rect GetPaintRect() const { return paint_rect_; }
+ Size GetPaintSize() const { return paint_size_; }
private:
platform::graph::IPainter* painter_;
- Rect paint_rect_;
+ Size paint_size_;
};
enum class FlexDirection {
diff --git a/include/cru/ui/render/BorderRenderObject.hpp b/include/cru/ui/render/BorderRenderObject.hpp
index 6c33473a..db989453 100644
--- a/include/cru/ui/render/BorderRenderObject.hpp
+++ b/include/cru/ui/render/BorderRenderObject.hpp
@@ -62,11 +62,11 @@ class BorderRenderObject : public RenderObject {
void SetBorderStyle(const BorderStyle& style);
- void Draw(platform::graph::IPainter* painter) override;
-
RenderObject* HitTest(const Point& point) override;
protected:
+ void OnDrawCore(platform::graph::IPainter* painter) override;
+
Size OnMeasureCore(const MeasureRequirement& requirement,
const MeasureSize& preferred_size) override;
void OnLayoutCore() override;
diff --git a/include/cru/ui/render/CanvasRenderObject.hpp b/include/cru/ui/render/CanvasRenderObject.hpp
index 323b4800..3216f08c 100644
--- a/include/cru/ui/render/CanvasRenderObject.hpp
+++ b/include/cru/ui/render/CanvasRenderObject.hpp
@@ -15,8 +15,6 @@ class CanvasRenderObject : public RenderObject {
~CanvasRenderObject();
public:
- void Draw(platform::graph::IPainter* painter) override;
-
RenderObject* HitTest(const Point& point) override;
Size GetDesiredSize() const { return desired_size_; }
@@ -24,6 +22,8 @@ class CanvasRenderObject : public RenderObject {
IEvent<CanvasPaintEventArgs>* PaintEvent() { return &paint_event_; }
protected:
+ void OnDrawContent(platform::graph::IPainter* painter) override;
+
Size OnMeasureContent(const MeasureRequirement& requirement,
const MeasureSize& preferred_size) override;
void OnLayoutContent(const Rect& content_rect) override;
diff --git a/include/cru/ui/render/LayoutRenderObject.hpp b/include/cru/ui/render/LayoutRenderObject.hpp
index 1eb9a816..b46ba0d0 100644
--- a/include/cru/ui/render/LayoutRenderObject.hpp
+++ b/include/cru/ui/render/LayoutRenderObject.hpp
@@ -35,8 +35,6 @@ class LayoutRenderObject : public RenderObject {
return this->child_layout_data_[position];
}
- void Draw(platform::graph::IPainter* painter) override;
-
RenderObject* HitTest(const Point& point) override;
protected:
@@ -48,17 +46,6 @@ class LayoutRenderObject : public RenderObject {
};
template <typename TChildLayoutData>
-void LayoutRenderObject<TChildLayoutData>::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 <typename TChildLayoutData>
RenderObject* LayoutRenderObject<TChildLayoutData>::HitTest(
const Point& point) {
const auto& children = GetChildren();
diff --git a/include/cru/ui/render/RenderObject.hpp b/include/cru/ui/render/RenderObject.hpp
index 09f140db..2d9cd817 100644
--- a/include/cru/ui/render/RenderObject.hpp
+++ b/include/cru/ui/render/RenderObject.hpp
@@ -121,7 +121,7 @@ class RenderObject : public Object {
// This will set offset of this render object and call OnLayoutCore.
void Layout(const Point& offset);
- virtual void Draw(platform::graph::IPainter* painter) = 0;
+ void Draw(platform::graph::IPainter* painter);
// Param point must be relative the lefttop of render object including margin.
// Add offset before pass point to children.
@@ -145,6 +145,17 @@ class RenderObject : public Object {
// default is to invalidate both layout and paint
virtual void OnRemoveChild(RenderObject* removed_child, Index position);
+ // Draw all children with offset.
+ void DefaultDrawChildren(platform::graph::IPainter* painter);
+
+ // Draw all children with translation of content rect lefttop.
+ void DefaultDrawContent(platform::graph::IPainter* painter);
+
+ // Call DefaultDrawContent. Then call DefaultDrawChildren.
+ virtual void OnDrawCore(platform::graph::IPainter* painter);
+
+ virtual void OnDrawContent(platform::graph::IPainter* painter);
+
// Size measure including margin and padding. Please reduce margin and padding
// or other custom things and pass the result content measure requirement and
// preferred size to OnMeasureContent. Return value must not be negative and
diff --git a/include/cru/ui/render/ScrollRenderObject.hpp b/include/cru/ui/render/ScrollRenderObject.hpp
index 9799c0d9..43e6d7f9 100644
--- a/include/cru/ui/render/ScrollRenderObject.hpp
+++ b/include/cru/ui/render/ScrollRenderObject.hpp
@@ -13,8 +13,6 @@ class ScrollRenderObject : public RenderObject {
~ScrollRenderObject() override = default;
- void Draw(platform::graph::IPainter* painter) override;
-
RenderObject* HitTest(const Point& point) override;
// Return the coerced scroll offset.
@@ -23,11 +21,14 @@ class ScrollRenderObject : public RenderObject {
Point GetRawScrollOffset() const { return scroll_offset_; }
protected:
+ void OnDrawCore(platform::graph::IPainter* painter) 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, const MeasureSize& preferred_size) override;
+ Size OnMeasureContent(const MeasureRequirement& requirement,
+ const MeasureSize& preferred_size) override;
void OnLayoutContent(const Rect& content_rect) override;
private:
diff --git a/include/cru/ui/render/TextRenderObject.hpp b/include/cru/ui/render/TextRenderObject.hpp
index efa8c2b8..26c8db40 100644
--- a/include/cru/ui/render/TextRenderObject.hpp
+++ b/include/cru/ui/render/TextRenderObject.hpp
@@ -72,11 +72,11 @@ class TextRenderObject : public RenderObject {
float GetCaretWidth() const { return caret_width_; }
void SetCaretWidth(float width);
- void Draw(platform::graph::IPainter* painter) override;
-
RenderObject* HitTest(const Point& point) override;
protected:
+ void OnDrawContent(platform::graph::IPainter* painter) override;
+
// See remarks of this class.
Size OnMeasureContent(const MeasureRequirement& requirement,
const MeasureSize& preferred_size) override;
diff --git a/include/cru/ui/render/WindowRenderObject.hpp b/include/cru/ui/render/WindowRenderObject.hpp
index d64a216d..4c254f42 100644
--- a/include/cru/ui/render/WindowRenderObject.hpp
+++ b/include/cru/ui/render/WindowRenderObject.hpp
@@ -11,8 +11,6 @@ class WindowRenderObject : public RenderObject {
WindowRenderObject& operator=(WindowRenderObject&& other) = delete;
~WindowRenderObject() override = default;
- void Draw(platform::graph::IPainter* painter) override;
-
RenderObject* HitTest(const Point& point) override;
protected:
diff --git a/src/ui/UiHost.cpp b/src/ui/UiHost.cpp
index 56ce1eb9..9bde06ad 100644
--- a/src/ui/UiHost.cpp
+++ b/src/ui/UiHost.cpp
@@ -231,6 +231,7 @@ void UiHost::OnNativeDestroy(INativeWindow* window, std::nullptr_t) {
void UiHost::OnNativePaint(INativeWindow* window, std::nullptr_t) {
auto painter = window->BeginPaint();
+ painter->Clear(colors::white);
root_render_object_->Draw(painter.get());
painter->EndDraw();
}
diff --git a/src/ui/render/BorderRenderObject.cpp b/src/ui/render/BorderRenderObject.cpp
index 74e50561..6513c4c4 100644
--- a/src/ui/render/BorderRenderObject.cpp
+++ b/src/ui/render/BorderRenderObject.cpp
@@ -16,28 +16,6 @@ BorderRenderObject::BorderRenderObject() {
BorderRenderObject::~BorderRenderObject() {}
-void BorderRenderObject::Draw(platform::graph::IPainter* painter) {
- if (background_brush_ != nullptr)
- painter->FillGeometry(border_inner_geometry_.get(),
- background_brush_.get());
- if (is_border_enabled_) {
- if (border_brush_ == nullptr) {
- log::Warn("Border is enabled but brush is null");
- } else {
- painter->FillGeometry(geometry_.get(), border_brush_.get());
- }
- }
- if (const auto child = GetSingleChild()) {
- auto offset = child->GetOffset();
- platform::graph::util::WithTransform(
- painter, platform::Matrix::Translation(offset.x, offset.y),
- [child](auto p) { child->Draw(p); });
- }
- if (foreground_brush_ != nullptr)
- painter->FillGeometry(border_inner_geometry_.get(),
- foreground_brush_.get());
-}
-
void BorderRenderObject::SetBorderStyle(const BorderStyle& style) {
border_brush_ = style.border_brush;
border_thickness_ = style.border_thickness;
@@ -73,6 +51,27 @@ RenderObject* BorderRenderObject::HitTest(const Point& point) {
}
}
+void BorderRenderObject::OnDrawCore(platform::graph::IPainter* painter) {
+ if (background_brush_ != nullptr)
+ painter->FillGeometry(border_inner_geometry_.get(),
+ background_brush_.get());
+ if (is_border_enabled_) {
+ if (border_brush_ == nullptr) {
+ log::Warn("Border is enabled but brush is null");
+ } else {
+ painter->FillGeometry(geometry_.get(), border_brush_.get());
+ }
+ }
+
+ DefaultDrawContent(painter);
+
+ if (foreground_brush_ != nullptr)
+ painter->FillGeometry(border_inner_geometry_.get(),
+ foreground_brush_.get());
+
+ DefaultDrawChildren(painter);
+}
+
Size BorderRenderObject::OnMeasureCore(const MeasureRequirement& requirement,
const MeasureSize& preferred_size) {
if (!is_border_enabled_) {
diff --git a/src/ui/render/CanvasRenderObject.cpp b/src/ui/render/CanvasRenderObject.cpp
index 211d1fce..967fdcec 100644
--- a/src/ui/render/CanvasRenderObject.cpp
+++ b/src/ui/render/CanvasRenderObject.cpp
@@ -5,17 +5,17 @@ CanvasRenderObject::CanvasRenderObject() : RenderObject(ChildMode::None) {}
CanvasRenderObject::~CanvasRenderObject() = default;
-void CanvasRenderObject::Draw(platform::graph::IPainter* painter) {
- const auto rect = GetContentRect();
- CanvasPaintEventArgs args{painter, rect};
- paint_event_.Raise(args);
-}
-
RenderObject* CanvasRenderObject::HitTest(const Point& point) {
const auto padding_rect = GetPaddingRect();
return padding_rect.IsPointInside(point) ? this : nullptr;
}
+void CanvasRenderObject::OnDrawContent(platform::graph::IPainter* painter) {
+ const auto rect = GetContentRect();
+ CanvasPaintEventArgs args{painter, rect.GetSize()};
+ paint_event_.Raise(args);
+}
+
Size CanvasRenderObject::OnMeasureContent(const MeasureRequirement& requirement,
const MeasureSize& preferred_size) {
return requirement.Coerce(Size{preferred_size.width.GetLengthOr(100),
diff --git a/src/ui/render/RenderObject.cpp b/src/ui/render/RenderObject.cpp
index ac38c6b5..d9977f2a 100644
--- a/src/ui/render/RenderObject.cpp
+++ b/src/ui/render/RenderObject.cpp
@@ -1,6 +1,7 @@
#include "cru/ui/render/RenderObject.hpp"
#include "cru/common/Logger.hpp"
+#include "cru/platform/graph/util/Painter.hpp"
#include "cru/ui/UiHost.hpp"
#include <algorithm>
@@ -76,6 +77,10 @@ void RenderObject::Layout(const Point& offset) {
OnLayoutCore();
}
+void RenderObject::Draw(platform::graph::IPainter* painter) {
+ OnDrawCore(painter);
+}
+
RenderObject* RenderObject::GetSingleChild() const {
Expects(child_mode_ == ChildMode::Single);
const auto& children = GetChildren();
@@ -107,6 +112,32 @@ void RenderObject::OnRemoveChild(RenderObject* removed_child, Index position) {
InvalidatePaint();
}
+void RenderObject::DefaultDrawChildren(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); });
+ }
+}
+
+void RenderObject::DefaultDrawContent(platform::graph::IPainter* painter) {
+ const auto content_rect = GetContentRect();
+
+ platform::graph::util::WithTransform(
+ painter, Matrix::Translation(content_rect.left, content_rect.top),
+ [this](auto p) { this->OnDrawContent(p); });
+}
+
+void RenderObject::OnDrawCore(platform::graph::IPainter* painter) {
+ DefaultDrawContent(painter);
+ DefaultDrawChildren(painter);
+}
+
+void RenderObject::OnDrawContent(platform::graph::IPainter* painter) {
+ CRU_UNUSED(painter);
+}
+
Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement,
const MeasureSize& preferred_size) {
const Size space_size{
diff --git a/src/ui/render/ScrollRenderObject.cpp b/src/ui/render/ScrollRenderObject.cpp
index e4cc27f3..aab8c003 100644
--- a/src/ui/render/ScrollRenderObject.cpp
+++ b/src/ui/render/ScrollRenderObject.cpp
@@ -31,17 +31,6 @@ Point CoerceScroll(const Point& scroll_offset, const Size& content_size,
}
} // namespace
-void ScrollRenderObject::Draw(platform::graph::IPainter* painter) {
- if (const auto child = GetSingleChild()) {
- painter->PushLayer(this->GetPaddingRect());
- const auto offset = child->GetOffset();
- platform::graph::util::WithTransform(
- painter, Matrix::Translation(offset.x, offset.y),
- [child](platform::graph::IPainter* p) { child->Draw(p); });
- painter->PopLayer();
- }
-}
-
RenderObject* ScrollRenderObject::HitTest(const Point& point) {
if (const auto child = GetSingleChild()) {
const auto offset = child->GetOffset();
@@ -53,6 +42,18 @@ RenderObject* ScrollRenderObject::HitTest(const Point& point) {
return rect.IsPointInside(point) ? this : nullptr;
} // namespace cru::ui::render
+void ScrollRenderObject::OnDrawCore(platform::graph::IPainter* painter) {
+ DefaultDrawContent(painter);
+ if (const auto child = GetSingleChild()) {
+ painter->PushLayer(this->GetPaddingRect());
+ const auto offset = child->GetOffset();
+ platform::graph::util::WithTransform(
+ painter, Matrix::Translation(offset.x, offset.y),
+ [child](platform::graph::IPainter* p) { child->Draw(p); });
+ painter->PopLayer();
+ }
+}
+
Point ScrollRenderObject::GetScrollOffset() {
if (const auto child = GetSingleChild())
return CoerceScroll(scroll_offset_, GetContentRect().GetSize(),
diff --git a/src/ui/render/TextRenderObject.cpp b/src/ui/render/TextRenderObject.cpp
index e0c68683..7efffafb 100644
--- a/src/ui/render/TextRenderObject.cpp
+++ b/src/ui/render/TextRenderObject.cpp
@@ -118,48 +118,42 @@ void TextRenderObject::SetCaretWidth(const float width) {
}
}
-void TextRenderObject::Draw(platform::graph::IPainter* painter) {
- platform::graph::util::WithTransform(
- painter,
- platform::Matrix::Translation(GetMargin().left + GetPadding().left,
- GetMargin().top + GetPadding().top),
- [this](platform::graph::IPainter* p) {
- if (this->selection_range_.has_value()) {
- const auto&& rects =
- text_layout_->TextRangeRect(this->selection_range_.value());
- for (const auto& rect : rects)
- p->FillRectangle(rect, this->GetSelectionBrush().get());
- }
-
- p->DrawText(Point{}, text_layout_.get(), brush_.get());
-
- if (this->draw_caret_ && this->caret_width_ != 0.0f) {
- auto caret_pos = this->caret_position_;
- gsl::index text_size = this->GetText().size();
- if (caret_pos < 0) {
- caret_pos = 0;
- } else if (caret_pos > text_size) {
- caret_pos = text_size;
- }
-
- const auto caret_top_center =
- this->text_layout_->TextSinglePoint(caret_pos, false);
-
- const auto font_height = this->font_->GetFontSize();
- const auto caret_width = this->caret_width_;
-
- p->FillRectangle(Rect{caret_top_center.x - caret_width / 2.0f,
- caret_top_center.y, caret_width, font_height},
- this->caret_brush_.get());
- }
- });
-}
-
RenderObject* TextRenderObject::HitTest(const Point& point) {
const auto padding_rect = GetPaddingRect();
return padding_rect.IsPointInside(point) ? this : nullptr;
}
+void TextRenderObject::OnDrawContent(platform::graph::IPainter* painter) {
+ if (this->selection_range_.has_value()) {
+ const auto&& rects =
+ text_layout_->TextRangeRect(this->selection_range_.value());
+ for (const auto& rect : rects)
+ painter->FillRectangle(rect, this->GetSelectionBrush().get());
+ }
+
+ painter->DrawText(Point{}, text_layout_.get(), brush_.get());
+
+ if (this->draw_caret_ && this->caret_width_ != 0.0f) {
+ auto caret_pos = this->caret_position_;
+ gsl::index text_size = this->GetText().size();
+ if (caret_pos < 0) {
+ caret_pos = 0;
+ } else if (caret_pos > text_size) {
+ caret_pos = text_size;
+ }
+
+ const auto caret_top_center =
+ this->text_layout_->TextSinglePoint(caret_pos, false);
+
+ const auto font_height = this->font_->GetFontSize();
+ const auto caret_width = this->caret_width_;
+
+ painter->FillRectangle(Rect{caret_top_center.x - caret_width / 2.0f,
+ caret_top_center.y, caret_width, font_height},
+ this->caret_brush_.get());
+ }
+}
+
Size TextRenderObject::OnMeasureContent(const MeasureRequirement& requirement,
const MeasureSize& preferred_size) {
float measure_width;
diff --git a/src/ui/render/WindowRenderObject.cpp b/src/ui/render/WindowRenderObject.cpp
index a2c7ae4d..4adf559e 100644
--- a/src/ui/render/WindowRenderObject.cpp
+++ b/src/ui/render/WindowRenderObject.cpp
@@ -12,16 +12,6 @@ WindowRenderObject::WindowRenderObject(UiHost* host) {
[this](auto) { NotifyAfterLayoutRecursive(this); }));
}
-void WindowRenderObject::Draw(platform::graph::IPainter* painter) {
- painter->Clear(colors::white);
- if (const auto child = GetChild()) {
- auto offset = child->GetOffset();
- platform::graph::util::WithTransform(
- painter, platform::Matrix::Translation(offset.x, offset.y),
- [child](platform::graph::IPainter* p) { child->Draw(p); });
- }
-}
-
RenderObject* WindowRenderObject::HitTest(const Point& point) {
if (const auto child = GetChild()) {
auto offset = child->GetOffset();