aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2018-11-06 16:32:38 +0800
committercrupest <crupest@outlook.com>2018-11-06 16:32:38 +0800
commit1d551a7666ee61074fd36fed4f919c9583477fef (patch)
tree0b445619b034a22f7d30642b0ba84e4d82dfa4da /src
parentbfdc5da41b9ab8b3f150a619c7893270dc8ccc7f (diff)
downloadcru-1d551a7666ee61074fd36fed4f919c9583477fef.tar.gz
cru-1d551a7666ee61074fd36fed4f919c9583477fef.tar.bz2
cru-1d551a7666ee61074fd36fed4f919c9583477fef.zip
Dev cursor for textbox.
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp7
-rw-r--r--src/ui/control.cpp23
-rw-r--r--src/ui/control.h12
-rw-r--r--src/ui/controls/text_control.cpp58
-rw-r--r--src/ui/controls/text_control.h3
-rw-r--r--src/ui/events/ui_event.cpp4
-rw-r--r--src/ui/events/ui_event.h3
-rw-r--r--src/ui/layout_base.h9
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()