Add support for noncontiguous selections to the duplicate lines commands

Originally committed to SVN as r6476.
This commit is contained in:
Thomas Goyne 2012-02-15 22:14:10 +00:00
parent d4e1c90a04
commit 9b69ce7a27
3 changed files with 56 additions and 41 deletions

View file

@ -133,6 +133,60 @@ struct edit_line_delete : public validate_sel_nonempty {
}
};
struct in_selection : public std::unary_function<AssEntry*, bool> {
SubtitleSelectionController::Selection const& sel;
in_selection(SubtitleSelectionController::Selection const& sel) : sel(sel) { }
bool operator()(AssEntry *e) const {
AssDialogue *d = dynamic_cast<AssDialogue*>(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<AssEntry*>::iterator start = c->ass->Line.begin();
std::list<AssEntry*>::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<AssEntry*>::iterator insert_pos = find_if(start, end, std::not1(sel));
std::list<AssEntry*>::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<AssDialogue*>((*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);
}
};

View file

@ -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<AssEntry*>::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
///

View file

@ -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