aboutsummaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2019-04-04 17:12:25 +0800
committercrupest <crupest@outlook.com>2019-04-04 17:12:25 +0800
commita410e2048db6f5ef6fb50e401a59b4b98b979050 (patch)
tree500680c63b074e8c3eefd756fd6a1d0f41840c1a /src/ui
parentfcaf471275a67d718887430ee63a53890915c4c7 (diff)
downloadcru-a410e2048db6f5ef6fb50e401a59b4b98b979050.tar.gz
cru-a410e2048db6f5ef6fb50e401a59b4b98b979050.tar.bz2
cru-a410e2048db6f5ef6fb50e401a59b4b98b979050.zip
...
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/content_control.cpp4
-rw-r--r--src/ui/content_control.hpp31
-rw-r--r--src/ui/control.cpp8
-rw-r--r--src/ui/control.hpp134
-rw-r--r--src/ui/input_util.cpp20
-rw-r--r--src/ui/input_util.hpp10
-rw-r--r--src/ui/layout_control.cpp7
-rw-r--r--src/ui/layout_control.hpp33
-rw-r--r--src/ui/no_child_control.cpp2
-rw-r--r--src/ui/no_child_control.hpp26
-rw-r--r--src/ui/render/text_render_object.cpp151
-rw-r--r--src/ui/ui_manager.cpp77
-rw-r--r--src/ui/ui_manager.hpp61
-rw-r--r--src/ui/window.cpp283
-rw-r--r--src/ui/window.hpp162
15 files changed, 84 insertions, 925 deletions
diff --git a/src/ui/content_control.cpp b/src/ui/content_control.cpp
index d5abca1c..3a23164c 100644
--- a/src/ui/content_control.cpp
+++ b/src/ui/content_control.cpp
@@ -1,7 +1,9 @@
-#include "content_control.hpp"
+#include "cru/ui/content_control.hpp"
#include "window.hpp"
+#include <cassert>
+
namespace cru::ui {
ContentControl::ContentControl()
: child_vector_{nullptr}, child_(child_vector_[0]) {}
diff --git a/src/ui/content_control.hpp b/src/ui/content_control.hpp
deleted file mode 100644
index 88e7f60f..00000000
--- a/src/ui/content_control.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-#include "control.hpp"
-
-namespace cru::ui {
-class ContentControl : public Control {
- protected:
- ContentControl();
-
- public:
- ContentControl(const ContentControl& other) = delete;
- ContentControl(ContentControl&& other) = delete;
- ContentControl& operator=(const ContentControl& other) = delete;
- ContentControl& operator=(ContentControl&& other) = delete;
- ~ContentControl() override;
-
- const std::vector<Control*>& GetChildren() const override final {
- return child_vector_;
- }
- Control* GetChild() const { return child_; }
- void SetChild(Control* child);
-
- protected:
- virtual void OnChildChanged(Control* old_child, Control* new_child);
-
- private:
- std::vector<Control*> child_vector_;
- Control*& child_;
-};
-} // namespace cru::ui
diff --git a/src/ui/control.cpp b/src/ui/control.cpp
index 318d591a..c5d02d40 100644
--- a/src/ui/control.cpp
+++ b/src/ui/control.cpp
@@ -1,7 +1,9 @@
-#include "control.hpp"
+#include "cru/ui/control.hpp"
#include "window.hpp"
+#include <cassert>
+
namespace cru::ui {
void Control::_SetParent(Control* parent) {
const auto old_parent = GetParent();
@@ -61,7 +63,7 @@ void Control::OnAttachToWindow(Window* window) {}
void Control::OnDetachToWindow(Window* window) {}
-void Control::OnMouseClickBegin(MouseButton button) {}
+void Control::OnMouseClickBegin(platform::MouseButton button) {}
-void Control::OnMouseClickEnd(MouseButton button) {}
+void Control::OnMouseClickEnd(platform::MouseButton button) {}
} // namespace cru::ui
diff --git a/src/ui/control.hpp b/src/ui/control.hpp
deleted file mode 100644
index b69734d6..00000000
--- a/src/ui/control.hpp
+++ /dev/null
@@ -1,134 +0,0 @@
-#pragma once
-#include "cru/common/base.hpp"
-
-#include "cru/ui/event/ui_event.hpp"
-
-#include ""
-
-#include <string_view>
-
-namespace cru::ui {
-class Window;
-
-class Control : public Object {
- friend class Window;
-
- protected:
- Control() = default;
-
- public:
- Control(const Control& other) = delete;
- Control(Control&& other) = delete;
- Control& operator=(const Control& other) = delete;
- Control& operator=(Control&& other) = delete;
- ~Control() override = default;
-
- public:
- virtual std::wstring_view GetControlType() const = 0;
-
- //*************** region: tree ***************
- public:
- // Get the window if attached, otherwise, return nullptr.
- Window* GetWindow() const { return window_; }
-
- Control* GetParent() const { return parent_; }
-
- virtual const std::vector<Control*>& GetChildren() const = 0;
-
- // Traverse the tree rooted the control including itself.
- void TraverseDescendants(const std::function<void(Control*)>& predicate);
-
- void _SetParent(Control* parent);
- void _SetDescendantWindow(Window* window);
-
- private:
- static void _TraverseDescendants(
- Control* control, const std::function<void(Control*)>& predicate);
-
- public:
- virtual render::RenderObject* GetRenderObject() const = 0;
-
- //*************** region: focus ***************
- public:
- bool RequestFocus();
-
- bool HasFocus();
-
- //*************** region: events ***************
- public:
- // Raised when mouse enter the control.
- events::RoutedEvent<events::MouseEventArgs>* MouseEnterEvent() {
- return &mouse_enter_event_;
- }
- // Raised when mouse is leave the control.
- events::RoutedEvent<events::MouseEventArgs>* MouseLeaveEvent() {
- return &mouse_leave_event_;
- }
- // Raised when mouse is move in the control.
- events::RoutedEvent<events::MouseEventArgs>* MouseMoveEvent() {
- return &mouse_move_event_;
- }
- // Raised when a mouse button is pressed in the control.
- events::RoutedEvent<events::MouseButtonEventArgs>* MouseDownEvent() {
- return &mouse_down_event_;
- }
- // Raised when a mouse button is released in the control.
- events::RoutedEvent<events::MouseButtonEventArgs>* MouseUpEvent() {
- return &mouse_up_event_;
- }
- // Raised when a mouse button is pressed in the control and released in the
- // control with mouse not leaving it between two operations.
- events::RoutedEvent<events::MouseButtonEventArgs>* MouseClickEvent() {
- return &mouse_click_event_;
- }
- events::RoutedEvent<events::MouseWheelEventArgs>* MouseWheelEvent() {
- return &mouse_wheel_event_;
- }
- events::RoutedEvent<events::KeyEventArgs>* KeyDownEvent() {
- return &key_down_event_;
- }
- events::RoutedEvent<events::KeyEventArgs>* KeyUpEvent() {
- return &key_up_event_;
- }
- events::RoutedEvent<events::CharEventArgs>* CharEvent() {
- return &char_event_;
- }
- events::RoutedEvent<events::FocusChangeEventArgs>* GainFocusEvent() {
- return &gain_focus_event_;
- }
- events::RoutedEvent<events::FocusChangeEventArgs>* LoseFocusEvent() {
- return &lose_focus_event_;
- }
-
- private:
- events::RoutedEvent<events::MouseEventArgs> mouse_enter_event_;
- events::RoutedEvent<events::MouseEventArgs> mouse_leave_event_;
- events::RoutedEvent<events::MouseEventArgs> mouse_move_event_;
- events::RoutedEvent<events::MouseButtonEventArgs> mouse_down_event_;
- events::RoutedEvent<events::MouseButtonEventArgs> mouse_up_event_;
- events::RoutedEvent<events::MouseButtonEventArgs> mouse_click_event_;
- events::RoutedEvent<events::MouseWheelEventArgs> mouse_wheel_event_;
-
- events::RoutedEvent<events::KeyEventArgs> key_down_event_;
- events::RoutedEvent<events::KeyEventArgs> key_up_event_;
- events::RoutedEvent<events::CharEventArgs> char_event_;
-
- events::RoutedEvent<events::FocusChangeEventArgs> gain_focus_event_;
- events::RoutedEvent<events::FocusChangeEventArgs> lose_focus_event_;
-
- //*************** region: tree ***************
- protected:
- virtual void OnParentChanged(Control* old_parent, Control* new_parent);
- virtual void OnAttachToWindow(Window* window);
- virtual void OnDetachToWindow(Window* window);
-
- //*************** region: additional mouse event ***************
- protected:
- virtual void OnMouseClickBegin(MouseButton button);
- virtual void OnMouseClickEnd(MouseButton button);
-
- private:
- Window* window_ = nullptr;
- Control* parent_ = nullptr;
-};
-} // namespace cru::ui
diff --git a/src/ui/input_util.cpp b/src/ui/input_util.cpp
deleted file mode 100644
index 193cba4a..00000000
--- a/src/ui/input_util.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "input_util.hpp"
-
-#include <Windows.h>
-
-namespace cru::ui {
-bool IsKeyDown(const int virtual_code) {
- const auto result = ::GetKeyState(virtual_code);
- return (static_cast<unsigned short>(result) & 0x8000) != 0;
-}
-
-bool IsKeyToggled(const int virtual_code) {
- const auto result = ::GetKeyState(virtual_code);
- return (static_cast<unsigned short>(result) & 1) != 0;
-}
-
-bool IsAnyMouseButtonDown() {
- return IsKeyDown(VK_LBUTTON) || IsKeyDown(VK_RBUTTON) ||
- IsKeyDown(VK_MBUTTON);
-}
-} // namespace cru::ui
diff --git a/src/ui/input_util.hpp b/src/ui/input_util.hpp
deleted file mode 100644
index 2d01f725..00000000
--- a/src/ui/input_util.hpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-namespace cru::ui {
-enum class MouseButton { Left, Right, Middle };
-
-bool IsKeyDown(int virtual_code);
-bool IsKeyToggled(int virtual_code);
-bool IsAnyMouseButtonDown();
-} // namespace cru::ui
diff --git a/src/ui/layout_control.cpp b/src/ui/layout_control.cpp
index c0c4a7fe..9d789670 100644
--- a/src/ui/layout_control.cpp
+++ b/src/ui/layout_control.cpp
@@ -1,7 +1,9 @@
-#include "layout_control.hpp"
+#include "cru/ui/layout_control.hpp"
#include "window.hpp"
+#include <cassert>
+
namespace cru::ui {
LayoutControl::~LayoutControl() {
for (const auto child : children_) delete child;
@@ -10,7 +12,8 @@ LayoutControl::~LayoutControl() {
void LayoutControl::AddChild(Control* control, const int position) {
assert(control->GetParent() == nullptr); // The control already has a parent.
assert(!dynamic_cast<Window*>(control)); // Can't add a window as child.
- assert(position >= 0 || position <= this->children_.size()); // The position is out of range.
+ assert(position >= 0 ||
+ position <= this->children_.size()); // The position is out of range.
children_.insert(this->children_.cbegin() + position, control);
diff --git a/src/ui/layout_control.hpp b/src/ui/layout_control.hpp
deleted file mode 100644
index 53f53186..00000000
--- a/src/ui/layout_control.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-#include "control.hpp"
-
-namespace cru::ui {
-class LayoutControl : public Control {
- protected:
- LayoutControl() = default;
-
- public:
- LayoutControl(const LayoutControl& other) = delete;
- LayoutControl(LayoutControl&& other) = delete;
- LayoutControl& operator=(const LayoutControl& other) = delete;
- LayoutControl& operator=(LayoutControl&& other) = delete;
- ~LayoutControl() override;
-
- const std::vector<Control*>& GetChildren() const override final {
- return children_;
- }
-
- void AddChild(Control* control, int position);
-
- void RemoveChild(int position);
-
- protected:
- virtual void OnAddChild(Control* child, int position);
- virtual void OnRemoveChild(Control* child, int position);
-
- private:
- std::vector<Control*> children_;
-};
-} // namespace cru::ui
diff --git a/src/ui/no_child_control.cpp b/src/ui/no_child_control.cpp
index e6bbe813..81299411 100644
--- a/src/ui/no_child_control.cpp
+++ b/src/ui/no_child_control.cpp
@@ -1,4 +1,4 @@
-#include "no_child_control.hpp"
+#include "cru/ui/no_child_control.hpp"
namespace cru::ui {
const std::vector<Control*> NoChildControl::empty_control_vector{};
diff --git a/src/ui/no_child_control.hpp b/src/ui/no_child_control.hpp
deleted file mode 100644
index 26b5546f..00000000
--- a/src/ui/no_child_control.hpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-#include "control.hpp"
-
-namespace cru::ui {
-class NoChildControl : public Control {
- private:
- static const std::vector<Control*> empty_control_vector;
-
- protected:
- NoChildControl() = default;
-
- public:
- NoChildControl(const NoChildControl& other) = delete;
- NoChildControl(NoChildControl&& other) = delete;
- NoChildControl& operator=(const NoChildControl& other) = delete;
- NoChildControl& operator=(NoChildControl&& other) = delete;
- ~NoChildControl() override = default;
-
- protected:
- const std::vector<Control*>& GetChildren() const override final {
- return empty_control_vector;
- }
-};
-} // namespace cru::ui
diff --git a/src/ui/render/text_render_object.cpp b/src/ui/render/text_render_object.cpp
index 69563ad7..bdf48c9a 100644
--- a/src/ui/render/text_render_object.cpp
+++ b/src/ui/render/text_render_object.cpp
@@ -1,103 +1,61 @@
-#include "text_render_object.hpp"
+#include "cru/ui/render/text_render_object.hpp"
-#include <d2d1.h>
-#include <dwrite.h>
-#include <algorithm>
+#include "cru/platform/graph_factory.hpp"
+#include "cru/platform/painter_util.hpp"
+#include "cru/platform/text_layout.hpp"
+#include "cru/platform/ui_applicaition.hpp"
-#include "exception.hpp"
-#include "graph/graph_manager.hpp"
-#include "graph/graph_util.hpp"
-#include "util/com_util.hpp"
+#include <algorithm>
+#include <cassert>
namespace cru::ui::render {
-TextRenderObject::TextRenderObject(ID2D1Brush* brush, IDWriteTextFormat* format,
- ID2D1Brush* selection_brush) {
+TextRenderObject::TextRenderObject(
+ std::shared_ptr<platform::Brush> brush,
+ std::shared_ptr<platform::FontDescriptor> font,
+ std::shared_ptr<platform::Brush> selection_brush) {
assert(brush);
- assert(format);
+ assert(font);
assert(selection_brush);
- brush->AddRef();
- format->AddRef();
- selection_brush->AddRef();
- this->brush_ = brush;
- this->text_format_ = format;
- this->selection_brush_ = selection_brush;
- try {
- RecreateTextLayout();
- } catch (...) {
- brush->Release();
- format->Release();
- selection_brush->Release();
- throw;
- }
-}
-TextRenderObject::~TextRenderObject() {
- util::SafeRelease(brush_);
- util::SafeRelease(text_format_);
- util::SafeRelease(text_layout_);
- util::SafeRelease(selection_brush_);
-}
+ brush.swap(brush_);
+ font.swap(font_);
+ selection_brush.swap(selection_brush_);
-void TextRenderObject::SetBrush(ID2D1Brush* new_brush) {
- assert(new_brush);
- util::SafeRelease(brush_);
- new_brush->AddRef();
- brush_ = new_brush;
-}
+ const auto graph_factory =
+ platform::UiApplication::GetInstance()->GetGraphFactory();
-void TextRenderObject::SetTextFormat(IDWriteTextFormat* new_text_format) {
- assert(new_text_format);
- util::SafeRelease(text_format_);
- new_text_format->AddRef();
- text_format_ = new_text_format;
- RecreateTextLayout();
+ text_layout_.reset(graph_factory->CreateTextLayout(font_, L""));
}
-void TextRenderObject::SetSelectionBrush(ID2D1Brush* new_brush) {
- assert(new_brush);
- util::SafeRelease(selection_brush_);
- new_brush->AddRef();
- selection_brush_ = new_brush;
+std::wstring TextRenderObject::GetText() const {
+ return text_layout_->GetText();
}
-namespace {
-void DrawSelectionRect(ID2D1RenderTarget* render_target,
- IDWriteTextLayout* layout, ID2D1Brush* brush,
- const std::optional<TextRange> range) {
- if (range.has_value()) {
- DWRITE_TEXT_METRICS text_metrics{};
- ThrowIfFailed(layout->GetMetrics(&text_metrics));
- const auto metrics_count =
- text_metrics.lineCount * text_metrics.maxBidiReorderingDepth;
-
- std::vector<DWRITE_HIT_TEST_METRICS> hit_test_metrics(metrics_count);
- UINT32 actual_count;
- layout->HitTestTextRange(range.value().position, range.value().count, 0, 0,
- hit_test_metrics.data(), metrics_count,
- &actual_count);
+void TextRenderObject::SetText(std::wstring new_text) {
+ text_layout_->SetText(std::move(new_text));
+}
- hit_test_metrics.erase(hit_test_metrics.cbegin() + actual_count,
- hit_test_metrics.cend());
+std::shared_ptr<platform::FontDescriptor> TextRenderObject::GetFont() const {
+ return text_layout_->GetFont();
+}
- for (const auto& metrics : hit_test_metrics)
- render_target->FillRoundedRectangle(
- D2D1::RoundedRect(D2D1::RectF(metrics.left, metrics.top,
- metrics.left + metrics.width,
- metrics.top + metrics.height),
- 3, 3),
- brush);
- }
+void TextRenderObject::SetFont(std::shared_ptr<platform::FontDescriptor> font) {
+ text_layout_->SetFont(std::move(font));
}
-} // namespace
-void TextRenderObject::Draw(ID2D1RenderTarget* render_target) {
- graph::WithTransform(
- render_target,
- D2D1::Matrix3x2F::Translation(GetMargin().left + GetPadding().left,
+void TextRenderObject::Draw(platform::Painter* painter) {
+ platform::util::WithTransform(
+ painter,
+ platform::Matrix::Translation(GetMargin().left + GetPadding().left,
GetMargin().top + GetPadding().top),
- [this](auto rt) {
- DrawSelectionRect(rt, text_layout_, selection_brush_, selection_range_);
- rt->DrawTextLayout(D2D1::Point2F(), text_layout_, brush_);
+ [this](platform::Painter* p) {
+ if (this->selection_range_.has_value()) {
+ const auto&& rects =
+ text_layout_->TextRangeRect(this->selection_range_.value());
+ for (const auto& rect : rects)
+ p->FillRectangle(rect, this->GetSelectionBrush().get());
+ }
+ p->DrawText(Point{}, text_layout_.get(), brush_.get());
});
}
@@ -115,34 +73,15 @@ RenderObject* TextRenderObject::HitTest(const Point& point) {
void TextRenderObject::OnSizeChanged(const Size& old_size,
const Size& new_size) {
const auto&& size = GetContentRect().GetSize();
- ThrowIfFailed(text_layout_->SetMaxWidth(size.width));
- ThrowIfFailed(text_layout_->SetMaxHeight(size.height));
+ text_layout_->SetMaxWidth(size.width);
+ text_layout_->SetMaxHeight(size.height);
}
Size TextRenderObject::OnMeasureContent(const Size& available_size) {
- ThrowIfFailed(text_layout_->SetMaxWidth(available_size.width));
- ThrowIfFailed(text_layout_->SetMaxHeight(available_size.height));
-
- DWRITE_TEXT_METRICS metrics;
- ThrowIfFailed(text_layout_->GetMetrics(&metrics));
-
- return Size(metrics.width, metrics.height);
+ text_layout_->SetMaxWidth(available_size.width);
+ text_layout_->SetMaxHeight(available_size.height);
+ return text_layout_->GetTextBounds().GetSize();
}
void TextRenderObject::OnLayoutContent(const Rect& content_rect) {}
-
-void TextRenderObject::RecreateTextLayout() {
- assert(text_format_ != nullptr);
-
- util::SafeRelease(text_layout_);
-
- const auto dwrite_factory =
- graph::GraphManager::GetInstance()->GetDWriteFactory();
-
- const auto&& size = GetContentRect().GetSize();
-
- ThrowIfFailed(dwrite_factory->CreateTextLayout(
- text_.c_str(), static_cast<UINT32>(text_.size()), text_format_,
- size.width, size.height, &text_layout_));
-}
} // namespace cru::ui::render
diff --git a/src/ui/ui_manager.cpp b/src/ui/ui_manager.cpp
index 4d14575b..9c3c00d2 100644
--- a/src/ui/ui_manager.cpp
+++ b/src/ui/ui_manager.cpp
@@ -1,74 +1,27 @@
-#include "ui_manager.hpp"
+#include "cru/ui/ui_manager.hpp"
-#include <Windows.h>
-#include <d2d1.h>
-#include <dwrite.h>
-
-#include "application.hpp"
-#include "exception.hpp"
-#include "graph/graph_manager.hpp"
-#include "graph/graph_util.hpp"
-#include "util/com_util.hpp"
+#include "cru/platform/graph_factory.hpp"
+#include "cru/platform/ui_applicaition.hpp"
namespace cru::ui {
-namespace {
-void GetSystemCaretInfo(CaretInfo* caret_info) {
- caret_info->caret_blink_duration =
- std::chrono::milliseconds(::GetCaretBlinkTime());
- DWORD caret_width;
- if (!::SystemParametersInfoW(SPI_GETCARETWIDTH, 0, &caret_width, 0))
- throw Win32Error(::GetLastError(), "Failed to get system caret width.");
- caret_info->half_caret_width = caret_width / 2.0f;
-}
-
-IDWriteTextFormat* CreateDefaultTextFormat() {
- const auto dwrite_factory =
- graph::GraphManager::GetInstance()->GetDWriteFactory();
- IDWriteTextFormat* text_format;
-
- ThrowIfFailed(dwrite_factory->CreateTextFormat(
- L"等线", nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
- DWRITE_FONT_STRETCH_NORMAL, 24.0, L"zh-cn", &text_format));
-
- ThrowIfFailed(text_format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER));
- ThrowIfFailed(
- text_format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER));
-
- return text_format;
-}
-} // namespace
-
PredefineResources::PredefineResources() {
- try {
- button_normal_border_brush =
- graph::CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black));
+ const auto graph_factory =
+ platform::UiApplication::GetInstance()->GetGraphFactory();
- text_block_selection_brush =
- graph::CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::LightSkyBlue));
- text_block_text_brush =
- graph::CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black));
- text_block_text_format = CreateDefaultTextFormat();
- } catch (...) {
- util::SafeRelease(button_normal_border_brush);
- util::SafeRelease(text_block_selection_brush);
- util::SafeRelease(text_block_text_brush);
- util::SafeRelease(text_block_text_format);
- }
-}
+ button_normal_border_brush.reset(
+ graph_factory->CreateSolidColorBrush(colors::black));
-PredefineResources::~PredefineResources() {
- util::SafeRelease(button_normal_border_brush);
- util::SafeRelease(text_block_selection_brush);
- util::SafeRelease(text_block_text_brush);
- util::SafeRelease(text_block_text_format);
+ text_block_selection_brush.reset(
+ graph_factory->CreateSolidColorBrush(colors::skyblue));
+ text_block_text_brush.reset(
+ graph_factory->CreateSolidColorBrush(colors::black));
+ text_block_font.reset(graph_factory->CreateFontDescriptor(L"等线", 24.0f));
}
UiManager* UiManager::GetInstance() {
- return Application::GetInstance()->ResolveSingleton<UiManager>(
- [](auto) { return new UiManager{}; });
+ static UiManager instance;
+ return &instance;
}
-UiManager::UiManager() : predefine_resources_() {
- GetSystemCaretInfo(&caret_info_);
-}
+UiManager::UiManager() : predefine_resources_(new PredefineResources()) {}
} // namespace cru::ui
diff --git a/src/ui/ui_manager.hpp b/src/ui/ui_manager.hpp
deleted file mode 100644
index 107b536c..00000000
--- a/src/ui/ui_manager.hpp
+++ /dev/null
@@ -1,61 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-#include "base.hpp"
-
-struct ID2D1Brush;
-struct IDWriteTextFormat;
-namespace cru::graph {
-class GraphManager;
-}
-
-namespace cru::ui {
-struct CaretInfo {
- std::chrono::milliseconds caret_blink_duration;
- float half_caret_width;
-};
-
-class PredefineResources : public Object {
- public:
- PredefineResources();
- PredefineResources(const PredefineResources& other) = delete;
- PredefineResources(PredefineResources&& other) = delete;
- PredefineResources& operator=(const PredefineResources& other) = delete;
- PredefineResources& operator=(PredefineResources&& other) = delete;
- ~PredefineResources() override;
-
- // region Button
- ID2D1Brush* button_normal_border_brush = nullptr;
-
- // region TextBlock
- ID2D1Brush* text_block_selection_brush = nullptr;
- ID2D1Brush* text_block_text_brush = nullptr;
- IDWriteTextFormat* text_block_text_format = nullptr;
-};
-
-class UiManager : public Object {
- public:
- static UiManager* GetInstance();
-
- private:
- UiManager();
-
- public:
- UiManager(const UiManager& other) = delete;
- UiManager(UiManager&& other) = delete;
- UiManager& operator=(const UiManager& other) = delete;
- UiManager& operator=(UiManager&& other) = delete;
- ~UiManager() override = default;
-
- CaretInfo GetCaretInfo() const { return caret_info_; }
-
- const PredefineResources* GetPredefineResources() const {
- return &predefine_resources_;
- }
-
- private:
- CaretInfo caret_info_;
-
- PredefineResources predefine_resources_;
-};
-} // namespace cru::ui
diff --git a/src/ui/window.cpp b/src/ui/window.cpp
index d138424f..1065a3fb 100644
--- a/src/ui/window.cpp
+++ b/src/ui/window.cpp
@@ -1,14 +1,10 @@
-#include "window.hpp"
+#include "cru/ui/window.hpp"
-#include <d2d1_1.h>
-#include <windowsx.h>
+#include "cru/ui/render/window_render_object.hpp"
+#include "cru/platform/ui_applicaition.hpp"
+#include "cru/platform/native_window.hpp"
-#include "application.hpp"
-#include "exception.hpp"
-#include "graph/graph_manager.hpp"
-#include "graph/graph_util.hpp"
-#include "graph/window_render_target.hpp"
-#include "render/window_render_object.hpp"
+#include <cassert>
namespace cru::ui {
namespace {
@@ -27,7 +23,7 @@ namespace {
// as the rest arguments.
template <typename EventArgs, typename... Args>
void DispatchEvent(Control* const original_sender,
- events::RoutedEvent<EventArgs>* (Control::*event_ptr)(),
+ event::RoutedEvent<EventArgs>* (Control::*event_ptr)(),
Control* const last_receiver, Args&&... args) {
std::list<Control*> receive_list;
@@ -97,232 +93,31 @@ Control* FindLowestCommonAncestor(Control* left, Control* right) {
}
} // namespace
-
-inline Point PiToDip(const POINT& pi_point) {
- return Point(graph::PixelToDipX(pi_point.x), graph::PixelToDipY(pi_point.y));
-}
-
-inline POINT DipToPi(const Point& dip_point) {
- POINT result;
- result.x = graph::DipToPixelX(dip_point.x);
- result.y = graph::DipToPixelY(dip_point.y);
- return result;
-}
-
Window* Window::CreateOverlapped() {
return new Window(tag_overlapped_constructor{});
}
-Window* Window::CreatePopup(Window* parent, const bool caption) {
- return new Window(tag_popup_constructor{}, parent, caption);
-}
Window::Window(tag_overlapped_constructor) {
- BeforeCreateHwnd();
-
- const auto window_manager = WindowManager::GetInstance();
-
- hwnd_ =
- CreateWindowEx(0, window_manager->GetGeneralWindowClass()->GetName(), L"",
- WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr,
- Application::GetInstance()->GetInstanceHandle(), nullptr);
-
- if (hwnd_ == nullptr)
- throw Win32Error(::GetLastError(), "Failed to create window.");
-
- AfterCreateHwnd(window_manager);
-}
-
-Window::Window(tag_popup_constructor, Window* parent, const bool caption) {
- assert(parent == nullptr ||
- parent->IsWindowValid()); // Parent window is not valid.
-
- BeforeCreateHwnd();
-
- parent_window_ = parent;
-
- const auto window_manager = WindowManager::GetInstance();
-
- hwnd_ = CreateWindowEx(
- 0, window_manager->GetGeneralWindowClass()->GetName(), L"",
- caption ? (WS_POPUPWINDOW | WS_CAPTION) : WS_POPUP, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
- parent == nullptr ? nullptr : parent->GetWindowHandle(), nullptr,
- Application::GetInstance()->GetInstanceHandle(), nullptr);
-
- if (hwnd_ == nullptr)
- throw Win32Error(::GetLastError(), "Failed to create window.");
-
- AfterCreateHwnd(window_manager);
-}
-
-void Window::BeforeCreateHwnd() { window_ = this; }
-
-void Window::AfterCreateHwnd(WindowManager* window_manager) {
- window_manager->RegisterWindow(hwnd_, this);
-
- render_target_.reset(
- new graph::WindowRenderTarget(graph::GraphManager::GetInstance(), hwnd_));
-
+ native_window_ = platform::UiApplication::GetInstance()->CreateWindow(nullptr);
render_object_.reset(new render::WindowRenderObject(this));
}
Window::~Window() {
-
TraverseDescendants(
[this](Control* control) { control->OnDetachToWindow(this); });
}
-StringView Window::GetControlType() const { return control_type; }
+std::wstring_view Window::GetControlType() const { return control_type; }
render::RenderObject* Window::GetRenderObject() const {
return render_object_.get();
}
-bool Window::HandleWindowMessage(HWND hwnd, int msg, WPARAM w_param,
- LPARAM l_param, LRESULT& result) {
- events::WindowNativeMessageEventArgs args(this, this,
- {hwnd, msg, w_param, l_param});
- native_message_event_.Raise(args);
- if (args.GetResult().has_value()) {
- result = args.GetResult().value();
- return true;
- }
-
- switch (msg) {
- case WM_PAINT:
- OnPaintInternal();
- result = 0;
- return true;
- case WM_ERASEBKGND:
- result = 1;
- return true;
- case WM_SETFOCUS:
- OnSetFocusInternal();
- result = 0;
- return true;
- case WM_KILLFOCUS:
- OnKillFocusInternal();
- result = 0;
- return true;
- case WM_MOUSEMOVE: {
- POINT point;
- point.x = GET_X_LPARAM(l_param);
- point.y = GET_Y_LPARAM(l_param);
- OnMouseMoveInternal(point);
- result = 0;
- return true;
- }
- case WM_LBUTTONDOWN: {
- POINT point;
- point.x = GET_X_LPARAM(l_param);
- point.y = GET_Y_LPARAM(l_param);
- OnMouseDownInternal(MouseButton::Left, point);
- result = 0;
- return true;
- }
- case WM_LBUTTONUP: {
- POINT point;
- point.x = GET_X_LPARAM(l_param);
- point.y = GET_Y_LPARAM(l_param);
- OnMouseUpInternal(MouseButton::Left, point);
- result = 0;
- return true;
- }
- case WM_RBUTTONDOWN: {
- POINT point;
- point.x = GET_X_LPARAM(l_param);
- point.y = GET_Y_LPARAM(l_param);
- OnMouseDownInternal(MouseButton::Right, point);
- result = 0;
- return true;
- }
- case WM_RBUTTONUP: {
- POINT point;
- point.x = GET_X_LPARAM(l_param);
- point.y = GET_Y_LPARAM(l_param);
- OnMouseUpInternal(MouseButton::Right, point);
- result = 0;
- return true;
- }
- case WM_MBUTTONDOWN: {
- POINT point;
- point.x = GET_X_LPARAM(l_param);
- point.y = GET_Y_LPARAM(l_param);
- OnMouseDownInternal(MouseButton::Middle, point);
- result = 0;
- return true;
- }
- case WM_MBUTTONUP: {
- POINT point;
- point.x = GET_X_LPARAM(l_param);
- point.y = GET_Y_LPARAM(l_param);
- OnMouseUpInternal(MouseButton::Middle, point);
- result = 0;
- return true;
- }
- case WM_MOUSEWHEEL:
- POINT point;
- point.x = GET_X_LPARAM(l_param);
- point.y = GET_Y_LPARAM(l_param);
- ScreenToClient(hwnd, &point);
- OnMouseWheelInternal(GET_WHEEL_DELTA_WPARAM(w_param), point);
- result = 0;
- return true;
- case WM_KEYDOWN:
- OnKeyDownInternal(static_cast<int>(w_param));
- result = 0;
- return true;
- case WM_KEYUP:
- OnKeyUpInternal(static_cast<int>(w_param));
- result = 0;
- return true;
- case WM_CHAR:
- OnCharInternal(static_cast<wchar_t>(w_param));
- result = 0;
- return true;
- case WM_SIZE:
- OnResizeInternal(LOWORD(l_param), HIWORD(l_param));
- result = 0;
- return true;
- case WM_ACTIVATE:
- if (w_param == WA_ACTIVE || w_param == WA_CLICKACTIVE)
- OnActivatedInternal();
- else if (w_param == WA_INACTIVE)
- OnDeactivatedInternal();
- result = 0;
- return true;
- case WM_DESTROY:
- OnDestroyInternal();
- result = 0;
- return true;
- default:
- return false;
- }
-}
-
-Point Window::GetMousePosition() {
- if (!IsWindowValid()) return Point::Zero();
- POINT point;
- ::GetCursorPos(&point);
- ::ScreenToClient(hwnd_, &point);
- return PiToDip(point);
-}
-
bool Window::RequestFocusFor(Control* control) {
assert(control != nullptr); // The control to request focus can't be null.
// You can set it as the window.
- if (!IsWindowValid()) return false;
-
- if (!window_focus_) {
- focus_control_ = control;
- ::SetFocus(hwnd_);
- return true; // event dispatch will be done in window message handling
- // function "OnSetFocusInternal".
- }
-
if (focus_control_ == control) return true;
DispatchEvent(focus_control_, &Control::LoseFocusEvent, nullptr, false);
@@ -336,41 +131,6 @@ bool Window::RequestFocusFor(Control* control) {
Control* Window::GetFocusControl() { return focus_control_; }
-Control* Window::CaptureMouseFor(Control* control) {
- if (control != nullptr) {
- ::SetCapture(hwnd_);
- std::swap(mouse_capture_control_, control);
- DispatchMouseHoverControlChangeEvent(
- control ? control : mouse_hover_control_, mouse_capture_control_,
- GetMousePosition());
- return control;
- } else {
- return ReleaseCurrentMouseCapture();
- }
-}
-
-Control* Window::ReleaseCurrentMouseCapture() {
- if (mouse_capture_control_) {
- const auto previous = mouse_capture_control_;
- mouse_capture_control_ = nullptr;
- ::ReleaseCapture();
- DispatchMouseHoverControlChangeEvent(previous, mouse_hover_control_,
- GetMousePosition());
- return previous;
- } else {
- return nullptr;
- }
-}
-
-#ifdef CRU_DEBUG_LAYOUT
-void Window::SetDebugLayout(const bool value) {
- if (debug_layout_ != value) {
- debug_layout_ = value;
- InvalidateDraw();
- }
-}
-#endif
-
void Window::OnChildChanged(Control* old_child, Control* new_child) {
if (old_child) render_object_->RemoveChild(0);
if (new_child) render_object_->AddChild(new_child->GetRenderObject(), 0);
@@ -380,32 +140,9 @@ Control* Window::HitTest(const Point& point) {
return render_object_->HitTest(point)->GetAttachedControl();
}
-RECT Window::GetClientRectPixel() {
- RECT rect{};
- GetClientRect(hwnd_, &rect);
- return rect;
-}
-
-bool Window::IsMessageInQueue(UINT message) {
- MSG msg;
- 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);
- }
-}
-
-void Window::OnDestroyInternal() {
- WindowManager::GetInstance()->UnregisterWindow(hwnd_);
- hwnd_ = nullptr;
- if (delete_this_on_destroy_) InvokeLater([this] { delete this; });
-}
+void Window::OnNativeDestroy() { delete this; }
-void Window::OnPaintInternal() {
+void Window::OnNativePaint() {
render_target_->SetAsTarget();
auto device_context =
diff --git a/src/ui/window.hpp b/src/ui/window.hpp
deleted file mode 100644
index f38743dc..00000000
--- a/src/ui/window.hpp
+++ /dev/null
@@ -1,162 +0,0 @@
-#pragma once
-#include "cru/common/pre_config.hpp"
-
-#include <map>
-#include <memory>
-
-#include "content_control.hpp"
-#include "events/ui_event.hpp"
-#include "window_class.hpp"
-
-
-namespace cru::ui {
-
-
-class Window final : public ContentControl {
- public:
- static constexpr auto control_type = L"Window";
-
- public:
- static Window* CreateOverlapped();
- static Window* CreatePopup(Window* parent, bool caption = false);
-
- private:
- struct tag_overlapped_constructor {};
- struct tag_popup_constructor {};
-
- explicit Window(tag_overlapped_constructor);
- Window(tag_popup_constructor, Window* parent, bool caption);
-
- void BeforeCreateHwnd();
- void AfterCreateHwnd(WindowManager* window_manager);
-
- public:
- Window(const Window& other) = delete;
- Window(Window&& other) = delete;
- Window& operator=(const Window& other) = delete;
- Window& operator=(Window&& other) = delete;
- ~Window() override;
-
- public:
- StringView GetControlType() const override final;
-
- render::RenderObject* GetRenderObject() const override;
-
-
-
-
- //*************** region: window operations ***************
-
- // Get the client size.
- Size GetClientSize();
-
- // Set the client size and repaint.
- void SetClientSize(const Size& size);
-
- // Get the rect of the window containing frame.
- // The lefttop of the rect is relative to screen lefttop.
- Rect GetWindowRect();
-
- // Set the rect of the window containing frame.
- // The lefttop of the rect is relative to screen lefttop.
- void SetWindowRect(const Rect& rect);
-
- // Set the lefttop of the window relative to screen.
- void SetWindowPosition(const Point& position);
-
- Point PointToScreen(const Point& point);
-
- Point PointFromScreen(const Point& point);
-
- // Handle the raw window message.
- // Return true if the message is handled and get the result through "result"
- // argument. 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: focus ***************
-
- // Request focus for specified control.
- bool RequestFocusFor(Control* control);
-
- // Get the control that has focus.
- Control* GetFocusControl();
-
- //*************** region: mouse capture ***************
-
- Control* CaptureMouseFor(Control* control);
- Control* ReleaseCurrentMouseCapture();
-
- //*************** region: events ***************
- public:
- Event<events::UiEventArgs>* ActivatedEvent() { return &activated_event_; }
- Event<events::UiEventArgs>* DeactivatedEvent() { return &deactivated_event_; }
- Event<events::WindowNativeMessageEventArgs>* NativeMessageEvent() {
- return &native_message_event_;
- }
-
- private:
- Event<events::UiEventArgs> activated_event_;
- Event<events::UiEventArgs> deactivated_event_;
- Event<events::WindowNativeMessageEventArgs> native_message_event_;
-
- protected:
- void OnChildChanged(Control* old_child, Control* new_child) override;
-
- private:
- Control* HitTest(const Point& point);
-
- //*************** region: native operations ***************
-
- // Get the client rect in pixel.
- RECT GetClientRectPixel();
-
- bool IsMessageInQueue(UINT message);
-
- void SetCursorInternal(HCURSOR cursor);
-
- //*************** region: native messages ***************
-
- void OnDestroyInternal();
- void OnPaintInternal();
- void OnResizeInternal(int new_width, int new_height);
-
- void OnSetFocusInternal();
- void OnKillFocusInternal();
-
- void OnMouseMoveInternal(POINT point);
- void OnMouseLeaveInternal();
- void OnMouseDownInternal(MouseButton button, POINT point);
- void OnMouseUpInternal(MouseButton button, POINT point);
-
- void OnMouseWheelInternal(short delta, POINT point);
- void OnKeyDownInternal(int virtual_code);
- void OnKeyUpInternal(int virtual_code);
- void OnCharInternal(wchar_t c);
-
- void OnActivatedInternal();
- void OnDeactivatedInternal();
-
- //*************** region: event dispatcher helper ***************
-
- void DispatchMouseHoverControlChangeEvent(Control* old_control,
- Control* new_control,
- const Point& point);
-
- private:
- std::shared_ptr<graph::WindowRenderTarget> render_target_{};
- std::shared_ptr<render::WindowRenderObject> render_object_{};
-
- Control* mouse_hover_control_ = nullptr;
-
- bool window_focus_ = false;
- Control* focus_control_ = this; // "focus_control_" can't be nullptr
- Control* mouse_capture_control_ = nullptr;
-};
-} // namespace cru::ui