mirror of https://github.com/odrling/Aegisub
Add a generic function for invoking functions on the GUI thread
This commit is contained in:
parent
1d020b851e
commit
947dc537d1
|
@ -223,9 +223,6 @@ namespace Automation4 {
|
|||
}
|
||||
|
||||
// ProgressSink
|
||||
wxDEFINE_EVENT(EVT_SHOW_DIALOG, wxThreadEvent);
|
||||
wxDEFINE_EVENT(EVT_SHOW_SCRIPT_DIALOG, wxThreadEvent);
|
||||
|
||||
ProgressSink::ProgressSink(agi::ProgressSink *impl, BackgroundScriptRunner *bsr)
|
||||
: impl(impl)
|
||||
, bsr(bsr)
|
||||
|
@ -235,74 +232,35 @@ namespace Automation4 {
|
|||
|
||||
void ProgressSink::ShowDialog(ScriptDialog *config_dialog)
|
||||
{
|
||||
wxSemaphore sema(0, 1);
|
||||
wxThreadEvent *evt = new wxThreadEvent(EVT_SHOW_SCRIPT_DIALOG);
|
||||
evt->SetPayload(std::make_pair(config_dialog, &sema));
|
||||
bsr->QueueEvent(evt);
|
||||
sema.Wait();
|
||||
InvokeOnMainThread([=] {
|
||||
wxDialog w; // container dialog box
|
||||
w.SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
|
||||
w.Create(bsr->GetParentWindow(), -1, bsr->GetTitle());
|
||||
wxBoxSizer *s = new wxBoxSizer(wxHORIZONTAL); // sizer for putting contents in
|
||||
wxWindow *ww = config_dialog->CreateWindow(&w); // generate actual dialog contents
|
||||
s->Add(ww, 0, wxALL, 5); // add contents to dialog
|
||||
w.SetSizerAndFit(s);
|
||||
w.CenterOnParent();
|
||||
w.ShowModal();
|
||||
});
|
||||
}
|
||||
|
||||
int ProgressSink::ShowDialog(wxDialog *dialog)
|
||||
{
|
||||
int ret = 0;
|
||||
wxSemaphore sema(0, 1);
|
||||
wxThreadEvent *evt = new wxThreadEvent(EVT_SHOW_DIALOG);
|
||||
evt->SetPayload(std::make_tuple(dialog, &sema, &ret));
|
||||
bsr->QueueEvent(evt);
|
||||
sema.Wait();
|
||||
InvokeOnMainThread([&] { ret = dialog->ShowModal(); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
BackgroundScriptRunner::BackgroundScriptRunner(wxWindow *parent, wxString const& title)
|
||||
: impl(new DialogProgress(parent, title))
|
||||
{
|
||||
impl->Bind(EVT_SHOW_DIALOG, &BackgroundScriptRunner::OnDialog, this);
|
||||
impl->Bind(EVT_SHOW_SCRIPT_DIALOG, &BackgroundScriptRunner::OnScriptDialog, this);
|
||||
}
|
||||
|
||||
BackgroundScriptRunner::~BackgroundScriptRunner()
|
||||
{
|
||||
}
|
||||
|
||||
void BackgroundScriptRunner::OnScriptDialog(wxThreadEvent &evt)
|
||||
{
|
||||
std::pair<ScriptDialog*, wxSemaphore*> payload = evt.GetPayload<std::pair<ScriptDialog*, wxSemaphore*> >();
|
||||
|
||||
wxDialog w; // container dialog box
|
||||
w.SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
|
||||
w.Create(impl.get(), -1, impl->GetTitle());
|
||||
wxBoxSizer *s = new wxBoxSizer(wxHORIZONTAL); // sizer for putting contents in
|
||||
wxWindow *ww = payload.first->CreateWindow(&w); // generate actual dialog contents
|
||||
s->Add(ww, 0, wxALL, 5); // add contents to dialog
|
||||
w.SetSizerAndFit(s);
|
||||
w.CenterOnParent();
|
||||
w.ShowModal();
|
||||
|
||||
// Tell the calling thread it can wake up now
|
||||
payload.second->Post();
|
||||
}
|
||||
|
||||
void BackgroundScriptRunner::OnDialog(wxThreadEvent &evt)
|
||||
{
|
||||
using namespace std;
|
||||
tuple<wxDialog*, wxSemaphore*, int*> payload = evt.GetPayload<tuple<wxDialog*, wxSemaphore*, int*> >();
|
||||
*get<2>(payload) = get<0>(payload)->ShowModal();
|
||||
get<1>(payload)->Post();
|
||||
}
|
||||
|
||||
void BackgroundScriptRunner::QueueEvent(wxEvent *evt)
|
||||
{
|
||||
wxQueueEvent(impl.get(), evt);
|
||||
}
|
||||
|
||||
// Convert a function taking an Automation4::ProgressSink to one taking an
|
||||
// agi::ProgressSink so that we can pass it to an agi::BackgroundWorker
|
||||
static void progress_sink_wrapper(std::function<void (ProgressSink*)> task, agi::ProgressSink *ps, BackgroundScriptRunner *bsr)
|
||||
{
|
||||
ProgressSink aps(ps, bsr);
|
||||
task(&aps);
|
||||
}
|
||||
|
||||
void BackgroundScriptRunner::Run(std::function<void (ProgressSink*)> task)
|
||||
{
|
||||
int prio = OPT_GET("Automation/Thread Priority")->GetInt();
|
||||
|
@ -311,7 +269,10 @@ namespace Automation4 {
|
|||
else if (prio == 2) prio = 10; // lowest
|
||||
else prio = 50; // fallback normal
|
||||
|
||||
impl->Run(bind(progress_sink_wrapper, task, std::placeholders::_1, this), prio);
|
||||
impl->Run([&](agi::ProgressSink *ps) {
|
||||
ProgressSink aps(ps, this);
|
||||
task(&aps);
|
||||
}, prio);
|
||||
}
|
||||
|
||||
wxWindow *BackgroundScriptRunner::GetParentWindow() const
|
||||
|
@ -319,6 +280,11 @@ namespace Automation4 {
|
|||
return impl.get();
|
||||
}
|
||||
|
||||
wxString BackgroundScriptRunner::GetTitle() const
|
||||
{
|
||||
return impl->GetTitle();
|
||||
}
|
||||
|
||||
// Script
|
||||
Script::Script(wxString const& filename)
|
||||
: filename(filename)
|
||||
|
|
|
@ -124,11 +124,9 @@ namespace Automation4 {
|
|||
class BackgroundScriptRunner {
|
||||
agi::scoped_ptr<DialogProgress> impl;
|
||||
|
||||
void OnDialog(wxThreadEvent &evt);
|
||||
void OnScriptDialog(wxThreadEvent &evt);
|
||||
public:
|
||||
void QueueEvent(wxEvent *evt);
|
||||
wxWindow *GetParentWindow() const;
|
||||
wxString GetTitle() const;
|
||||
|
||||
void Run(std::function<void(ProgressSink*)> task);
|
||||
|
||||
|
|
|
@ -144,6 +144,10 @@ bool AegisubApp::OnInit() {
|
|||
SetAppName("aegisub");
|
||||
#endif
|
||||
|
||||
Bind(EVT_CALL_THUNK, [](wxThreadEvent &evt) {
|
||||
evt.GetPayload<std::function<void()>>()();
|
||||
});
|
||||
|
||||
// logging.
|
||||
agi::log::log = new agi::log::LogSink;
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
#include "compat.h"
|
||||
#include "main.h"
|
||||
|
||||
wxDEFINE_EVENT(EVT_CALL_THUNK, wxThreadEvent);
|
||||
|
||||
wxString MakeRelativePath(wxString _path, wxString reference) {
|
||||
if (_path.empty() || _path[0] == '?') return _path;
|
||||
wxFileName path(_path);
|
||||
|
|
|
@ -39,9 +39,11 @@
|
|||
#include <cstdint>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/thread.h>
|
||||
#endif
|
||||
|
@ -182,3 +184,19 @@ struct cast {
|
|||
return dynamic_cast<Out>(&in);
|
||||
}
|
||||
};
|
||||
|
||||
wxDECLARE_EVENT(EVT_CALL_THUNK, wxThreadEvent);
|
||||
|
||||
template<typename Function>
|
||||
void InvokeOnMainThreadAsync(Function const& f) {
|
||||
wxThreadEvent *evt = new wxThreadEvent(EVT_CALL_THUNK);
|
||||
evt->SetPayload<std::function<void()>>(f);
|
||||
wxTheApp->QueueEvent(evt);
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
void InvokeOnMainThread(Function const& f) {
|
||||
wxSemaphore sema(0, 1);
|
||||
InvokeOnMainThreadAsync([&] { f(); sema.Post(); });
|
||||
sema.Wait();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue