From 9b69ce7a27ff2497bd96e579a32d0a8e399a5010 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Wed, 15 Feb 2012 22:14:10 +0000 Subject: [PATCH] Add support for noncontiguous selections to the duplicate lines commands Originally committed to SVN as r6476. --- aegisub/src/command/edit.cpp | 60 +++++++++++++++++++++++++++++++++--- aegisub/src/subs_grid.cpp | 31 ------------------- aegisub/src/subs_grid.h | 6 ---- 3 files changed, 56 insertions(+), 41 deletions(-) diff --git a/aegisub/src/command/edit.cpp b/aegisub/src/command/edit.cpp index 34cd16e16..f8ec605d4 100644 --- a/aegisub/src/command/edit.cpp +++ b/aegisub/src/command/edit.cpp @@ -133,6 +133,60 @@ struct edit_line_delete : public validate_sel_nonempty { } }; +struct in_selection : public std::unary_function { + SubtitleSelectionController::Selection const& sel; + in_selection(SubtitleSelectionController::Selection const& sel) : sel(sel) { } + bool operator()(AssEntry *e) const { + AssDialogue *d = dynamic_cast(e); + return d && sel.count(d); + } +}; + +static void duplicate_lines(agi::Context *c, bool shift) { + in_selection sel(c->selectionController->GetSelectedSet()); + SubtitleSelectionController::Selection new_sel; + AssDialogue *new_active = 0; + + std::list::iterator start = c->ass->Line.begin(); + std::list::iterator end = c->ass->Line.end(); + while (start != end) { + // Find the first line in the selection + start = find_if(start, end, sel); + if (start == end) break; + + // And the last line in this contiguous selection + std::list::iterator insert_pos = find_if(start, end, std::not1(sel)); + std::list::iterator last = insert_pos; + --last; + + // Duplicate each of the selected lines, inserting them in a block + // after the selected block + do { + AssDialogue *new_diag = static_cast((*start)->Clone()); + + c->ass->Line.insert(insert_pos, new_diag); + new_sel.insert(new_diag); + if (!new_active) + new_active = new_diag; + + if (shift) { + int pos = c->videoController->FrameAtTime(new_diag->End, agi::vfr::END) + 1; + new_diag->Start = c->videoController->TimeAtFrame(pos, agi::vfr::START); + new_diag->End = c->videoController->TimeAtFrame(pos, agi::vfr::END); + } + } while (start++ != last); + + // Skip over the lines we just made + start = insert_pos; + } + + if (new_sel.empty()) return; + + c->ass->Commit(_("duplicate lines"), AssFile::COMMIT_DIAG_ADDREM); + + c->selectionController->SetSelectedSet(new_sel); + c->selectionController->SetActiveLine(new_active); +} /// Duplicate the selected lines. struct edit_line_duplicate : public validate_sel_nonempty { @@ -142,8 +196,7 @@ struct edit_line_duplicate : public validate_sel_nonempty { STR_HELP("Duplicate the selected lines") void operator()(agi::Context *c) { - wxArrayInt sels = c->subsGrid->GetSelection(); - c->subsGrid->DuplicateLines(sels.front(), sels.back(), false); + duplicate_lines(c, false); } }; @@ -161,8 +214,7 @@ struct edit_line_duplicate_shift : public Command { } void operator()(agi::Context *c) { - wxArrayInt sels = c->subsGrid->GetSelection(); - c->subsGrid->DuplicateLines(sels.front(), sels.back(), true); + duplicate_lines(c, true); } }; diff --git a/aegisub/src/subs_grid.cpp b/aegisub/src/subs_grid.cpp index c53083911..7d1397ab2 100644 --- a/aegisub/src/subs_grid.cpp +++ b/aegisub/src/subs_grid.cpp @@ -373,37 +373,6 @@ void SubtitlesGrid::AdjoinLines(int n1,int n2,bool setStart) { context->ass->Commit(_("adjoin"), AssFile::COMMIT_DIAG_TIME); } -void SubtitlesGrid::DuplicateLines(int n1, int n2, bool nextFrame) { - std::list::iterator insert_pos = find(context->ass->Line.begin(), context->ass->Line.end(), GetDialogue(n2)); - if (insert_pos != context->ass->Line.end()) - ++insert_pos; - - Selection newsel; - - AssDialogue *first = 0; - - for (int i = n1; i <= n2; ++i) { - AssDialogue *diag = new AssDialogue(*GetDialogue(i)); - if (!first) - first = diag; - - context->ass->Line.insert(insert_pos, diag); - newsel.insert(diag); - - // Shift to next frame - if (nextFrame) { - int posFrame = context->videoController->FrameAtTime(diag->End, agi::vfr::END) + 1; - diag->Start = context->videoController->TimeAtFrame(posFrame, agi::vfr::START); - diag->End = context->videoController->TimeAtFrame(posFrame, agi::vfr::END); - } - } - - context->ass->Commit(_("duplicate lines"), AssFile::COMMIT_DIAG_ADDREM); - - SetSelectedSet(newsel); - SetActiveLine(first); -} - /// @brief Retrieve a list of selected lines in the actual ASS file (ie. not as displayed in the grid but as represented in the file) /// @return /// diff --git a/aegisub/src/subs_grid.h b/aegisub/src/subs_grid.h index 56d79bfb4..192b6327a 100644 --- a/aegisub/src/subs_grid.h +++ b/aegisub/src/subs_grid.h @@ -58,12 +58,6 @@ public: /// @param setStart Set the start times (rather than end times) void AdjoinLines(int first,int last,bool setStart); - /// @brief Duplicate lines - /// @param n1 First frame to duplicate - /// @param n2 Last frame to duplicate - /// @param nextFrame Set the new lines to start and end on the next frame - void DuplicateLines(int first,int last,bool nextFrame=false); - void InsertLine(AssDialogue *line,int position,bool insertAfter,bool update=true); /// @brief Delete selected lines /// @param target Lines to delete