diff options
author | crupest <crupest@outlook.com> | 2021-11-20 21:25:29 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-11-20 21:25:29 +0800 |
commit | 1a53ed0791d9793ed8030d3a44e833e5e7c4542b (patch) | |
tree | 28aedaabee675b192e414489122349ad4985a31b | |
parent | a9da4c10459e3c45115c8a42e771b00cb1caeab7 (diff) | |
download | cru-1a53ed0791d9793ed8030d3a44e833e5e7c4542b.tar.gz cru-1a53ed0791d9793ed8030d3a44e833e5e7c4542b.tar.bz2 cru-1a53ed0791d9793ed8030d3a44e833e5e7c4542b.zip |
...
-rw-r--r-- | demos/main/main.cpp | 13 | ||||
-rw-r--r-- | include/cru/ui/components/Menu.hpp | 29 | ||||
-rw-r--r-- | include/cru/ui/controls/Popup.hpp | 8 | ||||
-rw-r--r-- | include/cru/ui/host/WindowHost.hpp | 5 | ||||
-rw-r--r-- | src/osx/graphics/quartz/TextLayout.cpp | 2 | ||||
-rw-r--r-- | src/osx/gui/Window.mm | 17 | ||||
-rw-r--r-- | src/ui/components/Menu.cpp | 37 | ||||
-rw-r--r-- | src/ui/host/WindowHost.cpp | 14 |
8 files changed, 113 insertions, 12 deletions
diff --git a/demos/main/main.cpp b/demos/main/main.cpp index 9a28ade8..1a92e5ff 100644 --- a/demos/main/main.cpp +++ b/demos/main/main.cpp @@ -1,13 +1,16 @@ +#include <memory> #include "cru/platform/HeapDebug.hpp" #include "cru/platform/bootstrap/Bootstrap.hpp" #include "cru/platform/gui/UiApplication.hpp" #include "cru/platform/gui/Window.hpp" #include "cru/ui/Base.hpp" +#include "cru/ui/components/Menu.hpp" #include "cru/ui/controls/Button.hpp" #include "cru/ui/controls/FlexLayout.hpp" #include "cru/ui/controls/TextBlock.hpp" #include "cru/ui/controls/TextBox.hpp" #include "cru/ui/controls/Window.hpp" +#include "cru/ui/events/UiEvent.hpp" #include "cru/ui/host/WindowHost.hpp" using cru::platform::gui::IUiApplication; @@ -40,6 +43,16 @@ int main() { const auto text_box = TextBox::Create(); flex_layout->AddChild(text_box, 2); + auto popup_menu = std::make_unique<cru::ui::components::PopupMenu>(window); + popup_menu->GetMenu()->AddTextItem(u"Item 1"); + popup_menu->GetMenu()->AddTextItem(u"Item 2000"); + + window->MouseDownEvent()->Bubble()->AddHandler( + [window, &popup_menu](cru::ui::event::MouseButtonEventArgs& e) { + popup_menu->SetPosition(e.GetPoint()); + popup_menu->Show(); + }); + window->Show(); return application->Run(); diff --git a/include/cru/ui/components/Menu.hpp b/include/cru/ui/components/Menu.hpp index d60d38eb..96b21173 100644 --- a/include/cru/ui/components/Menu.hpp +++ b/include/cru/ui/components/Menu.hpp @@ -4,9 +4,9 @@ #include "cru/ui/controls/Button.hpp" #include "cru/ui/controls/Control.hpp" #include "cru/ui/controls/FlexLayout.hpp" +#include "cru/ui/controls/Popup.hpp" #include "cru/ui/controls/TextBlock.hpp" -#include <string> #include <vector> namespace cru::ui::components { @@ -40,6 +40,8 @@ class Menu : public Component { ~Menu(); public: + controls::Control* GetRootControl() override { return container_; } + gsl::index GetItemCount() const { return static_cast<gsl::index>(items_.size()); } @@ -57,4 +59,29 @@ class Menu : public Component { controls::FlexLayout* container_; std::vector<Component*> items_; }; + +class PopupMenu : public Component { + public: + explicit PopupMenu(controls::Control* attached_control = nullptr); + + CRU_DELETE_COPY(PopupMenu) + CRU_DELETE_MOVE(PopupMenu) + + ~PopupMenu(); + + public: + controls::Control* GetRootControl() override; + + controls::Popup* GetPopup() { return popup_; } + Menu* GetMenu() { return menu_; } + + void SetPosition(const Point& position); + void Show(); + + private: + controls::Control* attached_control_; + + controls::Popup* popup_; + Menu* menu_; +}; } // namespace cru::ui::components diff --git a/include/cru/ui/controls/Popup.hpp b/include/cru/ui/controls/Popup.hpp index 321bbbc6..cd5e1813 100644 --- a/include/cru/ui/controls/Popup.hpp +++ b/include/cru/ui/controls/Popup.hpp @@ -8,6 +8,12 @@ namespace cru::ui::controls { class Popup : public RootControl { public: + static constexpr StringView kControlType = u"Popup"; + + static Popup* Create(Control* attached_control = nullptr) { + return new Popup(attached_control); + } + explicit Popup(Control* attached_control = nullptr); CRU_DELETE_COPY(Popup) @@ -15,6 +21,8 @@ class Popup : public RootControl { ~Popup() override; + String GetControlType() const override { return kControlType.ToString(); } + protected: gsl::not_null<platform::gui::INativeWindow*> CreateNativeWindow( gsl::not_null<host::WindowHost*> host, diff --git a/include/cru/ui/host/WindowHost.hpp b/include/cru/ui/host/WindowHost.hpp index 258b0c4c..f3caeeef 100644 --- a/include/cru/ui/host/WindowHost.hpp +++ b/include/cru/ui/host/WindowHost.hpp @@ -59,7 +59,8 @@ class WindowHost : public Object { } void Relayout(); - void Relayout(const Size& available_size); + void RelayoutWithSize(const Size& available_size = Size::Infinate(), + bool set_window_size_to_fit_content = false); void Repaint(); @@ -173,7 +174,7 @@ class WindowHost : public Object { controls::Control* mouse_captured_control_ = nullptr; - bool layout_prefer_to_fill_window_ = true; + bool layout_prefer_to_fill_window_ = false; Event<platform::gui::INativeWindow*> native_window_change_event_; diff --git a/src/osx/graphics/quartz/TextLayout.cpp b/src/osx/graphics/quartz/TextLayout.cpp index a5607854..c3a138f2 100644 --- a/src/osx/graphics/quartz/TextLayout.cpp +++ b/src/osx/graphics/quartz/TextLayout.cpp @@ -115,6 +115,8 @@ void OsxCTTextLayout::SetEditMode(bool enable) { } Rect OsxCTTextLayout::GetTextBounds(bool includingTrailingSpace) { + if (text_.empty() && edit_mode_) return Rect(0, 0, 0, font_->GetFontSize()); + auto result = DoGetTextBoundsIncludingEmptyLines(includingTrailingSpace); return Rect(0, 0, result.size.width, result.size.height); } diff --git a/src/osx/gui/Window.mm b/src/osx/gui/Window.mm index 0112fd43..9f0d9742 100644 --- a/src/osx/gui/Window.mm +++ b/src/osx/gui/Window.mm @@ -71,7 +71,13 @@ void OsxWindowPrivate::OnWindowDidResize() { [view addTrackingArea:tracking_area]; CGLayerRelease(draw_layer_); - draw_layer_ = CGLayerCreateWithContext(nullptr, rect.size, nullptr); + + // If size is 0 then create layer will fail. + auto s = rect.size; + if (s.width == 0) s.width = 1; + if (s.height == 0) s.height = 1; + + draw_layer_ = CGLayerCreateWithContext(nullptr, s, nullptr); Ensures(draw_layer_); resize_event_.Raise(osx_window_->GetClientSize()); @@ -252,8 +258,13 @@ void OsxWindow::CreateWindow() { [p_->window_ setContentView:content_view]; - p_->draw_layer_ = CGLayerCreateWithContext( - nullptr, cru::platform::graphics::osx::quartz::Convert(p_->content_rect_.GetSize()), nullptr); + // If size is 0 then create layer will fail. + auto s = p_->content_rect_.GetSize(); + if (s.width == 0) s.width = 1; + if (s.height == 0) s.height = 1; + + p_->draw_layer_ = + CGLayerCreateWithContext(nullptr, cru::platform::graphics::osx::quartz::Convert(s), nullptr); Ensures(p_->draw_layer_); RequestRepaint(); diff --git a/src/ui/components/Menu.cpp b/src/ui/components/Menu.cpp index afd1ab71..af54c46c 100644 --- a/src/ui/components/Menu.cpp +++ b/src/ui/components/Menu.cpp @@ -1,12 +1,12 @@ #include "cru/ui/components/Menu.hpp" #include "cru/ui/UiManager.hpp" #include "cru/ui/controls/Button.hpp" +#include "cru/ui/controls/Control.hpp" #include "cru/ui/controls/FlexLayout.hpp" #include "cru/ui/controls/TextBlock.hpp" +#include "cru/ui/host/WindowHost.hpp" #include "cru/ui/style/StyleRuleSet.hpp" -#include <string> - namespace cru::ui::components { MenuItem::MenuItem() { container_ = controls::Button::Create(); @@ -56,4 +56,37 @@ Component* Menu::RemoveItem(gsl::index index) { return item; } + +void Menu::AddTextItem(String text, gsl::index index) { + MenuItem* item = new MenuItem(std::move(text)); + AddItem(item, index); +} + +PopupMenu::PopupMenu(controls::Control* attached_control) + : attached_control_(attached_control) { + popup_ = controls::Popup::Create(attached_control); + + menu_ = new Menu(); + + popup_->AddChild(menu_->GetRootControl(), 0); +} + +PopupMenu::~PopupMenu() { + delete menu_; + + if (!popup_->GetWindowHost()) { + delete popup_; + } +} + +controls::Control* PopupMenu::GetRootControl() { return popup_; } + +void PopupMenu::SetPosition(const Point& position) { + popup_->SetRect(Rect{position, {}}); +} + +void PopupMenu::Show() { + popup_->GetWindowHost()->RelayoutWithSize(Size::Infinate(), true); + popup_->Show(); +} } // namespace cru::ui::components diff --git a/src/ui/host/WindowHost.cpp b/src/ui/host/WindowHost.cpp index f60e2809..d26b43ab 100644 --- a/src/ui/host/WindowHost.cpp +++ b/src/ui/host/WindowHost.cpp @@ -180,18 +180,24 @@ void WindowHost::SetLayoutPreferToFillWindow(bool value) { void WindowHost::Relayout() { const auto available_size = - native_window_ ? native_window_->GetClientSize() - : Size{100, 100}; // a reasonable assumed size - Relayout(available_size); + native_window_ ? native_window_->GetClientSize() : Size::Infinate(); + RelayoutWithSize(available_size); } -void WindowHost::Relayout(const Size& available_size) { +void WindowHost::RelayoutWithSize(const Size& available_size, + bool set_window_size_to_fit_content) { root_render_object_->Measure( render::MeasureRequirement{available_size, IsLayoutPreferToFillWindow() ? render::MeasureSize(available_size) : render::MeasureSize::NotSpecified()}, render::MeasureSize::NotSpecified()); + + if (set_window_size_to_fit_content) { + auto rect = GetWindowRect(); + SetWindowRect({rect.GetLeftTop(), root_render_object_->GetSize()}); + } + root_render_object_->Layout(Point{}); for (auto& action : after_layout_stable_action_) action(); after_layout_event_.Raise(AfterLayoutEventArgs{}); |