aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-11-21 15:18:28 +0800
committercrupest <crupest@outlook.com>2021-11-21 15:18:28 +0800
commiteeb1f55d5a483720441c3f44e83d02cc882a3bc0 (patch)
treee8d8a49d26602ac3f8097aa4d2fff65d70bbfba5
parent2b28ec296fdc72050569b9fedc1664ada7791497 (diff)
downloadcru-eeb1f55d5a483720441c3f44e83d02cc882a3bc0.tar.gz
cru-eeb1f55d5a483720441c3f44e83d02cc882a3bc0.tar.bz2
cru-eeb1f55d5a483720441c3f44e83d02cc882a3bc0.zip
...
-rw-r--r--demos/input_method/main.cpp4
-rw-r--r--demos/main/main.cpp3
-rw-r--r--demos/scroll_view/main.cpp4
-rw-r--r--include/cru/osx/gui/Window.hpp4
-rw-r--r--include/cru/platform/gui/Window.hpp6
-rw-r--r--include/cru/ui/controls/RootControl.hpp10
-rw-r--r--include/cru/ui/host/WindowHost.hpp14
-rw-r--r--src/osx/gui/Window.mm58
-rw-r--r--src/osx/gui/WindowPrivate.h10
-rw-r--r--src/ui/components/Menu.cpp8
-rw-r--r--src/ui/controls/Popup.cpp8
-rw-r--r--src/ui/controls/RootControl.cpp42
-rw-r--r--src/ui/controls/Window.cpp3
-rw-r--r--src/ui/host/WindowHost.cpp13
14 files changed, 105 insertions, 82 deletions
diff --git a/demos/input_method/main.cpp b/demos/input_method/main.cpp
index 913f0ae2..1c61f668 100644
--- a/demos/input_method/main.cpp
+++ b/demos/input_method/main.cpp
@@ -17,7 +17,7 @@ int main() {
auto graphics_factory = application->GetGraphicsFactory();
- auto window = application->CreateWindow(nullptr);
+ auto window = application->CreateWindow();
auto input_method_context = window->GetInputMethodContext();
@@ -141,7 +141,7 @@ int main() {
window->RequestRepaint();
});
- window->SetVisible(true);
+ window->SetVisibility(WindowVisibilityType::Show);
return application->Run();
}
diff --git a/demos/main/main.cpp b/demos/main/main.cpp
index 5c51a05a..8880495d 100644
--- a/demos/main/main.cpp
+++ b/demos/main/main.cpp
@@ -56,7 +56,8 @@ int main() {
popup_menu->Show();
});
- window->GetWindowHost()->GetNativeWindow()->SetVisible(true);
+ window->GetWindowHost()->GetNativeWindow()->SetVisibility(
+ cru::platform::gui::WindowVisibilityType::Show);
return application->Run();
}
diff --git a/demos/scroll_view/main.cpp b/demos/scroll_view/main.cpp
index c3593986..a8ddeeb1 100644
--- a/demos/scroll_view/main.cpp
+++ b/demos/scroll_view/main.cpp
@@ -1,5 +1,6 @@
#include "cru/platform/bootstrap/Bootstrap.hpp"
#include "cru/platform/gui/UiApplication.hpp"
+#include "cru/platform/gui/Window.hpp"
#include "cru/ui/controls/ScrollView.hpp"
#include "cru/ui/controls/TextBlock.hpp"
#include "cru/ui/controls/Window.hpp"
@@ -81,7 +82,8 @@ The cold never bothered me anyway)");
scroll_view->SetChild(text_block);
- window->GetWindowHost()->GetNativeWindow()->SetVisible(true);
+ window->GetWindowHost()->GetNativeWindow()->SetVisibility(
+ cru::platform::gui::WindowVisibilityType::Show);
return application->Run();
}
diff --git a/include/cru/osx/gui/Window.hpp b/include/cru/osx/gui/Window.hpp
index 5383ca1b..2a81d38a 100644
--- a/include/cru/osx/gui/Window.hpp
+++ b/include/cru/osx/gui/Window.hpp
@@ -33,8 +33,8 @@ class OsxWindow : public OsxGuiResource, public INativeWindow {
INativeWindow* GetParent() override;
void SetParent(INativeWindow* parent) override;
- WindowStyleFlag GetShowFlag() override;
- void SetShowFlag(WindowStyleFlag flag) override;
+ WindowStyleFlag GetStyleFlag() override;
+ void SetStyleFlag(WindowStyleFlag flag) override;
WindowVisibilityType GetVisibility() override;
void SetVisibility(WindowVisibilityType visibility) override;
diff --git a/include/cru/platform/gui/Window.hpp b/include/cru/platform/gui/Window.hpp
index ab96045e..f6e1d650 100644
--- a/include/cru/platform/gui/Window.hpp
+++ b/include/cru/platform/gui/Window.hpp
@@ -50,8 +50,8 @@ struct INativeWindow : virtual IPlatformResource {
virtual INativeWindow* GetParent() = 0;
virtual void SetParent(INativeWindow* parent) = 0;
- virtual WindowStyleFlag GetShowFlag() = 0;
- virtual void SetShowFlag(WindowStyleFlag flag) = 0;
+ virtual WindowStyleFlag GetStyleFlag() = 0;
+ virtual void SetStyleFlag(WindowStyleFlag flag) = 0;
virtual WindowVisibilityType GetVisibility() = 0;
virtual void SetVisibility(WindowVisibilityType visibility) = 0;
@@ -90,7 +90,7 @@ struct INativeWindow : virtual IPlatformResource {
virtual IEvent<std::nullptr_t>* DestroyEvent() = 0;
virtual IEvent<std::nullptr_t>* PaintEvent() = 0;
- virtual IEvent<WindowVisibilityType>* VisibilityChangeEvent();
+ virtual IEvent<WindowVisibilityType>* VisibilityChangeEvent() = 0;
virtual IEvent<Size>* ResizeEvent() = 0;
virtual IEvent<FocusChangeType>* FocusEvent() = 0;
diff --git a/include/cru/ui/controls/RootControl.hpp b/include/cru/ui/controls/RootControl.hpp
index 44722cef..823b9f03 100644
--- a/include/cru/ui/controls/RootControl.hpp
+++ b/include/cru/ui/controls/RootControl.hpp
@@ -2,6 +2,7 @@
#include "LayoutControl.hpp"
#include "cru/common/Base.hpp"
+#include "cru/common/Event.hpp"
#include "cru/platform/gui/Base.hpp"
#include "cru/ui/Base.hpp"
#include "cru/ui/host/WindowHost.hpp"
@@ -9,8 +10,7 @@
namespace cru::ui::controls {
class RootControl : public LayoutControl {
protected:
- explicit RootControl(Control* attached_control,
- host::CreateWindowParams params);
+ explicit RootControl(Control* attached_control);
public:
CRU_DELETE_COPY(RootControl)
@@ -24,15 +24,13 @@ class RootControl : public LayoutControl {
void SetGainFocusOnCreateAndDestroyWhenLoseFocus(bool value);
private:
- platform::gui::INativeWindow* GetNativeWindow(bool create);
-
- private:
std::unique_ptr<host::WindowHost> window_host_;
std::unique_ptr<render::StackLayoutRenderObject> render_object_;
Control* attached_control_;
- bool gain_focus_on_create_and_destroy_when_lose_focus_ = false;
+ EventRevokerListGuard
+ gain_focus_on_create_and_destroy_when_lose_focus_event_guard_;
};
} // namespace cru::ui::controls
diff --git a/include/cru/ui/host/WindowHost.hpp b/include/cru/ui/host/WindowHost.hpp
index 6fb853b6..2fc174c6 100644
--- a/include/cru/ui/host/WindowHost.hpp
+++ b/include/cru/ui/host/WindowHost.hpp
@@ -16,21 +16,12 @@ class LayoutPaintCycler;
struct AfterLayoutEventArgs {};
-struct CreateWindowParams {
- CreateWindowParams(platform::gui::INativeWindow* parent = nullptr,
- platform::gui::CreateWindowFlag flag = {})
- : parent(parent), flag(flag) {}
-
- platform::gui::INativeWindow* parent;
- platform::gui::CreateWindowFlag flag;
-};
-
// The bridge between control tree and native window.
class WindowHost : public Object {
CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::host::WindowHost")
public:
- WindowHost(controls::Control* root_control, CreateWindowParams params);
+ explicit WindowHost(controls::Control* root_control);
CRU_DELETE_COPY(WindowHost)
CRU_DELETE_MOVE(WindowHost)
@@ -112,8 +103,7 @@ class WindowHost : public Object {
void SetOverrideCursor(std::shared_ptr<platform::gui::ICursor> cursor);
private:
- gsl::not_null<platform::gui::INativeWindow*> CreateNativeWindow(
- CreateWindowParams params);
+ gsl::not_null<platform::gui::INativeWindow*> CreateNativeWindow();
//*************** region: native messages ***************
void OnNativeDestroy(platform::gui::INativeWindow* window, std::nullptr_t);
diff --git a/src/osx/gui/Window.mm b/src/osx/gui/Window.mm
index 87660ac6..06bbaff9 100644
--- a/src/osx/gui/Window.mm
+++ b/src/osx/gui/Window.mm
@@ -49,6 +49,16 @@ inline NSWindowStyleMask CalcWindowStyleMask(WindowStyleFlag flag) {
}
namespace details {
+OsxWindowPrivate::OsxWindowPrivate(OsxWindow* osx_window) : osx_window_(osx_window) {
+ window_delegate_ = [[CruWindowDelegate alloc] init:this];
+
+ content_rect_ = {100, 100, 400, 200};
+
+ input_method_context_ = std::make_unique<OsxInputMethodContext>(osx_window);
+}
+
+OsxWindowPrivate::~OsxWindowPrivate() {}
+
void OsxWindowPrivate::OnWindowWillClose() {
destroy_event_.Raise(nullptr);
window_ = nil;
@@ -72,12 +82,9 @@ void OsxWindowPrivate::OnWindowDidResize() {
[view addTrackingArea:tracking_area];
CGLayerRelease(draw_layer_);
-
draw_layer_ = CreateLayer(Convert(content_rect_.GetSize()));
resize_event_.Raise(osx_window_->GetClientSize());
-
- osx_window_->RequestRepaint();
}
void OsxWindowPrivate::OnBecomeKeyWindow() { focus_event_.Raise(FocusChangeType::Gain); }
@@ -149,7 +156,7 @@ void OsxWindowPrivate::CreateWindow() {
auto cr = content_rect;
cr.origin.y = GetScreenSize().height - content_rect.origin.y - content_rect.size.height;
- window_ = [[CruWindow alloc] init:this contentRect:content_rect style:style_mask];
+ window_ = [[CruWindow alloc] init:this contentRect:cr style:style_mask];
Ensures(window_);
[window_ setDelegate:window_delegate_];
@@ -188,16 +195,12 @@ Rect OsxWindowPrivate::RetrieveContentRect() {
}
OsxWindow::OsxWindow(OsxUiApplication* ui_application)
- : OsxGuiResource(ui_application), p_(new details::OsxWindowPrivate(this)) {
- p_->window_delegate_ = [[CruWindowDelegate alloc] init:p_.get()];
-
- p_->content_rect_ = {100, 100, 400, 200};
-
- p_->input_method_context_ = std::make_unique<OsxInputMethodContext>(this);
-}
+ : OsxGuiResource(ui_application), p_(new details::OsxWindowPrivate(this)) {}
OsxWindow::~OsxWindow() {
- Close();
+ if (p_->window_) {
+ [p_->window_ close];
+ }
dynamic_cast<OsxUiApplication*>(GetUiApplication())->UnregisterWindow(this);
}
@@ -209,6 +212,26 @@ void OsxWindow::Close() {
INativeWindow* OsxWindow::GetParent() { return p_->parent_; }
+void OsxWindow::SetParent(INativeWindow* parent) {
+ auto p = CheckPlatform<OsxWindow>(parent, GetPlatformId());
+
+ p_->parent_ = parent;
+
+ if (p_->window_) {
+ [p_->window_ setParentWindow:p->p_->window_];
+ }
+}
+
+WindowStyleFlag OsxWindow::GetStyleFlag() { return p_->style_flag_; }
+
+void OsxWindow::SetStyleFlag(WindowStyleFlag flag) {
+ p_->style_flag_ = flag;
+
+ if (p_->window_) {
+ [p_->window_ close];
+ }
+}
+
WindowVisibilityType OsxWindow::GetVisibility() {
if (!p_->window_) return WindowVisibilityType::Hide;
return [p_->window_ isVisible] ? WindowVisibilityType::Show : WindowVisibilityType::Hide;
@@ -218,13 +241,16 @@ void OsxWindow::SetVisibility(WindowVisibilityType visibility) {
if (p_->window_) {
if (visibility == WindowVisibilityType::Show) {
[p_->window_ orderFront:nil];
+ p_->visibility_change_event_.Raise(WindowVisibilityType::Show);
} else {
[p_->window_ orderOut:nil];
+ p_->visibility_change_event_.Raise(WindowVisibilityType::Hide);
}
} else {
if (visibility == WindowVisibilityType::Show) {
p_->CreateWindow();
[p_->window_ orderFront:nil];
+ p_->visibility_change_event_.Raise(WindowVisibilityType::Show);
}
}
}
@@ -233,7 +259,9 @@ Size OsxWindow::GetClientSize() { return p_->content_rect_.GetSize(); }
void OsxWindow::SetClientSize(const Size& size) {
if (p_->window_) {
- [p_->window_ setContentSize:NSSize{size.width, size.height}];
+ auto rect = GetWindowRect();
+ rect.SetSize(size);
+ SetWindowRect(rect);
} else {
p_->content_rect_.SetSize(size);
}
@@ -278,6 +306,10 @@ void OsxWindow::RequestRepaint() {
}
std::unique_ptr<graphics::IPainter> OsxWindow::BeginPaint() {
+ if (!p_->window_) {
+ p_->CreateWindow();
+ }
+
CGContextRef cg_context = CGLayerGetContext(p_->draw_layer_);
return std::make_unique<cru::platform::graphics::osx::quartz::QuartzCGContextPainter>(
diff --git a/src/osx/gui/WindowPrivate.h b/src/osx/gui/WindowPrivate.h
index d8deaa0c..674ba70f 100644
--- a/src/osx/gui/WindowPrivate.h
+++ b/src/osx/gui/WindowPrivate.h
@@ -35,12 +35,12 @@ class OsxWindowPrivate {
friend OsxInputMethodContextPrivate;
public:
- explicit OsxWindowPrivate(OsxWindow* osx_window) : osx_window_(osx_window) {}
+ explicit OsxWindowPrivate(OsxWindow* osx_window);
CRU_DELETE_COPY(OsxWindowPrivate)
CRU_DELETE_MOVE(OsxWindowPrivate)
- ~OsxWindowPrivate() = default;
+ ~OsxWindowPrivate();
public:
void OnMouseEnterLeave(MouseEnterLeaveType type);
@@ -80,15 +80,15 @@ class OsxWindowPrivate {
private:
OsxWindow* osx_window_;
- INativeWindow* parent_;
- WindowStyleFlag style_flag_;
+ INativeWindow* parent_ = nullptr;
+ WindowStyleFlag style_flag_ = WindowStyleFlag{};
Rect content_rect_;
NSWindow* window_ = nil;
CruWindowDelegate* window_delegate_ = nil;
- CGLayerRef draw_layer_;
+ CGLayerRef draw_layer_ = nullptr;
bool mouse_in_ = false;
diff --git a/src/ui/components/Menu.cpp b/src/ui/components/Menu.cpp
index 964eead9..c3359cf9 100644
--- a/src/ui/components/Menu.cpp
+++ b/src/ui/components/Menu.cpp
@@ -28,7 +28,10 @@ MenuItem::~MenuItem() {
void MenuItem::SetText(String text) { text_->SetText(std::move(text)); }
-Menu::Menu() { container_ = controls::FlexLayout::Create(); }
+Menu::Menu() {
+ container_ = controls::FlexLayout::Create();
+ container_->SetFlexDirection(FlexDirection::Vertical);
+}
Menu::~Menu() {
if (!container_->GetWindowHost()) {
@@ -88,6 +91,7 @@ void PopupMenu::SetPosition(const Point& position) {
void PopupMenu::Show() {
popup_->GetWindowHost()->RelayoutWithSize(Size::Infinate(), true);
- popup_->GetWindowHost()->GetNativeWindow()->SetVisible(true);
+ popup_->GetWindowHost()->GetNativeWindow()->SetVisibility(
+ platform::gui::WindowVisibilityType::Show);
}
} // namespace cru::ui::components
diff --git a/src/ui/controls/Popup.cpp b/src/ui/controls/Popup.cpp
index ae6ac1d2..b386165b 100644
--- a/src/ui/controls/Popup.cpp
+++ b/src/ui/controls/Popup.cpp
@@ -8,11 +8,9 @@
#include <memory>
namespace cru::ui::controls {
-Popup::Popup(Control* attached_control)
- : RootControl(
- attached_control,
- host::CreateWindowParams{
- nullptr, platform::gui::CreateWindowFlags::NoCaptionAndBorder}) {
+Popup::Popup(Control* attached_control) : RootControl(attached_control) {
+ GetWindowHost()->GetNativeWindow()->SetStyleFlag(
+ cru::platform::gui::WindowStyleFlags::NoCaptionAndBorder);
SetGainFocusOnCreateAndDestroyWhenLoseFocus(true);
}
diff --git a/src/ui/controls/RootControl.cpp b/src/ui/controls/RootControl.cpp
index 4ae41c80..d89982c5 100644
--- a/src/ui/controls/RootControl.cpp
+++ b/src/ui/controls/RootControl.cpp
@@ -11,29 +11,12 @@
#include <memory>
namespace cru::ui::controls {
-RootControl::RootControl(Control* attached_control,
- host::CreateWindowParams params)
+RootControl::RootControl(Control* attached_control)
: attached_control_(attached_control) {
render_object_ = std::make_unique<render::StackLayoutRenderObject>();
render_object_->SetAttachedControl(this);
SetContainerRenderObject(render_object_.get());
- window_host_ = std::make_unique<host::WindowHost>(this, params);
-
- if (gain_focus_on_create_and_destroy_when_lose_focus_) {
- auto native_window = window_host_->GetNativeWindow();
- native_window->CreateEvent()->AddHandler(
- [](platform::gui::INativeWindow* window) {
- window->CreateEvent()->AddHandler(
- [window](std::nullptr_t) { window->RequestFocus(); });
- });
-
- native_window->FocusEvent()->AddHandler(
- [native_window](platform::gui::FocusChangeType type) {
- if (type == platform::gui::FocusChangeType::Lost) {
- native_window->Close();
- }
- });
- }
+ window_host_ = std::make_unique<host::WindowHost>(this);
}
RootControl::~RootControl() {}
@@ -43,6 +26,25 @@ render::RenderObject* RootControl::GetRenderObject() const {
}
void RootControl::SetGainFocusOnCreateAndDestroyWhenLoseFocus(bool value) {
- gain_focus_on_create_and_destroy_when_lose_focus_ = value;
+ gain_focus_on_create_and_destroy_when_lose_focus_event_guard_.Clear();
+ if (value) {
+ auto native_window = window_host_->GetNativeWindow();
+
+ gain_focus_on_create_and_destroy_when_lose_focus_event_guard_ +=
+ native_window->VisibilityChangeEvent()->AddHandler(
+ [native_window](platform::gui::WindowVisibilityType type) {
+ if (type == platform::gui::WindowVisibilityType::Show) {
+ native_window->RequestFocus();
+ }
+ });
+
+ gain_focus_on_create_and_destroy_when_lose_focus_event_guard_ +=
+ native_window->FocusEvent()->AddHandler(
+ [native_window](platform::gui::FocusChangeType type) {
+ if (type == platform::gui::FocusChangeType::Lost) {
+ native_window->Close();
+ }
+ });
+ }
}
} // namespace cru::ui::controls
diff --git a/src/ui/controls/Window.cpp b/src/ui/controls/Window.cpp
index 00fab8e9..76203f22 100644
--- a/src/ui/controls/Window.cpp
+++ b/src/ui/controls/Window.cpp
@@ -12,8 +12,7 @@ Window* Window::Create(Control* attached_control) {
return new Window(attached_control);
}
-Window::Window(Control* attached_control)
- : RootControl(attached_control, host::CreateWindowParams{}) {}
+Window::Window(Control* attached_control) : RootControl(attached_control) {}
Window::~Window() {}
} // namespace cru::ui::controls
diff --git a/src/ui/host/WindowHost.cpp b/src/ui/host/WindowHost.cpp
index 3f3976b4..034d9bd8 100644
--- a/src/ui/host/WindowHost.cpp
+++ b/src/ui/host/WindowHost.cpp
@@ -8,7 +8,6 @@
#include "cru/platform/gui/UiApplication.hpp"
#include "cru/platform/gui/Window.hpp"
#include "cru/ui/DebugFlags.hpp"
-#include "cru/ui/controls/Window.hpp"
#include "cru/ui/host/LayoutPaintCycler.hpp"
#include "cru/ui/render/MeasureRequirement.hpp"
#include "cru/ui/render/RenderObject.hpp"
@@ -104,8 +103,7 @@ inline void BindNativeEvent(
}
} // namespace
-WindowHost::WindowHost(controls::Control* root_control,
- CreateWindowParams params)
+WindowHost::WindowHost(controls::Control* root_control)
: root_control_(root_control), focus_control_(root_control) {
root_control_->TraverseDescendants([this](controls::Control* control) {
control->window_host_ = this;
@@ -117,17 +115,16 @@ WindowHost::WindowHost(controls::Control* root_control,
this->layout_paint_cycler_ = std::make_unique<LayoutPaintCycler>(this);
- CreateNativeWindow(params);
+ CreateNativeWindow();
}
WindowHost::~WindowHost() {}
-gsl::not_null<platform::gui::INativeWindow*> WindowHost::CreateNativeWindow(
- CreateWindowParams create_window_params) {
+gsl::not_null<platform::gui::INativeWindow*> WindowHost::CreateNativeWindow() {
const auto ui_application = IUiApplication::GetInstance();
- auto native_window = ui_application->CreateWindow(create_window_params.parent,
- create_window_params.flag);
+ auto native_window = ui_application->CreateWindow();
+ Ensures(native_window);
native_window_ = native_window;