aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/application.cpp8
-rw-r--r--src/ui/control.cpp8
-rw-r--r--src/ui/control.h8
-rw-r--r--src/ui/controls/button.cpp2
-rw-r--r--src/ui/cursor.cpp7
-rw-r--r--src/ui/cursor.h16
-rw-r--r--src/ui/window.cpp39
-rw-r--r--src/ui/window.h13
8 files changed, 85 insertions, 16 deletions
diff --git a/src/application.cpp b/src/application.cpp
index 7be56f56..79aaf38d 100644
--- a/src/application.cpp
+++ b/src/application.cpp
@@ -103,9 +103,9 @@ namespace cru {
void LoadSystemCursor(HINSTANCE h_instance)
{
- ui::cursors[ui::cursor_arrow_key] = std::make_shared<ui::Cursor>(::LoadCursorW(h_instance, MAKEINTRESOURCEW(IDC_ARROW)), false);
- ui::cursors[ui::cursor_hand_key] = std::make_shared<ui::Cursor>(::LoadCursorW(h_instance, MAKEINTRESOURCEW(IDC_HAND)), false);
- ui::cursors[ui::cursor_i_beam_key] = std::make_shared<ui::Cursor>(::LoadCursorW(h_instance, MAKEINTRESOURCEW(IDC_IBEAM)), false);
+ ui::cursors::arrow = std::make_shared<ui::Cursor>(::LoadCursorW(nullptr, MAKEINTRESOURCEW(IDC_ARROW)), false);
+ ui::cursors::hand = std::make_shared<ui::Cursor>(::LoadCursorW(nullptr, MAKEINTRESOURCEW(IDC_HAND)), false);
+ ui::cursors::i_beam = std::make_shared<ui::Cursor>(::LoadCursorW(nullptr, MAKEINTRESOURCEW(IDC_IBEAM)), false);
}
}
@@ -137,8 +137,6 @@ namespace cru {
Application::~Application()
{
- ui::cursors.clear();
-
animation_manager_.reset();
instance_ = nullptr;
}
diff --git a/src/ui/control.cpp b/src/ui/control.cpp
index d080ebb0..5215c107 100644
--- a/src/ui/control.cpp
+++ b/src/ui/control.cpp
@@ -322,6 +322,14 @@ namespace cru {
}
}
+ void Control::SetCursor(const Cursor::Ptr& cursor)
+ {
+ cursor_ = cursor;
+ const auto window = GetWindow();
+ if (window && window->GetMouseHoverControl() == this)
+ window->UpdateCursor();
+ }
+
void Control::OnAddChild(Control* child)
{
if (auto window = GetWindow())
diff --git a/src/ui/control.h b/src/ui/control.h
index a9dbc7a4..db89b3b6 100644
--- a/src/ui/control.h
+++ b/src/ui/control.h
@@ -226,8 +226,9 @@ namespace cru
//*************** region: cursor ***************
- //TODO!
- /*
+ // If cursor is set to null, then it uses parent's cursor.
+ // Window's cursor can't be null.
+
Cursor::Ptr GetCursor() const
{
return cursor_;
@@ -235,9 +236,6 @@ namespace cru
void SetCursor(const Cursor::Ptr& cursor);
- Cursor::Ptr GetCursorInherit();
- */
-
//*************** region: events ***************
//Raised when mouse enter the control.
diff --git a/src/ui/controls/button.cpp b/src/ui/controls/button.cpp
index 6c1024c4..11f8e31b 100644
--- a/src/ui/controls/button.cpp
+++ b/src/ui/controls/button.cpp
@@ -20,6 +20,8 @@ namespace cru::ui::controls
SetBordered(true);
GetBorderProperty() = normal_border_;
+
+ SetCursor(cursors::hand);
}
StringView Button::GetControlType() const
diff --git a/src/ui/cursor.cpp b/src/ui/cursor.cpp
index e0bd1814..e1f0e5ef 100644
--- a/src/ui/cursor.cpp
+++ b/src/ui/cursor.cpp
@@ -16,5 +16,10 @@ namespace cru::ui
::DestroyCursor(handle_);
}
- std::unordered_map<String, Cursor::Ptr> cursors;
+ namespace cursors
+ {
+ Cursor::Ptr arrow{};
+ Cursor::Ptr hand{};
+ Cursor::Ptr i_beam{};
+ }
}
diff --git a/src/ui/cursor.h b/src/ui/cursor.h
index b57db9b7..3c09b35e 100644
--- a/src/ui/cursor.h
+++ b/src/ui/cursor.h
@@ -20,14 +20,20 @@ namespace cru::ui
Cursor& operator=(Cursor&& other) = delete;
~Cursor() override;
+ HCURSOR GetHandle() const
+ {
+ return handle_;
+ }
+
private:
HCURSOR handle_;
bool auto_release_;
};
-
- extern std::unordered_map<String, Cursor::Ptr> cursors;
- constexpr auto cursor_arrow_key = L"System_Arrow";
- constexpr auto cursor_hand_key = L"System_Hand";
- constexpr auto cursor_i_beam_key = L"System_IBeam";
+ namespace cursors
+ {
+ extern Cursor::Ptr arrow;
+ extern Cursor::Ptr hand;
+ extern Cursor::Ptr i_beam;
+ }
}
diff --git a/src/ui/window.cpp b/src/ui/window.cpp
index 947516e0..50959c91 100644
--- a/src/ui/window.cpp
+++ b/src/ui/window.cpp
@@ -3,6 +3,7 @@
#include "application.h"
#include "graph/graph.h"
#include "exception.h"
+#include "cursor.h"
namespace cru
{
@@ -91,6 +92,21 @@ namespace cru
);
}
+ namespace
+ {
+ Cursor::Ptr GetCursorInherit(Control* control)
+ {
+ while (control != nullptr)
+ {
+ const auto cursor = control->GetCursor();
+ if (cursor != nullptr)
+ return cursor;
+ control = control->GetParent();
+ }
+ return cursors::arrow;
+ }
+ }
+
Window::Window() : Control(WindowConstructorTag{}, this), control_list_({ this }) {
const auto app = Application::GetInstance();
hwnd_ = CreateWindowEx(0,
@@ -106,6 +122,8 @@ namespace cru
app->GetWindowManager()->RegisterWindow(hwnd_, this);
render_target_ = app->GetGraphManager()->CreateWindowRenderTarget(hwnd_);
+
+ SetCursor(cursors::arrow);
}
Window::~Window() {
@@ -442,6 +460,14 @@ namespace cru
}
}
+ void Window::UpdateCursor()
+ {
+ if (IsWindowValid() && mouse_hover_control_ != nullptr)
+ {
+ SetCursorInternal(GetCursorInherit(mouse_hover_control_)->GetHandle());
+ }
+ }
+
#ifdef CRU_DEBUG_LAYOUT
void Window::SetDebugLayout(const bool value)
{
@@ -465,6 +491,16 @@ namespace cru
return ::PeekMessageW(&msg, hwnd_, message, message, PM_NOREMOVE) != 0;
}
+ void Window::SetCursorInternal(HCURSOR cursor)
+ {
+ if (IsWindowValid())
+ {
+ ::SetClassLongPtrW(GetWindowHandle(), GCLP_HCURSOR, reinterpret_cast<LONG_PTR>(cursor));
+ if (mouse_hover_control_ != nullptr)
+ ::SetCursor(cursor);
+ }
+ }
+
Size Window::OnMeasureContent(const Size& available_size)
{
for (auto control: GetChildren())
@@ -618,7 +654,10 @@ namespace cru
if (old_control != nullptr) // if last mouse-hover-on control exists
DispatchEvent(old_control, &Control::RaiseMouseLeaveEvent, lowest_common_ancestor); // dispatch mouse leave event.
if (new_control != nullptr)
+ {
DispatchEvent(new_control, &Control::RaiseMouseEnterEvent, lowest_common_ancestor, point); // dispatch mouse enter event.
+ UpdateCursor();
+ }
}
}
}
diff --git a/src/ui/window.h b/src/ui/window.h
index d6560c0f..1d188a05 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -143,8 +143,15 @@ namespace cru {
//Return false if the message is not handled.
bool HandleWindowMessage(HWND hwnd, int msg, WPARAM w_param, LPARAM l_param, LRESULT& result);
+ //*************** region: mouse ***************
+
Point GetMousePosition();
+ Control* GetMouseHoverControl() const
+ {
+ return mouse_hover_control_;
+ }
+
//*************** region: position and size ***************
//Always return (0, 0) for a window.
@@ -187,6 +194,10 @@ namespace cru {
Control* CaptureMouseFor(Control* control);
Control* ReleaseCurrentMouseCapture();
+
+ //*************** region: cursor ***************
+ void UpdateCursor();
+
//*************** region: debug ***************
#ifdef CRU_DEBUG_LAYOUT
bool IsDebugLayout() const
@@ -212,6 +223,8 @@ namespace cru {
bool IsMessageInQueue(UINT message);
+ void SetCursorInternal(HCURSOR cursor);
+
//*************** region: layout ***************