Replace uses of wxThreadEvent with a statically typed event

This commit is contained in:
Thomas Goyne 2015-01-01 08:12:05 -08:00
parent ef4424f5e2
commit 57edbafdda
10 changed files with 88 additions and 39 deletions

View File

@ -20,7 +20,7 @@
#include <boost/gil/gil_all.hpp> #include <boost/gil/gil_all.hpp>
wxDEFINE_EVENT(EVT_COLOR, wxThreadEvent); AGI_DEFINE_EVENT(EVT_COLOR, agi::Color);
ColourButton::ColourButton(wxWindow *parent, wxSize const& size, bool alpha, agi::Color col, wxValidator const& validator) ColourButton::ColourButton(wxWindow *parent, wxSize const& size, bool alpha, agi::Color col, wxValidator const& validator)
: wxButton(parent, -1, "", wxDefaultPosition, wxSize(size.GetWidth() + 6, size.GetHeight() + 6), 0, validator) : wxButton(parent, -1, "", wxDefaultPosition, wxSize(size.GetWidth() + 6, size.GetHeight() + 6), 0, validator)
@ -33,9 +33,8 @@ ColourButton::ColourButton(wxWindow *parent, wxSize const& size, bool alpha, agi
colour = new_color; colour = new_color;
UpdateBitmap(); UpdateBitmap();
wxThreadEvent evt(EVT_COLOR, GetId()); ValueEvent<agi::Color> evt(EVT_COLOR, GetId(), colour);
evt.SetEventObject(this); evt.SetEventObject(this);
evt.SetPayload(colour);
AddPendingEvent(evt); AddPendingEvent(evt);
}); });
}); });
@ -43,7 +42,8 @@ ColourButton::ColourButton(wxWindow *parent, wxSize const& size, bool alpha, agi
void ColourButton::UpdateBitmap() { void ColourButton::UpdateBitmap() {
using namespace boost::gil; using namespace boost::gil;
fill_pixels(interleaved_view(bmp.GetWidth(), bmp.GetHeight(), (bgr8_pixel_t*)bmp.GetData(), 3 * bmp.GetWidth()), fill_pixels(interleaved_view(bmp.GetWidth(), bmp.GetHeight(),
(bgr8_pixel_t*)bmp.GetData(), 3 * bmp.GetWidth()),
bgr8_pixel_t(colour.r, colour.g, colour.b)); bgr8_pixel_t(colour.r, colour.g, colour.b));
SetBitmapLabel(bmp); SetBitmapLabel(bmp);
} }

View File

@ -18,9 +18,11 @@
#include <libaegisub/color.h> #include <libaegisub/color.h>
#include "value_event.h"
/// Emitted by ColourButton when the user picks a new color, with the chosen /// Emitted by ColourButton when the user picks a new color, with the chosen
/// color set to the event payload /// color set to the event payload
wxDECLARE_EVENT(EVT_COLOR, wxThreadEvent); AGI_DECLARE_EVENT(EVT_COLOR, agi::Color);
/// A button which displays a currently-selected color and lets the user pick /// A button which displays a currently-selected color and lets the user pick
/// a new color when clicked /// a new color when clicked

View File

@ -34,6 +34,7 @@
#include "options.h" #include "options.h"
#include "persist_location.h" #include "persist_location.h"
#include "utils.h" #include "utils.h"
#include "value_event.h"
#include <libaegisub/scoped_ptr.h> #include <libaegisub/scoped_ptr.h>
#include <libaegisub/make_unique.h> #include <libaegisub/make_unique.h>
@ -236,7 +237,7 @@ public:
#define STATIC_BORDER_FLAG wxSIMPLE_BORDER #define STATIC_BORDER_FLAG wxSIMPLE_BORDER
#endif #endif
wxDEFINE_EVENT(EVT_RECENT_SELECT, wxThreadEvent); wxDEFINE_EVENT(EVT_RECENT_SELECT, ValueEvent<agi::Color>);
/// @class ColorPickerRecent /// @class ColorPickerRecent
/// @brief A grid of recently used colors which can be selected by clicking on them /// @brief A grid of recently used colors which can be selected by clicking on them
@ -255,11 +256,8 @@ class ColorPickerRecent final : public wxStaticBitmap {
if (cx < 0 || cx > cols || cy < 0 || cy > rows) return; if (cx < 0 || cx > cols || cy < 0 || cy > rows) return;
int i = cols*cy + cx; int i = cols*cy + cx;
if (i >= 0 && i < (int)colors.size()) { if (i >= 0 && i < (int)colors.size())
wxThreadEvent evnt(EVT_RECENT_SELECT, GetId()); AddPendingEvent(ValueEvent<agi::Color>(EVT_RECENT_SELECT, GetId(), colors[i]));
evnt.SetPayload(colors[i]);
AddPendingEvent(evnt);
}
} }
void UpdateBitmap() { void UpdateBitmap() {
@ -331,7 +329,7 @@ public:
} }
}; };
wxDEFINE_EVENT(EVT_DROPPER_SELECT, wxThreadEvent); wxDEFINE_EVENT(EVT_DROPPER_SELECT, ValueEvent<agi::Color>);
class ColorPickerScreenDropper final : public wxControl { class ColorPickerScreenDropper final : public wxControl {
wxBitmap capture; wxBitmap capture;
@ -349,8 +347,7 @@ class ColorPickerScreenDropper final : public wxControl {
agi::Color color(pdi.Red(), pdi.Green(), pdi.Blue(), 0); agi::Color color(pdi.Red(), pdi.Green(), pdi.Blue(), 0);
wxThreadEvent evnt(EVT_DROPPER_SELECT, GetId()); wxThreadEvent evnt(EVT_DROPPER_SELECT, GetId());
evnt.SetPayload(color); AddPendingEvent(ValueEvent<agi::Color>(EVT_DROPPER_SELECT, GetId(), color));
AddPendingEvent(evnt);
} }
} }
@ -500,7 +497,7 @@ class DialogColorPicker final : public wxDialog {
void OnSpectrumChange(wxCommandEvent &evt); void OnSpectrumChange(wxCommandEvent &evt);
void OnSliderChange(wxCommandEvent &evt); void OnSliderChange(wxCommandEvent &evt);
void OnAlphaSliderChange(wxCommandEvent &evt); void OnAlphaSliderChange(wxCommandEvent &evt);
void OnRecentSelect(wxThreadEvent &evt); // also handles dropper pick void OnRecentSelect(ValueEvent<agi::Color>& evt); // also handles dropper pick
void OnDropperMouse(wxMouseEvent &evt); void OnDropperMouse(wxMouseEvent &evt);
void OnMouse(wxMouseEvent &evt); void OnMouse(wxMouseEvent &evt);
void OnCaptureLost(wxMouseCaptureLostEvent&); void OnCaptureLost(wxMouseCaptureLostEvent&);
@ -1045,8 +1042,8 @@ void DialogColorPicker::OnAlphaSliderChange(wxCommandEvent &) {
callback(cur_color); callback(cur_color);
} }
void DialogColorPicker::OnRecentSelect(wxThreadEvent &evt) { void DialogColorPicker::OnRecentSelect(ValueEvent<agi::Color> &evt) {
agi::Color new_color = evt.GetPayload<agi::Color>(); agi::Color new_color = evt.Get();
new_color.a = cur_color.a; new_color.a = cur_color.a;
SetColor(new_color); SetColor(new_color);
} }

View File

@ -136,7 +136,7 @@ DialogDummyVideo::DialogDummyVideo(wxWindow *parent)
d.CenterOnParent(); d.CenterOnParent();
d.Bind(wxEVT_COMBOBOX, &DialogDummyVideo::OnResolutionShortcut, this); d.Bind(wxEVT_COMBOBOX, &DialogDummyVideo::OnResolutionShortcut, this);
color_btn->Bind(EVT_COLOR, [=](wxThreadEvent& e) { color = color_btn->GetColor(); }); color_btn->Bind(EVT_COLOR, [=](ValueEvent<agi::Color>& e) { color = e.Get(); });
d.Bind(wxEVT_SPINCTRL, [&](wxCommandEvent&) { d.Bind(wxEVT_SPINCTRL, [&](wxCommandEvent&) {
d.TransferDataFromWindow(); d.TransferDataFromWindow();
UpdateLengthDisplay(); UpdateLengthDisplay();

View File

@ -24,6 +24,7 @@
#include "libresrc/libresrc.h" #include "libresrc/libresrc.h"
#include "options.h" #include "options.h"
#include "utils.h" #include "utils.h"
#include "value_event.h"
#include <libaegisub/dispatch.h> #include <libaegisub/dispatch.h>
#include <libaegisub/format_path.h> #include <libaegisub/format_path.h>
@ -63,7 +64,7 @@ class DialogFontsCollector final : public wxDialog {
void OnRadio(wxCommandEvent &e); void OnRadio(wxCommandEvent &e);
/// Append text to log message from worker thread /// Append text to log message from worker thread
void OnAddText(wxThreadEvent &event); void OnAddText(ValueEvent<std::pair<int, wxString>>& event);
/// Collection complete notification from the worker thread to reenable buttons /// Collection complete notification from the worker thread to reenable buttons
void OnCollectionComplete(wxThreadEvent &); void OnCollectionComplete(wxThreadEvent &);
@ -79,15 +80,14 @@ enum FcMode {
SymlinkToFolder = 4 SymlinkToFolder = 4
}; };
wxDEFINE_EVENT(EVT_ADD_TEXT, wxThreadEvent); using color_str_pair = std::pair<int, wxString>;
wxDEFINE_EVENT(EVT_ADD_TEXT, ValueEvent<color_str_pair>);
wxDEFINE_EVENT(EVT_COLLECTION_DONE, wxThreadEvent); wxDEFINE_EVENT(EVT_COLLECTION_DONE, wxThreadEvent);
void FontsCollectorThread(AssFile *subs, agi::fs::path const& destination, FcMode oper, wxEvtHandler *collector) { void FontsCollectorThread(AssFile *subs, agi::fs::path const& destination, FcMode oper, wxEvtHandler *collector) {
agi::dispatch::Background().Async([=]{ agi::dispatch::Background().Async([=]{
auto AppendText = [&](wxString text, int colour) { auto AppendText = [&](wxString text, int colour) {
wxThreadEvent event(EVT_ADD_TEXT); collector->AddPendingEvent(ValueEvent<color_str_pair>(EVT_ADD_TEXT, -1, {colour, text.Clone()}));
event.SetPayload(std::make_pair(colour, text));
collector->AddPendingEvent(event);
}; };
auto paths = FontCollector(AppendText).GetFontPaths(subs); auto paths = FontCollector(AppendText).GetFontPaths(subs);
@ -378,8 +378,8 @@ void DialogFontsCollector::OnRadio(wxCommandEvent &) {
} }
} }
void DialogFontsCollector::OnAddText(wxThreadEvent &event) { void DialogFontsCollector::OnAddText(ValueEvent<color_str_pair> &event) {
std::pair<int, wxString> str = event.GetPayload<std::pair<int, wxString>>(); auto const& str = event.Get();
collection_log->SetReadOnly(false); collection_log->SetReadOnly(false);
int pos = collection_log->GetLength(); int pos = collection_log->GetLength();
auto const& utf8 = str.second.utf8_str(); auto const& utf8 = str.second.utf8_str();

View File

@ -32,13 +32,14 @@
/// @ingroup style_editor /// @ingroup style_editor
/// ///
#include "dialog_style_editor.h"
#include "ass_dialogue.h" #include "ass_dialogue.h"
#include "ass_file.h" #include "ass_file.h"
#include "ass_style.h" #include "ass_style.h"
#include "ass_style_storage.h" #include "ass_style_storage.h"
#include "colour_button.h" #include "colour_button.h"
#include "compat.h" #include "compat.h"
#include "dialog_style_editor.h"
#include "help_button.h" #include "help_button.h"
#include "include/aegisub/context.h" #include "include/aegisub/context.h"
#include "libresrc/libresrc.h" #include "libresrc/libresrc.h"
@ -487,7 +488,7 @@ void DialogStyleEditor::UpdateWorkStyle() {
work->strikeout = BoxStrikeout->IsChecked(); work->strikeout = BoxStrikeout->IsChecked();
} }
void DialogStyleEditor::OnSetColor(wxThreadEvent&) { void DialogStyleEditor::OnSetColor(ValueEvent<agi::Color>&) {
TransferDataFromWindow(); TransferDataFromWindow();
SubsPreview->SetStyle(*work); SubsPreview->SetStyle(*work);
} }
@ -503,9 +504,9 @@ void DialogStyleEditor::OnPreviewTextChange (wxCommandEvent &event) {
event.Skip(); event.Skip();
} }
void DialogStyleEditor::OnPreviewColourChange(wxThreadEvent &evt) { void DialogStyleEditor::OnPreviewColourChange(ValueEvent<agi::Color> &evt) {
SubsPreview->SetColour(evt.GetPayload<agi::Color>()); SubsPreview->SetColour(evt.Get());
OPT_SET("Colour/Style Editor/Background/Preview")->SetColor(evt.GetPayload<agi::Color>()); OPT_SET("Colour/Style Editor/Background/Preview")->SetColor(evt.Get());
} }
void DialogStyleEditor::OnCommandPreviewUpdate(wxCommandEvent &event) { void DialogStyleEditor::OnCommandPreviewUpdate(wxCommandEvent &event) {

View File

@ -45,7 +45,8 @@ class wxSpinCtrl;
class wxTextCtrl; class wxTextCtrl;
class wxThreadEvent; class wxThreadEvent;
class wxWindow; class wxWindow;
namespace agi { struct Context; } namespace agi { struct Context; struct Color; }
template<typename T> class ValueEvent;
class DialogStyleEditor final : public wxDialog { class DialogStyleEditor final : public wxDialog {
agi::Context *c; agi::Context *c;
@ -90,14 +91,14 @@ class DialogStyleEditor final : public wxDialog {
void OnCommandPreviewUpdate(wxCommandEvent &event); void OnCommandPreviewUpdate(wxCommandEvent &event);
void OnPreviewTextChange(wxCommandEvent &event); void OnPreviewTextChange(wxCommandEvent &event);
void OnPreviewColourChange(wxThreadEvent &event); void OnPreviewColourChange(ValueEvent<agi::Color> &event);
/// @brief Maybe apply changes and maybe close the dialog /// @brief Maybe apply changes and maybe close the dialog
/// @param apply Should changes be applied? /// @param apply Should changes be applied?
/// @param close Should the dialog be closed? /// @param close Should the dialog be closed?
void Apply(bool apply,bool close); void Apply(bool apply,bool close);
/// @brief Sets color for one of the four color buttons /// @brief Sets color for one of the four color buttons
void OnSetColor(wxThreadEvent& evt); void OnSetColor(ValueEvent<agi::Color>& evt);
public: public:
DialogStyleEditor(wxWindow *parent, AssStyle *style, agi::Context *c, AssStyleStorage *store, std::string const& new_name, wxArrayString const& font_list); DialogStyleEditor(wxWindow *parent, AssStyle *style, agi::Context *c, AssStyleStorage *store, std::string const& new_name, wxArrayString const& font_list);

View File

@ -53,6 +53,7 @@
#include "subs_controller.h" #include "subs_controller.h"
#include "subtitles_provider_libass.h" #include "subtitles_provider_libass.h"
#include "utils.h" #include "utils.h"
#include "value_event.h"
#include "version.h" #include "version.h"
#include <libaegisub/dispatch.h> #include <libaegisub/dispatch.h>
@ -99,7 +100,9 @@ AegisubApp::AegisubApp() {
wxSetEnv("UBUNTU_MENUPROXY", "0"); wxSetEnv("UBUNTU_MENUPROXY", "0");
} }
wxDEFINE_EVENT(EVT_CALL_THUNK, wxThreadEvent); namespace {
wxDEFINE_EVENT(EVT_CALL_THUNK, ValueEvent<agi::dispatch::Thunk>);
}
/// Message displayed when an exception has occurred. /// Message displayed when an exception has occurred.
static wxString exception_message = "Oops, Aegisub has crashed!\n\nAn attempt has been made to save a copy of your file to:\n\n%s\n\nAegisub will now close."; static wxString exception_message = "Oops, Aegisub has crashed!\n\nAn attempt has been made to save a copy of your file to:\n\n%s\n\nAegisub will now close.";
@ -146,14 +149,13 @@ bool AegisubApp::OnInit() {
// Pointless `this` capture required due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51494 // Pointless `this` capture required due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51494
agi::dispatch::Init([this](agi::dispatch::Thunk f) { agi::dispatch::Init([this](agi::dispatch::Thunk f) {
auto evt = new wxThreadEvent(EVT_CALL_THUNK); auto evt = new ValueEvent<agi::dispatch::Thunk>(EVT_CALL_THUNK, -1, std::move(f));
evt->SetPayload(f);
wxTheApp->QueueEvent(evt); wxTheApp->QueueEvent(evt);
}); });
wxTheApp->Bind(EVT_CALL_THUNK, [this](wxThreadEvent &evt) { wxTheApp->Bind(EVT_CALL_THUNK, [this](ValueEvent<agi::dispatch::Thunk>& evt) {
try { try {
evt.GetPayload<std::function<void()>>()(); evt.Get()();
} }
catch (...) { catch (...) {
OnExceptionInMainLoop(); OnExceptionInMainLoop();

View File

@ -57,7 +57,7 @@ OPTION_UPDATER(IntUpdater, wxSpinEvent, OptionValueInt, evt.GetInt());
OPTION_UPDATER(IntCBUpdater, wxCommandEvent, OptionValueInt, evt.GetInt()); OPTION_UPDATER(IntCBUpdater, wxCommandEvent, OptionValueInt, evt.GetInt());
OPTION_UPDATER(DoubleUpdater, wxSpinEvent, OptionValueDouble, evt.GetInt()); OPTION_UPDATER(DoubleUpdater, wxSpinEvent, OptionValueDouble, evt.GetInt());
OPTION_UPDATER(BoolUpdater, wxCommandEvent, OptionValueBool, !!evt.GetInt()); OPTION_UPDATER(BoolUpdater, wxCommandEvent, OptionValueBool, !!evt.GetInt());
OPTION_UPDATER(ColourUpdater, wxThreadEvent, OptionValueColor, evt.GetPayload<agi::Color>()); OPTION_UPDATER(ColourUpdater, ValueEvent<agi::Color>, OptionValueColor, evt.Get());
static void browse_button(wxTextCtrl *ctrl) { static void browse_button(wxTextCtrl *ctrl) {
wxDirDialog dlg(nullptr, _("Please choose the folder:"), config::path->Decode(from_wx(ctrl->GetValue())).wstring()); wxDirDialog dlg(nullptr, _("Please choose the folder:"), config::path->Decode(from_wx(ctrl->GetValue())).wstring());

46
src/value_event.h Normal file
View File

@ -0,0 +1,46 @@
// Copyright (c) 2015, Thomas Goyne <plorkyeran@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Aegisub Project http://www.aegisub.org/
#pragma once
#include <wx/event.h>
/// A wxEvent which holds a single templated value
template<typename T>
class ValueEvent : public wxEvent {
const T value;
public:
ValueEvent(wxEventType type, int id, T value)
: wxEvent(id, type)
, value(std::move(value))
{ }
wxEvent *Clone() const override;
T const& Get() const { return value; }
};
// Defined out-of-line so that `extern template` can suppress the emission of
// the vtable in every object file that includes the declaration
template<typename T>
wxEvent *ValueEvent<T>::Clone() const { return new ValueEvent<T>(*this); }
#define AGI_DECLARE_EVENT(evt_type, value_type) \
wxDECLARE_EVENT(evt_type, ValueEvent<value_type>); \
extern template class ValueEvent<value_type>;
#define AGI_DEFINE_EVENT(evt_type, value_type) \
wxDEFINE_EVENT(evt_type, ValueEvent<value_type>); \
template class ValueEvent<value_type>;