aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ui/click_detector.cpp7
-rw-r--r--src/ui/control.cpp19
-rw-r--r--src/ui/controls/button.cpp84
-rw-r--r--src/ui/controls/flex_layout.cpp5
-rw-r--r--src/ui/controls/text_block.cpp1
-rw-r--r--src/ui/render/border_render_object.cpp2
-rw-r--r--src/ui/render/flex_layout_render_object.cpp2
-rw-r--r--src/ui/render/window_render_object.cpp2
-rw-r--r--src/ui/window.cpp8
-rw-r--r--src/win/native/native_window.cpp9
10 files changed, 105 insertions, 34 deletions
diff --git a/src/ui/click_detector.cpp b/src/ui/click_detector.cpp
index 1442b885..b335f3b5 100644
--- a/src/ui/click_detector.cpp
+++ b/src/ui/click_detector.cpp
@@ -12,8 +12,9 @@ ClickDetector::ClickDetector(Control* control) {
EventRevokerGuard(control->MouseDownEvent()->Direct()->AddHandler(
[this, control](event::MouseButtonEventArgs& args) {
if (!control->CaptureMouse()) return; // capture failed
- FromButton(args.GetMouseButton()) =
- args.GetPoint(); // save mouse down point
+ const auto button = args.GetMouseButton();
+ FromButton(button) = args.GetPoint(); // save mouse down point
+ begin_event_.Raise(button);
})));
event_rovoker_guards_.push_front(
@@ -25,8 +26,10 @@ ClickDetector::ClickDetector(Control* control) {
if (down_point.has_value()) {
event_.Raise(ClickEventArgs(control, down_point.value(),
args.GetPoint(), button));
+ end_event_.Raise(button);
down_point = std::nullopt;
}
+ control->ReleaseMouse();
})));
}
} // namespace cru::ui
diff --git a/src/ui/control.cpp b/src/ui/control.cpp
index d529b687..7bd33d84 100644
--- a/src/ui/control.cpp
+++ b/src/ui/control.cpp
@@ -54,6 +54,7 @@ void Control::_TraverseDescendants(
predicate(control);
for (auto c : control->GetChildren()) _TraverseDescendants(c, predicate);
}
+
bool Control::RequestFocus() {
auto window = GetWindow();
if (window == nullptr) return false;
@@ -68,15 +69,21 @@ bool Control::HasFocus() {
return window->GetFocusControl() == this;
}
-void Control::OnParentChanged(Control* old_parent, Control* new_parent) {}
+bool Control::CaptureMouse() {
+ return GetWindow()->CaptureMouseFor(this);
+}
-void Control::OnAttachToWindow(Window* window) {}
+bool Control::ReleaseMouse() {
+ return GetWindow()->CaptureMouseFor(nullptr);
+}
-void Control::OnDetachToWindow(Window* window) {}
+bool Control::IsMouseCaptured() {
+ return GetWindow()->GetMouseCaptureControl() == this;
+}
-void Control::OnMouseClickBegin(platform::native::MouseButton button) {}
+void Control::OnParentChanged(Control* old_parent, Control* new_parent) {}
-void Control::OnMouseClickEnd(platform::native::MouseButton button) {}
+void Control::OnAttachToWindow(Window* window) {}
-void Control::OnMouseClickCancel(platform::native::MouseButton button) {}
+void Control::OnDetachToWindow(Window* window) {}
} // namespace cru::ui
diff --git a/src/ui/controls/button.cpp b/src/ui/controls/button.cpp
index 618371fb..42a08e33 100644
--- a/src/ui/controls/button.cpp
+++ b/src/ui/controls/button.cpp
@@ -1,17 +1,60 @@
#include "cru/ui/controls/button.hpp"
+#include <memory>
+#include "cru/platform/graph/brush.hpp"
+#include "cru/platform/graph/graph_factory.hpp"
+#include "cru/platform/native/native_window.hpp"
#include "cru/ui/render/border_render_object.hpp"
#include "cru/ui/ui_manager.hpp"
+#include "cru/ui/window.hpp"
namespace cru::ui::controls {
-Button::Button() {
- const auto predefined_resource =
- UiManager::GetInstance()->GetPredefineResources();
- render_object_.reset(new render::BorderRenderObject(
- predefined_resource->button_normal_border_brush));
+Button::Button() : click_detector_(this) {
+ // const auto predefined_resource =
+ // UiManager::GetInstance()->GetPredefineResources();
+
+ const auto factory = platform::graph::GraphFactory::GetInstance();
+ border_style_.normal.brush = std::shared_ptr<platform::graph::Brush>(
+ factory->CreateSolidColorBrush(Color::FromHex(0x00bfff)));
+ border_style_.hover.brush = std::shared_ptr<platform::graph::Brush>(
+ factory->CreateSolidColorBrush(Color::FromHex(0x47d1ff)));
+ border_style_.press.brush = std::shared_ptr<platform::graph::Brush>(
+ factory->CreateSolidColorBrush(Color::FromHex(0x91e4ff)));
+
+ border_style_.normal.thickness = border_style_.hover.thickness =
+ border_style_.press.thickness = Thickness{3};
+
+ border_style_.normal.corner_radius = border_style_.hover.corner_radius =
+ border_style_.press.corner_radius = render::CornerRadius{Point{10, 5}};
+
+ render_object_.reset(
+ new render::BorderRenderObject(border_style_.normal.brush));
+ render_object_->SetAttachedControl(this);
render_object_->SetEnabled(true);
- render_object_->SetBorderWidth(Thickness{3});
- render_object_->SetCornerRadius(render::CornerRadius{Point{10, 5}});
+ render_object_->SetStyle(border_style_.normal);
+
+ MouseEnterEvent()->Direct()->AddHandler([this](event::MouseEventArgs& args) {
+ if (click_detector_.GetPressingButton() & trigger_button_) {
+ SetState(ButtonState::Press);
+ } else {
+ SetState(ButtonState::Hover);
+ }
+ });
+
+ MouseLeaveEvent()->Direct()->AddHandler(
+ [this](event::MouseEventArgs& args) { SetState(ButtonState::Normal); });
+
+ click_detector_.ClickBeginEvent()->AddHandler([this](MouseButton button) {
+ if (button & trigger_button_) {
+ SetState(ButtonState::Press);
+ }
+ });
+
+ click_detector_.ClickEndEvent()->AddHandler([this](MouseButton button) {
+ if (button & trigger_button_) {
+ SetState(ButtonState::Normal);
+ }
+ });
}
render::RenderObject* Button::GetRenderObject() const {
@@ -24,21 +67,18 @@ void Button::OnChildChanged(Control* old_child, Control* new_child) {
render_object_->AddChild(new_child->GetRenderObject(), 0);
}
-void Button::OnMouseClickBegin(platform::native::MouseButton button) {
- if (button & trigger_button_) {
- SetState(ButtonState::Press);
- //TODO!
- }
-}
-
-void Button::OnMouseClickEnd(platform::native::MouseButton button) {
- if (button & trigger_button_) {
- SetState(ButtonState::Normal);
- //TODO!
- }
-}
-
void Button::OnStateChange(ButtonState oldState, ButtonState newState) {
-
+ switch (newState) {
+ case ButtonState::Normal:
+ render_object_->SetStyle(border_style_.normal);
+ break;
+ case ButtonState::Hover:
+ render_object_->SetStyle(border_style_.hover);
+ break;
+ case ButtonState::Press:
+ render_object_->SetStyle(border_style_.press);
+ break;
+ }
+ GetWindow()->GetNativeWindow()->Repaint();
}
} // namespace cru::ui::controls
diff --git a/src/ui/controls/flex_layout.cpp b/src/ui/controls/flex_layout.cpp
index 3b70c98c..340710cc 100644
--- a/src/ui/controls/flex_layout.cpp
+++ b/src/ui/controls/flex_layout.cpp
@@ -5,7 +5,10 @@
namespace cru::ui::controls {
using render::FlexLayoutRenderObject;
-FlexLayout::FlexLayout() { render_object_.reset(new FlexLayoutRenderObject()); }
+FlexLayout::FlexLayout() {
+ render_object_.reset(new FlexLayoutRenderObject());
+ render_object_->SetAttachedControl(this);
+}
render::RenderObject* FlexLayout::GetRenderObject() const {
return render_object_.get();
diff --git a/src/ui/controls/text_block.cpp b/src/ui/controls/text_block.cpp
index 55d83acc..71903981 100644
--- a/src/ui/controls/text_block.cpp
+++ b/src/ui/controls/text_block.cpp
@@ -13,6 +13,7 @@ TextBlock::TextBlock() {
new TextRenderObject(predefined_resources->text_block_text_brush,
predefined_resources->text_block_font,
predefined_resources->text_block_selection_brush));
+ render_object_->SetAttachedControl(this);
}
render::RenderObject* TextBlock::GetRenderObject() const {
diff --git a/src/ui/render/border_render_object.cpp b/src/ui/render/border_render_object.cpp
index 1bec3e0b..4b61e511 100644
--- a/src/ui/render/border_render_object.cpp
+++ b/src/ui/render/border_render_object.cpp
@@ -30,7 +30,7 @@ RenderObject* BorderRenderObject::HitTest(const Point& point) {
if (const auto child = GetChild()) {
auto offset = child->GetOffset();
Point p{point.x - offset.x, point.y - offset.y};
- const auto result = child->HitTest(point);
+ const auto result = child->HitTest(p);
if (result != nullptr) {
return result;
}
diff --git a/src/ui/render/flex_layout_render_object.cpp b/src/ui/render/flex_layout_render_object.cpp
index 8ce2db0a..5e313e49 100644
--- a/src/ui/render/flex_layout_render_object.cpp
+++ b/src/ui/render/flex_layout_render_object.cpp
@@ -29,7 +29,7 @@ RenderObject* FlexLayoutRenderObject::HitTest(const Point& point) {
for (auto i = children.crbegin(); i != children.crend(); ++i) {
auto offset = (*i)->GetOffset();
Point p{point.x - offset.x, point.y - offset.y};
- const auto result = (*i)->HitTest(point);
+ const auto result = (*i)->HitTest(p);
if (result != nullptr) {
return result;
}
diff --git a/src/ui/render/window_render_object.cpp b/src/ui/render/window_render_object.cpp
index 89bb0beb..18faeee8 100644
--- a/src/ui/render/window_render_object.cpp
+++ b/src/ui/render/window_render_object.cpp
@@ -27,7 +27,7 @@ RenderObject* WindowRenderObject::HitTest(const Point& point) {
if (const auto child = GetChild()) {
auto offset = child->GetOffset();
Point p{point.x - offset.x, point.y - offset.y};
- const auto result = child->HitTest(point);
+ const auto result = child->HitTest(p);
if (result != nullptr) {
return result;
}
diff --git a/src/ui/window.cpp b/src/ui/window.cpp
index 47509749..1ec34c1d 100644
--- a/src/ui/window.cpp
+++ b/src/ui/window.cpp
@@ -7,6 +7,7 @@
#include "routed_event_dispatch.hpp"
#include <cassert>
+#include <list>
namespace cru::ui {
namespace {
@@ -54,6 +55,7 @@ Control* FindLowestCommonAncestor(Control* left, Control* right,
*find_result = in_right;
return result;
}
+ ++right_i;
}
return result;
}
@@ -64,6 +66,7 @@ Control* FindLowestCommonAncestor(Control* left, Control* right,
*find_result = in_left;
return result;
}
+ ++left_i;
}
return result;
}
@@ -75,13 +78,16 @@ Control* FindLowestCommonAncestor(Control* left, Control* right,
*find_result = in_right;
return result;
}
+ ++right_i;
}
while (left_i != left_list.cend()) {
if (*left_i == find_control) {
*find_result = in_left;
return result;
}
+ ++left_i;
}
+ return result;
}
++left_i;
++right_i;
@@ -107,9 +113,11 @@ Window::Window(tag_overlapped_constructor)
: mouse_hover_control_(nullptr),
focus_control_(this),
mouse_captured_control_(nullptr) {
+ window_ = this;
native_window_ =
platform::native::UiApplication::GetInstance()->CreateWindow(nullptr);
render_object_.reset(new render::WindowRenderObject(this));
+ render_object_->SetAttachedControl(this);
BindNativeEvent(this, native_window_->DestroyEvent(),
&Window::OnNativeDestroy, event_revoker_guards_);
diff --git a/src/win/native/native_window.cpp b/src/win/native/native_window.cpp
index 5da121cf..f301f955 100644
--- a/src/win/native/native_window.cpp
+++ b/src/win/native/native_window.cpp
@@ -147,6 +147,15 @@ bool WinNativeWindow::ReleaseMouse() {
return false;
}
+void WinNativeWindow::Repaint() {
+ if (IsValid()) {
+ if (!::InvalidateRect(hwnd_, nullptr, FALSE))
+ throw Win32Error(::GetLastError(), "Failed to invalidate window.");
+ if (!::UpdateWindow(hwnd_))
+ throw Win32Error(::GetLastError(), "Failed to update window.");
+ }
+}
+
graph::Painter* WinNativeWindow::BeginPaint() {
return new WindowD2DPainter(this);
}