diff options
author | crupest <crupest@outlook.com> | 2019-03-23 00:15:18 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2019-03-23 00:15:18 +0800 |
commit | 39d2c8b3d957e75c3a2a1c738c1628e3eb5c0173 (patch) | |
tree | 72fff34573ffc7e788051bd7911032283340588d | |
parent | 63a5d619ac81ba3f48e95c890d96fa7d9047bb26 (diff) | |
download | cru-39d2c8b3d957e75c3a2a1c738c1628e3eb5c0173.tar.gz cru-39d2c8b3d957e75c3a2a1c738c1628e3eb5c0173.tar.bz2 cru-39d2c8b3d957e75c3a2a1c738c1628e3eb5c0173.zip |
...
-rw-r--r-- | CruUI.vcxproj | 2 | ||||
-rw-r--r-- | CruUI.vcxproj.filters | 6 | ||||
-rw-r--r-- | src/ui/render/border_render_object.cpp | 96 | ||||
-rw-r--r-- | src/ui/render/border_render_object.hpp | 71 | ||||
-rw-r--r-- | src/ui/render/flex_layout_render_object.hpp | 10 | ||||
-rw-r--r-- | src/ui/render/render_object.cpp | 30 | ||||
-rw-r--r-- | src/ui/render/render_object.hpp | 9 | ||||
-rw-r--r-- | src/ui/render/text_render_object.hpp | 7 |
8 files changed, 206 insertions, 25 deletions
diff --git a/CruUI.vcxproj b/CruUI.vcxproj index a6daa3c4..374a882c 100644 --- a/CruUI.vcxproj +++ b/CruUI.vcxproj @@ -120,6 +120,7 @@ <ClCompile Include="src\ui\content_control.cpp" /> <ClCompile Include="src\ui\layout_control.cpp" /> <ClCompile Include="src\ui\no_child_control.cpp" /> + <ClCompile Include="src\ui\render\border_render_object.cpp" /> <ClCompile Include="src\ui\render\text_render_object.cpp" /> <ClCompile Include="src\ui\render\window_render_object.cpp" /> <ClCompile Include="src\ui\window_class.cpp" /> @@ -136,6 +137,7 @@ <ClInclude Include="src\ui\content_control.hpp" /> <ClInclude Include="src\ui\layout_control.hpp" /> <ClInclude Include="src\ui\no_child_control.hpp" /> + <ClInclude Include="src\ui\render\border_render_object.hpp" /> <ClInclude Include="src\ui\render\window_render_object.hpp" /> <ClInclude Include="src\ui\render\text_render_object.hpp" /> <ClInclude Include="src\ui\window_class.hpp" /> diff --git a/CruUI.vcxproj.filters b/CruUI.vcxproj.filters index 36ae998d..5554927b 100644 --- a/CruUI.vcxproj.filters +++ b/CruUI.vcxproj.filters @@ -87,6 +87,9 @@ <ClCompile Include="src\ui\no_child_control.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="src\ui\render\border_render_object.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="src\graph\graph.hpp"> @@ -182,6 +185,9 @@ <ClInclude Include="src\ui\no_child_control.hpp"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="src\ui\render\border_render_object.hpp"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="src\application.cpp"> diff --git a/src/ui/render/border_render_object.cpp b/src/ui/render/border_render_object.cpp new file mode 100644 index 00000000..c98d6c29 --- /dev/null +++ b/src/ui/render/border_render_object.cpp @@ -0,0 +1,96 @@ +#include "border_render_object.hpp" + +#include "cru_debug.hpp" + +namespace cru::ui::render { +BorderRenderObject::BorderRenderObject(Microsoft::WRL::ComPtr<ID2D1Brush> brush) + : border_brush_(std::move(brush)) {} + +void BorderRenderObject::OnMeasureCore(const Size& available_size) { + const auto margin = GetMargin(); + const auto padding = GetPadding(); + Size margin_border_padding_size{ + margin.GetHorizontalTotal() + padding.GetHorizontalTotal(), + margin.GetVerticalTotal() + padding.GetVerticalTotal()}; + + if (is_enabled_) { + margin_border_padding_size.width += border_width_.GetHorizontalTotal(); + margin_border_padding_size.height += border_width_.GetVerticalTotal(); + } + + auto coerced_margin_border_padding_size = margin_border_padding_size; + if (coerced_margin_border_padding_size.width > available_size.width) { + debug::DebugMessage( + L"Measure: horizontal length of padding, border and margin is bigger " + L"than available length."); + coerced_margin_border_padding_size.width = available_size.width; + } + if (coerced_margin_border_padding_size.height > available_size.height) { + debug::DebugMessage( + L"Measure: vertical length of padding, border and margin is bigger " + L"than available length."); + coerced_margin_border_padding_size.height = available_size.height; + } + + const auto coerced_content_available_size = + available_size - coerced_margin_border_padding_size; + + const auto actual_content_size = + OnMeasureContent(coerced_content_available_size); + + SetPreferredSize(coerced_margin_border_padding_size + actual_content_size); +} + +void BorderRenderObject::OnLayoutCore(const Rect& rect) { + const auto margin = GetMargin(); + const auto padding = GetPadding(); + Size margin_border_padding_size{ + margin.GetHorizontalTotal() + padding.GetHorizontalTotal(), + margin.GetVerticalTotal() + padding.GetVerticalTotal()}; + + if (is_enabled_) { + margin_border_padding_size.width += border_width_.GetHorizontalTotal(); + margin_border_padding_size.height += border_width_.GetVerticalTotal(); + } + + const auto content_available_size = + rect.GetSize() - margin_border_padding_size; + auto coerced_content_available_size = content_available_size; + + if (coerced_content_available_size.width < 0) { + debug::DebugMessage( + L"Layout: horizontal length of padding, border and margin is bigger " + L"than available length."); + coerced_content_available_size.width = 0; + } + if (coerced_content_available_size.height < 0) { + debug::DebugMessage( + L"Layout: vertical length of padding, border and margin is bigger than " + L"available length."); + coerced_content_available_size.height = 0; + } + + OnLayoutContent( + Rect{margin.left + (is_enabled_ ? border_width_.left : 0) + padding.left, + margin.top + (is_enabled_ ? border_width_.top : 0) + padding.top, + coerced_content_available_size.width, + coerced_content_available_size.height}); +} + +Size BorderRenderObject::OnMeasureContent(const Size& available_size) { + const auto child = GetChild(); + if (child) { + child->Measure(available_size); + return child->GetPreferredSize(); + } else { + return Size::Zero(); + } +} + +void BorderRenderObject::OnLayoutContent(const Rect& content_rect) { + const auto child = GetChild(); + if (child) { + child->Layout(content_rect); + } +} +} // namespace cru::ui::render diff --git a/src/ui/render/border_render_object.hpp b/src/ui/render/border_render_object.hpp new file mode 100644 index 00000000..d7a595af --- /dev/null +++ b/src/ui/render/border_render_object.hpp @@ -0,0 +1,71 @@ +#pragma once +#include "pre.hpp" + +#include <wrl/client.h> // for ComPtr + +#include "render_object.hpp" + +// forward declarations +struct ID2D1Brush; +struct ID2D1Geometry; + +struct CornerRadius { + float left_top; + float right_top; + float left_bottom; + float right_bottom; +}; + +namespace cru::ui::render { +class BorderRenderObject : public RenderObject { + public: + explicit BorderRenderObject(Microsoft::WRL::ComPtr<ID2D1Brush> brush); + BorderRenderObject(const BorderRenderObject& other) = delete; + BorderRenderObject(BorderRenderObject&& other) = delete; + BorderRenderObject& operator=(const BorderRenderObject& other) = delete; + BorderRenderObject& operator=(BorderRenderObject&& other) = delete; + ~BorderRenderObject() override = default; + + bool IsEnabled() const { return is_enabled_; } + void SetEnabled(bool enabled) { is_enabled_ = enabled; } + + Microsoft::WRL::ComPtr<ID2D1Brush> GetBrush() const { return border_brush_; } + void SetBrush(const Microsoft::WRL::ComPtr<ID2D1Brush> new_brush) { + border_brush_ = std::move(new_brush); + } + + Thickness GetBorderWidth() const { return border_width_; } + void SetBorderWidth(const Thickness& thickness) { border_width_ = thickness; } + + CornerRadius GetCornerRadius() const { return corner_radius_; } + void SetCornerRadius(const CornerRadius& new_corner_radius) { + corner_radius_ = new_corner_radius; + } + + void RecreateGeometry(); // TODO + + void Draw(ID2D1RenderTarget* render_target) override; // TODO + + RenderObject* HitTest(const Point& point) override; // TODO + + 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; + + private: + RenderObject* GetChild() const { + return GetChildren().empty() ? nullptr : GetChildren()[0]; + } + + private: + bool is_enabled_; + + Microsoft::WRL::ComPtr<ID2D1Brush> border_brush_; + Thickness border_width_; + CornerRadius corner_radius_; + + Microsoft::WRL::ComPtr<ID2D1Geometry> geometry_; +}; +} // namespace cru::ui::render diff --git a/src/ui/render/flex_layout_render_object.hpp b/src/ui/render/flex_layout_render_object.hpp index b12362e8..ac4c2c0f 100644 --- a/src/ui/render/flex_layout_render_object.hpp +++ b/src/ui/render/flex_layout_render_object.hpp @@ -16,7 +16,7 @@ enum class FlexDirection { enum class Alignment { Start, End, Center }; struct FlexChildLayoutData { - std::optional<float> flex_basis; + std::optional<float> flex_basis; // nullopt stands for content float flex_grow = 0; float flex_shrink = 0; Alignment alignment = Alignment::Center; @@ -35,12 +35,8 @@ class FlexLayoutRenderObject : public RenderObject { FlexDirection GetFlexDirection() const { return direction_; } void SetFlexDirection(FlexDirection direction) { direction_ = direction; } - Alignment GetContentMainAlign() const { - return content_main_align_; - } - void SetContentMainAlign(Alignment align) { - content_main_align_ = align; - } + Alignment GetContentMainAlign() const { return content_main_align_; } + void SetContentMainAlign(Alignment align) { content_main_align_ = align; } FlexChildLayoutData* GetChildLayoutData(int position); diff --git a/src/ui/render/render_object.cpp b/src/ui/render/render_object.cpp index 6380c2fe..f56baa8f 100644 --- a/src/ui/render/render_object.cpp +++ b/src/ui/render/render_object.cpp @@ -1,5 +1,8 @@ #include "render_object.hpp" +#include <d2d1.h> +#include <dwrite.h> + #include "cru_debug.hpp" namespace cru::ui::render { @@ -44,36 +47,31 @@ void RenderObject::OnRemoveChild(RenderObject* removed_child, int position) {} void RenderObject::OnSizeChanged(const Size& old_size, const Size& new_size) {} -void RenderObject::SetParent(RenderObject* new_parent) { - const auto old_parent = parent_; - parent_ = new_parent; - OnParentChanged(old_parent, new_parent); -} - void RenderObject::OnMeasureCore(const Size& available_size) { Size margin_padding_size{ margin_.GetHorizontalTotal() + padding_.GetHorizontalTotal(), margin_.GetVerticalTotal() + padding_.GetVerticalTotal()}; - const auto content_available_size = available_size - margin_padding_size; - auto coerced_content_available_size = content_available_size; - if (coerced_content_available_size.width < 0) { + auto coerced_margin_padding_size = margin_padding_size; + if (coerced_margin_padding_size.width > available_size.width) { debug::DebugMessage( L"Measure: horizontal length of padding and margin is bigger than " L"available length."); - coerced_content_available_size.width = 0; + coerced_margin_padding_size.width = available_size.width; } - if (coerced_content_available_size.height < 0) { + if (coerced_margin_padding_size.height > available_size.height) { debug::DebugMessage( L"Measure: vertical length of padding and margin is bigger than " L"available length."); - coerced_content_available_size.height = 0; + coerced_margin_padding_size.height = available_size.height; } + const auto coerced_content_available_size = + available_size - coerced_margin_padding_size; const auto actual_content_size = OnMeasureContent(coerced_content_available_size); - SetPreferredSize(margin_padding_size + actual_content_size); + SetPreferredSize(coerced_margin_padding_size + actual_content_size); } void RenderObject::OnLayoutCore(const Rect& rect) { @@ -100,4 +98,10 @@ void RenderObject::OnLayoutCore(const Rect& rect) { coerced_content_available_size.width, coerced_content_available_size.height}); } + +void RenderObject::SetParent(RenderObject* new_parent) { + const auto old_parent = parent_; + parent_ = new_parent; + OnParentChanged(old_parent, new_parent); +} } // namespace cru::ui::render diff --git a/src/ui/render/render_object.hpp b/src/ui/render/render_object.hpp index a9950198..51b0c3ae 100644 --- a/src/ui/render/render_object.hpp +++ b/src/ui/render/render_object.hpp @@ -3,11 +3,13 @@ #include <optional> #include <vector> -#include "system_headers.hpp" #include "base.hpp" #include "ui/ui_base.hpp" +// forward declarations +struct ID2D1RenderTarget; + namespace cru::ui { class Control; } @@ -70,15 +72,14 @@ class RenderObject : public Object { virtual void OnSizeChanged(const Size& old_size, const Size& new_size); + 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; private: void SetParent(RenderObject* new_parent); - void OnMeasureCore(const Size& available_size); - void OnLayoutCore(const Rect& rect); - private: Control* control_ = nullptr; diff --git a/src/ui/render/text_render_object.hpp b/src/ui/render/text_render_object.hpp index 4361b9c0..ac874b75 100644 --- a/src/ui/render/text_render_object.hpp +++ b/src/ui/render/text_render_object.hpp @@ -1,10 +1,15 @@ #pragma once #include "pre.hpp" -#include "system_headers.hpp" +#include <wrl/client.h> // for ComPtr #include "render_object.hpp" +// forward declarations +struct ID2D1Brush; +struct IDWriteTextFormat; +struct IDWriteTextLayout; + namespace cru::ui::render { class TextRenderObject : public RenderObject { public: |