diff options
-rw-r--r-- | CruUI.vcxproj | 2 | ||||
-rw-r--r-- | CruUI.vcxproj.filters | 6 | ||||
-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 |
6 files changed, 93 insertions, 26 deletions
diff --git a/CruUI.vcxproj b/CruUI.vcxproj index 0c0ba1b6..3ca8fb40 100644 --- a/CruUI.vcxproj +++ b/CruUI.vcxproj @@ -131,12 +131,14 @@ <ClCompile Include="src\ui\controls\button.cpp" /> <ClCompile Include="src\ui\controls\linear_layout.cpp" /> <ClCompile Include="src\ui\controls\list_item.cpp" /> + <ClCompile Include="src\ui\controls\popup_menu.cpp" /> <ClCompile Include="src\ui\controls\text_block.cpp" /> <ClCompile Include="src\ui\controls\text_box.cpp" /> <ClInclude Include="src\any_map.hpp" /> <ClInclude Include="src\format.hpp" /> <ClInclude Include="src\ui\border_property.hpp" /> <ClInclude Include="src\ui\controls\list_item.hpp" /> + <ClInclude Include="src\ui\controls\popup_menu.hpp" /> <ClInclude Include="src\ui\controls\text_control.hpp" /> <ClCompile Include="src\ui\controls\toggle_button.cpp" /> <ClCompile Include="src\ui\cursor.cpp" /> diff --git a/CruUI.vcxproj.filters b/CruUI.vcxproj.filters index 7a84270a..460cd233 100644 --- a/CruUI.vcxproj.filters +++ b/CruUI.vcxproj.filters @@ -84,6 +84,9 @@ <ClCompile Include="src\ui\controls\list_item.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="src\ui\controls\popup_menu.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="src\graph\graph.hpp"> @@ -170,6 +173,9 @@ <ClInclude Include="src\ui\convert_util.hpp"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="src\ui\controls\popup_menu.hpp"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="src\application.cpp"> 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() { |