| 557 | } |
| 558 | |
| 559 | static void delete_lines(agi::Context *c, wxString const& commit_message) { |
| 560 | auto const& sel = c->selectionController->GetSelectedSet(); |
| 561 | |
| 562 | // Find a line near the active line not being deleted to make the new active line |
| 563 | AssDialogue *pre_sel = nullptr; |
| 564 | AssDialogue *post_sel = nullptr; |
| 565 | bool hit_selection = false; |
| 566 | |
| 567 | for (auto& diag : c->ass->Events) { |
| 568 | if (sel.count(&diag)) |
| 569 | hit_selection = true; |
| 570 | else if (hit_selection && !post_sel) { |
| 571 | post_sel = &diag; |
| 572 | break; |
| 573 | } |
| 574 | else |
| 575 | pre_sel = &diag; |
| 576 | } |
| 577 | |
| 578 | // Remove the selected lines, but defer the deletion until after we select |
| 579 | // different lines. We can't just change the selection first because we may |
| 580 | // need to create a new dialogue line for it, and we can't select dialogue |
| 581 | // lines until after they're committed. |
| 582 | std::vector<std::unique_ptr<AssDialogue>> to_delete; |
| 583 | c->ass->Events.remove_and_dispose_if([&sel](AssDialogue const& e) { |
| 584 | return sel.count(const_cast<AssDialogue *>(&e)); |
| 585 | }, [&](AssDialogue *e) { |
| 586 | to_delete.emplace_back(e); |
| 587 | }); |
| 588 | |
| 589 | AssDialogue *new_active = post_sel; |
| 590 | if (!new_active) |
| 591 | new_active = pre_sel; |
| 592 | // If we didn't get a new active line then we just deleted all the dialogue |
| 593 | // lines, so make a new one |
| 594 | if (!new_active) { |
| 595 | new_active = new AssDialogue; |
| 596 | c->ass->Events.push_back(*new_active); |
| 597 | } |
| 598 | |
| 599 | c->ass->Commit(commit_message, AssFile::COMMIT_DIAG_ADDREM); |
| 600 | c->selectionController->SetSelectionAndActive({ new_active }, new_active); |
| 601 | } |
| 602 | |
| 603 | struct edit_line_copy final : public validate_sel_nonempty { |
| 604 | CMD_NAME("edit/line/copy") |
no test coverage detected