diff options
| author | Yuqian Yang <crupest@crupest.life> | 2025-11-18 17:31:23 +0800 |
|---|---|---|
| committer | Yuqian Yang <crupest@crupest.life> | 2025-11-18 17:31:23 +0800 |
| commit | 04d243699cbde40fe69472f4c4df38c36f7942ef (patch) | |
| tree | af2a2031ab7f2d9ce03cf677eba066e11f32a0c9 | |
| parent | 358dc1498623d53f1d8bedf5172743deb6c03811 (diff) | |
| download | cru-04d243699cbde40fe69472f4c4df38c36f7942ef.tar.gz cru-04d243699cbde40fe69472f4c4df38c36f7942ef.tar.bz2 cru-04d243699cbde40fe69472f4c4df38c36f7942ef.zip | |
Move delete later to platform::gui.
18 files changed, 82 insertions, 69 deletions
diff --git a/include/cru/ui/DeleteLater.h b/include/cru/platform/gui/DeleteLater.h index 95301bc0..c0578974 100644 --- a/include/cru/ui/DeleteLater.h +++ b/include/cru/platform/gui/DeleteLater.h @@ -1,20 +1,21 @@ #pragma once -#include "Base.h" +#include "UiApplication.h" #include <cru/base/Guard.h> #include <memory> #include <utility> -namespace cru::ui { -class CRU_UI_API DeleteLaterImpl { - CRU_DEFINE_CLASS_LOG_TAG("cru::ui::DeleteLaterImpl") +namespace cru::platform::gui { +template <typename TSelf> +class DeleteLaterImpl { + CRU_DEFINE_CLASS_LOG_TAG("cru::platform::gui::DeleteLaterImpl") + public: - DeleteLaterImpl(); - virtual ~DeleteLaterImpl(); - void DeleteLater(); + virtual ~DeleteLaterImpl() {} - private: - bool delete_later_scheduled_; + void DeleteLater() { + IUiApplication::GetInstance()->DeleteLater(static_cast<TSelf*>(this)); + } }; namespace details { @@ -37,4 +38,4 @@ DeleteLaterPtr<T> MakeDeleteLater(Args&&... args) { return DeleteLaterPtr<T>(new T(std::forward<Args>(args)...)); } -} // namespace cru::ui +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/UiApplication.h b/include/cru/platform/gui/UiApplication.h index 84011275..c4454b2e 100644 --- a/include/cru/platform/gui/UiApplication.h +++ b/include/cru/platform/gui/UiApplication.h @@ -16,6 +16,18 @@ struct INativeWindow; struct IInputMethodContext; struct IClipboard; +class CRU_PLATFORM_GUI_API DeleteLaterPool : public Object { + public: + void Add(Object* object); + + void Clean(); + + private: + // May contain duplicate object pointer. When performing deleting, use a set + // to record deleted objects to avoid double delete. + std::vector<Object*> pool_; +}; + // The entry point of a ui application. struct CRU_PLATFORM_GUI_API IUiApplication : public virtual IPlatformResource { public: @@ -51,6 +63,8 @@ struct CRU_PLATFORM_GUI_API IUiApplication : public virtual IPlatformResource { // result in no-op. virtual void CancelTimer(long long id) = 0; + virtual void DeleteLater(Object* object) = 0; + virtual std::vector<INativeWindow*> GetAllWindow() = 0; virtual INativeWindow* CreateWindow() = 0; diff --git a/include/cru/platform/gui/win/UiApplication.h b/include/cru/platform/gui/win/UiApplication.h index b2d1f39b..c5057c4b 100644 --- a/include/cru/platform/gui/win/UiApplication.h +++ b/include/cru/platform/gui/win/UiApplication.h @@ -48,6 +48,8 @@ class CRU_WIN_GUI_API WinUiApplication : public WinNativeResource, std::function<void()> action) override; void CancelTimer(long long id) override; + void DeleteLater(Object* object) override; + std::vector<INativeWindow*> GetAllWindow() override; INativeWindow* CreateWindow() override; @@ -79,6 +81,7 @@ class CRU_WIN_GUI_API WinUiApplication : public WinNativeResource, graph_factory_; TimerRegistry<std::function<void()>> timers_; + DeleteLaterPool delete_later_pool_; std::unique_ptr<WindowClass> general_window_class_; std::vector<WinNativeWindow*> windows_; diff --git a/include/cru/ui/components/Component.h b/include/cru/ui/components/Component.h index d8966a89..1e002e5f 100644 --- a/include/cru/ui/components/Component.h +++ b/include/cru/ui/components/Component.h @@ -1,6 +1,7 @@ #pragma once #include "../Base.h" -#include "../DeleteLater.h" + +#include <cru/platform/gui/DeleteLater.h> namespace cru::ui::components { /** @@ -8,7 +9,9 @@ namespace cru::ui::components { * \remarks Component should respect children's Component::IsDeleteByParent * value and decide whether to delete it. */ -class CRU_UI_API Component : public Object, public DeleteLaterImpl { +class CRU_UI_API Component + : public Object, + public cru::platform::gui::DeleteLaterImpl<Component> { public: virtual controls::Control* GetRootControl() = 0; diff --git a/include/cru/ui/controls/Control.h b/include/cru/ui/controls/Control.h index 9e5e86b8..6a85d25a 100644 --- a/include/cru/ui/controls/Control.h +++ b/include/cru/ui/controls/Control.h @@ -1,6 +1,5 @@ #pragma once #include "../Base.h" -#include "../DeleteLater.h" #include "../events/KeyEventArgs.h" #include "../events/MouseWheelEventArgs.h" #include "../events/UiEvents.h" @@ -9,6 +8,7 @@ #include "../style/StyleRuleSet.h" #include <cru/base/SelfResolvable.h> +#include <cru/platform/gui/DeleteLater.h> namespace cru::ui::controls { @@ -22,7 +22,7 @@ namespace cru::ui::controls { * The last two methods are totally for convenient control tree management. */ class CRU_UI_API Control : public Object, - public DeleteLaterImpl, + public cru::platform::gui::DeleteLaterImpl<Control>, public SelfResolvable<Control> { friend class ControlHost; diff --git a/src/ThemeBuilder/components/StyleRuleSetEditor.cpp b/src/ThemeBuilder/components/StyleRuleSetEditor.cpp index fd159a44..9159e966 100644 --- a/src/ThemeBuilder/components/StyleRuleSetEditor.cpp +++ b/src/ThemeBuilder/components/StyleRuleSetEditor.cpp @@ -1,5 +1,5 @@ #include "StyleRuleSetEditor.h" -#include "cru/ui/DeleteLater.h" +#include "cru/platform/gui/DeleteLater.h" #include "cru/ui/ThemeManager.h" #include "cru/ui/controls/FlexLayout.h" #include "cru/ui/model/IListChangeNotify.h" @@ -49,11 +49,11 @@ void StyleRuleSetEditor::BindStyleRuleSet( } Index StyleRuleSetEditor::IndexOfRuleEditor(StyleRuleEditor* editor) { - auto iter = - std::find_if(style_rule_editors_.cbegin(), style_rule_editors_.cend(), - [editor](const ui::DeleteLaterPtr<StyleRuleEditor>& p) { - return p.get() == editor; - }); + auto iter = std::find_if( + style_rule_editors_.cbegin(), style_rule_editors_.cend(), + [editor](const platform::gui::DeleteLaterPtr<StyleRuleEditor>& p) { + return p.get() == editor; + }); return iter - style_rule_editors_.cbegin(); } @@ -66,7 +66,8 @@ void StyleRuleSetEditor::UpdateView( for (auto i = change->position; i < change->position + change->count; ++i) { const auto& rule = style_rule_set->GetStyleRule(i); - auto style_rule_editor = ui::MakeDeleteLater<StyleRuleEditor>(); + auto style_rule_editor = + platform::gui::MakeDeleteLater<StyleRuleEditor>(); style_rule_editor->SetValue(rule, false); style_rule_editor->RemoveEvent()->AddSpyOnlyHandler( [this, editor = style_rule_editor.get()] { @@ -80,8 +81,8 @@ void StyleRuleSetEditor::UpdateView( }); style_rule_editors_.insert(style_rule_editors_.cbegin() + i, std::move(style_rule_editor)); - rules_layout_.InsertChildAt(style_rule_editors_.back()->GetRootControl(), - i); + rules_layout_.InsertChildAt( + style_rule_editors_.back()->GetRootControl(), i); } break; } diff --git a/src/ThemeBuilder/components/StyleRuleSetEditor.h b/src/ThemeBuilder/components/StyleRuleSetEditor.h index 03148889..36ac8626 100644 --- a/src/ThemeBuilder/components/StyleRuleSetEditor.h +++ b/src/ThemeBuilder/components/StyleRuleSetEditor.h @@ -1,8 +1,8 @@ #pragma once #include "StyleRuleEditor.h" -#include "cru/ui/DeleteLater.h" +#include "cru/platform/gui/DeleteLater.h" #include "cru/ui/components/Component.h" -#include "cru/ui/controls/Button.h" +#include "cru/ui/controls/IconButton.h" #include "cru/ui/controls/Control.h" #include "cru/ui/controls/FlexLayout.h" #include "cru/ui/controls/ScrollView.h" @@ -36,7 +36,7 @@ class StyleRuleSetEditor : public ui::components::Component { ui::controls::ScrollView scroll_view_; ui::controls::FlexLayout container_; ui::controls::FlexLayout rules_layout_; - std::vector<ui::DeleteLaterPtr<StyleRuleEditor>> style_rule_editors_; + std::vector<platform::gui::DeleteLaterPtr<StyleRuleEditor>> style_rule_editors_; ui::controls::IconButton add_button_; bool suppress_next_set_ = false; diff --git a/src/ThemeBuilder/components/conditions/CompoundConditionEditor.cpp b/src/ThemeBuilder/components/conditions/CompoundConditionEditor.cpp index d7324350..8501d7cd 100644 --- a/src/ThemeBuilder/components/conditions/CompoundConditionEditor.cpp +++ b/src/ThemeBuilder/components/conditions/CompoundConditionEditor.cpp @@ -7,7 +7,7 @@ #include "cru/base/ClonePtr.h" #include "cru/platform/Color.h" #include "cru/ui/Base.h" -#include "cru/ui/DeleteLater.h" +#include "cru/platform/gui/DeleteLater.h" #include "cru/ui/ThemeManager.h" #include "cru/ui/controls/FlexLayout.h" #include "cru/ui/style/Condition.h" @@ -69,7 +69,7 @@ CompoundConditionEditor::CompoundConditionEditor() { this->children_container_.RemoveChildAt(index); RaiseChangeEvent(); }); - children_.push_back(ui::ToDeleteLaterPtr(std::move(editor))); + children_.push_back(platform::gui::ToDeleteLaterPtr(std::move(editor))); children_container_.AddChild(children_.back()->GetRootControl()); RaiseChangeEvent(); } @@ -100,7 +100,7 @@ void CompoundConditionEditor::SetChildren( this->children_container_.RemoveChildAt(index); RaiseChangeEvent(); }); - children_.push_back(ui::ToDeleteLaterPtr(std::move(editor))); + children_.push_back(platform::gui::ToDeleteLaterPtr(std::move(editor))); children_container_.AddChild(children_.back()->GetRootControl()); } if (trigger_change) { diff --git a/src/ThemeBuilder/components/conditions/CompoundConditionEditor.h b/src/ThemeBuilder/components/conditions/CompoundConditionEditor.h index af632758..c0f0891a 100644 --- a/src/ThemeBuilder/components/conditions/CompoundConditionEditor.h +++ b/src/ThemeBuilder/components/conditions/CompoundConditionEditor.h @@ -23,7 +23,7 @@ class CompoundConditionEditor : public ConditionEditor { private: ui::components::PopupMenuIconButton add_child_button_; ui::controls::FlexLayout children_container_; - std::vector<ui::DeleteLaterPtr<ConditionEditor>> children_; + std::vector<platform::gui::DeleteLaterPtr<ConditionEditor>> children_; }; class AndConditionEditor : public CompoundConditionEditor { diff --git a/src/ThemeBuilder/components/stylers/CompoundStylerEditor.cpp b/src/ThemeBuilder/components/stylers/CompoundStylerEditor.cpp index 90d19a68..698cc699 100644 --- a/src/ThemeBuilder/components/stylers/CompoundStylerEditor.cpp +++ b/src/ThemeBuilder/components/stylers/CompoundStylerEditor.cpp @@ -7,7 +7,7 @@ #include "PaddingStylerEditor.h" #include "PreferredSizeStylerEditor.h" #include "cru/base/ClonePtr.h" -#include "cru/ui/DeleteLater.h" +#include "cru/platform/gui/DeleteLater.h" #include "cru/ui/ThemeManager.h" #include "cru/ui/style/Styler.h" @@ -71,7 +71,7 @@ CompoundStylerEditor::CompoundStylerEditor() { this->children_container_.RemoveChildAt(index); RaiseChangeEvent(); }); - children_.push_back(ui::ToDeleteLaterPtr(std::move(editor))); + children_.push_back(platform::gui::ToDeleteLaterPtr(std::move(editor))); children_container_.AddChild(editor->GetRootControl()); RaiseChangeEvent(); } @@ -100,7 +100,7 @@ void CompoundStylerEditor::SetValue(ui::style::CompoundStyler* value, this->children_container_.RemoveChildAt(index); RaiseChangeEvent(); }); - children_.push_back(ui::ToDeleteLaterPtr(std::move(editor))); + children_.push_back(platform::gui::ToDeleteLaterPtr(std::move(editor))); children_container_.AddChild(children_.back()->GetRootControl()); } } diff --git a/src/ThemeBuilder/components/stylers/CompoundStylerEditor.h b/src/ThemeBuilder/components/stylers/CompoundStylerEditor.h index f9265fbf..454b3622 100644 --- a/src/ThemeBuilder/components/stylers/CompoundStylerEditor.h +++ b/src/ThemeBuilder/components/stylers/CompoundStylerEditor.h @@ -1,7 +1,7 @@ #pragma once #include "StylerEditor.h" #include "cru/base/ClonePtr.h" -#include "cru/ui/DeleteLater.h" +#include "cru/platform/gui/DeleteLater.h" #include "cru/ui/components/PopupButton.h" #include "cru/ui/controls/FlexLayout.h" #include "cru/ui/style/Styler.h" @@ -24,7 +24,7 @@ class CompoundStylerEditor : public StylerEditor { private: ui::controls::FlexLayout children_container_; - std::vector<ui::DeleteLaterPtr<StylerEditor>> children_; + std::vector<platform::gui::DeleteLaterPtr<StylerEditor>> children_; ui::components::PopupMenuIconButton add_child_button_; }; } // namespace cru::theme_builder::components::stylers diff --git a/src/platform/gui/UiApplication.cpp b/src/platform/gui/UiApplication.cpp index f035224f..56570125 100644 --- a/src/platform/gui/UiApplication.cpp +++ b/src/platform/gui/UiApplication.cpp @@ -1,9 +1,23 @@ #include "cru/platform/gui/UiApplication.h" - #include "cru/base/Base.h" +#include <unordered_set> + namespace cru::platform::gui { +void DeleteLaterPool::Add(Object* object) { pool_.push_back(object); } + +void DeleteLaterPool::Clean() { + std::unordered_set<Object*> deleted; + for (auto object : pool_) { + if (!deleted.contains(object)) { + deleted.insert(object); + delete object; + } + } + pool_.clear(); +} + namespace { IUiApplication* instance = nullptr; } @@ -12,7 +26,7 @@ IUiApplication* IUiApplication::GetInstance() { return instance; } IUiApplication::IUiApplication() { if (instance) { - throw std::runtime_error("An ui application has already been created."); + throw Exception("A ui application has already been created."); } instance = this; diff --git a/src/platform/gui/win/UiApplication.cpp b/src/platform/gui/win/UiApplication.cpp index eb85ef90..e1c21d59 100644 --- a/src/platform/gui/win/UiApplication.cpp +++ b/src/platform/gui/win/UiApplication.cpp @@ -71,6 +71,8 @@ int WinUiApplication::Run() { break; } } + + delete_later_pool_.Clean(); } for (const auto& handler : quit_handlers_) handler(); @@ -103,6 +105,10 @@ long long WinUiApplication::SetInterval(std::chrono::milliseconds milliseconds, void WinUiApplication::CancelTimer(long long id) { timers_.Remove(id); } +void WinUiApplication::DeleteLater(Object* object) { + delete_later_pool_.Add(object); +} + std::vector<INativeWindow*> WinUiApplication::GetAllWindow() { std::vector<INativeWindow*> result; for (const auto w : windows_) { diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index e931b678..d2188e0b 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -1,5 +1,4 @@ add_library(CruUi - DeleteLater.cpp Helper.cpp ThemeManager.cpp ThemeResourceDictionary.cpp diff --git a/src/ui/DeleteLater.cpp b/src/ui/DeleteLater.cpp deleted file mode 100644 index 90b07b71..00000000 --- a/src/ui/DeleteLater.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "cru/ui/DeleteLater.h" - -#include "Helper.h" -#include "cru/base/log/Logger.h" -#include "cru/platform/gui/UiApplication.h" - -namespace cru::ui { - -DeleteLaterImpl::DeleteLaterImpl() : delete_later_scheduled_(false) {} - -DeleteLaterImpl::~DeleteLaterImpl() { - CRU_LOG_TAG_DEBUG("Delete later object being deleted {}.", - static_cast<void*>(this)); -} - -void DeleteLaterImpl::DeleteLater() { - if (!delete_later_scheduled_) { - CRU_LOG_TAG_DEBUG("Schedule delete later {}.", static_cast<void*>(this)); - GetUiApplication()->SetImmediate([this] { delete this; }); - delete_later_scheduled_ = true; - } -} -} // namespace cru::ui diff --git a/test/platform/CMakeLists.txt b/test/platform/CMakeLists.txt index e4237cd3..ea6493c4 100644 --- a/test/platform/CMakeLists.txt +++ b/test/platform/CMakeLists.txt @@ -1,5 +1,6 @@ add_executable(CruPlatformBaseTest ColorTest.cpp + DeleteLaterTest.cpp MatrixTest.cpp ) target_link_libraries(CruPlatformBaseTest PRIVATE CruPlatformBase CruTestBase) diff --git a/test/ui/DeleteLaterTest.cpp b/test/platform/DeleteLaterTest.cpp index c9d600de..932ac357 100644 --- a/test/ui/DeleteLaterTest.cpp +++ b/test/platform/DeleteLaterTest.cpp @@ -1,4 +1,4 @@ -#include "cru/ui/DeleteLater.h" +#include "cru/platform/gui/DeleteLater.h" #include <catch2/catch_test_macros.hpp> @@ -9,7 +9,7 @@ struct MockDeleteLater { }; TEST_CASE("DeleteLaterPtr should work.", "[delete-later]") { - auto ptr = cru::ui::MakeDeleteLater<MockDeleteLater>(); + auto ptr = cru::platform::gui::MakeDeleteLater<MockDeleteLater>(); auto p = ptr.get(); ptr.reset(); REQUIRE(p->triggered); diff --git a/test/ui/CMakeLists.txt b/test/ui/CMakeLists.txt index 66a7cd27..e69de29b 100644 --- a/test/ui/CMakeLists.txt +++ b/test/ui/CMakeLists.txt @@ -1,6 +0,0 @@ -add_executable(CruUiTest - DeleteLaterTest.cpp -) -target_link_libraries(CruUiTest PRIVATE CruUi CruTestBase) - -cru_catch_discover_tests(CruUiTest) |
