aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author杨宇千 <crupest@outlook.com>2018-11-11 17:45:58 +0800
committerGitHub <noreply@github.com>2018-11-11 17:45:58 +0800
commit92bec65a76b62bbbee56b44c3020171606bb8bbb (patch)
tree2594670863ef855222cb5af1798807f2c263ab66
parent3cc588ade5ac08e53c406cea6bfcaaafac4346cf (diff)
parent61b44c223df9c3d2a6daec85f693a2b9a406f5c9 (diff)
downloadcru-92bec65a76b62bbbee56b44c3020171606bb8bbb.tar.gz
cru-92bec65a76b62bbbee56b44c3020171606bb8bbb.tar.bz2
cru-92bec65a76b62bbbee56b44c3020171606bb8bbb.zip
Merge pull request #14 from crupest/popup-menu
Add popup menu. Fix a potential bug in window destroy.
-rw-r--r--CruUI.vcxproj2
-rw-r--r--CruUI.vcxproj.filters6
-rw-r--r--src/main.cpp31
-rw-r--r--src/ui/controls/popup_menu.cpp58
-rw-r--r--src/ui/controls/popup_menu.hpp20
-rw-r--r--src/ui/window.cpp2
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() {