diff options
-rw-r--r-- | include/cru/ui/Base.hpp | 8 | ||||
-rw-r--r-- | include/cru/ui/render/BorderRenderObject.hpp | 4 | ||||
-rw-r--r-- | include/cru/ui/render/CanvasRenderObject.hpp | 4 | ||||
-rw-r--r-- | include/cru/ui/render/LayoutRenderObject.hpp | 13 | ||||
-rw-r--r-- | include/cru/ui/render/RenderObject.hpp | 13 | ||||
-rw-r--r-- | include/cru/ui/render/ScrollRenderObject.hpp | 7 | ||||
-rw-r--r-- | include/cru/ui/render/TextRenderObject.hpp | 4 | ||||
-rw-r--r-- | include/cru/ui/render/WindowRenderObject.hpp | 2 | ||||
-rw-r--r-- | src/ui/UiHost.cpp | 1 | ||||
-rw-r--r-- | src/ui/render/BorderRenderObject.cpp | 43 | ||||
-rw-r--r-- | src/ui/render/CanvasRenderObject.cpp | 12 | ||||
-rw-r--r-- | src/ui/render/RenderObject.cpp | 31 | ||||
-rw-r--r-- | src/ui/render/ScrollRenderObject.cpp | 23 | ||||
-rw-r--r-- | src/ui/render/TextRenderObject.cpp | 68 | ||||
-rw-r--r-- | src/ui/render/WindowRenderObject.cpp | 10 |
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(); |