aboutsummaryrefslogtreecommitdiff
path: root/src/ui/controls
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/controls')
-rw-r--r--src/ui/controls/Button.cpp17
-rw-r--r--src/ui/controls/ContentControl.cpp25
-rw-r--r--src/ui/controls/Control.cpp157
-rw-r--r--src/ui/controls/LayoutControl.cpp3
-rw-r--r--src/ui/controls/NoChildControl.cpp3
-rw-r--r--src/ui/controls/TextControlService.hpp8
-rw-r--r--src/ui/controls/Window.cpp32
7 files changed, 232 insertions, 13 deletions
diff --git a/src/ui/controls/Button.cpp b/src/ui/controls/Button.cpp
index 5f7ed143..b7407ec2 100644
--- a/src/ui/controls/Button.cpp
+++ b/src/ui/controls/Button.cpp
@@ -5,9 +5,9 @@
#include "cru/platform/graphics/Brush.hpp"
#include "cru/platform/gui/Cursor.hpp"
#include "cru/platform/gui/UiApplication.hpp"
-#include "cru/ui/render/BorderRenderObject.hpp"
#include "cru/ui/UiManager.hpp"
-#include "cru/ui/Window.hpp"
+#include "cru/ui/helper/ClickDetector.hpp"
+#include "cru/ui/render/BorderRenderObject.hpp"
namespace cru::ui::controls {
using cru::platform::gui::SystemCursorType;
@@ -21,8 +21,7 @@ void Set(render::BorderRenderObject* o, const ButtonStateStyle& s) {
o->SetBackgroundBrush(s.background_brush);
}
-std::shared_ptr<platform::gui::ICursor> GetSystemCursor(
- SystemCursorType type) {
+std::shared_ptr<platform::gui::ICursor> GetSystemCursor(SystemCursorType type) {
return GetUiApplication()->GetCursorManager()->GetSystemCursor(type);
}
} // namespace
@@ -36,21 +35,21 @@ Button::Button() : click_detector_(this) {
render_object_->SetBorderEnabled(true);
click_detector_.StateChangeEvent()->AddHandler(
- [this](const ClickState& state) {
+ [this](const helper::ClickState& state) {
switch (state) {
- case ClickState::None:
+ case helper::ClickState::None:
Set(render_object_.get(), style_.normal);
SetCursor(GetSystemCursor(SystemCursorType::Arrow));
break;
- case ClickState::Hover:
+ case helper::ClickState::Hover:
Set(render_object_.get(), style_.hover);
SetCursor(GetSystemCursor(SystemCursorType::Hand));
break;
- case ClickState::Press:
+ case helper::ClickState::Press:
Set(render_object_.get(), style_.press);
SetCursor(GetSystemCursor(SystemCursorType::Hand));
break;
- case ClickState::PressInactive:
+ case helper::ClickState::PressInactive:
Set(render_object_.get(), style_.press_cancel);
SetCursor(GetSystemCursor(SystemCursorType::Arrow));
break;
diff --git a/src/ui/controls/ContentControl.cpp b/src/ui/controls/ContentControl.cpp
new file mode 100644
index 00000000..653882c0
--- /dev/null
+++ b/src/ui/controls/ContentControl.cpp
@@ -0,0 +1,25 @@
+#include "cru/ui/controls/ContentControl.hpp"
+
+namespace cru::ui::controls {
+Control* ContentControl::GetChild() const {
+ if (GetChildren().empty()) return nullptr;
+ return GetChildren()[0];
+}
+
+void ContentControl::SetChild(Control* child) {
+ Control* old_child = nullptr;
+ if (!GetChildren().empty()) {
+ old_child = GetChildren()[0];
+ this->RemoveChild(0);
+ }
+ if (child) {
+ this->AddChild(child, 0);
+ }
+ OnChildChanged(old_child, child);
+}
+
+void ContentControl::OnChildChanged(Control* old_child, Control* new_child) {
+ CRU_UNUSED(old_child)
+ CRU_UNUSED(new_child)
+}
+} // namespace cru::ui::controls
diff --git a/src/ui/controls/Control.cpp b/src/ui/controls/Control.cpp
new file mode 100644
index 00000000..c1316a62
--- /dev/null
+++ b/src/ui/controls/Control.cpp
@@ -0,0 +1,157 @@
+#include "cru/ui/controls/Control.hpp"
+
+#include "cru/common/Base.hpp"
+#include "cru/platform/gui/Cursor.hpp"
+#include "cru/platform/gui/UiApplication.hpp"
+#include "cru/ui/Base.hpp"
+#include "cru/ui/host/WindowHost.hpp"
+#include "cru/ui/render/RenderObject.hpp"
+
+#include <memory>
+
+namespace cru::ui::controls {
+using platform::gui::ICursor;
+using platform::gui::IUiApplication;
+using platform::gui::SystemCursorType;
+
+Control::Control() {
+ MouseEnterEvent()->Direct()->AddHandler([this](event::MouseEventArgs&) {
+ this->is_mouse_over_ = true;
+ this->OnMouseHoverChange(true);
+ });
+
+ MouseLeaveEvent()->Direct()->AddHandler([this](event::MouseEventArgs&) {
+ this->is_mouse_over_ = false;
+ this->OnMouseHoverChange(true);
+ });
+}
+
+Control::~Control() {
+ for (const auto child : children_) delete child;
+}
+
+host::WindowHost* Control::GetWindowHost() const { return window_host_; }
+
+void Control::TraverseDescendants(
+ const std::function<void(Control*)>& predicate) {
+ predicate(this);
+ for (auto c : GetChildren()) c->TraverseDescendants(predicate);
+}
+
+bool Control::HasFocus() {
+ auto host = GetWindowHost();
+ if (host == nullptr) return false;
+
+ return host->GetFocusControl() == this;
+}
+
+bool Control::CaptureMouse() {
+ auto host = GetWindowHost();
+ if (host == nullptr) return false;
+
+ return host->CaptureMouseFor(this);
+}
+
+void Control::SetFocus() {
+ auto host = GetWindowHost();
+ if (host == nullptr) return;
+
+ host->SetFocusControl(this);
+}
+
+bool Control::ReleaseMouse() {
+ auto host = GetWindowHost();
+ if (host == nullptr) return false;
+
+ return host->CaptureMouseFor(nullptr);
+}
+
+bool Control::IsMouseCaptured() {
+ auto host = GetWindowHost();
+ if (host == nullptr) return false;
+
+ return host->GetMouseCaptureControl() == this;
+}
+
+std::shared_ptr<ICursor> Control::GetCursor() { return cursor_; }
+
+std::shared_ptr<ICursor> Control::GetInheritedCursor() {
+ Control* control = this;
+ while (control != nullptr) {
+ const auto cursor = control->GetCursor();
+ if (cursor != nullptr) return cursor;
+ control = control->GetParent();
+ }
+ return IUiApplication::GetInstance()->GetCursorManager()->GetSystemCursor(
+ SystemCursorType::Arrow);
+}
+
+void Control::SetCursor(std::shared_ptr<ICursor> cursor) {
+ cursor_ = std::move(cursor);
+ const auto host = GetWindowHost();
+ if (host != nullptr) {
+ host->UpdateCursor();
+ }
+}
+
+void Control::AddChild(Control* control, const Index position) {
+ Expects(control->GetParent() ==
+ nullptr); // The control already has a parent.
+ Expects(position >= 0);
+ Expects(position <= static_cast<Index>(
+ children_.size())); // The position is out of range.
+
+ children_.insert(children_.cbegin() + position, control);
+
+ const auto old_parent = control->parent_;
+ control->parent_ = this;
+
+ OnAddChild(control, position);
+ control->OnParentChanged(old_parent, this);
+
+ if (window_host_)
+ control->TraverseDescendants([this](Control* control) {
+ control->window_host_ = window_host_;
+ control->OnAttachToHost(window_host_);
+ });
+}
+
+void Control::RemoveChild(const Index position) {
+ Expects(position >= 0);
+ Expects(position < static_cast<Index>(
+ children_.size())); // The position is out of range.
+
+ const auto i = children_.cbegin() + position;
+ const auto control = *i;
+
+ children_.erase(i);
+ control->parent_ = nullptr;
+
+ OnRemoveChild(control, position);
+ control->OnParentChanged(this, nullptr);
+
+ if (window_host_)
+ control->TraverseDescendants([this](Control* control) {
+ control->window_host_ = nullptr;
+ control->OnDetachFromHost(window_host_);
+ });
+}
+
+void Control::OnAddChild(Control* child, Index position) {
+ CRU_UNUSED(child)
+ CRU_UNUSED(position)
+}
+void Control::OnRemoveChild(Control* child, Index position) {
+ CRU_UNUSED(child)
+ CRU_UNUSED(position)
+}
+
+void Control::OnParentChanged(Control* old_parent, Control* new_parent) {
+ CRU_UNUSED(old_parent)
+ CRU_UNUSED(new_parent)
+}
+
+void Control::OnAttachToHost(host::WindowHost* host) { CRU_UNUSED(host) }
+
+void Control::OnDetachFromHost(host::WindowHost* host) { CRU_UNUSED(host) }
+} // namespace cru::ui::controls
diff --git a/src/ui/controls/LayoutControl.cpp b/src/ui/controls/LayoutControl.cpp
new file mode 100644
index 00000000..85417beb
--- /dev/null
+++ b/src/ui/controls/LayoutControl.cpp
@@ -0,0 +1,3 @@
+#include "cru/ui/controls/LayoutControl.hpp"
+
+namespace cru::ui::controls {}
diff --git a/src/ui/controls/NoChildControl.cpp b/src/ui/controls/NoChildControl.cpp
new file mode 100644
index 00000000..c62c5819
--- /dev/null
+++ b/src/ui/controls/NoChildControl.cpp
@@ -0,0 +1,3 @@
+#include "cru/ui/controls/NoChildControl.hpp"
+
+namespace cru::ui::controls {}
diff --git a/src/ui/controls/TextControlService.hpp b/src/ui/controls/TextControlService.hpp
index a7e4e440..8ad95dec 100644
--- a/src/ui/controls/TextControlService.hpp
+++ b/src/ui/controls/TextControlService.hpp
@@ -8,10 +8,10 @@
#include "cru/platform/gui/UiApplication.hpp"
#include "cru/platform/gui/Window.hpp"
#include "cru/ui/Base.hpp"
-#include "cru/ui/Control.hpp"
#include "cru/ui/DebugFlags.hpp"
-#include "cru/ui/ShortcutHub.hpp"
-#include "cru/ui/UiEvent.hpp"
+#include "cru/ui/controls/Control.hpp"
+#include "cru/ui/events/UiEvent.hpp"
+#include "cru/ui/helper/ShortcutHub.hpp"
#include "cru/ui/host/WindowHost.hpp"
#include "cru/ui/render/CanvasRenderObject.hpp"
#include "cru/ui/render/ScrollRenderObject.hpp"
@@ -472,7 +472,7 @@ class TextControlService : public Object {
platform::gui::TimerAutoCanceler caret_timer_canceler_;
int caret_blink_duration_ = k_default_caret_blink_duration;
- ShortcutHub shortcut_hub_;
+ helper::ShortcutHub shortcut_hub_;
// nullopt means not selecting
std::optional<MouseButton> select_down_button_;
diff --git a/src/ui/controls/Window.cpp b/src/ui/controls/Window.cpp
new file mode 100644
index 00000000..7ce40dfe
--- /dev/null
+++ b/src/ui/controls/Window.cpp
@@ -0,0 +1,32 @@
+#include "cru/ui/controls/Window.hpp"
+
+#include "cru/common/Base.hpp"
+#include "cru/ui/host/WindowHost.hpp"
+#include "cru/ui/render/Base.hpp"
+#include "cru/ui/render/StackLayoutRenderObject.hpp"
+
+namespace cru::ui::controls {
+Window* Window::CreateOverlapped() { return new Window(); }
+
+Window::Window() : render_object_(new render::StackLayoutRenderObject()) {
+ render_object_->SetAttachedControl(this);
+ window_host_ = std::make_unique<host::WindowHost>(this);
+}
+
+Window::~Window() {}
+
+std::u16string_view Window::GetControlType() const { return control_type; }
+
+render::RenderObject* Window::GetRenderObject() const {
+ return render_object_.get();
+}
+
+void Window::OnAddChild(Control* child, Index position) {
+ render_object_->AddChild(child->GetRenderObject(), position);
+}
+
+void Window::OnRemoveChild(Control* child, Index position) {
+ CRU_UNUSED(child);
+ render_object_->RemoveChild(position);
+}
+} // namespace cru::ui::controls