diff options
author | crupest <crupest@outlook.com> | 2018-11-06 16:32:38 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2018-11-06 16:32:38 +0800 |
commit | 1d551a7666ee61074fd36fed4f919c9583477fef (patch) | |
tree | 0b445619b034a22f7d30642b0ba84e4d82dfa4da /src | |
parent | bfdc5da41b9ab8b3f150a619c7893270dc8ccc7f (diff) | |
download | cru-1d551a7666ee61074fd36fed4f919c9583477fef.tar.gz cru-1d551a7666ee61074fd36fed4f919c9583477fef.tar.bz2 cru-1d551a7666ee61074fd36fed4f919c9583477fef.zip |
Dev cursor for textbox.
Diffstat (limited to 'src')
-rw-r--r-- | src/main.cpp | 7 | ||||
-rw-r--r-- | src/ui/control.cpp | 23 | ||||
-rw-r--r-- | src/ui/control.h | 12 | ||||
-rw-r--r-- | src/ui/controls/text_control.cpp | 58 | ||||
-rw-r--r-- | src/ui/controls/text_control.h | 3 | ||||
-rw-r--r-- | src/ui/events/ui_event.cpp | 4 | ||||
-rw-r--r-- | src/ui/events/ui_event.h | 3 | ||||
-rw-r--r-- | src/ui/layout_base.h | 9 |
8 files changed, 78 insertions, 41 deletions
diff --git a/src/main.cpp b/src/main.cpp index a9fa7126..ab641075 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,5 @@ #include "application.h" #include "ui/window.h" -#include "ui/events/ui_event.h" #include "ui/controls/linear_layout.h" #include "ui/controls/text_block.h" #include "ui/controls/toggle_button.h" @@ -150,12 +149,12 @@ int APIENTRY wWinMain( )); */ - const auto linear_layout = CreateWithLayout<LinearLayout>(Thickness(50, 50), Thickness(50, 50), LinearLayout::Orientation::Vertical, ControlList({ + const auto linear_layout = CreateWithLayout<LinearLayout>(Thickness(50, 50), Thickness(50, 50), LinearLayout::Orientation::Vertical, ControlList{ Button::Create({ TextBlock::Create(L"Button") }), - TextBox::Create() - })); + CreateWithLayout<TextBox>(Thickness(30), Thickness(20)) + }); linear_layout->SetBordered(true); diff --git a/src/ui/control.cpp b/src/ui/control.cpp index 5215c107..6746e820 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -307,6 +307,18 @@ namespace cru { return result; } + Point Control::TransformPoint(const Point& point, const RectRange from, const RectRange to) + { + const auto rect_from = GetRect(from); + const auto rect_to = GetRect(to); + auto p = point; + p.x += rect_from.left; + p.y += rect_from.top; + p.x -= rect_to.left; + p.y -= rect_to.top; + return p; + } + void Control::InvalidateBorder() { InvalidateLayout(); @@ -324,10 +336,13 @@ namespace cru { void Control::SetCursor(const Cursor::Ptr& cursor) { - cursor_ = cursor; - const auto window = GetWindow(); - if (window && window->GetMouseHoverControl() == this) - window->UpdateCursor(); + if (cursor != cursor_) + { + cursor_ = cursor; + const auto window = GetWindow(); + if (window && window->GetMouseHoverControl() == this) + window->UpdateCursor(); + } } void Control::OnAddChild(Control* child) diff --git a/src/ui/control.h b/src/ui/control.h index db89b3b6..2a608374 100644 --- a/src/ui/control.h +++ b/src/ui/control.h @@ -29,17 +29,6 @@ namespace cru Point lefttop_position_absolute; }; - - enum class RectRange - { - Content, // content excluding padding, border and margin - Padding, // only including content and padding - HalfBorder, // including content, padding and half border - FullBorder, // including content, padding and full border - Margin // including content, padding, border and margin - }; - - class Control : public Object { friend class Window; @@ -176,6 +165,7 @@ namespace cru Rect GetRect(RectRange range); + Point TransformPoint(const Point& point, RectRange from = RectRange::Margin, RectRange to = RectRange::Content); //*************** region: border *************** diff --git a/src/ui/controls/text_control.cpp b/src/ui/controls/text_control.cpp index 785e7577..6524df0e 100644 --- a/src/ui/controls/text_control.cpp +++ b/src/ui/controls/text_control.cpp @@ -65,10 +65,7 @@ namespace cru::ui::controls Repaint(); } is_selectable_ = is_selectable; - if (is_selectable) //TODO!!! - SetCursor(cursors::i_beam); - else - SetCursor(cursors::arrow); + UpdateCursor(std::nullopt); } } @@ -92,15 +89,12 @@ namespace cru::ui::controls namespace { - std::optional<unsigned> TextLayoutHitTest(IDWriteTextLayout* text_layout, const Point& point, const bool test_inside = true) + unsigned TextLayoutHitTest(IDWriteTextLayout* text_layout, const Point& point) { BOOL is_trailing, is_inside; DWRITE_HIT_TEST_METRICS metrics{}; text_layout->HitTestPoint(point.x, point.y, &is_trailing, &is_inside, &metrics); - if (!test_inside || is_inside) - return is_trailing == 0 ? metrics.textPosition : metrics.textPosition + 1; - else - return std::nullopt; + return is_trailing == 0 ? metrics.textPosition : metrics.textPosition + 1; } void DrawSelectionRect(ID2D1DeviceContext* device_context, IDWriteTextLayout* layout, ID2D1Brush* brush, const std::optional<TextRange> range) @@ -136,17 +130,14 @@ namespace cru::ui::controls void TextControl::OnMouseDownCore(events::MouseButtonEventArgs& args) { Control::OnMouseDownCore(args); - if (is_selectable_ && args.GetMouseButton() == MouseButton::Left) + if (is_selectable_ && args.GetMouseButton() == MouseButton::Left && GetRect(RectRange::Padding).IsPointInside(args.GetPoint(this, RectRange::Margin))) { selected_range_ = std::nullopt; - const auto hit_test_result = TextLayoutHitTest(text_layout_.Get(), args.GetPoint(this), true); - if (hit_test_result.has_value()) - { - RequestChangeCaretPosition(hit_test_result.value()); - mouse_down_position_ = hit_test_result.value(); - is_selecting_ = true; - GetWindow()->CaptureMouseFor(this); - } + const auto hit_test_result = TextLayoutHitTest(text_layout_.Get(), args.GetPoint(this)); + RequestChangeCaretPosition(hit_test_result); + mouse_down_position_ = hit_test_result; + is_selecting_ = true; + GetWindow()->CaptureMouseFor(this); Repaint(); } } @@ -156,11 +147,12 @@ namespace cru::ui::controls Control::OnMouseMoveCore(args); if (is_selecting_) { - const auto hit_test_result = TextLayoutHitTest(text_layout_.Get(), args.GetPoint(this), false).value(); + const auto hit_test_result = TextLayoutHitTest(text_layout_.Get(), args.GetPoint(this)); RequestChangeCaretPosition(hit_test_result); selected_range_ = TextRange::FromTwoSides(hit_test_result, mouse_down_position_); Repaint(); } + UpdateCursor(args.GetPoint(this, RectRange::Margin)); } void TextControl::OnMouseUpCore(events::MouseButtonEventArgs& args) @@ -235,4 +227,32 @@ namespace cru::ui::controls &text_layout_ )); } + + void TextControl::UpdateCursor(const std::optional<Point>& point) + { + if (!is_selectable_) + { + SetCursor(cursors::arrow); + return; + } + + const auto window = GetWindow(); + if (window == nullptr) + { + SetCursor(cursors::arrow); + return; + } + + if (is_selecting_) + { + SetCursor(cursors::i_beam); + return; + } + + const auto p = point.value_or(AbsoluteToLocal(window->GetMousePosition())); + if (GetRect(RectRange::Padding).IsPointInside(p)) + SetCursor(cursors::i_beam); + else + SetCursor(cursors::arrow); + } } diff --git a/src/ui/controls/text_control.h b/src/ui/controls/text_control.h index 18a258f2..bfdfe20f 100644 --- a/src/ui/controls/text_control.h +++ b/src/ui/controls/text_control.h @@ -79,6 +79,9 @@ namespace cru::ui::controls void RecreateTextLayout(); + // param point is the mouse point relative to this control. + void UpdateCursor(const std::optional<Point>& point); + private: String text_; diff --git a/src/ui/events/ui_event.cpp b/src/ui/events/ui_event.cpp index 59623bab..34339ff4 100644 --- a/src/ui/events/ui_event.cpp +++ b/src/ui/events/ui_event.cpp @@ -8,10 +8,10 @@ namespace cru { namespace events { - Point MouseEventArgs::GetPoint(Control* control) const + Point MouseEventArgs::GetPoint(Control* control, const RectRange range) const { if (point_.has_value()) - return control->AbsoluteToLocal(point_.value()); + return control->TransformPoint(control->AbsoluteToLocal(point_.value()), RectRange::Margin, range); return Point(); } } diff --git a/src/ui/events/ui_event.h b/src/ui/events/ui_event.h index b042b706..1a6f4046 100644 --- a/src/ui/events/ui_event.h +++ b/src/ui/events/ui_event.h @@ -6,6 +6,7 @@ #include "base.h" #include "cru_event.h" #include "ui/ui_base.h" +#include "ui/layout_base.h" namespace cru { @@ -54,7 +55,7 @@ namespace cru MouseEventArgs& operator=(MouseEventArgs&& other) = default; ~MouseEventArgs() override = default; - Point GetPoint(Control* control) const; + Point GetPoint(Control* control, RectRange range = RectRange::Content) const; private: std::optional<Point> point_; diff --git a/src/ui/layout_base.h b/src/ui/layout_base.h index e1759da2..0d924436 100644 --- a/src/ui/layout_base.h +++ b/src/ui/layout_base.h @@ -26,6 +26,15 @@ namespace cru Stretch }; + enum class RectRange + { + Content, // content excluding padding, border and margin + Padding, // only including content and padding + HalfBorder, // including content, padding and half border + FullBorder, // including content, padding and full border + Margin // including content, padding, border and margin + }; + struct Thickness { constexpr static Thickness Zero() |