diff options
author | crupest <crupest@outlook.com> | 2018-11-25 17:50:12 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2018-11-25 17:50:12 +0800 |
commit | 5391e781e4682731721c841462904809bc618870 (patch) | |
tree | e1315ff02ebdf63b80f2eb9e6a1f43a44a313249 | |
parent | abc776a9ea02a564dfe44141e51e4cbc87a7a3a1 (diff) | |
download | cru-5391e781e4682731721c841462904809bc618870.tar.gz cru-5391e781e4682731721c841462904809bc618870.tar.bz2 cru-5391e781e4682731721c841462904809bc618870.zip |
Change clip to padding into clip content.
-rw-r--r-- | src/ui/control.cpp | 92 | ||||
-rw-r--r-- | src/ui/control.hpp | 24 | ||||
-rw-r--r-- | src/ui/controls/scroll_control.cpp | 2 | ||||
-rw-r--r-- | src/ui/controls/text_control.cpp | 2 |
4 files changed, 80 insertions, 40 deletions
diff --git a/src/ui/control.cpp b/src/ui/control.cpp index 22b7164f..66f22c58 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -191,20 +191,21 @@ namespace cru::ui bool Control::IsPointInside(const Point & point) { - if (border_geometry_ != nullptr) + const auto border_geometry = geometry_info_.border_geometry; + if (border_geometry != nullptr) { if (IsBordered()) { BOOL contains; - border_geometry_->FillContainsPoint(Convert(point), D2D1::Matrix3x2F::Identity(), &contains); + border_geometry->FillContainsPoint(Convert(point), D2D1::Matrix3x2F::Identity(), &contains); if (!contains) - border_geometry_->StrokeContainsPoint(Convert(point), GetBorderProperty().GetStrokeWidth(), nullptr, D2D1::Matrix3x2F::Identity(), &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); + border_geometry->FillContainsPoint(Convert(point), D2D1::Matrix3x2F::Identity(), &contains); return contains != 0; } } @@ -215,8 +216,18 @@ namespace cru::ui { const auto point_inside = IsPointInside(point); - if (!point_inside && IsClipToPadding()) - return nullptr; // if clip then don't test children. + if (IsClipContent()) + { + if (!point_inside) + return nullptr; + if (geometry_info_.content_geometry != nullptr) + { + BOOL contains; + ThrowIfFailed(geometry_info_.content_geometry->FillContainsPoint(Convert(point), D2D1::Matrix3x2F::Identity(), &contains)); + if (contains == 0) + return this; + } + } const auto& children = GetChildren(); @@ -229,18 +240,15 @@ namespace cru::ui return child_hit_test_result; } - if (!point_inside) - return nullptr; - - return this; + return point_inside ? this : nullptr; } - void Control::SetClipToPadding(const bool clip) + void Control::SetClipContent(const bool clip) { - if (clip_to_padding_ == clip) + if (clip_content_ == clip) return; - clip_to_padding_ = clip; + clip_content_ = clip; InvalidateDraw(); } @@ -254,9 +262,9 @@ namespace cru::ui OnDrawDecoration(device_context); - const auto set_layer = in_border_geometry_ != nullptr && IsClipToPadding(); + const auto set_layer = geometry_info_.content_geometry != nullptr && IsClipContent(); if (set_layer) - device_context->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), in_border_geometry_.Get()), nullptr); + device_context->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), geometry_info_.content_geometry.Get()), nullptr); OnDrawCore(device_context); @@ -377,7 +385,7 @@ namespace cru::ui void Control::UpdateBorder() { - RegenerateBorderGeometry(); + RegenerateGeometries(); InvalidateLayout(); InvalidateDraw(); } @@ -447,9 +455,9 @@ namespace cru::ui } #endif - if (is_bordered_ && border_geometry_ != nullptr) + if (is_bordered_ && geometry_info_.border_geometry != nullptr) device_context->DrawGeometry( - border_geometry_.Get(), + geometry_info_.border_geometry.Get(), GetBorderProperty().GetBrush().Get(), GetBorderProperty().GetStrokeWidth(), GetBorderProperty().GetStrokeStyle().Get() @@ -458,9 +466,10 @@ namespace cru::ui void Control::OnDrawCore(ID2D1DeviceContext* device_context) { + const auto ground_geometry = geometry_info_.padding_content_geometry; //draw background. - if (in_border_geometry_ != nullptr && background_brush_ != nullptr) - device_context->FillGeometry(in_border_geometry_.Get(), background_brush_.Get()); + if (ground_geometry != nullptr && background_brush_ != nullptr) + device_context->FillGeometry(ground_geometry.Get(), background_brush_.Get()); const auto padding_rect = GetRect(RectRange::Padding); graph::WithTransform(device_context, D2D1::Matrix3x2F::Translation(padding_rect.left, padding_rect.top), [this](ID2D1DeviceContext* device_context) @@ -482,8 +491,8 @@ namespace cru::ui //draw foreground. - if (in_border_geometry_ != nullptr && foreground_brush_ != nullptr) - device_context->FillGeometry(in_border_geometry_.Get(), foreground_brush_.Get()); + if (ground_geometry != nullptr && foreground_brush_ != nullptr) + device_context->FillGeometry(ground_geometry.Get(), foreground_brush_.Get()); graph::WithTransform(device_context, D2D1::Matrix3x2F::Translation(padding_rect.left, padding_rect.top), [this](ID2D1DeviceContext* device_context) { @@ -545,7 +554,7 @@ namespace cru::ui void Control::OnSizeChangedCore(SizeChangedEventArgs & args) { - RegenerateBorderGeometry(); + RegenerateGeometries(); #ifdef CRU_DEBUG_LAYOUT margin_geometry_ = CalculateSquareRingGeometry(GetRect(RectRange::Margin), GetRect(RectRange::FullBorder)); padding_geometry_ = CalculateSquareRingGeometry(GetRect(RectRange::Padding), GetRect(RectRange::Content)); @@ -566,7 +575,7 @@ namespace cru::ui size_changed_event.Raise(args); } - void Control::RegenerateBorderGeometry() + void Control::RegenerateGeometries() { if (IsBordered()) { @@ -579,10 +588,10 @@ namespace cru::ui ThrowIfFailed( graph::GraphManager::GetInstance()->GetD2D1Factory()->CreateRoundedRectangleGeometry(bound_rounded_rect, &geometry) ); - border_geometry_ = std::move(geometry); + geometry_info_.border_geometry = std::move(geometry); - const auto in_border_rect = GetRect(RectRange::Padding); - const auto in_border_rounded_rect = D2D1::RoundedRect(Convert(in_border_rect), + const auto padding_rect = GetRect(RectRange::Padding); + const auto in_border_rounded_rect = D2D1::RoundedRect(Convert(padding_rect), GetBorderProperty().GetRadiusX() - GetBorderProperty().GetStrokeWidth() / 2.0f, GetBorderProperty().GetRadiusY() - GetBorderProperty().GetStrokeWidth() / 2.0f); @@ -590,7 +599,24 @@ namespace cru::ui ThrowIfFailed( graph::GraphManager::GetInstance()->GetD2D1Factory()->CreateRoundedRectangleGeometry(in_border_rounded_rect, &geometry2) ); - in_border_geometry_ = std::move(geometry2); + geometry_info_.padding_content_geometry = geometry2; + + + Microsoft::WRL::ComPtr<ID2D1RectangleGeometry> geometry3; + ThrowIfFailed( + graph::GraphManager::GetInstance()->GetD2D1Factory()->CreateRectangleGeometry(Convert(GetRect(RectRange::Content)), &geometry3) + ); + Microsoft::WRL::ComPtr<ID2D1PathGeometry> geometry4; + ThrowIfFailed( + graph::GraphManager::GetInstance()->GetD2D1Factory()->CreatePathGeometry(&geometry4) + ); + Microsoft::WRL::ComPtr<ID2D1GeometrySink> sink; + geometry4->Open(&sink); + ThrowIfFailed( + geometry3->CombineWithGeometry(geometry2.Get(), D2D1_COMBINE_MODE_INTERSECT, D2D1::Matrix3x2F::Identity(), sink.Get()) + ); + sink->Close(); + geometry_info_.content_geometry = std::move(geometry4); } else { @@ -599,8 +625,14 @@ namespace cru::ui ThrowIfFailed( graph::GraphManager::GetInstance()->GetD2D1Factory()->CreateRectangleGeometry(Convert(bound_rect), &geometry) ); - border_geometry_ = geometry; - in_border_geometry_ = std::move(geometry); + geometry_info_.border_geometry = geometry; + geometry_info_.padding_content_geometry = std::move(geometry); + + Microsoft::WRL::ComPtr<ID2D1RectangleGeometry> geometry2; + ThrowIfFailed( + graph::GraphManager::GetInstance()->GetD2D1Factory()->CreateRectangleGeometry(Convert(GetRect(RectRange::Content)), &geometry2) + ); + geometry_info_.content_geometry = std::move(geometry2); } } diff --git a/src/ui/control.hpp b/src/ui/control.hpp index 44c98728..6c5b0ea5 100644 --- a/src/ui/control.hpp +++ b/src/ui/control.hpp @@ -26,11 +26,21 @@ namespace cru::ui Point lefttop_position_absolute; }; + class Control : public Object { friend class Window; friend class LayoutManager; + private: + struct GeometryInfo + { + Microsoft::WRL::ComPtr<ID2D1Geometry> border_geometry = nullptr; + Microsoft::WRL::ComPtr<ID2D1Geometry> padding_content_geometry = nullptr; + Microsoft::WRL::ComPtr<ID2D1Geometry> content_geometry = nullptr; + }; + + protected: struct WindowConstructorTag {}; //Used for constructor for class Window. @@ -126,12 +136,12 @@ namespace cru::ui //*************** region: graphic *************** - bool IsClipToPadding() const + bool IsClipContent() const { - return clip_to_padding_; + return clip_content_; } - void SetClipToPadding(bool clip); + void SetClipContent(bool clip); //Draw this control and its child controls. void Draw(ID2D1DeviceContext* device_context); @@ -299,7 +309,7 @@ namespace cru::ui void RaisePositionChangedEvent(events::PositionChangedEventArgs& args); void RaiseSizeChangedEvent(events::SizeChangedEventArgs& args); - void RegenerateBorderGeometry(); + void RegenerateGeometries(); //*************** region: mouse event *************** virtual void OnMouseEnter(events::MouseEventArgs& args); @@ -403,11 +413,9 @@ namespace cru::ui bool is_bordered_ = false; BorderProperty border_property_; - bool clip_to_padding_ = false; + GeometryInfo geometry_info_{}; - Microsoft::WRL::ComPtr<ID2D1Geometry> border_geometry_ = nullptr; - // used for foreground and background brush and clip. - Microsoft::WRL::ComPtr<ID2D1Geometry> in_border_geometry_ = nullptr; + bool clip_content_ = false; Microsoft::WRL::ComPtr<ID2D1Brush> foreground_brush_ = nullptr; Microsoft::WRL::ComPtr<ID2D1Brush> background_brush_ = nullptr; diff --git a/src/ui/controls/scroll_control.cpp b/src/ui/controls/scroll_control.cpp index 00969ab7..6b6d899c 100644 --- a/src/ui/controls/scroll_control.cpp +++ b/src/ui/controls/scroll_control.cpp @@ -9,7 +9,7 @@ namespace cru::ui::controls { ScrollControl::ScrollControl(const bool container) : Control(container) { - SetClipToPadding(true); + SetClipContent(true); } ScrollControl::~ScrollControl() diff --git a/src/ui/controls/text_control.cpp b/src/ui/controls/text_control.cpp index c37441b3..d7d6b810 100644 --- a/src/ui/controls/text_control.cpp +++ b/src/ui/controls/text_control.cpp @@ -20,7 +20,7 @@ namespace cru::ui::controls selection_brush_ = UiManager::GetInstance()->GetPredefineResources()->text_control_selection_brush; - SetClipToPadding(true); + SetClipContent(true); } |