diff options
author | crupest <crupest@outlook.com> | 2018-11-11 17:38:05 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2018-11-11 17:38:05 +0800 |
commit | 61b44c223df9c3d2a6daec85f693a2b9a406f5c9 (patch) | |
tree | 2594670863ef855222cb5af1798807f2c263ab66 /src | |
parent | 3cc588ade5ac08e53c406cea6bfcaaafac4346cf (diff) | |
download | cru-61b44c223df9c3d2a6daec85f693a2b9a406f5c9.tar.gz cru-61b44c223df9c3d2a6daec85f693a2b9a406f5c9.tar.bz2 cru-61b44c223df9c3d2a6daec85f693a2b9a406f5c9.zip |
Add popup menu. Fix a potential bug in window destroy.
Diffstat (limited to 'src')
-rw-r--r-- | src/main.cpp | 31 | ||||
-rw-r--r-- | src/ui/controls/popup_menu.cpp | 58 | ||||
-rw-r--r-- | src/ui/controls/popup_menu.hpp | 20 | ||||
-rw-r--r-- | src/ui/window.cpp | 2 |
4 files changed, 85 insertions, 26 deletions
diff --git a/src/main.cpp b/src/main.cpp index 5ae7257e..76579c0d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "ui/controls/button.hpp" #include "ui/controls/text_box.hpp" #include "ui/controls/list_item.hpp" +#include "ui/controls/popup_menu.hpp" using cru::String; using cru::StringView; @@ -120,32 +121,12 @@ int APIENTRY wWinMain( button->AddChild(TextBlock::Create(L"Show popup window parenting this.")); button->mouse_click_event.AddHandler([window, button](auto) { - const auto popup = Window::CreatePopup(window); + std::vector<cru::ui::controls::MenuItemInfo> items; + items.emplace_back(L"Hello world!", []{}); + items.emplace_back(L"Item 2", []{}); + items.emplace_back(L"Close parent window.", [window]{ window->Close(); }); - auto create_menu_item = [](const String& text) -> ListItem* - { - auto text_block = TextBlock::Create(text); - text_block->GetLayoutParams()->width.alignment = Alignment::Start; - - return CreateWithLayout<ListItem>( - LayoutSideParams::Stretch(Alignment::Center), - LayoutSideParams::Content(Alignment::Start), - ControlList{ text_block } - ); - }; - - const auto menu = LinearLayout::Create(LinearLayout::Orientation::Vertical, ControlList{ - create_menu_item(L"copy"), - create_menu_item(L"cut"), - create_menu_item(L"paste") - }); - - popup->AddChild(menu); - - popup->SetSizeFitContent(); - popup->SetWindowPosition(window->PointToScreen(button->GetPositionAbsolute())); - - popup->Show(); + cru::ui::controls::CreatePopupMenu(window->PointToScreen(button->GetPositionAbsolute()), items, window)->Show(); }); layout->AddChild(button); } diff --git a/src/ui/controls/popup_menu.cpp b/src/ui/controls/popup_menu.cpp new file mode 100644 index 00000000..88ea8f17 --- /dev/null +++ b/src/ui/controls/popup_menu.cpp @@ -0,0 +1,58 @@ +#include "popup_menu.hpp" + +#include "ui/window.hpp" +#include "text_block.hpp" +#include "list_item.hpp" +#include "linear_layout.hpp" +#include "ui/events/ui_event.hpp" + +namespace cru::ui::controls +{ + Window* CreatePopupMenu(const Point& anchor, const std::vector<MenuItemInfo>& items, Window* parent) + { + const auto popup = Window::CreatePopup(parent); + + popup->lose_focus_event.AddHandler([popup](events::FocusChangeEventArgs& args) + { + if (args.IsWindow()) + popup->Close(); + }); + + const auto create_menu_item = [popup](const String& text, const std::function<void()>& action) -> ListItem* + { + auto text_block = TextBlock::Create(text); + text_block->GetLayoutParams()->width.alignment = Alignment::Start; + + auto list_item = CreateWithLayout<ListItem>( + LayoutSideParams::Stretch(Alignment::Center), + LayoutSideParams::Content(Alignment::Start), + ControlList{ text_block } + ); + + list_item->mouse_click_event.AddHandler([popup, action](events::MouseButtonEventArgs& args) + { + if (args.GetMouseButton() == MouseButton::Left) + { + action(); + popup->Close(); + } + }); + + return list_item; + }; + + const auto menu = LinearLayout::Create(LinearLayout::Orientation::Vertical); + + menu->SetBordered(true); + + for (const auto& item : items) + menu->AddChild(create_menu_item(item.first, item.second)); + + popup->AddChild(menu); + + popup->SetSizeFitContent(); + popup->SetWindowPosition(anchor); + + return popup; + } +} diff --git a/src/ui/controls/popup_menu.hpp b/src/ui/controls/popup_menu.hpp new file mode 100644 index 00000000..d47e3eb6 --- /dev/null +++ b/src/ui/controls/popup_menu.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include <vector> +#include <utility> +#include <functional> + +#include "base.hpp" +#include "ui/ui_base.hpp" + +namespace cru::ui +{ + class Window; +} + +namespace cru::ui::controls +{ + using MenuItemInfo = std::pair<String, std::function<void()>>; + + Window* CreatePopupMenu(const Point& anchor, const std::vector<MenuItemInfo>& items, Window* parent = nullptr); +} diff --git a/src/ui/window.cpp b/src/ui/window.cpp index f8e6d4f3..862267fc 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -627,7 +627,7 @@ namespace cru::ui WindowManager::GetInstance()->UnregisterWindow(hwnd_); hwnd_ = nullptr; if (delete_this_on_destroy_) - delete this; + InvokeLater([this]{ delete this; }); } void Window::OnPaintInternal() { |