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; AssKaraoke kara;
std::set<AssDialogue*> sel = c->selectionController->GetSelectedSet(); SubtitleSelection sel = c->selectionController->GetSelectedSet();
bool did_split = false; bool did_split = false;
for (std::list<AssEntry*>::iterator it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { 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)) , file_changed(c->ass->AddCommitListener(&AudioKaraoke::OnFileChanged, this))
, audio_opened(c->audioController->AddAudioOpenListener(&AudioKaraoke::OnAudioOpened, this)) , audio_opened(c->audioController->AddAudioOpenListener(&AudioKaraoke::OnAudioOpened, this))
, audio_closed(c->audioController->AddAudioCloseListener(&AudioKaraoke::OnAudioClosed, this)) , audio_closed(c->audioController->AddAudioCloseListener(&AudioKaraoke::OnAudioClosed, this))
, active_line_changed(c->selectionController->AddActiveLineListener(&AudioKaraoke::OnActiveLineChanged, this))
, active_line(0) , active_line(0)
, kara(new AssKaraoke) , kara(new AssKaraoke)
, scroll_x(0) , scroll_x(0)
@ -106,15 +107,12 @@ AudioKaraoke::AudioKaraoke(wxWindow *parent, agi::Context *c)
split_area->Bind(wxEVT_CONTEXT_MENU, &AudioKaraoke::OnContextMenu, this); split_area->Bind(wxEVT_CONTEXT_MENU, &AudioKaraoke::OnContextMenu, this);
scroll_timer.Bind(wxEVT_TIMER, &AudioKaraoke::OnScrollTimer, this); scroll_timer.Bind(wxEVT_TIMER, &AudioKaraoke::OnScrollTimer, this);
c->selectionController->AddSelectionListener(this);
accept_button->Enable(false); accept_button->Enable(false);
cancel_button->Enable(false); cancel_button->Enable(false);
enabled = false; enabled = false;
} }
AudioKaraoke::~AudioKaraoke() { AudioKaraoke::~AudioKaraoke() {
c->selectionController->RemoveSelectionListener(this);
} }
void AudioKaraoke::OnActiveLineChanged(AssDialogue *new_line) { void AudioKaraoke::OnActiveLineChanged(AssDialogue *new_line) {

View File

@ -33,8 +33,6 @@
#include <libaegisub/scoped_ptr.h> #include <libaegisub/scoped_ptr.h>
#include <libaegisub/signal.h> #include <libaegisub/signal.h>
#include "selection_controller.h"
class AssDialogue; class AssDialogue;
class AssKaraoke; class AssKaraoke;
class wxButton; class wxButton;
@ -72,11 +70,12 @@ namespace agi { struct Context; }
/// actually updated until the line is committed (which if auto-commit timing /// 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 /// changes is on, will happen as soon as the user adjusts the timing of the
/// new syllable). /// new syllable).
class AudioKaraoke : public wxWindow, private SelectionListener<AssDialogue> { class AudioKaraoke : public wxWindow {
agi::Context *c; ///< Project context agi::Context *c; ///< Project context
agi::signal::Connection file_changed; ///< File changed slot agi::signal::Connection file_changed; ///< File changed slot
agi::signal::Connection audio_opened; ///< Audio opened connection agi::signal::Connection audio_opened; ///< Audio opened connection
agi::signal::Connection audio_closed; ///< Audio closed connection agi::signal::Connection audio_closed; ///< Audio closed connection
agi::signal::Connection active_line_changed;
/// Currently active dialogue line /// Currently active dialogue line
AssDialogue *active_line; AssDialogue *active_line;
@ -145,7 +144,6 @@ class AudioKaraoke : public wxWindow, private SelectionListener<AssDialogue> {
void OnMouse(wxMouseEvent &event); void OnMouse(wxMouseEvent &event);
void OnPaint(wxPaintEvent &event); void OnPaint(wxPaintEvent &event);
void OnSize(wxSizeEvent &event); void OnSize(wxSizeEvent &event);
void OnSelectedSetChanged(Selection const&, Selection const&) { }
void OnAudioOpened(); void OnAudioOpened();
void OnAudioClosed(); void OnAudioClosed();
void OnScrollTimer(wxTimerEvent &event); 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 /// 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 /// as the active line starts/ends can optionally be dragged along with the
/// active line's markers, updating those lines as well. /// 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 /// The rendering style for the active line's start marker
Pen style_left; Pen style_left;
/// The rendering style for the active line's end marker /// 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 audio_open_connection;
agi::signal::Connection inactive_line_mode_connection; agi::signal::Connection inactive_line_mode_connection;
agi::signal::Connection inactive_line_comment_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 /// Update the audio controller's selection
void UpdateSelection(); void UpdateSelection();
@ -349,7 +351,7 @@ class AudioTimingControllerDialogue : public AudioTimingController, private Sele
void RegenerateSelectedLines(); void RegenerateSelectedLines();
/// Add a line to the list of timeable inactive lines /// 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 /// Regenerate the list of active and inactive line markers
void RegenerateMarkers(); void RegenerateMarkers();
@ -377,7 +379,7 @@ class AudioTimingControllerDialogue : public AudioTimingController, private Sele
// SubtitleSelectionListener interface // SubtitleSelectionListener interface
void OnActiveLineChanged(AssDialogue *new_line); 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 // AssFile events
void OnFileChanged(int type); void OnFileChanged(int type);
@ -409,8 +411,6 @@ public:
/// Constructor /// Constructor
/// @param c Project context /// @param c Project context
AudioTimingControllerDialogue(agi::Context *c); AudioTimingControllerDialogue(agi::Context *c);
/// Destructor
~AudioTimingControllerDialogue();
}; };
AudioTimingController *CreateDialogueTimingController(agi::Context *c) AudioTimingController *CreateDialogueTimingController(agi::Context *c)
@ -434,8 +434,9 @@ AudioTimingControllerDialogue::AudioTimingControllerDialogue(agi::Context *c)
, commit_connection(c->ass->AddCommitListener(&AudioTimingControllerDialogue::OnFileChanged, this)) , commit_connection(c->ass->AddCommitListener(&AudioTimingControllerDialogue::OnFileChanged, this))
, inactive_line_mode_connection(OPT_SUB("Audio/Inactive Lines Display Mode", &AudioTimingControllerDialogue::RegenerateInactiveLines, 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)) , 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))); keyframes_provider.AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
video_position_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))); seconds_provider.AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
@ -443,12 +444,6 @@ AudioTimingControllerDialogue::AudioTimingControllerDialogue(agi::Context *c)
Revert(); Revert();
} }
AudioTimingControllerDialogue::~AudioTimingControllerDialogue()
{
context->selectionController->RemoveSelectionListener(this);
}
void AudioTimingControllerDialogue::GetMarkers(const TimeRange &range, AudioMarkerVector &out_markers) const void AudioTimingControllerDialogue::GetMarkers(const TimeRange &range, AudioMarkerVector &out_markers) const
{ {
// The order matters here; later markers are painted on top of earlier // The order matters here; later markers are painted on top of earlier
@ -471,7 +466,7 @@ void AudioTimingControllerDialogue::OnActiveLineChanged(AssDialogue *new_line)
Revert(); Revert();
} }
void AudioTimingControllerDialogue::OnSelectedSetChanged(Selection const&, Selection const&) void AudioTimingControllerDialogue::OnSelectedSetChanged(SubtitleSelection const&, SubtitleSelection const&)
{ {
RegenerateSelectedLines(); RegenerateSelectedLines();
RegenerateInactiveLines(); RegenerateInactiveLines();
@ -746,7 +741,7 @@ void AudioTimingControllerDialogue::RegenerateInactiveLines()
bool was_empty = inactive_lines.empty(); bool was_empty = inactive_lines.empty();
inactive_lines.clear(); inactive_lines.clear();
Selection sel = context->selectionController->GetSelectedSet(); SubtitleSelection sel = context->selectionController->GetSelectedSet();
switch (int mode = inactive_line_mode->GetInt()) switch (int mode = inactive_line_mode->GetInt())
{ {
@ -796,7 +791,7 @@ void AudioTimingControllerDialogue::RegenerateInactiveLines()
RegenerateMarkers(); RegenerateMarkers();
} }
void AudioTimingControllerDialogue::AddInactiveLine(Selection const& sel, AssDialogue *diag) void AudioTimingControllerDialogue::AddInactiveLine(SubtitleSelection const& sel, AssDialogue *diag)
{ {
if (sel.count(diag)) return; if (sel.count(diag)) return;
@ -810,8 +805,8 @@ void AudioTimingControllerDialogue::RegenerateSelectedLines()
selected_lines.clear(); selected_lines.clear();
AssDialogue *active = context->selectionController->GetActiveLine(); AssDialogue *active = context->selectionController->GetActiveLine();
Selection sel = context->selectionController->GetSelectedSet(); SubtitleSelection sel = context->selectionController->GetSelectedSet();
for (Selection::iterator it = sel.begin(); it != sel.end(); ++it) for (SubtitleSelection::iterator it = sel.begin(); it != sel.end(); ++it)
{ {
if (*it == active) continue; if (*it == active) continue;

View File

@ -842,7 +842,7 @@ namespace Automation4 {
static int transform_selection(lua_State *L, const agi::Context *c) 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(); AssDialogue *active_line = c->selectionController->GetActiveLine();
lua_newtable(L); lua_newtable(L);

View File

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

View File

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

View File

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

View File

@ -414,7 +414,7 @@ struct grid_swap : public Command {
} }
void operator()(agi::Context *c) { void operator()(agi::Context *c) {
SelectionController<AssDialogue>::Selection sel = c->selectionController->GetSelectedSet(); SubtitleSelection sel = c->selectionController->GetSelectedSet();
if (sel.size() == 2) { if (sel.size() == 2) {
entryIter a = find(c->ass->Line.begin(), c->ass->Line.end(), *sel.begin()); 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()); 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); c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM);
SelectionController<AssDialogue>::Selection sel; SubtitleSelection sel;
sel.insert(new_line); sel.insert(new_line);
c->selectionController->SetSelectionAndActive(sel, 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); c->ass->Commit(_("line insertion"), AssFile::COMMIT_DIAG_ADDREM);
SelectionController<AssDialogue>::Selection sel; SubtitleSelection sel;
sel.insert(new_line); sel.insert(new_line);
c->selectionController->SetSelectionAndActive(sel, new_line); c->selectionController->SetSelectionAndActive(sel, new_line);
} }
@ -385,7 +385,7 @@ struct subtitle_select_all : public Command {
STR_HELP("Selects all dialogue lines") STR_HELP("Selects all dialogue lines")
void operator()(agi::Context *c) { void operator()(agi::Context *c) {
SelectionController<AssDialogue>::Selection sel; SubtitleSelection sel;
transform(c->ass->Line.begin(), c->ass->Line.end(), transform(c->ass->Line.begin(), c->ass->Line.end(),
inserter(sel, sel.begin()), cast<AssDialogue*>()); inserter(sel, sel.begin()), cast<AssDialogue*>());
sel.erase(0); sel.erase(0);

View File

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

View File

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

View File

@ -224,7 +224,7 @@ void DialogSelection::Process(wxCommandEvent&) {
int action = selection_change_type->GetSelection(); int action = selection_change_type->GetSelection();
SelectionController<AssDialogue>::Selection old_sel, new_sel; SubtitleSelection old_sel, new_sel;
if (action != ACTION_SET) if (action != ACTION_SET)
con->selectionController->GetSelectedSet(old_sel); 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_filename(STD_STR(StandardPaths::DecodePath("?user/shift_history.json")))
, history(new json::Array) , history(new json::Array)
, timecodes_loaded_slot(context->videoController->AddTimecodesListener(&DialogShiftTimes::OnTimecodesLoaded, this)) , 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)); SetIcon(GETICON(shift_times_toolbutton_16));
@ -129,7 +130,7 @@ DialogShiftTimes::DialogShiftTimes(agi::Context *context)
shift_backward = new wxRadioButton(this, -1, _("&Backward")); shift_backward = new wxRadioButton(this, -1, _("&Backward"));
shift_backward->SetToolTip(_("Shifts subs backward, making them appear earlier. Use if they are appearing too late.")); 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); 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") }; 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 // Set initial control states
OnTimecodesLoaded(context->videoController->FPS()); OnTimecodesLoaded(context->videoController->FPS());
OnSelectedSetChanged(Selection(), Selection()); OnSelectedSetChanged();
LoadHistory(); LoadHistory();
shift_time->SetTime(OPT_GET("Tool/Shift Times/Time")->GetInt()); 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); Bind(wxEVT_COMMAND_BUTTON_CLICKED, std::tr1::bind(&HelpButton::OpenPage, "Shift Times"), wxID_HELP);
shift_time->Bind(wxEVT_COMMAND_TEXT_ENTER, &DialogShiftTimes::Process, this); shift_time->Bind(wxEVT_COMMAND_TEXT_ENTER, &DialogShiftTimes::Process, this);
history_box->Bind(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, &DialogShiftTimes::OnHistoryClick, this); history_box->Bind(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, &DialogShiftTimes::OnHistoryClick, this);
context->selectionController->AddSelectionListener(this);
} }
DialogShiftTimes::~DialogShiftTimes() { DialogShiftTimes::~DialogShiftTimes() {
@ -209,8 +209,6 @@ DialogShiftTimes::~DialogShiftTimes() {
OPT_SET("Tool/Shift Times/Type")->SetInt(time_fields->GetSelection()); 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/Affect")->SetInt(selection_mode->GetSelection());
OPT_SET("Tool/Shift Times/Direction")->SetBool(shift_backward->GetValue()); OPT_SET("Tool/Shift Times/Direction")->SetBool(shift_backward->GetValue());
context->selectionController->RemoveSelectionListener(this);
} }
void DialogShiftTimes::OnTimecodesLoaded(agi::vfr::Framerate const& new_fps) { 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()) { if (context->selectionController->GetSelectedSet().empty()) {
selection_mode->Enable(1, false); selection_mode->Enable(1, false);
selection_mode->Enable(2, false); selection_mode->Enable(2, false);
@ -335,7 +333,7 @@ void DialogShiftTimes::Process(wxCommandEvent &) {
bool start = type != 2; bool start = type != 2;
bool end = type != 1; bool end = type != 1;
Selection sel = context->selectionController->GetSelectedSet(); SubtitleSelection sel = context->selectionController->GetSelectedSet();
long shift; long shift;
if (by_time) { if (by_time) {

View File

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

View File

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

View File

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

View File

@ -47,7 +47,6 @@
#include <libaegisub/signal.h> #include <libaegisub/signal.h>
#include "ass_style_storage.h" #include "ass_style_storage.h"
#include "selection_controller.h"
namespace agi { struct Context; } namespace agi { struct Context; }
class AssDialogue; class AssDialogue;
@ -61,11 +60,12 @@ class PersistLocation;
/// @brief DOCME /// @brief DOCME
/// ///
/// DOCME /// DOCME
class DialogStyleManager : public wxDialog, private SelectionListener<AssDialogue> { class DialogStyleManager : public wxDialog {
agi::Context *c; ///< Project context agi::Context *c; ///< Project context
agi::scoped_ptr<PersistLocation> persist; agi::scoped_ptr<PersistLocation> persist;
agi::signal::Connection commit_connection; agi::signal::Connection commit_connection;
agi::signal::Connection active_line_connection;
/// Styles in the current subtitle file /// Styles in the current subtitle file
std::vector<AssStyle*> styleMap; std::vector<AssStyle*> styleMap;
@ -152,7 +152,6 @@ class DialogStyleManager : public wxDialog, private SelectionListener<AssDialogu
void CopyToClipboard(wxListBox *list, T const& v); void CopyToClipboard(wxListBox *list, T const& v);
void OnActiveLineChanged(AssDialogue *new_line); void OnActiveLineChanged(AssDialogue *new_line);
void OnSelectedSetChanged(const Selection &, const Selection &) { }
public: public:
DialogStyleManager(agi::Context *context); 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) DialogStyling::DialogStyling(agi::Context *context)
: wxDialog(context->parent, -1, _("Styling Assistant"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX) : wxDialog(context->parent, -1, _("Styling Assistant"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX)
, c(context) , c(context)
, active_line_connection(context->selectionController->AddActiveLineListener(&DialogStyling::OnActiveLineChanged, this))
, active_line(0) , active_line(0)
{ {
SetIcon(GETICON(styling_toolbutton_16)); 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->Add(button_sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 5);
} }
main_sizer->SetSizeHints(this); SetSizerAndFit(main_sizer);
SetSizer(main_sizer);
persist.reset(new PersistLocation(this, "Tool/Styling Assistant")); persist.reset(new PersistLocation(this, "Tool/Styling Assistant"));
c->selectionController->AddSelectionListener(this);
Bind(wxEVT_ACTIVATE, &DialogStyling::OnActivate, this); Bind(wxEVT_ACTIVATE, &DialogStyling::OnActivate, this);
Bind(wxEVT_CHAR_HOOK, &DialogStyling::OnCharHook, this); Bind(wxEVT_CHAR_HOOK, &DialogStyling::OnCharHook, this);
style_name->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 () { DialogStyling::~DialogStyling () {
c->selectionController->RemoveSelectionListener(this);
} }
void DialogStyling::OnActiveLineChanged(AssDialogue *new_line) { void DialogStyling::OnActiveLineChanged(AssDialogue *new_line) {

View File

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

View File

@ -309,7 +309,7 @@ std::vector<AssDialogue*> DialogTimingProcessor::SortDialogues() {
sorted.reserve(c->ass->Line.size()); sorted.reserve(c->ass->Line.size());
if (onlySelection->IsChecked()) { 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), remove_copy_if(sel.begin(), sel.end(), back_inserter(sorted),
bind(bad_line, &styles, _1)); 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) : wxDialog(c->parent, -1, _("Translation Assistant"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX)
, c(c) , c(c)
, file_change_connection(c->ass->AddCommitListener(&DialogTranslation::OnExternalCommit, this)) , file_change_connection(c->ass->AddCommitListener(&DialogTranslation::OnExternalCommit, this))
, active_line_connection(c->selectionController->AddActiveLineListener(&DialogTranslation::OnActiveLineChanged, this))
, active_line(c->selectionController->GetActiveLine()) , active_line(c->selectionController->GetActiveLine())
, cur_block(0) , cur_block(0)
, line_count(count_if(c->ass->Line.begin(), c->ass->Line.end(), cast<AssDialogue*>())) , line_count(count_if(c->ass->Line.begin(), c->ass->Line.end(), cast<AssDialogue*>()))
@ -167,12 +168,9 @@ DialogTranslation::DialogTranslation(agi::Context *c)
} }
else else
UpdateDisplay(); UpdateDisplay();
c->selectionController->AddSelectionListener(this);
} }
DialogTranslation::~DialogTranslation() { DialogTranslation::~DialogTranslation() {
c->selectionController->RemoveSelectionListener(this);
} }
void DialogTranslation::OnActiveLineChanged(AssDialogue *new_line) { void DialogTranslation::OnActiveLineChanged(AssDialogue *new_line) {

View File

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

View File

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

View File

@ -39,30 +39,7 @@
#include <set> #include <set>
#endif #endif
/// @class SelectionListener #include <libaegisub/signal.h>
/// @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;
};
/// @class SelectionController /// @class SelectionController
/// @brief Abstract interface for selection controllers /// @brief Abstract interface for selection controllers
@ -88,8 +65,13 @@ public:
template <typename ItemDataType> template <typename ItemDataType>
class SelectionController { class SelectionController {
public: 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 destructor for safety
virtual ~SelectionController() { } virtual ~SelectionController() { }
@ -103,11 +85,11 @@ public:
/// the active line was actually changed. /// the active line was actually changed.
/// ///
/// This method must not affect the selected set. /// 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 /// @brief Obtain the active line
/// @return The active line or NULL if there is none /// @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 /// @brief Change the selected set
/// @param new_selection The set of subtitle lines to become the new 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 /// 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 to either of them, and is guaranteed to announce the active line
/// change before the selection change. /// 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 /// @brief Change the active line to the next in sequence
/// ///
@ -152,78 +134,10 @@ public:
/// the active line was changed. /// the active line was changed.
virtual void PrevLine() = 0; virtual void PrevLine() = 0;
/// @brief Subscribe an object to receive change notifications DEFINE_SIGNAL_ADDERS(AnnounceSelectedSetChanged, AddSelectionListener)
/// @param listener Object to subscribe to change notifications DEFINE_SIGNAL_ADDERS(AnnounceActiveLineChanged, AddActiveLineListener)
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;
}; };
class AssDialogue;
/// @class BaseSelectionController typedef SelectionController<AssDialogue *> SubtitleSelectionController;
/// @brief Base-implementation of SelectionController typedef SubtitleSelectionController::Selection SubtitleSelection;
///
/// 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) { }
};

View File

@ -246,13 +246,13 @@ SubsEditBox::SubsEditBox(wxWindow *parent, agi::Context *context)
wxSizeEvent evt; wxSizeEvent evt;
OnSize(evt); OnSize(evt);
c->selectionController->AddSelectionListener(this);
file_changed_slot = c->ass->AddCommitListener(&SubsEditBox::OnCommit, 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() { SubsEditBox::~SubsEditBox() {
c->selectionController->RemoveSelectionListener(this);
} }
wxTextCtrl *SubsEditBox::MakeMarginCtrl(wxString const& tooltip, void (SubsEditBox::*handler)(wxCommandEvent&)) { 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(); sel = c->selectionController->GetSelectedSet();
initialTimes.clear(); initialTimes.clear();
} }
@ -456,7 +456,7 @@ void SubsEditBox::CommitText(wxString desc) {
} }
void SubsEditBox::CommitTimes(TimeField field) { 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; AssDialogue *d = *cur;
if (!initialTimes.count(d)) if (!initialTimes.count(d))

View File

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

View File

@ -42,8 +42,6 @@
#include <libaegisub/signal.h> #include <libaegisub/signal.h>
#include "selection_controller.h"
namespace agi { struct Context; } namespace agi { struct Context; }
class AssDialogue; class AssDialogue;
class wxComboBox; class wxComboBox;
@ -51,7 +49,7 @@ class wxTextCtrl;
/// @class VideoBox /// @class VideoBox
/// @brief The box containing the video display and associated controls /// @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; std::list<agi::signal::Connection> slots;
agi::Context *context; ///< Project context agi::Context *context; ///< Project context
wxTextCtrl *VideoPosition; ///< Current frame/time wxTextCtrl *VideoPosition; ///< Current frame/time
@ -60,10 +58,6 @@ class VideoBox : public wxPanel, private SelectionListener<AssDialogue> {
/// Update VideoPosition and VideoSubsPos /// Update VideoPosition and VideoSubsPos
void UpdateTimeBoxes(); void UpdateTimeBoxes();
void OnSelectedSetChanged(Selection const&, Selection const&) { }
void OnActiveLineChanged(AssDialogue*) { UpdateTimeBoxes(); }
public: public:
VideoBox(wxWindow *parent, bool isDetached, agi::Context *context); 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); c->ass->GetResolution(script_w, script_h);
script_res = Vector2D(script_w, script_h); script_res = Vector2D(script_w, script_h);
active_line = GetActiveDialogueLine(); 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)); connections.push_back(c->videoController->AddSeekListener(&VisualToolBase::OnSeek, this));
parent->Bind(wxEVT_MOUSE_CAPTURE_LOST, &VisualToolBase::OnMouseCaptureLost, this); parent->Bind(wxEVT_MOUSE_CAPTURE_LOST, &VisualToolBase::OnMouseCaptureLost, this);
} }
VisualToolBase::~VisualToolBase() { VisualToolBase::~VisualToolBase() {
c->selectionController->RemoveSelectionListener(this);
} }
void VisualToolBase::OnCommit(int type) { void VisualToolBase::OnCommit(int type) {
@ -285,7 +284,7 @@ void VisualTool<FeatureType>::OnMouseEvent(wxMouseEvent &event) {
else { else {
if (!alt_down && features.size() > 1) { if (!alt_down && features.size() > 1) {
sel_features.clear(); sel_features.clear();
Selection sel; SubtitleSelection sel;
sel.insert(c->selectionController->GetActiveLine()); sel.insert(c->selectionController->GetActiveLine());
c->selectionController->SetSelectedSet(sel); c->selectionController->SetSelectedSet(sel);
need_render = true; need_render = true;
@ -328,7 +327,7 @@ void VisualTool<FeatureType>::SetSelection(feature_iterator feat, bool clear) {
sel_features.clear(); sel_features.clear();
if (sel_features.insert(feat).second && feat->line) { if (sel_features.insert(feat).second && feat->line) {
Selection sel; SubtitleSelection sel;
if (!clear) if (!clear)
sel = c->selectionController->GetSelectedSet(); sel = c->selectionController->GetSelectedSet();
if (sel.insert(feat->line).second) if (sel.insert(feat->line).second)
@ -344,7 +343,7 @@ void VisualTool<FeatureType>::RemoveSelection(feature_iterator feat) {
if ((*it)->line == feat->line) return; if ((*it)->line == feat->line) return;
} }
Selection sel = c->selectionController->GetSelectedSet(); SubtitleSelection sel = c->selectionController->GetSelectedSet();
// Don't deselect the only selected line // Don't deselect the only selected line
if (sel.size() <= 1) return; 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 /// different VisualTool<T>s are unrelated types otherwise. In addition, as much
/// functionality as possible is implemented here to avoid having four copies /// 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) /// of each method for no good reason (and four times as many error messages)
class VisualToolBase : protected SelectionListener<AssDialogue> { class VisualToolBase {
std::deque<agi::signal::Connection> connections;
void OnCommit(int type); void OnCommit(int type);
void OnSeek(int new_frame); void OnSeek(int new_frame);
@ -70,7 +68,6 @@ class VisualToolBase : protected SelectionListener<AssDialogue> {
// SubtitleSelectionListener implementation // SubtitleSelectionListener implementation
void OnActiveLineChanged(AssDialogue *new_line); void OnActiveLineChanged(AssDialogue *new_line);
void OnSelectedSetChanged(const Selection &, const Selection &) { }
// Below here are the virtuals that must be implemented // Below here are the virtuals that must be implemented
@ -92,6 +89,8 @@ class VisualToolBase : protected SelectionListener<AssDialogue> {
virtual void DoRefresh() { } virtual void DoRefresh() { }
protected: protected:
std::deque<agi::signal::Connection> connections;
OpenGLWrapper gl; OpenGLWrapper gl;
/// Called when the user double-clicks /// Called when the user double-clicks

View File

@ -42,8 +42,8 @@ VisualToolCross::~VisualToolCross() {
void VisualToolCross::OnDoubleClick() { void VisualToolCross::OnDoubleClick() {
Vector2D d = ToScriptCoords(mouse_pos) - GetLinePosition(active_line); Vector2D d = ToScriptCoords(mouse_pos) - GetLinePosition(active_line);
Selection sel = c->selectionController->GetSelectedSet(); SubtitleSelection sel = c->selectionController->GetSelectedSet();
for (Selection::const_iterator it = sel.begin(); it != sel.end(); ++it) { for (SubtitleSelection::const_iterator it = sel.begin(); it != sel.end(); ++it) {
Vector2D p1, p2; Vector2D p1, p2;
int t1, t2; int t1, t2;
if (GetLineMove(*it, p1, p2, 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) , button_is_move(true)
{ {
c->selectionController->GetSelectedSet(selection); c->selectionController->GetSelectedSet(selection);
connections.push_back(c->selectionController->AddSelectionListener(&VisualToolDrag::OnSelectedSetChanged, this));
} }
void VisualToolDrag::SetToolbar(wxToolBar *tb) { void VisualToolDrag::SetToolbar(wxToolBar *tb) {
@ -82,7 +83,7 @@ void VisualToolDrag::UpdateToggleButtons() {
void VisualToolDrag::OnSubTool(wxCommandEvent &) { void VisualToolDrag::OnSubTool(wxCommandEvent &) {
// Toggle \move <-> \pos // Toggle \move <-> \pos
VideoContext *vc = c->videoController; 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; AssDialogue *line = *cur;
Vector2D p1, p2; Vector2D p1, p2;
int t1, t2; 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(); 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); c->selectionController->GetSelectedSet(selection);
bool any_changed = false; bool any_changed = false;
@ -310,8 +311,8 @@ void VisualToolDrag::UpdateDrag(feature_iterator feature) {
void VisualToolDrag::OnDoubleClick() { void VisualToolDrag::OnDoubleClick() {
Vector2D d = ToScriptCoords(mouse_pos) - (primary ? ToScriptCoords(primary->pos) : GetLinePosition(active_line)); Vector2D d = ToScriptCoords(mouse_pos) - (primary ? ToScriptCoords(primary->pos) : GetLinePosition(active_line));
Selection sel = c->selectionController->GetSelectedSet(); SubtitleSelection sel = c->selectionController->GetSelectedSet();
for (Selection::const_iterator it = sel.begin(); it != sel.end(); ++it) { for (SubtitleSelection::const_iterator it = sel.begin(); it != sel.end(); ++it) {
Vector2D p1, p2; Vector2D p1, p2;
int t1, t2; int t1, t2;
if (GetLineMove(*it, p1, p2, t1, t2)) { if (GetLineMove(*it, p1, p2, t1, t2)) {

View File

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