aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author杨宇千 <crupest@outlook.com>2018-11-13 22:44:07 +0800
committerGitHub <noreply@github.com>2018-11-13 22:44:07 +0800
commitb08ba6c83902d140fb14131b3f01837985d39c17 (patch)
tree98719593d5854f2162ea8d87b7fecdc3472968bc
parent91dda866a0919f9e6cfb5e7857ac0466572d96d8 (diff)
parent6d0a44597eb6e35993b46642ebf85abd94bca2d7 (diff)
downloadcru-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.cpp53
-rw-r--r--CruUI-Generate/cru_ui.hpp14
-rw-r--r--src/ui/control.cpp48
-rw-r--r--src/ui/control.hpp6
-rw-r--r--src/ui/convert_util.hpp5
-rw-r--r--src/ui/window.cpp5
-rw-r--r--src/ui/window.hpp3
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();