blob: 8e8819de6f55c6538f0f6103c9d087a2d195b645 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#include "cru/ui/control.hpp"
#include "cru/platform/native/basic_types.hpp"
#include "cru/platform/native/cursor.hpp"
#include "cru/platform/native/native_window.hpp"
#include "cru/platform/native/ui_application.hpp"
#include "cru/ui/base.hpp"
#include "cru/ui/event/ui_event.hpp"
#include "cru/ui/window.hpp"
#include "routed_event_dispatch.hpp"
#include <cassert>
#include <memory>
namespace cru::ui {
using platform::native::Cursor;
using platform::native::SystemCursor;
using platform::native::UiApplication;
Control::Control() {
MouseEnterEvent()->Direct()->AddHandler(
[this](event::MouseEventArgs&) { this->is_mouse_over_ = true; });
MouseLeaveEvent()->Direct()->AddHandler(
[this](event::MouseEventArgs&) { this->is_mouse_over_ = false; });
}
void Control::_SetParent(Control* parent) {
const auto old_parent = GetParent();
parent_ = parent;
const auto new_parent = GetParent();
if (old_parent != new_parent) OnParentChanged(old_parent, new_parent);
}
void Control::_SetDescendantWindow(Window* window) {
if (window == nullptr && window_ == nullptr) return;
// You can only attach or detach window.
assert((window != nullptr && window_ == nullptr) ||
(window == nullptr && window_ != nullptr));
if (window == nullptr) {
const auto old = window_;
TraverseDescendants([old](Control* control) {
control->window_ = nullptr;
control->OnDetachToWindow(old);
});
} else
TraverseDescendants([window](Control* control) {
control->window_ = window;
control->OnAttachToWindow(window);
});
}
void Control::TraverseDescendants(
const std::function<void(Control*)>& predicate) {
_TraverseDescendants(this, predicate);
}
void Control::_TraverseDescendants(
Control* control, const std::function<void(Control*)>& predicate) {
predicate(control);
for (auto c : control->GetChildren()) _TraverseDescendants(c, predicate);
}
bool Control::RequestFocus() {
auto window = GetWindow();
if (window == nullptr) return false;
return window->RequestFocusFor(this);
}
bool Control::HasFocus() {
auto window = GetWindow();
if (window == nullptr) return false;
return window->GetFocusControl() == this;
}
bool Control::CaptureMouse() { return GetWindow()->CaptureMouseFor(this); }
bool Control::ReleaseMouse() { return GetWindow()->CaptureMouseFor(nullptr); }
bool Control::IsMouseCaptured() {
return GetWindow()->GetMouseCaptureControl() == this;
}
std::shared_ptr<Cursor> Control::GetCursor() { return cursor_; }
std::shared_ptr<Cursor> Control::GetInheritedCursor() {
Control* control = this;
while (control != nullptr) {
const auto cursor = control->GetCursor();
if (cursor != nullptr) return cursor;
control = control->GetParent();
}
return UiApplication::GetInstance()->GetCursorManager()->GetSystemCursor(
SystemCursor::Arrow);
}
void Control::SetCursor(std::shared_ptr<Cursor> cursor) {
cursor_ = std::move(cursor);
const auto window = GetWindow();
if (window != nullptr) {
window->UpdateCursor();
}
}
void Control::OnParentChanged(Control* old_parent, Control* new_parent) {}
void Control::OnAttachToWindow(Window* window) {}
void Control::OnDetachToWindow(Window* window) {}
} // namespace cru::ui
|