diff --git a/aegisub/src/ass_karaoke.cpp b/aegisub/src/ass_karaoke.cpp index cd9c9375e..c83f21671 100644 --- a/aegisub/src/ass_karaoke.cpp +++ b/aegisub/src/ass_karaoke.cpp @@ -288,7 +288,7 @@ void AssKaraoke::SplitLines(std::set const& lines, agi::Context *c AssKaraoke kara; - std::set sel = c->selectionController->GetSelectedSet(); + SubtitleSelection sel = c->selectionController->GetSelectedSet(); bool did_split = false; for (std::list::iterator it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { diff --git a/aegisub/src/audio_karaoke.cpp b/aegisub/src/audio_karaoke.cpp index 806891cf2..54c55dc55 100644 --- a/aegisub/src/audio_karaoke.cpp +++ b/aegisub/src/audio_karaoke.cpp @@ -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) { diff --git a/aegisub/src/audio_karaoke.h b/aegisub/src/audio_karaoke.h index 9b04a48da..486ae2e3f 100644 --- a/aegisub/src/audio_karaoke.h +++ b/aegisub/src/audio_karaoke.h @@ -33,8 +33,6 @@ #include #include -#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 { +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 { 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); diff --git a/aegisub/src/audio_timing_dialogue.cpp b/aegisub/src/audio_timing_dialogue.cpp index 2ceb2c1d2..44feff0ec 100644 --- a/aegisub/src/audio_timing_dialogue.cpp +++ b/aegisub/src/audio_timing_dialogue.cpp @@ -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 { +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; diff --git a/aegisub/src/auto4_lua.cpp b/aegisub/src/auto4_lua.cpp index e193fa50f..7f586a701 100644 --- a/aegisub/src/auto4_lua.cpp +++ b/aegisub/src/auto4_lua.cpp @@ -842,7 +842,7 @@ namespace Automation4 { static int transform_selection(lua_State *L, const agi::Context *c) { - std::set sel = c->selectionController->GetSelectedSet(); + SubtitleSelection const& sel = c->selectionController->GetSelectedSet(); AssDialogue *active_line = c->selectionController->GetActiveLine(); lua_newtable(L); diff --git a/aegisub/src/base_grid.cpp b/aegisub/src/base_grid.cpp index 8f134143b..95cf95c8a 100644 --- a/aegisub/src/base_grid.cpp +++ b/aegisub/src/base_grid.cpp @@ -1104,12 +1104,11 @@ void BaseGrid::NextLine() { } } - void BaseGrid::AnnounceActiveLineChanged(AssDialogue *new_line) { if (batch_level > 0) batch_active_line_changed = true; else - BaseSelectionController::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::AnnounceSelectedSetChanged(lines_added, lines_removed); + SubtitleSelectionController::AnnounceSelectedSetChanged(lines_added, lines_removed); } } diff --git a/aegisub/src/base_grid.h b/aegisub/src/base_grid.h index 839c7f550..b022b53a3 100644 --- a/aegisub/src/base_grid.h +++ b/aegisub/src/base_grid.h @@ -55,16 +55,12 @@ namespace agi { } class AssDialogue; -typedef SelectionController SubtitleSelectionController; -typedef SelectionListener SubtitleSelectionListener; - - /// DOCME /// @class BaseGrid /// @brief DOCME /// /// DOCME -class BaseGrid : public wxWindow, public BaseSelectionController { +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 diff --git a/aegisub/src/command/audio.cpp b/aegisub/src/command/audio.cpp index e590d7800..6d8bee177 100644 --- a/aegisub/src/command/audio.cpp +++ b/aegisub/src/command/audio.cpp @@ -58,7 +58,6 @@ #include "../video_context.h" namespace { - typedef SelectionController::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); } diff --git a/aegisub/src/command/edit.cpp b/aegisub/src/command/edit.cpp index 4c7c9ab56..69e125f0a 100644 --- a/aegisub/src/command/edit.cpp +++ b/aegisub/src/command/edit.cpp @@ -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::Selection sel = c->selectionController->GetSelectedSet(); + SubtitleSelection sel = c->selectionController->GetSelectedSet(); AssDialogue *first = 0; entryIter out = c->ass->Line.begin(); diff --git a/aegisub/src/command/grid.cpp b/aegisub/src/command/grid.cpp index ed41b5996..8a96b1f7a 100644 --- a/aegisub/src/command/grid.cpp +++ b/aegisub/src/command/grid.cpp @@ -414,7 +414,7 @@ struct grid_swap : public Command { } void operator()(agi::Context *c) { - SelectionController::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()); diff --git a/aegisub/src/command/subtitle.cpp b/aegisub/src/command/subtitle.cpp index f0ad5e249..644fc5eb4 100644 --- a/aegisub/src/command/subtitle.cpp +++ b/aegisub/src/command/subtitle.cpp @@ -172,7 +172,7 @@ struct subtitle_insert_after : public validate_nonempty_selection { } c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM); - SelectionController::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::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::Selection sel; + SubtitleSelection sel; transform(c->ass->Line.begin(), c->ass->Line.end(), inserter(sel, sel.begin()), cast()); sel.erase(0); diff --git a/aegisub/src/command/time.cpp b/aegisub/src/command/time.cpp index 1fc432b65..1ee397385 100644 --- a/aegisub/src/command/time.cpp +++ b/aegisub/src/command/time.cpp @@ -69,7 +69,7 @@ namespace { struct validate_adjoinable : public Command { CMD_TYPE(COMMAND_VALIDATE) bool Validate(const agi::Context *c) { - SelectionController::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 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::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 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::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) diff --git a/aegisub/src/dialog_search_replace.cpp b/aegisub/src/dialog_search_replace.cpp index aef8f3f69..c6a613051 100644 --- a/aegisub/src/dialog_search_replace.cpp +++ b/aegisub/src/dialog_search_replace.cpp @@ -362,7 +362,7 @@ void SearchReplaceEngine::ReplaceAll() { reg.Compile(LookFor, regFlags); // Selection - std::set sel = context->selectionController->GetSelectedSet(); + SubtitleSelection const& sel = context->selectionController->GetSelectedSet(); bool hasSelection = !sel.empty(); bool inSel = affect == 1; diff --git a/aegisub/src/dialog_selection.cpp b/aegisub/src/dialog_selection.cpp index dc89eff5a..572747d49 100644 --- a/aegisub/src/dialog_selection.cpp +++ b/aegisub/src/dialog_selection.cpp @@ -224,7 +224,7 @@ void DialogSelection::Process(wxCommandEvent&) { int action = selection_change_type->GetSelection(); - SelectionController::Selection old_sel, new_sel; + SubtitleSelection old_sel, new_sel; if (action != ACTION_SET) con->selectionController->GetSelectedSet(old_sel); diff --git a/aegisub/src/dialog_shift_times.cpp b/aegisub/src/dialog_shift_times.cpp index 3c9a6ad76..82e16afe1 100644 --- a/aegisub/src/dialog_shift_times.cpp +++ b/aegisub/src/dialog_shift_times.cpp @@ -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) { diff --git a/aegisub/src/dialog_shift_times.h b/aegisub/src/dialog_shift_times.h index 9295d9c9d..3f98f639a 100644 --- a/aegisub/src/dialog_shift_times.h +++ b/aegisub/src/dialog_shift_times.h @@ -50,13 +50,14 @@ namespace json { /// @brief DOCME /// /// DOCME -class DialogShiftTimes : public wxDialog, private SelectionListener { +class DialogShiftTimes : public wxDialog { agi::Context *context; std::string history_filename; agi::scoped_ptr 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 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: diff --git a/aegisub/src/dialog_spellchecker.cpp b/aegisub/src/dialog_spellchecker.cpp index 642fb9762..3e03d4226 100644 --- a/aegisub/src/dialog_spellchecker.cpp +++ b/aegisub/src/dialog_spellchecker.cpp @@ -267,7 +267,7 @@ bool DialogSpellChecker::CheckLine(AssDialogue *active_line, int start_pos, int replace_word->Remove(0, -1); #endif - SelectionController::Selection sel; + SubtitleSelection sel; sel.insert(active_line); context->selectionController->SetSelectionAndActive(sel, active_line); SetWord(word); diff --git a/aegisub/src/dialog_style_manager.cpp b/aegisub/src/dialog_style_manager.cpp index a783cd522..93be95b30 100644 --- a/aegisub/src/dialog_style_manager.cpp +++ b/aegisub/src/dialog_style_manager.cpp @@ -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) { diff --git a/aegisub/src/dialog_style_manager.h b/aegisub/src/dialog_style_manager.h index 6afe4e488..99efa36fd 100644 --- a/aegisub/src/dialog_style_manager.h +++ b/aegisub/src/dialog_style_manager.h @@ -47,7 +47,6 @@ #include #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 { +class DialogStyleManager : public wxDialog { agi::Context *c; ///< Project context agi::scoped_ptr persist; agi::signal::Connection commit_connection; + agi::signal::Connection active_line_connection; /// Styles in the current subtitle file std::vector styleMap; @@ -152,7 +152,6 @@ class DialogStyleManager : public wxDialog, private SelectionListenerparent, -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) { diff --git a/aegisub/src/dialog_styling_assistant.h b/aegisub/src/dialog_styling_assistant.h index 7d0187663..4ca9a0e20 100644 --- a/aegisub/src/dialog_styling_assistant.h +++ b/aegisub/src/dialog_styling_assistant.h @@ -43,8 +43,9 @@ class wxTextCtrl; /// @brief DOCME /// /// DOCME -class DialogStyling : public wxDialog, public SelectionListener { +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 { void OnStyleBoxModified(wxCommandEvent &evt); void OnActiveLineChanged(AssDialogue *); - void OnSelectedSetChanged(Selection const&, Selection const&) { } AssDialogue *active_line; diff --git a/aegisub/src/dialog_timing_processor.cpp b/aegisub/src/dialog_timing_processor.cpp index e8ffae7ea..62d4aefc0 100644 --- a/aegisub/src/dialog_timing_processor.cpp +++ b/aegisub/src/dialog_timing_processor.cpp @@ -309,7 +309,7 @@ std::vector DialogTimingProcessor::SortDialogues() { sorted.reserve(c->ass->Line.size()); if (onlySelection->IsChecked()) { - SelectionController::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)); } diff --git a/aegisub/src/dialog_translation.cpp b/aegisub/src/dialog_translation.cpp index 8ce038703..75b62079d 100644 --- a/aegisub/src/dialog_translation.cpp +++ b/aegisub/src/dialog_translation.cpp @@ -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())) @@ -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) { diff --git a/aegisub/src/dialog_translation.h b/aegisub/src/dialog_translation.h index 74df386c3..ca861d086 100644 --- a/aegisub/src/dialog_translation.h +++ b/aegisub/src/dialog_translation.h @@ -28,8 +28,6 @@ #include #include -#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 { +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 *selectionController; + SelectionController *selectionController; VideoContext *videoController; // Things that should probably be in some sort of UI-context-model diff --git a/aegisub/src/selection_controller.h b/aegisub/src/selection_controller.h index affaba7a3..e73cffaed 100644 --- a/aegisub/src/selection_controller.h +++ b/aegisub/src/selection_controller.h @@ -39,30 +39,7 @@ #include #endif -/// @class SelectionListener -/// @brief Abstract interface for classes wanting to subtitle selection change notifications -template -class SelectionListener { -public: - typedef std::set 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 /// @class SelectionController /// @brief Abstract interface for selection controllers @@ -88,8 +65,13 @@ public: template class SelectionController { public: - typedef std::set Selection; + typedef std::set Selection; +protected: + agi::signal::Signal AnnounceActiveLineChanged; + agi::signal::Signal 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 *listener) = 0; - - /// @brief Unsubscribe an object from change notifications - /// @param listener Object to unsubscribe from change notifications - virtual void RemoveSelectionListener(SelectionListener *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 -class BaseSelectionController : public SelectionController { -public: - typedef typename SelectionController::Selection Selection; -private: - typedef std::set *> 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 *listener) - { - listeners.insert(listener); - } - - virtual void RemoveSelectionListener(SelectionListener *listener) - { - listeners.erase(listener); - } -}; - -/// Do-nothing selection controller, can be considered to always operate on an empty subtitle file -template -class DummySelectionController : public SelectionController { -public: - typedef typename SelectionController::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 *listener) { } - virtual void RemoveSelectionListener(SelectionListener *listener) { } -}; +class AssDialogue; +typedef SelectionController SubtitleSelectionController; +typedef SubtitleSelectionController::Selection SubtitleSelection; diff --git a/aegisub/src/subs_edit_box.cpp b/aegisub/src/subs_edit_box.cpp index c059af654..a566a583e 100644 --- a/aegisub/src/subs_edit_box.cpp +++ b/aegisub/src/subs_edit_box.cpp @@ -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)) diff --git a/aegisub/src/subs_edit_box.h b/aegisub/src/subs_edit_box.h index 687193206..c5b540018 100644 --- a/aegisub/src/subs_edit_box.h +++ b/aegisub/src/subs_edit_box.h @@ -35,6 +35,7 @@ /// #ifndef AGI_PRE +#include #include #include @@ -71,17 +72,19 @@ template class Placeholder; /// @brief Main subtitle edit box /// /// Controls the text edit and all surrounding controls -class SubsEditBox : public wxPanel, protected SelectionListener { +class SubsEditBox : public wxPanel { enum TimeField { TIME_START = 0, TIME_END, TIME_DURATION }; + std::deque 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 { 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); diff --git a/aegisub/src/video_box.cpp b/aegisub/src/video_box.cpp index 6b30faac2..6963872a8 100644 --- a/aegisub/src/video_box.cpp +++ b/aegisub/src/video_box.cpp @@ -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() { diff --git a/aegisub/src/video_box.h b/aegisub/src/video_box.h index df25761e8..ba0981d5b 100644 --- a/aegisub/src/video_box.h +++ b/aegisub/src/video_box.h @@ -42,8 +42,6 @@ #include -#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 { +class VideoBox : public wxPanel { std::list slots; agi::Context *context; ///< Project context wxTextCtrl *VideoPosition; ///< Current frame/time @@ -60,10 +58,6 @@ class VideoBox : public wxPanel, private SelectionListener { /// 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(); }; diff --git a/aegisub/src/visual_tool.cpp b/aegisub/src/visual_tool.cpp index 3d0f34240..e3dc19d22 100644 --- a/aegisub/src/visual_tool.cpp +++ b/aegisub/src/visual_tool.cpp @@ -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::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::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::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; diff --git a/aegisub/src/visual_tool.h b/aegisub/src/visual_tool.h index 6dc565557..16f229c19 100644 --- a/aegisub/src/visual_tool.h +++ b/aegisub/src/visual_tool.h @@ -56,9 +56,7 @@ namespace agi { /// different VisualTools 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 { - std::deque connections; - +class VisualToolBase { void OnCommit(int type); void OnSeek(int new_frame); @@ -70,7 +68,6 @@ class VisualToolBase : protected SelectionListener { // 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 { virtual void DoRefresh() { } protected: + std::deque connections; + OpenGLWrapper gl; /// Called when the user double-clicks diff --git a/aegisub/src/visual_tool_cross.cpp b/aegisub/src/visual_tool_cross.cpp index 38582c77a..1a8057b20 100644 --- a/aegisub/src/visual_tool_cross.cpp +++ b/aegisub/src/visual_tool_cross.cpp @@ -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)) { diff --git a/aegisub/src/visual_tool_drag.cpp b/aegisub/src/visual_tool_drag.cpp index 3d3f847fa..9e701752f 100644 --- a/aegisub/src/visual_tool_drag.cpp +++ b/aegisub/src/visual_tool_drag.cpp @@ -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 static bool line_not_present(C const& set, T const& i return find_if(set.begin(), set.end(), bind(cmp_line, 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)) { diff --git a/aegisub/src/visual_tool_drag.h b/aegisub/src/visual_tool_drag.h index 6462c1a8c..03d6f59e1 100644 --- a/aegisub/src/visual_tool_drag.h +++ b/aegisub/src/visual_tool_drag.h @@ -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 { @@ -48,7 +47,7 @@ class VisualToolDrag : public VisualTool { /// 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 { 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();