diff options
-rw-r--r-- | demos/input_method/main.cpp | 4 | ||||
-rw-r--r-- | demos/main/main.cpp | 3 | ||||
-rw-r--r-- | demos/scroll_view/main.cpp | 4 | ||||
-rw-r--r-- | include/cru/osx/gui/Window.hpp | 4 | ||||
-rw-r--r-- | include/cru/platform/gui/Window.hpp | 6 | ||||
-rw-r--r-- | include/cru/ui/controls/RootControl.hpp | 10 | ||||
-rw-r--r-- | include/cru/ui/host/WindowHost.hpp | 14 | ||||
-rw-r--r-- | src/osx/gui/Window.mm | 58 | ||||
-rw-r--r-- | src/osx/gui/WindowPrivate.h | 10 | ||||
-rw-r--r-- | src/ui/components/Menu.cpp | 8 | ||||
-rw-r--r-- | src/ui/controls/Popup.cpp | 8 | ||||
-rw-r--r-- | src/ui/controls/RootControl.cpp | 42 | ||||
-rw-r--r-- | src/ui/controls/Window.cpp | 3 | ||||
-rw-r--r-- | src/ui/host/WindowHost.cpp | 13 |
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; |