From 06d1d0442276a05b6caad6e3468f4afb1e8ee5df Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 28 Jun 2020 00:03:11 +0800 Subject: ... --- include/cru/ui/Base.hpp | 281 ++++++++++++++++++++++++++++++++++ include/cru/ui/Control.hpp | 152 ++++++++++++++++++ include/cru/ui/Window.hpp | 40 +++++ include/cru/ui/base.hpp | 281 ---------------------------------- include/cru/ui/control.hpp | 152 ------------------ include/cru/ui/controls/Base.hpp | 24 +++ include/cru/ui/controls/Button.hpp | 42 +++++ include/cru/ui/controls/Container.hpp | 28 ++++ include/cru/ui/controls/base.hpp | 24 --- include/cru/ui/controls/button.hpp | 42 ----- include/cru/ui/controls/container.hpp | 28 ---- include/cru/ui/render/Base.hpp | 12 ++ include/cru/ui/render/base.hpp | 12 -- include/cru/ui/window.hpp | 40 ----- 14 files changed, 579 insertions(+), 579 deletions(-) create mode 100644 include/cru/ui/Base.hpp create mode 100644 include/cru/ui/Control.hpp create mode 100644 include/cru/ui/Window.hpp delete mode 100644 include/cru/ui/base.hpp delete mode 100644 include/cru/ui/control.hpp create mode 100644 include/cru/ui/controls/Base.hpp create mode 100644 include/cru/ui/controls/Button.hpp create mode 100644 include/cru/ui/controls/Container.hpp delete mode 100644 include/cru/ui/controls/base.hpp delete mode 100644 include/cru/ui/controls/button.hpp delete mode 100644 include/cru/ui/controls/container.hpp create mode 100644 include/cru/ui/render/Base.hpp delete mode 100644 include/cru/ui/render/base.hpp delete mode 100644 include/cru/ui/window.hpp (limited to 'include/cru/ui') diff --git a/include/cru/ui/Base.hpp b/include/cru/ui/Base.hpp new file mode 100644 index 00000000..b9ce0c88 --- /dev/null +++ b/include/cru/ui/Base.hpp @@ -0,0 +1,281 @@ +#pragma once +#include "cru/common/Base.hpp" +#include "cru/platform/graph/Base.hpp" +#include "cru/platform/native/Base.hpp" + +#include +#include +#include +#include + +namespace cru::ui { +//-------------------- region: import -------------------- +using cru::platform::Color; +using cru::platform::Ellipse; +using cru::platform::Matrix; +using cru::platform::Point; +using cru::platform::Rect; +using cru::platform::RoundedRect; +using cru::platform::Size; +using cru::platform::TextRange; +using cru::platform::Thickness; +using cru::platform::native::MouseButton; + +namespace mouse_buttons { +using cru::platform::native::mouse_buttons::left; +using cru::platform::native::mouse_buttons::middle; +using cru::platform::native::mouse_buttons::right; +} // namespace mouse_buttons + +namespace colors { +using cru::platform::colors::aliceblue; +using cru::platform::colors::antiquewhite; +using cru::platform::colors::aqua; +using cru::platform::colors::aquamarine; +using cru::platform::colors::azure; +using cru::platform::colors::beige; +using cru::platform::colors::bisque; +using cru::platform::colors::black; +using cru::platform::colors::blanchedalmond; +using cru::platform::colors::blue; +using cru::platform::colors::blueviolet; +using cru::platform::colors::brown; +using cru::platform::colors::burlywood; +using cru::platform::colors::cadetblue; +using cru::platform::colors::chartreuse; +using cru::platform::colors::chocolate; +using cru::platform::colors::coral; +using cru::platform::colors::cornflowerblue; +using cru::platform::colors::cornsilk; +using cru::platform::colors::crimson; +using cru::platform::colors::cyan; +using cru::platform::colors::darkblue; +using cru::platform::colors::darkcyan; +using cru::platform::colors::darkgoldenrod; +using cru::platform::colors::darkgray; +using cru::platform::colors::darkgreen; +using cru::platform::colors::darkgrey; +using cru::platform::colors::darkkhaki; +using cru::platform::colors::darkmagenta; +using cru::platform::colors::darkolivegreen; +using cru::platform::colors::darkorange; +using cru::platform::colors::darkorchid; +using cru::platform::colors::darkred; +using cru::platform::colors::darksalmon; +using cru::platform::colors::darkseagreen; +using cru::platform::colors::darkslateblue; +using cru::platform::colors::darkslategray; +using cru::platform::colors::darkslategrey; +using cru::platform::colors::darkturquoise; +using cru::platform::colors::darkviolet; +using cru::platform::colors::deeppink; +using cru::platform::colors::deepskyblue; +using cru::platform::colors::dimgray; +using cru::platform::colors::dimgrey; +using cru::platform::colors::dodgerblue; +using cru::platform::colors::firebrick; +using cru::platform::colors::floralwhite; +using cru::platform::colors::forestgreen; +using cru::platform::colors::fuchsia; +using cru::platform::colors::gainsboro; +using cru::platform::colors::ghostwhite; +using cru::platform::colors::gold; +using cru::platform::colors::goldenrod; +using cru::platform::colors::gray; +using cru::platform::colors::green; +using cru::platform::colors::greenyellow; +using cru::platform::colors::grey; +using cru::platform::colors::honeydew; +using cru::platform::colors::hotpink; +using cru::platform::colors::indianred; +using cru::platform::colors::indigo; +using cru::platform::colors::ivory; +using cru::platform::colors::khaki; +using cru::platform::colors::lavender; +using cru::platform::colors::lavenderblush; +using cru::platform::colors::lawngreen; +using cru::platform::colors::lemonchiffon; +using cru::platform::colors::lightblue; +using cru::platform::colors::lightcoral; +using cru::platform::colors::lightcyan; +using cru::platform::colors::lightgoldenrodyellow; +using cru::platform::colors::lightgray; +using cru::platform::colors::lightgreen; +using cru::platform::colors::lightgrey; +using cru::platform::colors::lightpink; +using cru::platform::colors::lightsalmon; +using cru::platform::colors::lightseagreen; +using cru::platform::colors::lightskyblue; +using cru::platform::colors::lightslategray; +using cru::platform::colors::lightslategrey; +using cru::platform::colors::lightsteelblue; +using cru::platform::colors::lightyellow; +using cru::platform::colors::lime; +using cru::platform::colors::limegreen; +using cru::platform::colors::linen; +using cru::platform::colors::magenta; +using cru::platform::colors::maroon; +using cru::platform::colors::mediumaquamarine; +using cru::platform::colors::mediumblue; +using cru::platform::colors::mediumorchid; +using cru::platform::colors::mediumpurple; +using cru::platform::colors::mediumseagreen; +using cru::platform::colors::mediumslateblue; +using cru::platform::colors::mediumspringgreen; +using cru::platform::colors::mediumturquoise; +using cru::platform::colors::mediumvioletred; +using cru::platform::colors::midnightblue; +using cru::platform::colors::mintcream; +using cru::platform::colors::mistyrose; +using cru::platform::colors::moccasin; +using cru::platform::colors::navajowhite; +using cru::platform::colors::navy; +using cru::platform::colors::oldlace; +using cru::platform::colors::olive; +using cru::platform::colors::olivedrab; +using cru::platform::colors::orange; +using cru::platform::colors::orangered; +using cru::platform::colors::orchid; +using cru::platform::colors::palegoldenrod; +using cru::platform::colors::palegreen; +using cru::platform::colors::paleturquoise; +using cru::platform::colors::palevioletred; +using cru::platform::colors::papayawhip; +using cru::platform::colors::peachpuff; +using cru::platform::colors::peru; +using cru::platform::colors::pink; +using cru::platform::colors::plum; +using cru::platform::colors::powderblue; +using cru::platform::colors::purple; +using cru::platform::colors::rebeccapurple; +using cru::platform::colors::red; +using cru::platform::colors::rosybrown; +using cru::platform::colors::royalblue; +using cru::platform::colors::saddlebrown; +using cru::platform::colors::salmon; +using cru::platform::colors::sandybrown; +using cru::platform::colors::seagreen; +using cru::platform::colors::seashell; +using cru::platform::colors::sienna; +using cru::platform::colors::silver; +using cru::platform::colors::skyblue; +using cru::platform::colors::slateblue; +using cru::platform::colors::slategray; +using cru::platform::colors::slategrey; +using cru::platform::colors::snow; +using cru::platform::colors::springgreen; +using cru::platform::colors::steelblue; +using cru::platform::colors::tan; +using cru::platform::colors::teal; +using cru::platform::colors::thistle; +using cru::platform::colors::tomato; +using cru::platform::colors::transparent; +using cru::platform::colors::turquoise; +using cru::platform::colors::violet; +using cru::platform::colors::wheat; +using cru::platform::colors::white; +using cru::platform::colors::whitesmoke; +using cru::platform::colors::yellow; +using cru::platform::colors::yellowgreen; +} // namespace colors + +//-------------------- region: forward declaration -------------------- +class Window; +class Control; +class ClickDetector; +class UiHost; + +//-------------------- region: basic types -------------------- +namespace internal { +constexpr int align_start = 0; +constexpr int align_end = align_start + 1; +constexpr int align_center = align_end + 1; +} // namespace internal + +enum class Alignment { + Start = internal::align_start, + End = internal::align_end, + Center = internal::align_center, +}; + +struct CornerRadius { + constexpr CornerRadius() + : left_top(), right_top(), left_bottom(), right_bottom() {} + constexpr CornerRadius(const float& value) + : CornerRadius(Point{value, value}) {} + constexpr CornerRadius(const Point& value) + : left_top(value), + right_top(value), + left_bottom(value), + right_bottom(value) {} + constexpr CornerRadius(Point left_top, Point right_top, Point left_bottom, + Point right_bottom) + : left_top(left_top), + right_top(right_top), + left_bottom(left_bottom), + right_bottom(right_bottom) {} + + Point left_top; + Point right_top; + Point left_bottom; + Point right_bottom; +}; + +inline bool operator==(const CornerRadius& left, const CornerRadius& right) { + return left.left_top == right.left_top && + left.left_bottom == right.left_bottom && + left.right_top == right.right_top && + left.right_bottom == right.right_bottom; +} + +inline bool operator!=(const CornerRadius& left, const CornerRadius& right) { + return !(left == right); +} + +struct BorderStyle { + std::shared_ptr border_brush; + Thickness border_thickness; + CornerRadius border_radius; + std::shared_ptr foreground_brush; + std::shared_ptr background_brush; +}; + +class CanvasPaintEventArgs { + public: + CanvasPaintEventArgs(platform::graph::IPainter* painter, + const Rect& paint_rect) + : painter_(painter), paint_rect_(paint_rect) {} + CRU_DEFAULT_COPY(CanvasPaintEventArgs) + CRU_DEFAULT_MOVE(CanvasPaintEventArgs) + ~CanvasPaintEventArgs() = default; + + platform::graph::IPainter* GetPainter() const { return painter_; } + Rect GetPaintRect() const { return paint_rect_; } + + private: + platform::graph::IPainter* painter_; + Rect paint_rect_; +}; + +enum class FlexDirection { + Horizontal, + HorizontalReverse, + Vertical, + VertivalReverse +}; + +using FlexMainAlignment = Alignment; +using FlexCrossAlignment = Alignment; + +struct FlexChildLayoutData { + float expand_factor = 0; + float shrink_factor = 1; + // nullopt stands for looking at parent's setting + std::optional cross_alignment = std::nullopt; +}; + +struct StackChildLayoutData { + Alignment horizontal = Alignment::Start; + Alignment vertical = Alignment::Start; +}; +} // namespace cru::ui diff --git a/include/cru/ui/Control.hpp b/include/cru/ui/Control.hpp new file mode 100644 index 00000000..347163be --- /dev/null +++ b/include/cru/ui/Control.hpp @@ -0,0 +1,152 @@ +#pragma once +#include "Base.hpp" + +#include "cru/common/Event.hpp" +#include "render/Base.hpp" +#include "UiEvent.hpp" + +#include + +namespace cru::ui { +class Control : public Object { + friend UiHost; + + protected: + Control(); + + public: + Control(const Control& other) = delete; + Control(Control&& other) = delete; + Control& operator=(const Control& other) = delete; + Control& operator=(Control&& other) = delete; + ~Control() override = default; + + public: + virtual std::string_view GetControlType() const = 0; + + //*************** region: tree *************** + public: + // Get the ui host if attached, otherwise, return nullptr. + UiHost* GetUiHost() const { return ui_host_; } + + Control* GetParent() const { return parent_; } + + virtual const std::vector& GetChildren() const = 0; + + // Traverse the tree rooted the control including itself. + void TraverseDescendants(const std::function& predicate); + + void _SetParent(Control* parent); + void _SetDescendantUiHost(UiHost* host); + + private: + static void _TraverseDescendants( + Control* control, const std::function& predicate); + + public: + virtual render::RenderObject* GetRenderObject() const = 0; + + //*************** region: focus *************** + public: + bool RequestFocus(); + + bool HasFocus(); + + //*************** region: mouse *************** + public: + bool IsMouseOver() const { return is_mouse_over_; } + + bool CaptureMouse(); + + bool ReleaseMouse(); + + bool IsMouseCaptured(); + + //*************** region: cursor *************** + // Cursor is inherited from parent recursively if not set. + public: + // null for not set + std::shared_ptr GetCursor(); + + // will not return nullptr + std::shared_ptr GetInheritedCursor(); + + // null to unset + void SetCursor(std::shared_ptr cursor); + + //*************** region: events *************** + public: + // Raised when mouse enter the control. Even when the control itself captures + // the mouse, this event is raised as regular. But if mouse is captured by + // another control, the control will not receive any mouse enter event. You + // can use `IsMouseCaptured` to get more info. + event::RoutedEvent* MouseEnterEvent() { + return &mouse_enter_event_; + } + // Raised when mouse is leave the control. Even when the control itself + // captures the mouse, this event is raised as regular. But if mouse is + // captured by another control, the control will not receive any mouse leave + // event. You can use `IsMouseCaptured` to get more info. + event::RoutedEvent* MouseLeaveEvent() { + return &mouse_leave_event_; + } + // Raised when mouse is move in the control. + event::RoutedEvent* MouseMoveEvent() { + return &mouse_move_event_; + } + // Raised when a mouse button is pressed in the control. + event::RoutedEvent* MouseDownEvent() { + return &mouse_down_event_; + } + // Raised when a mouse button is released in the control. + event::RoutedEvent* MouseUpEvent() { + return &mouse_up_event_; + } + event::RoutedEvent* MouseWheelEvent() { + return &mouse_wheel_event_; + } + event::RoutedEvent* KeyDownEvent() { + return &key_down_event_; + } + event::RoutedEvent* KeyUpEvent() { + return &key_up_event_; + } + event::RoutedEvent* GainFocusEvent() { + return &gain_focus_event_; + } + event::RoutedEvent* LoseFocusEvent() { + return &lose_focus_event_; + } + + private: + event::RoutedEvent mouse_enter_event_; + event::RoutedEvent mouse_leave_event_; + event::RoutedEvent mouse_move_event_; + event::RoutedEvent mouse_down_event_; + event::RoutedEvent mouse_up_event_; + event::RoutedEvent mouse_wheel_event_; + + event::RoutedEvent key_down_event_; + event::RoutedEvent key_up_event_; + + event::RoutedEvent gain_focus_event_; + event::RoutedEvent lose_focus_event_; + + //*************** region: tree *************** + protected: + virtual void OnParentChanged(Control* old_parent, Control* new_parent); + virtual void OnAttachToHost(UiHost* host); + virtual void OnDetachFromHost(UiHost* host); + + virtual void OnMouseHoverChange(bool newHover) { CRU_UNUSED(newHover) } + + private: + UiHost* ui_host_ = nullptr; + Control* parent_ = nullptr; + + private: + bool is_mouse_over_ = false; + + std::shared_ptr cursor_ = nullptr; +}; +} // namespace cru::ui diff --git a/include/cru/ui/Window.hpp b/include/cru/ui/Window.hpp new file mode 100644 index 00000000..eb2ecfbb --- /dev/null +++ b/include/cru/ui/Window.hpp @@ -0,0 +1,40 @@ +#pragma once +#include "ContentControl.hpp" + +namespace cru::ui { +class Window final : public ContentControl { + friend UiHost; + + public: + static constexpr std::string_view control_type = "Window"; + + public: + static Window* CreateOverlapped(); + + private: + struct tag_overlapped_constructor {}; + + explicit Window(tag_overlapped_constructor); + + public: + Window(const Window& other) = delete; + Window(Window&& other) = delete; + Window& operator=(const Window& other) = delete; + Window& operator=(Window&& other) = delete; + ~Window() override; + + public: + std::string_view GetControlType() const final; + + render::RenderObject* GetRenderObject() const override; + + protected: + void OnChildChanged(Control* old_child, Control* new_child) override; + + private: + std::unique_ptr managed_ui_host_; + + // UiHost is responsible to take care of lifetime of this. + render::WindowRenderObject* render_object_; +}; +} // namespace cru::ui diff --git a/include/cru/ui/base.hpp b/include/cru/ui/base.hpp deleted file mode 100644 index b9ce0c88..00000000 --- a/include/cru/ui/base.hpp +++ /dev/null @@ -1,281 +0,0 @@ -#pragma once -#include "cru/common/Base.hpp" -#include "cru/platform/graph/Base.hpp" -#include "cru/platform/native/Base.hpp" - -#include -#include -#include -#include - -namespace cru::ui { -//-------------------- region: import -------------------- -using cru::platform::Color; -using cru::platform::Ellipse; -using cru::platform::Matrix; -using cru::platform::Point; -using cru::platform::Rect; -using cru::platform::RoundedRect; -using cru::platform::Size; -using cru::platform::TextRange; -using cru::platform::Thickness; -using cru::platform::native::MouseButton; - -namespace mouse_buttons { -using cru::platform::native::mouse_buttons::left; -using cru::platform::native::mouse_buttons::middle; -using cru::platform::native::mouse_buttons::right; -} // namespace mouse_buttons - -namespace colors { -using cru::platform::colors::aliceblue; -using cru::platform::colors::antiquewhite; -using cru::platform::colors::aqua; -using cru::platform::colors::aquamarine; -using cru::platform::colors::azure; -using cru::platform::colors::beige; -using cru::platform::colors::bisque; -using cru::platform::colors::black; -using cru::platform::colors::blanchedalmond; -using cru::platform::colors::blue; -using cru::platform::colors::blueviolet; -using cru::platform::colors::brown; -using cru::platform::colors::burlywood; -using cru::platform::colors::cadetblue; -using cru::platform::colors::chartreuse; -using cru::platform::colors::chocolate; -using cru::platform::colors::coral; -using cru::platform::colors::cornflowerblue; -using cru::platform::colors::cornsilk; -using cru::platform::colors::crimson; -using cru::platform::colors::cyan; -using cru::platform::colors::darkblue; -using cru::platform::colors::darkcyan; -using cru::platform::colors::darkgoldenrod; -using cru::platform::colors::darkgray; -using cru::platform::colors::darkgreen; -using cru::platform::colors::darkgrey; -using cru::platform::colors::darkkhaki; -using cru::platform::colors::darkmagenta; -using cru::platform::colors::darkolivegreen; -using cru::platform::colors::darkorange; -using cru::platform::colors::darkorchid; -using cru::platform::colors::darkred; -using cru::platform::colors::darksalmon; -using cru::platform::colors::darkseagreen; -using cru::platform::colors::darkslateblue; -using cru::platform::colors::darkslategray; -using cru::platform::colors::darkslategrey; -using cru::platform::colors::darkturquoise; -using cru::platform::colors::darkviolet; -using cru::platform::colors::deeppink; -using cru::platform::colors::deepskyblue; -using cru::platform::colors::dimgray; -using cru::platform::colors::dimgrey; -using cru::platform::colors::dodgerblue; -using cru::platform::colors::firebrick; -using cru::platform::colors::floralwhite; -using cru::platform::colors::forestgreen; -using cru::platform::colors::fuchsia; -using cru::platform::colors::gainsboro; -using cru::platform::colors::ghostwhite; -using cru::platform::colors::gold; -using cru::platform::colors::goldenrod; -using cru::platform::colors::gray; -using cru::platform::colors::green; -using cru::platform::colors::greenyellow; -using cru::platform::colors::grey; -using cru::platform::colors::honeydew; -using cru::platform::colors::hotpink; -using cru::platform::colors::indianred; -using cru::platform::colors::indigo; -using cru::platform::colors::ivory; -using cru::platform::colors::khaki; -using cru::platform::colors::lavender; -using cru::platform::colors::lavenderblush; -using cru::platform::colors::lawngreen; -using cru::platform::colors::lemonchiffon; -using cru::platform::colors::lightblue; -using cru::platform::colors::lightcoral; -using cru::platform::colors::lightcyan; -using cru::platform::colors::lightgoldenrodyellow; -using cru::platform::colors::lightgray; -using cru::platform::colors::lightgreen; -using cru::platform::colors::lightgrey; -using cru::platform::colors::lightpink; -using cru::platform::colors::lightsalmon; -using cru::platform::colors::lightseagreen; -using cru::platform::colors::lightskyblue; -using cru::platform::colors::lightslategray; -using cru::platform::colors::lightslategrey; -using cru::platform::colors::lightsteelblue; -using cru::platform::colors::lightyellow; -using cru::platform::colors::lime; -using cru::platform::colors::limegreen; -using cru::platform::colors::linen; -using cru::platform::colors::magenta; -using cru::platform::colors::maroon; -using cru::platform::colors::mediumaquamarine; -using cru::platform::colors::mediumblue; -using cru::platform::colors::mediumorchid; -using cru::platform::colors::mediumpurple; -using cru::platform::colors::mediumseagreen; -using cru::platform::colors::mediumslateblue; -using cru::platform::colors::mediumspringgreen; -using cru::platform::colors::mediumturquoise; -using cru::platform::colors::mediumvioletred; -using cru::platform::colors::midnightblue; -using cru::platform::colors::mintcream; -using cru::platform::colors::mistyrose; -using cru::platform::colors::moccasin; -using cru::platform::colors::navajowhite; -using cru::platform::colors::navy; -using cru::platform::colors::oldlace; -using cru::platform::colors::olive; -using cru::platform::colors::olivedrab; -using cru::platform::colors::orange; -using cru::platform::colors::orangered; -using cru::platform::colors::orchid; -using cru::platform::colors::palegoldenrod; -using cru::platform::colors::palegreen; -using cru::platform::colors::paleturquoise; -using cru::platform::colors::palevioletred; -using cru::platform::colors::papayawhip; -using cru::platform::colors::peachpuff; -using cru::platform::colors::peru; -using cru::platform::colors::pink; -using cru::platform::colors::plum; -using cru::platform::colors::powderblue; -using cru::platform::colors::purple; -using cru::platform::colors::rebeccapurple; -using cru::platform::colors::red; -using cru::platform::colors::rosybrown; -using cru::platform::colors::royalblue; -using cru::platform::colors::saddlebrown; -using cru::platform::colors::salmon; -using cru::platform::colors::sandybrown; -using cru::platform::colors::seagreen; -using cru::platform::colors::seashell; -using cru::platform::colors::sienna; -using cru::platform::colors::silver; -using cru::platform::colors::skyblue; -using cru::platform::colors::slateblue; -using cru::platform::colors::slategray; -using cru::platform::colors::slategrey; -using cru::platform::colors::snow; -using cru::platform::colors::springgreen; -using cru::platform::colors::steelblue; -using cru::platform::colors::tan; -using cru::platform::colors::teal; -using cru::platform::colors::thistle; -using cru::platform::colors::tomato; -using cru::platform::colors::transparent; -using cru::platform::colors::turquoise; -using cru::platform::colors::violet; -using cru::platform::colors::wheat; -using cru::platform::colors::white; -using cru::platform::colors::whitesmoke; -using cru::platform::colors::yellow; -using cru::platform::colors::yellowgreen; -} // namespace colors - -//-------------------- region: forward declaration -------------------- -class Window; -class Control; -class ClickDetector; -class UiHost; - -//-------------------- region: basic types -------------------- -namespace internal { -constexpr int align_start = 0; -constexpr int align_end = align_start + 1; -constexpr int align_center = align_end + 1; -} // namespace internal - -enum class Alignment { - Start = internal::align_start, - End = internal::align_end, - Center = internal::align_center, -}; - -struct CornerRadius { - constexpr CornerRadius() - : left_top(), right_top(), left_bottom(), right_bottom() {} - constexpr CornerRadius(const float& value) - : CornerRadius(Point{value, value}) {} - constexpr CornerRadius(const Point& value) - : left_top(value), - right_top(value), - left_bottom(value), - right_bottom(value) {} - constexpr CornerRadius(Point left_top, Point right_top, Point left_bottom, - Point right_bottom) - : left_top(left_top), - right_top(right_top), - left_bottom(left_bottom), - right_bottom(right_bottom) {} - - Point left_top; - Point right_top; - Point left_bottom; - Point right_bottom; -}; - -inline bool operator==(const CornerRadius& left, const CornerRadius& right) { - return left.left_top == right.left_top && - left.left_bottom == right.left_bottom && - left.right_top == right.right_top && - left.right_bottom == right.right_bottom; -} - -inline bool operator!=(const CornerRadius& left, const CornerRadius& right) { - return !(left == right); -} - -struct BorderStyle { - std::shared_ptr border_brush; - Thickness border_thickness; - CornerRadius border_radius; - std::shared_ptr foreground_brush; - std::shared_ptr background_brush; -}; - -class CanvasPaintEventArgs { - public: - CanvasPaintEventArgs(platform::graph::IPainter* painter, - const Rect& paint_rect) - : painter_(painter), paint_rect_(paint_rect) {} - CRU_DEFAULT_COPY(CanvasPaintEventArgs) - CRU_DEFAULT_MOVE(CanvasPaintEventArgs) - ~CanvasPaintEventArgs() = default; - - platform::graph::IPainter* GetPainter() const { return painter_; } - Rect GetPaintRect() const { return paint_rect_; } - - private: - platform::graph::IPainter* painter_; - Rect paint_rect_; -}; - -enum class FlexDirection { - Horizontal, - HorizontalReverse, - Vertical, - VertivalReverse -}; - -using FlexMainAlignment = Alignment; -using FlexCrossAlignment = Alignment; - -struct FlexChildLayoutData { - float expand_factor = 0; - float shrink_factor = 1; - // nullopt stands for looking at parent's setting - std::optional cross_alignment = std::nullopt; -}; - -struct StackChildLayoutData { - Alignment horizontal = Alignment::Start; - Alignment vertical = Alignment::Start; -}; -} // namespace cru::ui diff --git a/include/cru/ui/control.hpp b/include/cru/ui/control.hpp deleted file mode 100644 index 347163be..00000000 --- a/include/cru/ui/control.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/Event.hpp" -#include "render/Base.hpp" -#include "UiEvent.hpp" - -#include - -namespace cru::ui { -class Control : public Object { - friend UiHost; - - protected: - Control(); - - public: - Control(const Control& other) = delete; - Control(Control&& other) = delete; - Control& operator=(const Control& other) = delete; - Control& operator=(Control&& other) = delete; - ~Control() override = default; - - public: - virtual std::string_view GetControlType() const = 0; - - //*************** region: tree *************** - public: - // Get the ui host if attached, otherwise, return nullptr. - UiHost* GetUiHost() const { return ui_host_; } - - Control* GetParent() const { return parent_; } - - virtual const std::vector& GetChildren() const = 0; - - // Traverse the tree rooted the control including itself. - void TraverseDescendants(const std::function& predicate); - - void _SetParent(Control* parent); - void _SetDescendantUiHost(UiHost* host); - - private: - static void _TraverseDescendants( - Control* control, const std::function& predicate); - - public: - virtual render::RenderObject* GetRenderObject() const = 0; - - //*************** region: focus *************** - public: - bool RequestFocus(); - - bool HasFocus(); - - //*************** region: mouse *************** - public: - bool IsMouseOver() const { return is_mouse_over_; } - - bool CaptureMouse(); - - bool ReleaseMouse(); - - bool IsMouseCaptured(); - - //*************** region: cursor *************** - // Cursor is inherited from parent recursively if not set. - public: - // null for not set - std::shared_ptr GetCursor(); - - // will not return nullptr - std::shared_ptr GetInheritedCursor(); - - // null to unset - void SetCursor(std::shared_ptr cursor); - - //*************** region: events *************** - public: - // Raised when mouse enter the control. Even when the control itself captures - // the mouse, this event is raised as regular. But if mouse is captured by - // another control, the control will not receive any mouse enter event. You - // can use `IsMouseCaptured` to get more info. - event::RoutedEvent* MouseEnterEvent() { - return &mouse_enter_event_; - } - // Raised when mouse is leave the control. Even when the control itself - // captures the mouse, this event is raised as regular. But if mouse is - // captured by another control, the control will not receive any mouse leave - // event. You can use `IsMouseCaptured` to get more info. - event::RoutedEvent* MouseLeaveEvent() { - return &mouse_leave_event_; - } - // Raised when mouse is move in the control. - event::RoutedEvent* MouseMoveEvent() { - return &mouse_move_event_; - } - // Raised when a mouse button is pressed in the control. - event::RoutedEvent* MouseDownEvent() { - return &mouse_down_event_; - } - // Raised when a mouse button is released in the control. - event::RoutedEvent* MouseUpEvent() { - return &mouse_up_event_; - } - event::RoutedEvent* MouseWheelEvent() { - return &mouse_wheel_event_; - } - event::RoutedEvent* KeyDownEvent() { - return &key_down_event_; - } - event::RoutedEvent* KeyUpEvent() { - return &key_up_event_; - } - event::RoutedEvent* GainFocusEvent() { - return &gain_focus_event_; - } - event::RoutedEvent* LoseFocusEvent() { - return &lose_focus_event_; - } - - private: - event::RoutedEvent mouse_enter_event_; - event::RoutedEvent mouse_leave_event_; - event::RoutedEvent mouse_move_event_; - event::RoutedEvent mouse_down_event_; - event::RoutedEvent mouse_up_event_; - event::RoutedEvent mouse_wheel_event_; - - event::RoutedEvent key_down_event_; - event::RoutedEvent key_up_event_; - - event::RoutedEvent gain_focus_event_; - event::RoutedEvent lose_focus_event_; - - //*************** region: tree *************** - protected: - virtual void OnParentChanged(Control* old_parent, Control* new_parent); - virtual void OnAttachToHost(UiHost* host); - virtual void OnDetachFromHost(UiHost* host); - - virtual void OnMouseHoverChange(bool newHover) { CRU_UNUSED(newHover) } - - private: - UiHost* ui_host_ = nullptr; - Control* parent_ = nullptr; - - private: - bool is_mouse_over_ = false; - - std::shared_ptr cursor_ = nullptr; -}; -} // namespace cru::ui diff --git a/include/cru/ui/controls/Base.hpp b/include/cru/ui/controls/Base.hpp new file mode 100644 index 00000000..b550601b --- /dev/null +++ b/include/cru/ui/controls/Base.hpp @@ -0,0 +1,24 @@ +#pragma once +#include "../Base.hpp" + +namespace cru::ui::controls { +using ButtonStateStyle = BorderStyle; + +struct ButtonStyle { + // corresponds to ClickState::None + ButtonStateStyle normal; + // corresponds to ClickState::Hover + ButtonStateStyle hover; + // corresponds to ClickState::Press + ButtonStateStyle press; + // corresponds to ClickState::PressInactive + ButtonStateStyle press_cancel; +}; + +struct TextBoxBorderStyle { + BorderStyle normal; + BorderStyle hover; + BorderStyle focus; + BorderStyle focus_hover; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Button.hpp b/include/cru/ui/controls/Button.hpp new file mode 100644 index 00000000..8a11409c --- /dev/null +++ b/include/cru/ui/controls/Button.hpp @@ -0,0 +1,42 @@ +#pragma once +#include "../ContentControl.hpp" +#include "Base.hpp" + +#include "../ClickDetector.hpp" + +namespace cru::ui::controls { +class Button : public ContentControl { + public: + static constexpr std::string_view control_type = "Button"; + + static Button* Create() { return new Button(); } + + protected: + Button(); + + public: + Button(const Button& other) = delete; + Button(Button&& other) = delete; + Button& operator=(const Button& other) = delete; + Button& operator=(Button&& other) = delete; + ~Button() override; + + std::string_view GetControlType() const final { return control_type; } + + render::RenderObject* GetRenderObject() const override; + + public: + const ButtonStyle& GetStyle() const { return style_; } + void SetStyle(ButtonStyle style); + + protected: + void OnChildChanged(Control* old_child, Control* new_child) override; + + private: + std::unique_ptr render_object_{}; + + ButtonStyle style_; + + ClickDetector click_detector_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Container.hpp b/include/cru/ui/controls/Container.hpp new file mode 100644 index 00000000..e3d78365 --- /dev/null +++ b/include/cru/ui/controls/Container.hpp @@ -0,0 +1,28 @@ +#pragma once +#include "../ContentControl.hpp" + +namespace cru::ui::controls { +class Container : public ContentControl { + static constexpr std::string_view control_type = "Container"; + + protected: + Container(); + + public: + CRU_DELETE_COPY(Container) + CRU_DELETE_MOVE(Container) + + ~Container() override; + + public: + std::string_view GetControlType() const final { return control_type; } + + render::RenderObject* GetRenderObject() const override; + + protected: + void OnChildChanged(Control* old_child, Control* new_child) override; + + private: + std::unique_ptr render_object_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/base.hpp b/include/cru/ui/controls/base.hpp deleted file mode 100644 index b550601b..00000000 --- a/include/cru/ui/controls/base.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "../Base.hpp" - -namespace cru::ui::controls { -using ButtonStateStyle = BorderStyle; - -struct ButtonStyle { - // corresponds to ClickState::None - ButtonStateStyle normal; - // corresponds to ClickState::Hover - ButtonStateStyle hover; - // corresponds to ClickState::Press - ButtonStateStyle press; - // corresponds to ClickState::PressInactive - ButtonStateStyle press_cancel; -}; - -struct TextBoxBorderStyle { - BorderStyle normal; - BorderStyle hover; - BorderStyle focus; - BorderStyle focus_hover; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/button.hpp b/include/cru/ui/controls/button.hpp deleted file mode 100644 index 8a11409c..00000000 --- a/include/cru/ui/controls/button.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include "../ContentControl.hpp" -#include "Base.hpp" - -#include "../ClickDetector.hpp" - -namespace cru::ui::controls { -class Button : public ContentControl { - public: - static constexpr std::string_view control_type = "Button"; - - static Button* Create() { return new Button(); } - - protected: - Button(); - - public: - Button(const Button& other) = delete; - Button(Button&& other) = delete; - Button& operator=(const Button& other) = delete; - Button& operator=(Button&& other) = delete; - ~Button() override; - - std::string_view GetControlType() const final { return control_type; } - - render::RenderObject* GetRenderObject() const override; - - public: - const ButtonStyle& GetStyle() const { return style_; } - void SetStyle(ButtonStyle style); - - protected: - void OnChildChanged(Control* old_child, Control* new_child) override; - - private: - std::unique_ptr render_object_{}; - - ButtonStyle style_; - - ClickDetector click_detector_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/container.hpp b/include/cru/ui/controls/container.hpp deleted file mode 100644 index e3d78365..00000000 --- a/include/cru/ui/controls/container.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "../ContentControl.hpp" - -namespace cru::ui::controls { -class Container : public ContentControl { - static constexpr std::string_view control_type = "Container"; - - protected: - Container(); - - public: - CRU_DELETE_COPY(Container) - CRU_DELETE_MOVE(Container) - - ~Container() override; - - public: - std::string_view GetControlType() const final { return control_type; } - - render::RenderObject* GetRenderObject() const override; - - protected: - void OnChildChanged(Control* old_child, Control* new_child) override; - - private: - std::unique_ptr render_object_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/render/Base.hpp b/include/cru/ui/render/Base.hpp new file mode 100644 index 00000000..c2af5e99 --- /dev/null +++ b/include/cru/ui/render/Base.hpp @@ -0,0 +1,12 @@ +#pragma once +#include "../Base.hpp" + +namespace cru::ui::render { +class RenderObject; +class BorderRenderObject; +class CanvasRenderObject; +class FlexLayoutRenderObject; +class StackLayoutRenderObject; +class TextRenderObject; +class WindowRenderObject; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/base.hpp b/include/cru/ui/render/base.hpp deleted file mode 100644 index c2af5e99..00000000 --- a/include/cru/ui/render/base.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../Base.hpp" - -namespace cru::ui::render { -class RenderObject; -class BorderRenderObject; -class CanvasRenderObject; -class FlexLayoutRenderObject; -class StackLayoutRenderObject; -class TextRenderObject; -class WindowRenderObject; -} // namespace cru::ui::render diff --git a/include/cru/ui/window.hpp b/include/cru/ui/window.hpp deleted file mode 100644 index eb2ecfbb..00000000 --- a/include/cru/ui/window.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "ContentControl.hpp" - -namespace cru::ui { -class Window final : public ContentControl { - friend UiHost; - - public: - static constexpr std::string_view control_type = "Window"; - - public: - static Window* CreateOverlapped(); - - private: - struct tag_overlapped_constructor {}; - - explicit Window(tag_overlapped_constructor); - - public: - Window(const Window& other) = delete; - Window(Window&& other) = delete; - Window& operator=(const Window& other) = delete; - Window& operator=(Window&& other) = delete; - ~Window() override; - - public: - std::string_view GetControlType() const final; - - render::RenderObject* GetRenderObject() const override; - - protected: - void OnChildChanged(Control* old_child, Control* new_child) override; - - private: - std::unique_ptr managed_ui_host_; - - // UiHost is responsible to take care of lifetime of this. - render::WindowRenderObject* render_object_; -}; -} // namespace cru::ui -- cgit v1.2.3