diff options
author | 杨宇千 <crupest@outlook.com> | 2018-11-13 22:44:07 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-13 22:44:07 +0800 |
commit | b08ba6c83902d140fb14131b3f01837985d39c17 (patch) | |
tree | 98719593d5854f2162ea8d87b7fecdc3472968bc | |
parent | 91dda866a0919f9e6cfb5e7857ac0466572d96d8 (diff) | |
parent | 6d0a44597eb6e35993b46642ebf85abd94bca2d7 (diff) | |
download | cru-b08ba6c83902d140fb14131b3f01837985d39c17.tar.gz cru-b08ba6c83902d140fb14131b3f01837985d39c17.tar.bz2 cru-b08ba6c83902d140fb14131b3f01837985d39c17.zip |
Merge pull request #18 from crupest/bound
Add support for enhanced bound check.
-rw-r--r-- | CruUI-Generate/cru_ui.cpp | 53 | ||||
-rw-r--r-- | CruUI-Generate/cru_ui.hpp | 14 | ||||
-rw-r--r-- | src/ui/control.cpp | 48 | ||||
-rw-r--r-- | src/ui/control.hpp | 6 | ||||
-rw-r--r-- | src/ui/convert_util.hpp | 5 | ||||
-rw-r--r-- | src/ui/window.cpp | 5 | ||||
-rw-r--r-- | src/ui/window.hpp | 3 |
7 files changed, 130 insertions, 4 deletions
diff --git a/CruUI-Generate/cru_ui.cpp b/CruUI-Generate/cru_ui.cpp index 3036989d..252dfd9a 100644 --- a/CruUI-Generate/cru_ui.cpp +++ b/CruUI-Generate/cru_ui.cpp @@ -980,8 +980,24 @@ namespace cru::ui bool Control::IsPointInside(const Point & point) { - const auto size = GetSize(); - return point.x >= 0.0f && point.x < size.width && point.y >= 0.0f && point.y < size.height; + if (border_geometry_ != nullptr) + { + if (IsBordered()) + { + BOOL contains; + border_geometry_->FillContainsPoint(Convert(point), D2D1::Matrix3x2F::Identity(), &contains); + if (!contains) + border_geometry_->StrokeContainsPoint(Convert(point), GetBorderProperty().GetStrokeWidth(), nullptr, D2D1::Matrix3x2F::Identity(), &contains); + return contains != 0; + } + else + { + BOOL contains; + border_geometry_->FillContainsPoint(Convert(point), D2D1::Matrix3x2F::Identity(), &contains); + return contains != 0; + } + } + return false; } void Control::Draw(ID2D1DeviceContext* device_context) @@ -1108,6 +1124,7 @@ namespace cru::ui void Control::InvalidateBorder() { + RegenerateBorderGeometry(); InvalidateLayout(); Repaint(); } @@ -1275,6 +1292,7 @@ namespace cru::ui void Control::OnSizeChangedCore(SizeChangedEventArgs & args) { + RegenerateBorderGeometry(); #ifdef CRU_DEBUG_LAYOUT margin_geometry_ = CalculateSquareRingGeometry(GetRect(RectRange::Margin), GetRect(RectRange::FullBorder)); padding_geometry_ = CalculateSquareRingGeometry(GetRect(RectRange::Padding), GetRect(RectRange::Content)); @@ -1295,6 +1313,32 @@ namespace cru::ui size_changed_event.Raise(args); } + void Control::RegenerateBorderGeometry() + { + if (IsBordered()) + { + const auto bound_rect = GetRect(RectRange::HalfBorder); + const auto bound_rounded_rect = D2D1::RoundedRect(Convert(bound_rect), + GetBorderProperty().GetRadiusX(), + GetBorderProperty().GetRadiusY()); + + Microsoft::WRL::ComPtr<ID2D1RoundedRectangleGeometry> geometry; + ThrowIfFailed( + graph::GraphManager::GetInstance()->GetD2D1Factory()->CreateRoundedRectangleGeometry(bound_rounded_rect, &geometry) + ); + border_geometry_ = std::move(geometry); + } + else + { + const auto bound_rect = GetRect(RectRange::Padding); + Microsoft::WRL::ComPtr<ID2D1RectangleGeometry> geometry; + ThrowIfFailed( + graph::GraphManager::GetInstance()->GetD2D1Factory()->CreateRectangleGeometry(Convert(bound_rect), &geometry) + ); + border_geometry_ = std::move(geometry); + } + } + void Control::OnMouseEnter(MouseEventArgs & args) { } @@ -2495,6 +2539,11 @@ namespace cru::ui } + bool Window::IsPointInside(const Point& point) + { + return Rect(Point::Zero(), GetClientSize()).IsPointInside(point); + } + void Window::WindowInvalidateLayout() { if (is_layout_invalid_) diff --git a/CruUI-Generate/cru_ui.hpp b/CruUI-Generate/cru_ui.hpp index d6df9b13..302ce611 100644 --- a/CruUI-Generate/cru_ui.hpp +++ b/CruUI-Generate/cru_ui.hpp @@ -1596,6 +1596,8 @@ namespace cru::ui //Absolute point to local point. Point WindowToControl(const Point& point) const; + // Default implement in Control is test point in border geometry's + // fill and stroke with width of border. virtual bool IsPointInside(const Point& point); @@ -1743,6 +1745,8 @@ namespace cru::ui void RaisePositionChangedEvent(events::PositionChangedEventArgs& args); void RaiseSizeChangedEvent(events::SizeChangedEventArgs& args); + void RegenerateBorderGeometry(); + //*************** region: mouse event *************** virtual void OnMouseEnter(events::MouseEventArgs& args); virtual void OnMouseLeave(events::MouseEventArgs& args); @@ -1847,6 +1851,8 @@ namespace cru::ui bool is_bordered_ = false; BorderProperty border_property_; + Microsoft::WRL::ComPtr<ID2D1Geometry> border_geometry_ = nullptr; + AnyMap additional_property_map_{}; bool is_focus_on_pressed_ = true; @@ -2094,6 +2100,9 @@ namespace cru::ui //This method has no effect for a window. Use SetClientSize instead. void SetSize(const Size& size) override final; + //Override. If point is in client area, it is in window. + bool IsPointInside(const Point& point) override final; + //*************** region: layout *************** void WindowInvalidateLayout(); @@ -3025,6 +3034,11 @@ namespace cru::ui 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/control.cpp b/src/ui/control.cpp index 2d368673..42e5f71f 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -191,8 +191,24 @@ namespace cru::ui bool Control::IsPointInside(const Point & point) { - const auto size = GetSize(); - return point.x >= 0.0f && point.x < size.width && point.y >= 0.0f && point.y < size.height; + if (border_geometry_ != nullptr) + { + if (IsBordered()) + { + BOOL contains; + border_geometry_->FillContainsPoint(Convert(point), D2D1::Matrix3x2F::Identity(), &contains); + if (!contains) + border_geometry_->StrokeContainsPoint(Convert(point), GetBorderProperty().GetStrokeWidth(), nullptr, D2D1::Matrix3x2F::Identity(), &contains); + return contains != 0; + } + else + { + BOOL contains; + border_geometry_->FillContainsPoint(Convert(point), D2D1::Matrix3x2F::Identity(), &contains); + return contains != 0; + } + } + return false; } void Control::Draw(ID2D1DeviceContext* device_context) @@ -319,6 +335,7 @@ namespace cru::ui void Control::InvalidateBorder() { + RegenerateBorderGeometry(); InvalidateLayout(); Repaint(); } @@ -486,6 +503,7 @@ namespace cru::ui void Control::OnSizeChangedCore(SizeChangedEventArgs & args) { + RegenerateBorderGeometry(); #ifdef CRU_DEBUG_LAYOUT margin_geometry_ = CalculateSquareRingGeometry(GetRect(RectRange::Margin), GetRect(RectRange::FullBorder)); padding_geometry_ = CalculateSquareRingGeometry(GetRect(RectRange::Padding), GetRect(RectRange::Content)); @@ -506,6 +524,32 @@ namespace cru::ui size_changed_event.Raise(args); } + void Control::RegenerateBorderGeometry() + { + if (IsBordered()) + { + const auto bound_rect = GetRect(RectRange::HalfBorder); + const auto bound_rounded_rect = D2D1::RoundedRect(Convert(bound_rect), + GetBorderProperty().GetRadiusX(), + GetBorderProperty().GetRadiusY()); + + Microsoft::WRL::ComPtr<ID2D1RoundedRectangleGeometry> geometry; + ThrowIfFailed( + graph::GraphManager::GetInstance()->GetD2D1Factory()->CreateRoundedRectangleGeometry(bound_rounded_rect, &geometry) + ); + border_geometry_ = std::move(geometry); + } + else + { + const auto bound_rect = GetRect(RectRange::Padding); + Microsoft::WRL::ComPtr<ID2D1RectangleGeometry> geometry; + ThrowIfFailed( + graph::GraphManager::GetInstance()->GetD2D1Factory()->CreateRectangleGeometry(Convert(bound_rect), &geometry) + ); + border_geometry_ = std::move(geometry); + } + } + void Control::OnMouseEnter(MouseEventArgs & args) { } diff --git a/src/ui/control.hpp b/src/ui/control.hpp index 7afc0c4e..776eacb0 100644 --- a/src/ui/control.hpp +++ b/src/ui/control.hpp @@ -117,6 +117,8 @@ namespace cru::ui //Absolute point to local point. Point WindowToControl(const Point& point) const; + // Default implement in Control is test point in border geometry's + // fill and stroke with width of border. virtual bool IsPointInside(const Point& point); @@ -264,6 +266,8 @@ namespace cru::ui void RaisePositionChangedEvent(events::PositionChangedEventArgs& args); void RaiseSizeChangedEvent(events::SizeChangedEventArgs& args); + void RegenerateBorderGeometry(); + //*************** region: mouse event *************** virtual void OnMouseEnter(events::MouseEventArgs& args); virtual void OnMouseLeave(events::MouseEventArgs& args); @@ -368,6 +372,8 @@ namespace cru::ui bool is_bordered_ = false; BorderProperty border_property_; + Microsoft::WRL::ComPtr<ID2D1Geometry> border_geometry_ = nullptr; + AnyMap additional_property_map_{}; bool is_focus_on_pressed_ = true; diff --git a/src/ui/convert_util.hpp b/src/ui/convert_util.hpp index 1c18f59b..6deb7fff 100644 --- a/src/ui/convert_util.hpp +++ b/src/ui/convert_util.hpp @@ -6,6 +6,11 @@ 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/window.cpp b/src/ui/window.cpp index 862267fc..39b574bd 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -473,6 +473,11 @@ namespace cru::ui } + bool Window::IsPointInside(const Point& point) + { + return Rect(Point::Zero(), GetClientSize()).IsPointInside(point); + } + void Window::WindowInvalidateLayout() { if (is_layout_invalid_) diff --git a/src/ui/window.hpp b/src/ui/window.hpp index b2b8cde0..2955cd32 100644 --- a/src/ui/window.hpp +++ b/src/ui/window.hpp @@ -197,6 +197,9 @@ namespace cru::ui //This method has no effect for a window. Use SetClientSize instead. void SetSize(const Size& size) override final; + //Override. If point is in client area, it is in window. + bool IsPointInside(const Point& point) override final; + //*************** region: layout *************** void WindowInvalidateLayout(); |