diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ui/control.cpp | 2 | ||||
-rw-r--r-- | src/ui/controls/list_item.cpp | 2 | ||||
-rw-r--r-- | src/ui/controls/scroll_control.cpp | 2 | ||||
-rw-r--r-- | src/ui/controls/toggle_button.cpp | 2 | ||||
-rw-r--r-- | src/ui/convert_util.hpp | 21 | ||||
-rw-r--r-- | src/ui/d2d_util.hpp | 64 | ||||
-rw-r--r-- | src/ui/render/render_object.cpp | 99 | ||||
-rw-r--r-- | src/ui/render/render_object.hpp | 164 | ||||
-rw-r--r-- | src/ui/ui_base.hpp | 14 |
9 files changed, 333 insertions, 37 deletions
diff --git a/src/ui/control.cpp b/src/ui/control.cpp index 3987e818..9388c719 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -8,7 +8,7 @@ #include "graph/graph.hpp" #include "exception.hpp" #include "cru_debug.hpp" -#include "convert_util.hpp" +#include "d2d_util.hpp" #include "math_util.hpp" #ifdef CRU_DEBUG_LAYOUT diff --git a/src/ui/controls/list_item.cpp b/src/ui/controls/list_item.cpp index e0ca28a9..6dd37fe9 100644 --- a/src/ui/controls/list_item.cpp +++ b/src/ui/controls/list_item.cpp @@ -1,7 +1,7 @@ #include "list_item.hpp" #include "ui/ui_manager.hpp" -#include "ui/convert_util.hpp" +#include "ui/d2d_util.hpp" namespace cru::ui::controls { diff --git a/src/ui/controls/scroll_control.cpp b/src/ui/controls/scroll_control.cpp index 622b4e4c..a202e355 100644 --- a/src/ui/controls/scroll_control.cpp +++ b/src/ui/controls/scroll_control.cpp @@ -3,7 +3,7 @@ #include <limits> #include "cru_debug.hpp" -#include "ui/convert_util.hpp" +#include "ui/d2d_util.hpp" #include "exception.hpp" #include "math_util.hpp" #include "ui/ui_manager.hpp" diff --git a/src/ui/controls/toggle_button.cpp b/src/ui/controls/toggle_button.cpp index 6eb0bc40..db72d7bb 100644 --- a/src/ui/controls/toggle_button.cpp +++ b/src/ui/controls/toggle_button.cpp @@ -3,7 +3,7 @@ #include "graph/graph.hpp" #include "ui/animations/animation.hpp" #include "ui/ui_manager.hpp" -#include "ui/convert_util.hpp" +#include "ui/d2d_util.hpp" namespace cru::ui::controls { diff --git a/src/ui/convert_util.hpp b/src/ui/convert_util.hpp deleted file mode 100644 index 5408f2e4..00000000 --- a/src/ui/convert_util.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -// ReSharper disable once CppUnusedIncludeDirective -#include "pre.hpp" - -#include "system_headers.hpp" - -#include "ui_base.hpp" - -namespace cru::ui -{ - inline D2D1_POINT_2F Convert(const Point& point) - { - return D2D1::Point2F(point.x, point.y); - } - - inline D2D1_RECT_F Convert(const Rect& rect) - { - return D2D1::RectF(rect.left, rect.top, rect.left + rect.width, rect.top + rect.height); - } -} diff --git a/src/ui/d2d_util.hpp b/src/ui/d2d_util.hpp new file mode 100644 index 00000000..d4fff620 --- /dev/null +++ b/src/ui/d2d_util.hpp @@ -0,0 +1,64 @@ +#pragma once + +// ReSharper disable once CppUnusedIncludeDirective +#include "pre.hpp" + +#include "system_headers.hpp" + +#include "ui_base.hpp" + +namespace cru::ui +{ + inline D2D1_POINT_2F Convert(const Point& point) + { + return D2D1::Point2F(point.x, point.y); + } + + inline D2D1_RECT_F Convert(const Rect& rect) + { + return D2D1::RectF(rect.left, rect.top, rect.left + rect.width, rect.top + rect.height); + } + + inline Point Convert(const D2D1_POINT_2F& point) + { + return Point(point.x, point.y); + } + + inline Rect Convert(const D2D1_RECT_F& rect) + { + return Rect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); + } + + inline bool operator==(const D2D1_POINT_2F& left, const D2D1_POINT_2F& right) + { + return left.x == right.x && left.y == right.y; + } + + inline bool operator!=(const D2D1_POINT_2F& left, const D2D1_POINT_2F& right) + { + return !(left == right); + } + + inline bool operator==(const D2D1_RECT_F& left, const D2D1_RECT_F& right) + { + return left.left == right.left && + left.top == right.top && + left.right == right.right && + left.bottom == right.bottom; + } + + inline bool operator!=(const D2D1_RECT_F& left, const D2D1_RECT_F& right) + { + return !(left == right); + } + + inline bool operator==(const D2D1_ROUNDED_RECT& left, const D2D1_ROUNDED_RECT& right) + { + return left.rect == right.rect && left.radiusX == right.radiusX && left.radiusY == right.radiusY; + } + + inline bool operator!=(const D2D1_ROUNDED_RECT& left, const D2D1_ROUNDED_RECT& right) + { + return !(left == right); + } +} diff --git a/src/ui/render/render_object.cpp b/src/ui/render/render_object.cpp index 7b430f06..78445bf1 100644 --- a/src/ui/render/render_object.cpp +++ b/src/ui/render/render_object.cpp @@ -87,6 +87,9 @@ namespace cru::ui::render render_target->SetTransform(matrix); } + const MatrixRenderObject::MatrixApplier MatrixRenderObject::append_applier(ApplyAppendMatrix); + const MatrixRenderObject::MatrixApplier MatrixRenderObject::set_applier(ApplySetMatrix); + MatrixRenderObject::MatrixRenderObject(const D2D1_MATRIX_3X2_F& matrix, MatrixApplier applier) : matrix_(matrix), applier_(std::move(applier)) { @@ -128,6 +131,98 @@ namespace cru::ui::render SetMatrix(D2D1::Matrix3x2F::Translation(offset_x_, offset_y_)); } - const MatrixRenderObject::MatrixApplier MatrixRenderObject::append_applier(ApplyAppendMatrix); - const MatrixRenderObject::MatrixApplier MatrixRenderObject::set_applier(ApplySetMatrix); + void StrokeRenderObject::SetStrokeWidth(const float new_stroke_width) + { + if (stroke_width_ == new_stroke_width) + return; + + stroke_width_ = new_stroke_width; + InvalidateRenderHost(); + } + + void StrokeRenderObject::SetBrush(Microsoft::WRL::ComPtr<ID2D1Brush> new_brush) + { + if (brush_ == new_brush) + return; + + brush_ = std::move(new_brush); + InvalidateRenderHost(); + } + + void StrokeRenderObject::SetStrokeStyle(Microsoft::WRL::ComPtr<ID2D1StrokeStyle> new_stroke_style) + { + if (stroke_style_ == new_stroke_style) + return; + + stroke_style_ = std::move(new_stroke_style); + InvalidateRenderHost(); + } + + void FillRenderObject::SetBrush(Microsoft::WRL::ComPtr<ID2D1Brush> new_brush) + { + if (brush_ == new_brush) + return; + + brush_ = std::move(new_brush); + InvalidateRenderHost(); + } + + void RoundedRectangleRenderObject::SetRect(const Rect& rect) + { + const auto converted_rect = Convert(rect); + if (rounded_rect_.rect == converted_rect) + return; + + rounded_rect_.rect = converted_rect; + InvalidateRenderHost(); + } + + void RoundedRectangleRenderObject::SetRadiusX(const float new_radius_x) + { + if (rounded_rect_.radiusX == new_radius_x) + return; + + rounded_rect_.radiusX = new_radius_x; + InvalidateRenderHost(); + } + + void RoundedRectangleRenderObject::SetRadiusY(const float new_radius_y) + { + if (rounded_rect_.radiusY == new_radius_y) + return; + + rounded_rect_.radiusY = new_radius_y; + InvalidateRenderHost(); + } + + void RoundedRectangleRenderObject::SetRoundedRect(const D2D1_ROUNDED_RECT& new_rounded_rect) + { + if (rounded_rect_ == new_rounded_rect) + return; + + rounded_rect_ = new_rounded_rect; + InvalidateRenderHost(); + } + + void RoundedRectangleStrokeRenderObject::Draw(ID2D1RenderTarget* render_target) + { + const auto brush = GetBrush(); + if (brush != nullptr) + render_target->DrawRoundedRectangle(GetRoundedRect(), GetBrush().Get(), GetStrokeWidth()); + } + + void CustomDrawHandlerRenderObject::SetDrawHandler(DrawHandler new_draw_handler) + { + if (draw_handler_ == nullptr && new_draw_handler == nullptr) + return; + + draw_handler_ = std::move(new_draw_handler); + InvalidateRenderHost; + } + + void CustomDrawHandlerRenderObject::Draw(ID2D1RenderTarget * render_target) + { + if (draw_handler_ != nullptr) + draw_handler_(render_target); + } } diff --git a/src/ui/render/render_object.hpp b/src/ui/render/render_object.hpp index 675a1759..6603728d 100644 --- a/src/ui/render/render_object.hpp +++ b/src/ui/render/render_object.hpp @@ -7,6 +7,7 @@ #include "base.hpp" #include "ui/ui_base.hpp" +#include "ui/d2d_util.hpp" namespace cru::ui::render { @@ -193,11 +194,154 @@ namespace cru::ui::render float offset_y_; }; - class BorderRenderObject; //TODO! - class FillGeometryRenderObject; //TODO! + class StrokeRenderObject : public virtual RenderObject + { + protected: + StrokeRenderObject() = default; + public: + StrokeRenderObject(const StrokeRenderObject& other) = delete; + StrokeRenderObject(StrokeRenderObject&& other) = delete; + StrokeRenderObject& operator=(const StrokeRenderObject& other) = delete; + StrokeRenderObject& operator=(StrokeRenderObject&& other) = delete; + ~StrokeRenderObject() override = default; + + float GetStrokeWidth() const + { + return stroke_width_; + } + + void SetStrokeWidth(float new_stroke_width); + + Microsoft::WRL::ComPtr<ID2D1Brush> GetBrush() const + { + return brush_; + } + + void SetBrush(Microsoft::WRL::ComPtr<ID2D1Brush> new_brush); + + Microsoft::WRL::ComPtr<ID2D1StrokeStyle> GetStrokeStyle() const + { + return stroke_style_; + } + + void SetStrokeStyle(Microsoft::WRL::ComPtr<ID2D1StrokeStyle> new_stroke_style); + + private: + float stroke_width_ = 1.0f; + Microsoft::WRL::ComPtr<ID2D1Brush> brush_ = nullptr; + Microsoft::WRL::ComPtr<ID2D1StrokeStyle> stroke_style_ = nullptr; + }; + + + class FillRenderObject : public virtual RenderObject + { + protected: + FillRenderObject() = default; + public: + FillRenderObject(const FillRenderObject& other) = delete; + FillRenderObject(FillRenderObject&& other) = delete; + FillRenderObject& operator=(const FillRenderObject& other) = delete; + FillRenderObject& operator=(FillRenderObject&& other) = delete; + ~FillRenderObject() override = default; + + Microsoft::WRL::ComPtr<ID2D1Brush> GetBrush() const + { + return brush_; + } + + void SetBrush(Microsoft::WRL::ComPtr<ID2D1Brush> new_brush); + + private: + Microsoft::WRL::ComPtr<ID2D1Brush> brush_ = nullptr; + }; + + + class RoundedRectangleRenderObject : public virtual RenderObject + { + protected: + RoundedRectangleRenderObject() = default; + public: + RoundedRectangleRenderObject(const RoundedRectangleRenderObject& other) = delete; + RoundedRectangleRenderObject(RoundedRectangleRenderObject&& other) = delete; + RoundedRectangleRenderObject& operator=(const RoundedRectangleRenderObject& other) = delete; + RoundedRectangleRenderObject& operator=(RoundedRectangleRenderObject&& other) = delete; + ~RoundedRectangleRenderObject() override = default; + + Rect GetRect() const + { + return Convert(rounded_rect_.rect); + } + + void SetRect(const Rect& rect); + + float GetRadiusX() const + { + return rounded_rect_.radiusX; + } + + void SetRadiusX(float new_radius_x); + + float GetRadiusY() const + { + return rounded_rect_.radiusY; + } + + void SetRadiusY(float new_radius_y); + + D2D1_ROUNDED_RECT GetRoundedRect() const + { + return rounded_rect_; + } + + void SetRoundedRect(const D2D1_ROUNDED_RECT& new_rounded_rect); + + private: + D2D1_ROUNDED_RECT rounded_rect_ = D2D1::RoundedRect(D2D1::RectF(), 0.0f, 0.0f); + }; + + + class RoundedRectangleStrokeRenderObject final : public StrokeRenderObject, public RoundedRectangleRenderObject + { + public: + RoundedRectangleStrokeRenderObject() = default; + RoundedRectangleStrokeRenderObject(const RoundedRectangleStrokeRenderObject& other) = delete; + RoundedRectangleStrokeRenderObject(RoundedRectangleStrokeRenderObject&& other) = delete; + RoundedRectangleStrokeRenderObject& operator=(const RoundedRectangleStrokeRenderObject& other) = delete; + RoundedRectangleStrokeRenderObject& operator=(RoundedRectangleStrokeRenderObject&& other) = delete; + ~RoundedRectangleStrokeRenderObject() override = default; + + protected: + void Draw(ID2D1RenderTarget* render_target) override; + }; + + + class CustomDrawHandlerRenderObject : public RenderObject + { + public: + using DrawHandler = std::function<void(ID2D1RenderTarget*)>; + + CustomDrawHandlerRenderObject() = default; + CustomDrawHandlerRenderObject(const CustomDrawHandlerRenderObject& other) = delete; + CustomDrawHandlerRenderObject& operator=(const CustomDrawHandlerRenderObject& other) = delete; + CustomDrawHandlerRenderObject(CustomDrawHandlerRenderObject&& other) = delete; + CustomDrawHandlerRenderObject& operator=(CustomDrawHandlerRenderObject&& other) = delete; + ~CustomDrawHandlerRenderObject() override = default; + + DrawHandler GetDrawHandler() const + { + return draw_handler_; + } + + void SetDrawHandler(DrawHandler new_draw_handler); + + protected: + void Draw(ID2D1RenderTarget* render_target) override; + + private: + DrawHandler draw_handler_{}; + }; - class CustomDrawHandlerRenderObject; //TODO! class ContainerRenderObject; //TODO! @@ -215,7 +359,7 @@ namespace cru::ui::render // | // ContainerRO // / | - // BorderRO OffsetRO (padding offset) + // StrokeRO (border) OffsetRO (padding offset) // / | \ // / | \ // / | \ @@ -224,7 +368,7 @@ namespace cru::ui::render // / | \ // ContainerRO (background) | ContainerRO (foreground, symmetrical to background) // / \ | / \ - // GeometryFillRO CustomDrawHandlerRO | GeometryFillRO CustomDrawHandlerRO + // FillRO CustomDrawHandlerRO | FillRO CustomDrawHandlerRO // | // OffsetRO (content offset) // | @@ -247,13 +391,13 @@ namespace cru::ui::render ~ControlRenderObject() override = default; - D2D1_MATRIX_3X2_F GetControlTransform() const; - Microsoft::WRL::ComPtr<ID2D1Geometry> GetControlClip() const; + MatrixRenderObject* GetControlTransformRenderObject() const; + ClipRenderObject* GetControlClipRenderObject() const; - Point GetBorderOffset() const; - BorderRenderObject* GetBorderRenderObject() const; + OffsetRenderObject* GetBorderOffsetRenderObject() const; + RoundedRectangleStrokeRenderObject* GetBorderRenderObject() const; - Point GetPaddingOffset() const; + OffsetRenderObject* GetPaddingOffsetRenderObject() const; Microsoft::WRL::ComPtr<ID2D1Geometry> GetPaddingGeometry() const; Point GetContentOffset() const; diff --git a/src/ui/ui_base.hpp b/src/ui/ui_base.hpp index b898b2ed..5350e4e9 100644 --- a/src/ui/ui_base.hpp +++ b/src/ui/ui_base.hpp @@ -188,6 +188,20 @@ namespace cru::ui float height = 0.0f; }; + constexpr bool operator==(const Rect& left, const Rect& right) + { + return left.left == right.left && + left.top == right.top && + left.width == right.width && + left.height == right.height; + } + + constexpr bool operator!=(const Rect& left, const Rect& right) + { + return !(left == right); + } + + enum class MouseButton { Left, |