nim_duilib/ui_components/modal_wnd/async_modal_runner.h

84 lines
2.2 KiB
C
Raw Normal View History

2019-04-19 17:19:57 +08:00
// It is difficult to deal with nested modal dialogs. When our UI thread is
// already running a modal loop, if we run a second modal loop while dispatching
// a message, then the modal loops are nested. We cannot quit the outer loop
// util the inner has quit.
//
// To make the problem simple, we try to avoid the nested modal dialogs.
//
// When we want to run a modal dialog, the AsyncModalRunnerManager creates an
// AsyncModalRunner and then run the modal dialog on it.
//
// When the modal dialog ended, the AsyncModalRunner it ran on will destroy
// itself automatically.
//
// When the application wants to quit, it should call
// AsyncModalRunnerManager::CancelModalThenExit to cancel all running modal
// dialogs.
#ifndef NIM_WIN_GUI_MSG_BOX_ASYNC_MODAL_RUNNER_H_
#define NIM_WIN_GUI_MSG_BOX_ASYNC_MODAL_RUNNER_H_
#include "modal_wnd_base.h"
namespace nim_comp {
2019-04-19 17:19:57 +08:00
class AsyncModalRunner : protected nbase::Thread
{
public:
class Delegate
{
public:
virtual void OnThreadWillExit(AsyncModalRunner *runner) = 0;
};
// Once this method is called the runner will take
// the ownership of the dialog
bool DoModal(ModalWndBase *dlg);
void CancelModalThenExit();
2021-09-15 17:37:26 +08:00
template<class _Ty>
friend class Ref_count_obj;
2019-04-19 17:19:57 +08:00
private:
2021-09-15 17:37:26 +08:00
2019-04-19 17:19:57 +08:00
friend class AsyncModalRunnerManager;
friend class std::shared_ptr<AsyncModalRunner>;
friend class std::_Ref_count<AsyncModalRunner>;
2019-04-19 17:19:57 +08:00
AsyncModalRunner(Delegate *delegate);
virtual ~AsyncModalRunner();
void Run();
bool is_running_;
bool quit_posted_;
Delegate *delegate_;
nbase::WaitableEvent event_;
std::unique_ptr<ModalWndBase> modal_dlg_;
};
class AsyncModalRunnerManager : public AsyncModalRunner::Delegate, public nbase::SupportWeakCallback
{
public:
SINGLETON_DEFINE(AsyncModalRunnerManager);
// Once this method is called the runner will take
// the ownership of the dialog
bool DoModal(ModalWndBase *dlg);
void CancelAllThreads();
private:
AsyncModalRunnerManager();
virtual ~AsyncModalRunnerManager();
void OnThreadWillExit(AsyncModalRunner *runner);
void Deregister(AsyncModalRunner *runner);
nbase::NLock threads_lock_;
std::list<std::shared_ptr<AsyncModalRunner> > runners_;
};
}
2019-04-19 17:19:57 +08:00
#endif //NIM_WIN_GUI_MSG_BOX_ASYNC_MODAL_RUNNER_H_