Use signals for selection change notifications

This commit is contained in:
Thomas Goyne 2012-10-04 20:22:54 -07:00
parent a0c92f83f9
commit e4a6092b36
35 changed files with 100 additions and 223 deletions

View File

@ -288,7 +288,7 @@ void AssKaraoke::SplitLines(std::set<AssDialogue*> const& lines, agi::Context *c
AssKaraoke kara;
std::set<AssDialogue*> sel = c->selectionController->GetSelectedSet();
SubtitleSelection sel = c->selectionController->GetSelectedSet();
bool did_split = false;
for (std::list<AssEntry*>::iterator it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) {

View File

@ -69,6 +69,7 @@ AudioKaraoke::AudioKaraoke(wxWindow *parent, agi::Context *c)
, file_changed(c->ass->AddCommitListener(&AudioKaraoke::OnFileChanged, this))
, audio_opened(c->audioController->AddAudioOpenListener(&AudioKaraoke::OnAudioOpened, this))
, audio_closed(c->audioController->AddAudioCloseListener(&AudioKaraoke::OnAudioClosed, this))
, active_line_changed(c->selectionController->AddActiveLineListener(&AudioKaraoke::OnActiveLineChanged, this))
, active_line(0)
, kara(new AssKaraoke)
, scroll_x(0)
@ -106,15 +107,12 @@ AudioKaraoke::AudioKaraoke(wxWindow *parent, agi::Context *c)
split_area->Bind(wxEVT_CONTEXT_MENU, &AudioKaraoke::OnContextMenu, this);
scroll_timer.Bind(wxEVT_TIMER, &AudioKaraoke::OnScrollTimer, this);
c->selectionController->AddSelectionListener(this);
accept_button->Enable(false);
cancel_button->Enable(false);
enabled = false;
}
AudioKaraoke::~AudioKaraoke() {
c->selectionController->RemoveSelectionListener(this);
}
void AudioKaraoke::OnActiveLineChanged(AssDialogue *new_line) {

View File

@ -33,8 +33,6 @@
#include <libaegisub/scoped_ptr.h>
#include <libaegisub/signal.h>
#include "selection_controller.h"
class AssDialogue;
class AssKaraoke;
class wxButton;
@ -72,11 +70,12 @@ namespace agi { struct Context; }
/// actually updated until the line is committed (which if auto-commit timing
/// changes is on, will happen as soon as the user adjusts the timing of the
/// new syllable).
class AudioKaraoke : public wxWindow, private SelectionListener<AssDialogue> {
class AudioKaraoke : public wxWindow {
agi::Context *c; ///< Project context
agi::signal::Connection file_changed; ///< File changed slot
agi::signal::Connection audio_opened; ///< Audio opened connection
agi::signal::Connection audio_closed; ///< Audio closed connection
agi::signal::Connection active_line_changed;
/// Currently active dialogue line
AssDialogue *active_line;
@ -145,7 +144,6 @@ class AudioKaraoke : public wxWindow, private SelectionListener<AssDialogue> {
void OnMouse(wxMouseEvent &event);
void OnPaint(wxPaintEvent &event);
void OnSize(wxSizeEvent &event);
void OnSelectedSetChanged(Selection const&, Selection const&) { }
void OnAudioOpened();
void OnAudioClosed();
void OnScrollTimer(wxTimerEvent &event);

View File

@ -289,7 +289,7 @@ void DialogueTimingMarker::SetPosition(int new_position) {
/// addition, any markers for inactive lines that start/end at the same time
/// as the active line starts/ends can optionally be dragged along with the
/// active line's markers, updating those lines as well.
class AudioTimingControllerDialogue : public AudioTimingController, private SelectionListener<AssDialogue> {
class AudioTimingControllerDialogue : public AudioTimingController {
/// The rendering style for the active line's start marker
Pen style_left;
/// The rendering style for the active line's end marker
@ -338,6 +338,8 @@ class AudioTimingControllerDialogue : public AudioTimingController, private Sele
agi::signal::Connection audio_open_connection;
agi::signal::Connection inactive_line_mode_connection;
agi::signal::Connection inactive_line_comment_connection;
agi::signal::Connection active_line_connection;
agi::signal::Connection selection_connection;
/// Update the audio controller's selection
void UpdateSelection();
@ -349,7 +351,7 @@ class AudioTimingControllerDialogue : public AudioTimingController, private Sele
void RegenerateSelectedLines();
/// Add a line to the list of timeable inactive lines
void AddInactiveLine(Selection const& sel, AssDialogue *diag);
void AddInactiveLine(SubtitleSelection const& sel, AssDialogue *diag);
/// Regenerate the list of active and inactive line markers
void RegenerateMarkers();
@ -377,7 +379,7 @@ class AudioTimingControllerDialogue : public AudioTimingController, private Sele
// SubtitleSelectionListener interface
void OnActiveLineChanged(AssDialogue *new_line);
void OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed);
void OnSelectedSetChanged(const SubtitleSelection &lines_added, const SubtitleSelection &lines_removed);
// AssFile events
void OnFileChanged(int type);
@ -409,8 +411,6 @@ public:
/// Constructor
/// @param c Project context
AudioTimingControllerDialogue(agi::Context *c);
/// Destructor
~AudioTimingControllerDialogue();
};
AudioTimingController *CreateDialogueTimingController(agi::Context *c)
@ -434,8 +434,9 @@ AudioTimingControllerDialogue::AudioTimingControllerDialogue(agi::Context *c)
, commit_connection(c->ass->AddCommitListener(&AudioTimingControllerDialogue::OnFileChanged, this))
, inactive_line_mode_connection(OPT_SUB("Audio/Inactive Lines Display Mode", &AudioTimingControllerDialogue::RegenerateInactiveLines, this))
, inactive_line_comment_connection(OPT_SUB("Audio/Display/Draw/Inactive Comments", &AudioTimingControllerDialogue::RegenerateInactiveLines, this))
, active_line_connection(c->selectionController->AddActiveLineListener(&AudioTimingControllerDialogue::OnActiveLineChanged, this))
, selection_connection(c->selectionController->AddSelectionListener(&AudioTimingControllerDialogue::OnSelectedSetChanged, this))
{
c->selectionController->AddSelectionListener(this);
keyframes_provider.AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
video_position_provider.AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
seconds_provider.AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
@ -443,12 +444,6 @@ AudioTimingControllerDialogue::AudioTimingControllerDialogue(agi::Context *c)
Revert();
}
AudioTimingControllerDialogue::~AudioTimingControllerDialogue()
{
context->selectionController->RemoveSelectionListener(this);
}
void AudioTimingControllerDialogue::GetMarkers(const TimeRange &range, AudioMarkerVector &out_markers) const
{
// The order matters here; later markers are painted on top of earlier
@ -471,7 +466,7 @@ void AudioTimingControllerDialogue::OnActiveLineChanged(AssDialogue *new_line)
Revert();
}
void AudioTimingControllerDialogue::OnSelectedSetChanged(Selection const&, Selection const&)
void AudioTimingControllerDialogue::OnSelectedSetChanged(SubtitleSelection const&, SubtitleSelection const&)
{
RegenerateSelectedLines();
RegenerateInactiveLines();
@ -746,7 +741,7 @@ void AudioTimingControllerDialogue::RegenerateInactiveLines()
bool was_empty = inactive_lines.empty();
inactive_lines.clear();
Selection sel = context->selectionController->GetSelectedSet();
SubtitleSelection sel = context->selectionController->GetSelectedSet();
switch (int mode = inactive_line_mode->GetInt())
{
@ -796,7 +791,7 @@ void AudioTimingControllerDialogue::RegenerateInactiveLines()
RegenerateMarkers();
}
void AudioTimingControllerDialogue::AddInactiveLine(Selection const& sel, AssDialogue *diag)
void AudioTimingControllerDialogue::AddInactiveLine(SubtitleSelection const& sel, AssDialogue *diag)
{
if (sel.count(diag)) return;
@ -810,8 +805,8 @@ void AudioTimingControllerDialogue::RegenerateSelectedLines()
selected_lines.clear();
AssDialogue *active = context->selectionController->GetActiveLine();
Selection sel = context->selectionController->GetSelectedSet();
for (Selection::iterator it = sel.begin(); it != sel.end(); ++it)
SubtitleSelection sel = context->selectionController->GetSelectedSet();
for (SubtitleSelection::iterator it = sel.begin(); it != sel.end(); ++it)
{
if (*it == active) continue;

View File

@ -842,7 +842,7 @@ namespace Automation4 {
static int transform_selection(lua_State *L, const agi::Context *c)
{
std::set<AssDialogue*> sel = c->selectionController->GetSelectedSet();
SubtitleSelection const& sel = c->selectionController->GetSelectedSet();
AssDialogue *active_line = c->selectionController->GetActiveLine();
lua_newtable(L);

View File

@ -1104,12 +1104,11 @@ void BaseGrid::NextLine() {
}
}
void BaseGrid::AnnounceActiveLineChanged(AssDialogue *new_line) {
if (batch_level > 0)
batch_active_line_changed = true;
else
BaseSelectionController<AssDialogue>::AnnounceActiveLineChanged(new_line);
SubtitleSelectionController::AnnounceActiveLineChanged(new_line);
}
void BaseGrid::AnnounceSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed) {
@ -1129,6 +1128,6 @@ void BaseGrid::AnnounceSelectedSetChanged(const Selection &lines_added, const Se
batch_selection_removed.insert(lines_removed.begin(), lines_removed.end());
}
else {
BaseSelectionController<AssDialogue>::AnnounceSelectedSetChanged(lines_added, lines_removed);
SubtitleSelectionController::AnnounceSelectedSetChanged(lines_added, lines_removed);
}
}

View File

@ -55,16 +55,12 @@ namespace agi {
}
class AssDialogue;
typedef SelectionController<AssDialogue> SubtitleSelectionController;
typedef SelectionListener<AssDialogue> SubtitleSelectionListener;
/// DOCME
/// @class BaseGrid
/// @brief DOCME
///
/// DOCME
class BaseGrid : public wxWindow, public BaseSelectionController<AssDialogue> {
class BaseGrid : public wxWindow, public SubtitleSelectionController {
int lineHeight; ///< Height of a line in pixels in the current font
bool holding; ///< Is a drag selection in process?
wxFont font; ///< Current grid font

View File

@ -58,7 +58,6 @@
#include "../video_context.h"
namespace {
typedef SelectionController<AssDialogue>::Selection Selection;
using cmd::Command;
struct validate_audio_open : public Command {
@ -219,11 +218,11 @@ struct audio_save_clip : public Command {
}
void operator()(agi::Context *c) {
Selection sel = c->selectionController->GetSelectedSet();
SubtitleSelection sel = c->selectionController->GetSelectedSet();
if (sel.empty()) return;
AssTime start = INT_MAX, end = 0;
for (Selection::iterator it = sel.begin(); it != sel.end(); ++it) {
for (SubtitleSelection::iterator it = sel.begin(); it != sel.end(); ++it) {
start = std::min(start, (*it)->Start);
end = std::max(end, (*it)->End);
}

View File

@ -223,7 +223,7 @@ struct edit_line_duplicate_shift : public Command {
};
static void combine_lines(agi::Context *c, void (*combiner)(AssDialogue *, AssDialogue *), wxString const& message) {
SelectionController<AssDialogue>::Selection sel = c->selectionController->GetSelectedSet();
SubtitleSelection sel = c->selectionController->GetSelectedSet();
AssDialogue *first = 0;
entryIter out = c->ass->Line.begin();

View File

@ -414,7 +414,7 @@ struct grid_swap : public Command {
}
void operator()(agi::Context *c) {
SelectionController<AssDialogue>::Selection sel = c->selectionController->GetSelectedSet();
SubtitleSelection sel = c->selectionController->GetSelectedSet();
if (sel.size() == 2) {
entryIter a = find(c->ass->Line.begin(), c->ass->Line.end(), *sel.begin());
entryIter b = find(c->ass->Line.begin(), c->ass->Line.end(), *sel.rbegin());

View File

@ -172,7 +172,7 @@ struct subtitle_insert_after : public validate_nonempty_selection {
}
c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM);
SelectionController<AssDialogue>::Selection sel;
SubtitleSelection sel;
sel.insert(new_line);
c->selectionController->SetSelectionAndActive(sel, new_line);
}
@ -219,7 +219,7 @@ struct subtitle_insert_before : public validate_nonempty_selection {
}
c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM);
SelectionController<AssDialogue>::Selection sel;
SubtitleSelection sel;
sel.insert(new_line);
c->selectionController->SetSelectionAndActive(sel, new_line);
}
@ -385,7 +385,7 @@ struct subtitle_select_all : public Command {
STR_HELP("Selects all dialogue lines")
void operator()(agi::Context *c) {
SelectionController<AssDialogue>::Selection sel;
SubtitleSelection sel;
transform(c->ass->Line.begin(), c->ass->Line.end(),
inserter(sel, sel.begin()), cast<AssDialogue*>());
sel.erase(0);

View File

@ -69,7 +69,7 @@ namespace {
struct validate_adjoinable : public Command {
CMD_TYPE(COMMAND_VALIDATE)
bool Validate(const agi::Context *c) {
SelectionController<AssDialogue>::Selection sel = c->selectionController->GetSelectedSet();
SubtitleSelection sel = c->selectionController->GetSelectedSet();
if (sel.size() < 2) return false;
size_t found = 0;
@ -131,15 +131,15 @@ struct time_frame_current : public validate_video_loaded {
void operator()(agi::Context *c) {
if (!c->videoController->IsLoaded()) return;
std::set<AssDialogue*> sel = c->selectionController->GetSelectedSet();
AssDialogue *active_line = c->selectionController->GetActiveLine();
SubtitleSelection const& sel = c->selectionController->GetSelectedSet();
const AssDialogue *active_line = c->selectionController->GetActiveLine();
if (sel.empty() || !active_line) return;
int target_start = std::max(0, c->videoController->TimeAtFrame(c->videoController->GetFrameN(), agi::vfr::START));
int shift_by = target_start - active_line->Start;
for (std::set<AssDialogue*>::iterator it = sel.begin(); it != sel.end(); ++it) {
for (SubtitleSelection::const_iterator it = sel.begin(); it != sel.end(); ++it) {
(*it)->Start = (*it)->Start + shift_by;
(*it)->End = (*it)->End + shift_by;
}
@ -162,14 +162,14 @@ struct time_shift : public Command {
};
static void snap_subs_video(agi::Context *c, bool set_start) {
std::set<AssDialogue*> sel = c->selectionController->GetSelectedSet();
SubtitleSelection const& sel = c->selectionController->GetSelectedSet();
if (!c->videoController->IsLoaded() || sel.empty()) return;
int start = c->videoController->TimeAtFrame(c->videoController->GetFrameN(), agi::vfr::START);
int end = c->videoController->TimeAtFrame(c->videoController->GetFrameN(), agi::vfr::END);
for (std::set<AssDialogue*>::iterator it = sel.begin(); it != sel.end(); ++it) {
for (SubtitleSelection::const_iterator it = sel.begin(); it != sel.end(); ++it) {
if (set_start || (*it)->Start > start)
(*it)->Start = start;
if (!set_start || (*it)->End < end)

View File

@ -362,7 +362,7 @@ void SearchReplaceEngine::ReplaceAll() {
reg.Compile(LookFor, regFlags);
// Selection
std::set<AssDialogue*> sel = context->selectionController->GetSelectedSet();
SubtitleSelection const& sel = context->selectionController->GetSelectedSet();
bool hasSelection = !sel.empty();
bool inSel = affect == 1;

View File

@ -224,7 +224,7 @@ void DialogSelection::Process(wxCommandEvent&) {
int action = selection_change_type->GetSelection();
SelectionController<AssDialogue>::Selection old_sel, new_sel;
SubtitleSelection old_sel, new_sel;
if (action != ACTION_SET)
con->selectionController->GetSelectedSet(old_sel);

View File

@ -105,6 +105,7 @@ DialogShiftTimes::DialogShiftTimes(agi::Context *context)
, history_filename(STD_STR(StandardPaths::DecodePath("?user/shift_history.json")))
, history(new json::Array)
, timecodes_loaded_slot(context->videoController->AddTimecodesListener(&DialogShiftTimes::OnTimecodesLoaded, this))
, selected_set_changed_slot(context->selectionController->AddSelectionListener(&DialogShiftTimes::OnSelectedSetChanged, this))
{
SetIcon(GETICON(shift_times_toolbutton_16));
@ -129,7 +130,7 @@ DialogShiftTimes::DialogShiftTimes(agi::Context *context)
shift_backward = new wxRadioButton(this, -1, _("&Backward"));
shift_backward->SetToolTip(_("Shifts subs backward, making them appear earlier. Use if they are appearing too late."));
wxString selection_mode_vals[] = { _("&All rows"), _("Selected &rows"), _("Selection &onward") };
wxString selection_mode_vals[] = { _("&All rows"), _("Selected &rows"), _("SubtitleSelection &onward") };
selection_mode = new wxRadioBox(this, -1, _("Affect"), wxDefaultPosition, wxDefaultSize, 3, selection_mode_vals, 1);
wxString time_field_vals[] = { _("Start a&nd End times"), _("&Start times only"), _("&End times only") };
@ -142,7 +143,7 @@ DialogShiftTimes::DialogShiftTimes(agi::Context *context)
// Set initial control states
OnTimecodesLoaded(context->videoController->FPS());
OnSelectedSetChanged(Selection(), Selection());
OnSelectedSetChanged();
LoadHistory();
shift_time->SetTime(OPT_GET("Tool/Shift Times/Time")->GetInt());
@ -196,7 +197,6 @@ DialogShiftTimes::DialogShiftTimes(agi::Context *context)
Bind(wxEVT_COMMAND_BUTTON_CLICKED, std::tr1::bind(&HelpButton::OpenPage, "Shift Times"), wxID_HELP);
shift_time->Bind(wxEVT_COMMAND_TEXT_ENTER, &DialogShiftTimes::Process, this);
history_box->Bind(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, &DialogShiftTimes::OnHistoryClick, this);
context->selectionController->AddSelectionListener(this);
}
DialogShiftTimes::~DialogShiftTimes() {
@ -209,8 +209,6 @@ DialogShiftTimes::~DialogShiftTimes() {
OPT_SET("Tool/Shift Times/Type")->SetInt(time_fields->GetSelection());
OPT_SET("Tool/Shift Times/Affect")->SetInt(selection_mode->GetSelection());
OPT_SET("Tool/Shift Times/Direction")->SetBool(shift_backward->GetValue());
context->selectionController->RemoveSelectionListener(this);
}
void DialogShiftTimes::OnTimecodesLoaded(agi::vfr::Framerate const& new_fps) {
@ -226,7 +224,7 @@ void DialogShiftTimes::OnTimecodesLoaded(agi::vfr::Framerate const& new_fps) {
}
}
void DialogShiftTimes::OnSelectedSetChanged(Selection const&, Selection const&) {
void DialogShiftTimes::OnSelectedSetChanged() {
if (context->selectionController->GetSelectedSet().empty()) {
selection_mode->Enable(1, false);
selection_mode->Enable(2, false);
@ -335,7 +333,7 @@ void DialogShiftTimes::Process(wxCommandEvent &) {
bool start = type != 2;
bool end = type != 1;
Selection sel = context->selectionController->GetSelectedSet();
SubtitleSelection sel = context->selectionController->GetSelectedSet();
long shift;
if (by_time) {

View File

@ -50,13 +50,14 @@ namespace json {
/// @brief DOCME
///
/// DOCME
class DialogShiftTimes : public wxDialog, private SelectionListener<AssDialogue> {
class DialogShiftTimes : public wxDialog {
agi::Context *context;
std::string history_filename;
agi::scoped_ptr<json::Array> history;
agi::vfr::Framerate fps;
agi::signal::Connection timecodes_loaded_slot;
agi::signal::Connection selected_set_changed_slot;
TimeEdit *shift_time;
wxTextCtrl *shift_frames;
@ -78,8 +79,7 @@ class DialogShiftTimes : public wxDialog, private SelectionListener<AssDialogue>
void OnByFrames(wxCommandEvent&);
void OnHistoryClick(wxCommandEvent&);
void OnActiveLineChanged(AssDialogue*) { }
void OnSelectedSetChanged(Selection const&, Selection const&);
void OnSelectedSetChanged();
void OnTimecodesLoaded(agi::vfr::Framerate const& new_fps);
public:

View File

@ -267,7 +267,7 @@ bool DialogSpellChecker::CheckLine(AssDialogue *active_line, int start_pos, int
replace_word->Remove(0, -1);
#endif
SelectionController<AssDialogue>::Selection sel;
SubtitleSelection sel;
sel.insert(active_line);
context->selectionController->SetSelectionAndActive(sel, active_line);
SetWord(word);

View File

@ -167,6 +167,7 @@ DialogStyleManager::DialogStyleManager(agi::Context *context)
: wxDialog(context->parent, -1, _("Styles Manager"))
, c(context)
, commit_connection(c->ass->AddCommitListener(&DialogStyleManager::LoadCurrentStyles, this))
, active_line_connection(c->selectionController->AddActiveLineListener(&DialogStyleManager::OnActiveLineChanged, this))
{
using std::tr1::bind;
SetIcon(GETICON(style_toolbutton_16));
@ -276,12 +277,9 @@ DialogStyleManager::DialogStyleManager(agi::Context *context)
CurrentList->Bind(wxEVT_COMMAND_LISTBOX_SELECTED, bind(&DialogStyleManager::UpdateButtons, this));
CurrentList->Bind(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, bind(&DialogStyleManager::OnCurrentEdit, this));
c->selectionController->AddSelectionListener(this);
}
DialogStyleManager::~DialogStyleManager() {
c->selectionController->RemoveSelectionListener(this);
}
void DialogStyleManager::LoadCurrentStyles(int commit_type) {

View File

@ -47,7 +47,6 @@
#include <libaegisub/signal.h>
#include "ass_style_storage.h"
#include "selection_controller.h"
namespace agi { struct Context; }
class AssDialogue;
@ -61,11 +60,12 @@ class PersistLocation;
/// @brief DOCME
///
/// DOCME
class DialogStyleManager : public wxDialog, private SelectionListener<AssDialogue> {
class DialogStyleManager : public wxDialog {
agi::Context *c; ///< Project context
agi::scoped_ptr<PersistLocation> persist;
agi::signal::Connection commit_connection;
agi::signal::Connection active_line_connection;
/// Styles in the current subtitle file
std::vector<AssStyle*> styleMap;
@ -152,7 +152,6 @@ class DialogStyleManager : public wxDialog, private SelectionListener<AssDialogu
void CopyToClipboard(wxListBox *list, T const& v);
void OnActiveLineChanged(AssDialogue *new_line);
void OnSelectedSetChanged(const Selection &, const Selection &) { }
public:
DialogStyleManager(agi::Context *context);

View File

@ -57,6 +57,7 @@ static void add_hotkey(wxSizer *sizer, wxWindow *parent, const char *command, wx
DialogStyling::DialogStyling(agi::Context *context)
: wxDialog(context->parent, -1, _("Styling Assistant"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX)
, c(context)
, active_line_connection(context->selectionController->AddActiveLineListener(&DialogStyling::OnActiveLineChanged, this))
, active_line(0)
{
SetIcon(GETICON(styling_toolbutton_16));
@ -136,12 +137,10 @@ DialogStyling::DialogStyling(agi::Context *context)
main_sizer->Add(button_sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 5);
}
main_sizer->SetSizeHints(this);
SetSizer(main_sizer);
SetSizerAndFit(main_sizer);
persist.reset(new PersistLocation(this, "Tool/Styling Assistant"));
c->selectionController->AddSelectionListener(this);
Bind(wxEVT_ACTIVATE, &DialogStyling::OnActivate, this);
Bind(wxEVT_CHAR_HOOK, &DialogStyling::OnCharHook, this);
style_name->Bind(wxEVT_CHAR_HOOK, &DialogStyling::OnCharHook, this);
@ -156,7 +155,6 @@ DialogStyling::DialogStyling(agi::Context *context)
}
DialogStyling::~DialogStyling () {
c->selectionController->RemoveSelectionListener(this);
}
void DialogStyling::OnActiveLineChanged(AssDialogue *new_line) {

View File

@ -43,8 +43,9 @@ class wxTextCtrl;
/// @brief DOCME
///
/// DOCME
class DialogStyling : public wxDialog, public SelectionListener<AssDialogue> {
class DialogStyling : public wxDialog {
agi::Context *c;
agi::signal::Connection active_line_connection;
wxButton *play_audio;
wxButton *play_video;
@ -63,7 +64,6 @@ class DialogStyling : public wxDialog, public SelectionListener<AssDialogue> {
void OnStyleBoxModified(wxCommandEvent &evt);
void OnActiveLineChanged(AssDialogue *);
void OnSelectedSetChanged(Selection const&, Selection const&) { }
AssDialogue *active_line;

View File

@ -309,7 +309,7 @@ std::vector<AssDialogue*> DialogTimingProcessor::SortDialogues() {
sorted.reserve(c->ass->Line.size());
if (onlySelection->IsChecked()) {
SelectionController<AssDialogue>::Selection sel = c->selectionController->GetSelectedSet();
SubtitleSelection sel = c->selectionController->GetSelectedSet();
remove_copy_if(sel.begin(), sel.end(), back_inserter(sorted),
bind(bad_line, &styles, _1));
}

View File

@ -67,6 +67,7 @@ DialogTranslation::DialogTranslation(agi::Context *c)
: wxDialog(c->parent, -1, _("Translation Assistant"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX)
, c(c)
, file_change_connection(c->ass->AddCommitListener(&DialogTranslation::OnExternalCommit, this))
, active_line_connection(c->selectionController->AddActiveLineListener(&DialogTranslation::OnActiveLineChanged, this))
, active_line(c->selectionController->GetActiveLine())
, cur_block(0)
, line_count(count_if(c->ass->Line.begin(), c->ass->Line.end(), cast<AssDialogue*>()))
@ -167,12 +168,9 @@ DialogTranslation::DialogTranslation(agi::Context *c)
}
else
UpdateDisplay();
c->selectionController->AddSelectionListener(this);
}
DialogTranslation::~DialogTranslation() {
c->selectionController->RemoveSelectionListener(this);
}
void DialogTranslation::OnActiveLineChanged(AssDialogue *new_line) {

View File

@ -28,8 +28,6 @@
#include <libaegisub/scoped_ptr.h>
#include <libaegisub/signal.h>
#include "selection_controller.h"
namespace agi { struct Context; }
class AssDialogue;
class PersistLocation;
@ -42,10 +40,11 @@ class wxCheckBox;
/// @brief Assistant for translating subtitles in one language to another language
///
/// DOCME
class DialogTranslation : public wxDialog, private SelectionListener<AssDialogue> {
class DialogTranslation : public wxDialog {
agi::Context *c;
agi::signal::Connection file_change_connection;
agi::signal::Connection active_line_connection;
/// The active line
AssDialogue *active_line;
@ -74,7 +73,6 @@ class DialogTranslation : public wxDialog, private SelectionListener<AssDialogue
void UpdateDisplay();
void OnSelectedSetChanged(Selection const&, Selection const&) { }
void OnActiveLineChanged(AssDialogue *new_line);
public:

View File

@ -21,7 +21,7 @@ struct Context {
// Controllers
AudioController *audioController;
SelectionController<AssDialogue> *selectionController;
SelectionController<AssDialogue *> *selectionController;
VideoContext *videoController;
// Things that should probably be in some sort of UI-context-model

View File

@ -39,30 +39,7 @@
#include <set>
#endif
/// @class SelectionListener
/// @brief Abstract interface for classes wanting to subtitle selection change notifications
template <typename ItemDataType>
class SelectionListener {
public:
typedef std::set<ItemDataType*> Selection;
/// Virtual destructor for safety
virtual ~SelectionListener() { }
/// @brief Called when the active line changes
/// @param new_line The line that is now the active line
///
/// In case new_line is 0, the active line was changed to none.
virtual void OnActiveLineChanged(ItemDataType *new_line) = 0;
/// @brief Called when the selected set changes
/// @param lines_added Lines added to the selection
/// @param lines_removed Lines removed from the selection
///
/// The two sets must not intersect.
virtual void OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed) = 0;
};
#include <libaegisub/signal.h>
/// @class SelectionController
/// @brief Abstract interface for selection controllers
@ -88,8 +65,13 @@ public:
template <typename ItemDataType>
class SelectionController {
public:
typedef std::set<ItemDataType*> Selection;
typedef std::set<ItemDataType> Selection;
protected:
agi::signal::Signal<ItemDataType> AnnounceActiveLineChanged;
agi::signal::Signal<Selection const&, Selection const&> AnnounceSelectedSetChanged;
public:
/// Virtual destructor for safety
virtual ~SelectionController() { }
@ -103,11 +85,11 @@ public:
/// the active line was actually changed.
///
/// This method must not affect the selected set.
virtual void SetActiveLine(ItemDataType *new_line) = 0;
virtual void SetActiveLine(ItemDataType new_line) = 0;
/// @brief Obtain the active line
/// @return The active line or NULL if there is none
virtual ItemDataType * GetActiveLine() const = 0;
virtual ItemDataType GetActiveLine() const = 0;
/// @brief Change the selected set
/// @param new_selection The set of subtitle lines to become the new selected set
@ -136,7 +118,7 @@ public:
/// This sets both the active line and selected set before announcing the
/// change to either of them, and is guaranteed to announce the active line
/// change before the selection change.
virtual void SetSelectionAndActive(Selection const& new_selection, ItemDataType *new_line) = 0;
virtual void SetSelectionAndActive(Selection const& new_selection, ItemDataType new_line) = 0;
/// @brief Change the active line to the next in sequence
///
@ -152,78 +134,10 @@ public:
/// the active line was changed.
virtual void PrevLine() = 0;
/// @brief Subscribe an object to receive change notifications
/// @param listener Object to subscribe to change notifications
virtual void AddSelectionListener(SelectionListener<ItemDataType> *listener) = 0;
/// @brief Unsubscribe an object from change notifications
/// @param listener Object to unsubscribe from change notifications
virtual void RemoveSelectionListener(SelectionListener<ItemDataType> *listener) = 0;
DEFINE_SIGNAL_ADDERS(AnnounceSelectedSetChanged, AddSelectionListener)
DEFINE_SIGNAL_ADDERS(AnnounceActiveLineChanged, AddActiveLineListener)
};
/// @class BaseSelectionController
/// @brief Base-implementation of SelectionController
///
/// This class implements adding and removing listeners for selection change
/// notifications, and provides protected functions to announce selection changes.
///
/// This class should be derived from for most real-world uses, but might not
/// be desirable in some special cases such as test drivers.
template <typename ItemDataType>
class BaseSelectionController : public SelectionController<ItemDataType> {
public:
typedef typename SelectionController<ItemDataType>::Selection Selection;
private:
typedef std::set<SelectionListener<ItemDataType> *> SelectionListenerSet;
SelectionListenerSet listeners;
protected:
/// Call OnActiveLineChanged on all listeners
void AnnounceActiveLineChanged(ItemDataType *new_line)
{
for (typename SelectionListenerSet::iterator listener = listeners.begin(); listener != listeners.end(); ++listener)
{
(*listener)->OnActiveLineChanged(new_line);
}
}
/// Call OnSelectedSetChangedon all listeners
void AnnounceSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed)
{
for (typename SelectionListenerSet::iterator listener = listeners.begin(); listener != listeners.end(); ++listener)
{
(*listener)->OnSelectedSetChanged(lines_added, lines_removed);
}
}
public:
virtual ~BaseSelectionController() { }
virtual void AddSelectionListener(SelectionListener<ItemDataType> *listener)
{
listeners.insert(listener);
}
virtual void RemoveSelectionListener(SelectionListener<ItemDataType> *listener)
{
listeners.erase(listener);
}
};
/// Do-nothing selection controller, can be considered to always operate on an empty subtitle file
template <typename ItemDataType>
class DummySelectionController : public SelectionController<ItemDataType> {
public:
typedef typename SelectionController<ItemDataType>::Selection Selection;
virtual ~DummySelectionController() { }
virtual void SetActiveLine(ItemDataType *new_line) { }
virtual ItemDataType * GetActiveLine() const { return 0; }
virtual void SetSelectedSet(const Selection &new_selection) { }
virtual void GetSelectedSet(Selection &selection) const { }
virtual void SetSelectionAndActive(Selection const& new_selection, ItemDataType *new_line) { }
virtual void NextLine() { }
virtual void PrevLine() { }
virtual void AddSelectionListener(SelectionListener<ItemDataType> *listener) { }
virtual void RemoveSelectionListener(SelectionListener<ItemDataType> *listener) { }
};
class AssDialogue;
typedef SelectionController<AssDialogue *> SubtitleSelectionController;
typedef SubtitleSelectionController::Selection SubtitleSelection;

View File

@ -246,13 +246,13 @@ SubsEditBox::SubsEditBox(wxWindow *parent, agi::Context *context)
wxSizeEvent evt;
OnSize(evt);
c->selectionController->AddSelectionListener(this);
file_changed_slot = c->ass->AddCommitListener(&SubsEditBox::OnCommit, this);
context->videoController->AddTimecodesListener(&SubsEditBox::UpdateFrameTiming, this);
connections.push_back(context->videoController->AddTimecodesListener(&SubsEditBox::UpdateFrameTiming, this));
connections.push_back(context->selectionController->AddActiveLineListener(&SubsEditBox::OnActiveLineChanged, this));
connections.push_back(context->selectionController->AddSelectionListener(&SubsEditBox::OnSelectedSetChanged, this));
}
SubsEditBox::~SubsEditBox() {
c->selectionController->RemoveSelectionListener(this);
}
wxTextCtrl *SubsEditBox::MakeMarginCtrl(wxString const& tooltip, void (SubsEditBox::*handler)(wxCommandEvent&)) {
@ -398,7 +398,7 @@ void SubsEditBox::OnActiveLineChanged(AssDialogue *new_line) {
}
}
}
void SubsEditBox::OnSelectedSetChanged(const Selection &, const Selection &) {
void SubsEditBox::OnSelectedSetChanged(const SubtitleSelection &, const SubtitleSelection &) {
sel = c->selectionController->GetSelectedSet();
initialTimes.clear();
}
@ -456,7 +456,7 @@ void SubsEditBox::CommitText(wxString desc) {
}
void SubsEditBox::CommitTimes(TimeField field) {
for (Selection::iterator cur = sel.begin(); cur != sel.end(); ++cur) {
for (SubtitleSelection::iterator cur = sel.begin(); cur != sel.end(); ++cur) {
AssDialogue *d = *cur;
if (!initialTimes.count(d))

View File

@ -35,6 +35,7 @@
///
#ifndef AGI_PRE
#include <deque>
#include <map>
#include <vector>
@ -71,17 +72,19 @@ template<class Base> class Placeholder;
/// @brief Main subtitle edit box
///
/// Controls the text edit and all surrounding controls
class SubsEditBox : public wxPanel, protected SelectionListener<AssDialogue> {
class SubsEditBox : public wxPanel {
enum TimeField {
TIME_START = 0,
TIME_END,
TIME_DURATION
};
std::deque<agi::signal::Connection> connections;
/// Currently active dialogue line
AssDialogue *line;
/// Last seen grid selection
Selection sel;
SubtitleSelection sel;
/// Are the buttons currently split into two lines?
bool splitLineMode;
@ -149,7 +152,7 @@ class SubsEditBox : public wxPanel, protected SelectionListener<AssDialogue> {
void OnKeyDown(wxKeyEvent &event);
void OnActiveLineChanged(AssDialogue *new_line);
void OnSelectedSetChanged(const Selection &, const Selection &);
void OnSelectedSetChanged(const SubtitleSelection &, const SubtitleSelection &);
void OnFrameTimeRadio(wxCommandEvent &event);
void OnStyleChange(wxCommandEvent &event);

View File

@ -149,12 +149,7 @@ VideoBox::VideoBox(wxWindow *parent, bool isDetached, agi::Context *context)
slots.push_back(context->videoController->AddTimecodesListener(&VideoBox::UpdateTimeBoxes, this));
slots.push_back(context->videoController->AddVideoOpenListener(&VideoBox::UpdateTimeBoxes, this));
slots.push_back(context->ass->AddCommitListener(&VideoBox::UpdateTimeBoxes, this));
context->selectionController->AddSelectionListener(this);
}
VideoBox::~VideoBox() {
context->selectionController->RemoveSelectionListener(this);
slots.push_back(context->selectionController->AddSelectionListener(&VideoBox::UpdateTimeBoxes, this));
}
void VideoBox::UpdateTimeBoxes() {

View File

@ -42,8 +42,6 @@
#include <libaegisub/signal.h>
#include "selection_controller.h"
namespace agi { struct Context; }
class AssDialogue;
class wxComboBox;
@ -51,7 +49,7 @@ class wxTextCtrl;
/// @class VideoBox
/// @brief The box containing the video display and associated controls
class VideoBox : public wxPanel, private SelectionListener<AssDialogue> {
class VideoBox : public wxPanel {
std::list<agi::signal::Connection> slots;
agi::Context *context; ///< Project context
wxTextCtrl *VideoPosition; ///< Current frame/time
@ -60,10 +58,6 @@ class VideoBox : public wxPanel, private SelectionListener<AssDialogue> {
/// Update VideoPosition and VideoSubsPos
void UpdateTimeBoxes();
void OnSelectedSetChanged(Selection const&, Selection const&) { }
void OnActiveLineChanged(AssDialogue*) { UpdateTimeBoxes(); }
public:
VideoBox(wxWindow *parent, bool isDetached, agi::Context *context);
~VideoBox();
};

View File

@ -72,13 +72,12 @@ VisualToolBase::VisualToolBase(VideoDisplay *parent, agi::Context *context)
c->ass->GetResolution(script_w, script_h);
script_res = Vector2D(script_w, script_h);
active_line = GetActiveDialogueLine();
c->selectionController->AddSelectionListener(this);
connections.push_back(c->selectionController->AddActiveLineListener(&VisualToolBase::OnActiveLineChanged, this));
connections.push_back(c->videoController->AddSeekListener(&VisualToolBase::OnSeek, this));
parent->Bind(wxEVT_MOUSE_CAPTURE_LOST, &VisualToolBase::OnMouseCaptureLost, this);
}
VisualToolBase::~VisualToolBase() {
c->selectionController->RemoveSelectionListener(this);
}
void VisualToolBase::OnCommit(int type) {
@ -285,7 +284,7 @@ void VisualTool<FeatureType>::OnMouseEvent(wxMouseEvent &event) {
else {
if (!alt_down && features.size() > 1) {
sel_features.clear();
Selection sel;
SubtitleSelection sel;
sel.insert(c->selectionController->GetActiveLine());
c->selectionController->SetSelectedSet(sel);
need_render = true;
@ -328,7 +327,7 @@ void VisualTool<FeatureType>::SetSelection(feature_iterator feat, bool clear) {
sel_features.clear();
if (sel_features.insert(feat).second && feat->line) {
Selection sel;
SubtitleSelection sel;
if (!clear)
sel = c->selectionController->GetSelectedSet();
if (sel.insert(feat->line).second)
@ -344,7 +343,7 @@ void VisualTool<FeatureType>::RemoveSelection(feature_iterator feat) {
if ((*it)->line == feat->line) return;
}
Selection sel = c->selectionController->GetSelectedSet();
SubtitleSelection sel = c->selectionController->GetSelectedSet();
// Don't deselect the only selected line
if (sel.size() <= 1) return;

View File

@ -56,9 +56,7 @@ namespace agi {
/// different VisualTool<T>s are unrelated types otherwise. In addition, as much
/// functionality as possible is implemented here to avoid having four copies
/// of each method for no good reason (and four times as many error messages)
class VisualToolBase : protected SelectionListener<AssDialogue> {
std::deque<agi::signal::Connection> connections;
class VisualToolBase {
void OnCommit(int type);
void OnSeek(int new_frame);
@ -70,7 +68,6 @@ class VisualToolBase : protected SelectionListener<AssDialogue> {
// SubtitleSelectionListener implementation
void OnActiveLineChanged(AssDialogue *new_line);
void OnSelectedSetChanged(const Selection &, const Selection &) { }
// Below here are the virtuals that must be implemented
@ -92,6 +89,8 @@ class VisualToolBase : protected SelectionListener<AssDialogue> {
virtual void DoRefresh() { }
protected:
std::deque<agi::signal::Connection> connections;
OpenGLWrapper gl;
/// Called when the user double-clicks

View File

@ -42,8 +42,8 @@ VisualToolCross::~VisualToolCross() {
void VisualToolCross::OnDoubleClick() {
Vector2D d = ToScriptCoords(mouse_pos) - GetLinePosition(active_line);
Selection sel = c->selectionController->GetSelectedSet();
for (Selection::const_iterator it = sel.begin(); it != sel.end(); ++it) {
SubtitleSelection sel = c->selectionController->GetSelectedSet();
for (SubtitleSelection::const_iterator it = sel.begin(); it != sel.end(); ++it) {
Vector2D p1, p2;
int t1, t2;
if (GetLineMove(*it, p1, p2, t1, t2)) {

View File

@ -53,6 +53,7 @@ VisualToolDrag::VisualToolDrag(VideoDisplay *parent, agi::Context *context)
, button_is_move(true)
{
c->selectionController->GetSelectedSet(selection);
connections.push_back(c->selectionController->AddSelectionListener(&VisualToolDrag::OnSelectedSetChanged, this));
}
void VisualToolDrag::SetToolbar(wxToolBar *tb) {
@ -82,7 +83,7 @@ void VisualToolDrag::UpdateToggleButtons() {
void VisualToolDrag::OnSubTool(wxCommandEvent &) {
// Toggle \move <-> \pos
VideoContext *vc = c->videoController;
for (Selection::const_iterator cur = selection.begin(); cur != selection.end(); ++cur) {
for (SubtitleSelection::const_iterator cur = selection.begin(); cur != selection.end(); ++cur) {
AssDialogue *line = *cur;
Vector2D p1, p2;
int t1, t2;
@ -164,7 +165,7 @@ template<class C, class T> static bool line_not_present(C const& set, T const& i
return find_if(set.begin(), set.end(), bind(cmp_line<T>, it, std::tr1::placeholders::_1)) == set.end();
}
void VisualToolDrag::OnSelectedSetChanged(const Selection &added, const Selection &removed) {
void VisualToolDrag::OnSelectedSetChanged(const SubtitleSelection &added, const SubtitleSelection &removed) {
c->selectionController->GetSelectedSet(selection);
bool any_changed = false;
@ -310,8 +311,8 @@ void VisualToolDrag::UpdateDrag(feature_iterator feature) {
void VisualToolDrag::OnDoubleClick() {
Vector2D d = ToScriptCoords(mouse_pos) - (primary ? ToScriptCoords(primary->pos) : GetLinePosition(active_line));
Selection sel = c->selectionController->GetSelectedSet();
for (Selection::const_iterator it = sel.begin(); it != sel.end(); ++it) {
SubtitleSelection sel = c->selectionController->GetSelectedSet();
for (SubtitleSelection::const_iterator it = sel.begin(); it != sel.end(); ++it) {
Vector2D p1, p2;
int t1, t2;
if (GetLineMove(*it, p1, p2, t1, t2)) {

View File

@ -36,7 +36,6 @@ public:
class wxBitmapButton;
class wxToolBar;
/// DOCME
/// @class VisualToolDrag
/// @brief Moveable features for the positions of each visible line
class VisualToolDrag : public VisualTool<VisualToolDragDraggableFeature> {
@ -48,7 +47,7 @@ class VisualToolDrag : public VisualTool<VisualToolDragDraggableFeature> {
/// longer exists
Feature *primary;
/// The last announced selection set
Selection selection;
SubtitleSelection selection;
/// When the button is pressed, will it convert the line to a move (vs. from
/// move to pos)? Used to avoid changing the button's icon unnecessarily
@ -60,8 +59,7 @@ class VisualToolDrag : public VisualTool<VisualToolDragDraggableFeature> {
void MakeFeatures(AssDialogue *diag, feature_iterator pos);
void MakeFeatures(AssDialogue *diag);
// Overriding SubtitleSelectionListener inherited from base VisualTool<>
void OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed);
void OnSelectedSetChanged(SubtitleSelection const& lines_added, SubtitleSelection const& lines_removed);
void OnFrameChanged();
void OnFileChanged();