2012-03-09 01:23:41 +01:00
|
|
|
// Copyright (c) 2012, 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.
|
|
|
|
|
|
|
|
/// @file dialog_manager.h
|
|
|
|
/// @brief Manager for dialogs
|
|
|
|
/// @ingroup utility
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <typeinfo>
|
2012-03-10 03:15:58 +01:00
|
|
|
|
|
|
|
#include <wx/dialog.h>
|
2012-03-09 01:23:41 +01:00
|
|
|
|
2012-06-07 04:48:13 +02:00
|
|
|
#include "utils.h"
|
|
|
|
|
2012-03-09 01:23:41 +01:00
|
|
|
/// @brief A manager for dialogs
|
|
|
|
///
|
|
|
|
/// DialogManager keeps track of modal and modeless dialogs which have been
|
|
|
|
/// created, so that commands can be send to the appropriate places and so that
|
|
|
|
/// the same dialog can't be opened twice at once.
|
|
|
|
class DialogManager {
|
|
|
|
/// Comparer for pointers to std::type_info
|
|
|
|
struct type_info_lt {
|
|
|
|
bool operator()(const std::type_info *lft, const std::type_info *rgt) const {
|
|
|
|
return !!lft->before(*rgt);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::map<const std::type_info *, wxDialog *, type_info_lt> DialogMap;
|
|
|
|
|
|
|
|
/// Dialogs which currently exist
|
|
|
|
DialogMap created_dialogs;
|
|
|
|
|
|
|
|
/// Close handler which deletes and unregisters closed modeless dialogs
|
2013-07-09 17:33:04 +02:00
|
|
|
template<typename Event>
|
|
|
|
void OnClose(Event &evt) {
|
2012-03-09 01:23:41 +01:00
|
|
|
evt.Skip();
|
2013-07-09 17:33:04 +02:00
|
|
|
auto dialog = static_cast<wxWindow *>(evt.GetEventObject());
|
|
|
|
while (!dialog->IsTopLevel()) dialog = dialog->GetParent();
|
2012-03-09 01:23:41 +01:00
|
|
|
dialog->Destroy();
|
|
|
|
|
2012-12-23 00:35:13 +01:00
|
|
|
for (auto it = created_dialogs.begin(); it != created_dialogs.end(); ++it) {
|
2012-03-09 01:23:41 +01:00
|
|
|
if (it->second == dialog) {
|
|
|
|
created_dialogs.erase(it);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
/// Show a modeless dialog of the given type, creating it if needed
|
|
|
|
/// @tparam DialogType Type of dialog to show
|
|
|
|
template<class DialogType>
|
|
|
|
void Show(agi::Context *c) {
|
2012-12-23 00:35:13 +01:00
|
|
|
auto it = created_dialogs.find(&typeid(DialogType));
|
2012-03-09 01:23:41 +01:00
|
|
|
|
|
|
|
if (it != created_dialogs.end()) {
|
|
|
|
it->second->Show();
|
|
|
|
it->second->SetFocus();
|
|
|
|
}
|
|
|
|
else {
|
2012-05-18 16:01:56 +02:00
|
|
|
try {
|
|
|
|
wxDialog *d = new DialogType(c);
|
|
|
|
created_dialogs[&typeid(DialogType)] = d;
|
2013-07-09 17:33:04 +02:00
|
|
|
d->Bind(wxEVT_CLOSE_WINDOW, &DialogManager::OnClose<wxCloseEvent>, this);
|
2013-12-12 03:25:13 +01:00
|
|
|
d->Bind(wxEVT_BUTTON, &DialogManager::OnClose<wxCommandEvent>, this, wxID_CANCEL);
|
2012-05-18 16:01:56 +02:00
|
|
|
d->Show();
|
2012-06-07 04:48:13 +02:00
|
|
|
SetFloatOnParent(d);
|
2012-05-18 16:01:56 +02:00
|
|
|
}
|
|
|
|
catch (agi::UserCancelException const&) { }
|
2012-03-09 01:23:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Show a modal dialog of the given type, creating it if needed
|
|
|
|
/// @tparam DialogType Type of dialog to show
|
|
|
|
template<class DialogType>
|
|
|
|
void ShowModal(agi::Context *c) {
|
|
|
|
DialogType diag(c);
|
|
|
|
created_dialogs[&typeid(DialogType)] = &diag;
|
|
|
|
try {
|
|
|
|
diag.ShowModal();
|
|
|
|
}
|
|
|
|
catch (...) {
|
|
|
|
created_dialogs.erase(&typeid(DialogType));
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
created_dialogs.erase(&typeid(DialogType));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get the dialog of the given type
|
|
|
|
/// @tparam DialogType Type of dialog to get
|
2012-11-13 17:51:01 +01:00
|
|
|
/// @return A pointer to a DialogType or nullptr if no dialog of the given type has been created
|
2012-03-09 01:23:41 +01:00
|
|
|
template<class DialogType>
|
|
|
|
DialogType *Get() const {
|
2013-09-16 21:10:00 +02:00
|
|
|
auto it = created_dialogs.find(&typeid(DialogType));
|
|
|
|
return it != created_dialogs.end() ? static_cast<DialogType*>(it->second) : nullptr;
|
2012-03-09 01:23:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
~DialogManager() {
|
2012-11-04 04:53:03 +01:00
|
|
|
for (auto const& it : created_dialogs) {
|
2013-07-09 17:33:04 +02:00
|
|
|
it.second->Unbind(wxEVT_CLOSE_WINDOW, &DialogManager::OnClose<wxCloseEvent>, this);
|
2013-12-12 03:25:13 +01:00
|
|
|
it.second->Unbind(wxEVT_BUTTON, &DialogManager::OnClose<wxCommandEvent>, this, wxID_CANCEL);
|
2012-11-04 04:53:03 +01:00
|
|
|
it.second->Destroy();
|
2012-03-09 01:23:41 +01:00
|
|
|
}
|
|
|
|
created_dialogs.clear();
|
|
|
|
}
|
|
|
|
};
|