From 2e5dc176dbe999e9fcd46f8997eee98b5a41b9ef Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Fri, 9 Jul 2010 07:31:34 +0000 Subject: [PATCH] Rewrite Undo/Redo code Make the undo and redo stacks non-static members of AssFile, making it theoretically possible to have multiple open AssFiles with working undo. Slightly improve tracking of whether the file is modified: saving, making a change, then undoing the change now results in the file being shown as unmodified as with most programs with undo. Add basic undo coalescing support. Originally committed to SVN as r4667. --- aegisub/src/ass_file.cpp | 181 +++++++++-------------- aegisub/src/ass_file.h | 61 +++----- aegisub/src/audio_display.cpp | 2 +- aegisub/src/auto4_lua_assfile.cpp | 2 +- aegisub/src/dialog_attachments.cpp | 8 +- aegisub/src/dialog_fonts_collector.cpp | 2 +- aegisub/src/dialog_kara_timing_copy.cpp | 2 +- aegisub/src/dialog_properties.cpp | 2 +- aegisub/src/dialog_resample.cpp | 2 +- aegisub/src/dialog_search_replace.cpp | 4 +- aegisub/src/dialog_shift_times.cpp | 2 +- aegisub/src/dialog_spellchecker.cpp | 2 +- aegisub/src/dialog_style_editor.cpp | 2 +- aegisub/src/dialog_style_manager.cpp | 12 +- aegisub/src/dialog_styling_assistant.cpp | 6 +- aegisub/src/dialog_timing_processor.cpp | 2 +- aegisub/src/dialog_translation.cpp | 2 +- aegisub/src/frame_main.cpp | 11 +- aegisub/src/frame_main_events.cpp | 26 ++-- aegisub/src/subs_edit_box.cpp | 22 +-- aegisub/src/subs_grid.cpp | 22 +-- aegisub/src/visual_tool.cpp | 2 +- 22 files changed, 158 insertions(+), 219 deletions(-) diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp index b52b17176..d1efac841 100644 --- a/aegisub/src/ass_file.cpp +++ b/aegisub/src/ass_file.cpp @@ -61,10 +61,17 @@ #include "utils.h" #include "version.h" +namespace std { + template<> + void swap(AssFile &lft, AssFile &rgt) { + lft.swap(rgt); + } +} + /// @brief AssFile constructor -AssFile::AssFile () { - loaded = false; - Modified = false; +AssFile::AssFile () +: loaded(false) +{ } /// @brief AssFile destructor @@ -74,6 +81,7 @@ AssFile::~AssFile() { void AssFile::Load (const wxString &_filename,wxString charset,bool addToRecent) { bool ok = false; + Clear(); try { // Try to open file @@ -141,6 +149,10 @@ void AssFile::Load (const wxString &_filename,wxString charset,bool addToRecent) AddComment(_T("http://www.aegisub.org/")); SetScriptInfo(_T("ScriptType"),_T("v4.00+")); + // Push the initial state of the file onto the undo stack + Commit("", commitId); + savedCommitId = commitId; + // Add to recent if (addToRecent) AddToRecent(_filename); } @@ -171,7 +183,7 @@ void AssFile::Save(wxString _filename,bool setfilename,bool addToRecent,const wx // Done if (setfilename) { - Modified = false; + savedCommitId = commitId; filename = _filename; } } @@ -416,7 +428,11 @@ void AssFile::Clear() { loaded = false; filename.clear(); - Modified = false; + UndoStack.clear(); + RedoStack.clear(); + undoDescription.clear(); + commitId = -1; + savedCommitId = 0; } void AssFile::LoadDefault (bool defline) { @@ -445,20 +461,30 @@ void AssFile::LoadDefault (bool defline) { AddLine(def.GetEntryData(),_T("[Events]"),version); } + Commit(""); + savedCommitId = commitId; loaded = true; } -AssFile::AssFile (const AssFile &from) { - filename = from.filename; - loaded = from.loaded; - Modified = from.Modified; +void AssFile::swap(AssFile &that) throw() { + // Intentionally does not swap undo stack related things + std::swap(filename, that.filename); + std::swap(loaded, that.loaded); + std::swap(commitId, that.commitId); + std::swap(undoDescription, that.undoDescription); + std::swap(Line, that.Line); +} + +AssFile::AssFile(const AssFile &from) +: undoDescription(from.undoDescription) +, commitId(from.commitId) +, filename(from.filename) +, loaded(from.loaded) +{ std::transform(from.Line.begin(), from.Line.end(), std::back_inserter(Line), std::mem_fun(&AssEntry::Clone)); } AssFile& AssFile::operator=(AssFile from) { - filename = from.filename; - loaded = from.loaded; - Modified = from.Modified; - std::swap(Line, from.Line); + std::swap(*this, from); return *this; } @@ -747,120 +773,55 @@ void AssFile::CompressForStack() { } } -bool AssFile::IsModified() { - return Modified; -} - -void AssFile::FlagAsModified(wxString desc) { - if (!RedoStack.empty()) { - delete_clear(RedoStack); +int AssFile::Commit(wxString desc, int amendId) { + ++commitId; + // Allow coalescing only if it's the last change and the file has not been + // saved since the last change + if (commitId == amendId+1 && RedoStack.empty() && savedCommitId != commitId) { + UndoStack.back() = *this; + UndoStack.back().CompressForStack(); + return commitId; } - Modified = true; - StackPush(desc); -} + RedoStack.clear(); -void AssFile::StackPush(wxString desc) { - // Places copy on stack - AssFile *curcopy = new AssFile(*top); - curcopy->CompressForStack(); - curcopy->undodescription = desc; - UndoStack.push_back(curcopy); - StackModified = true; + // Place copy on stack + undoDescription = desc; + UndoStack.push_back(*this); + UndoStack.back().CompressForStack(); // Cap depth - int n = 0; - for (std::list::iterator cur=UndoStack.begin();cur!=UndoStack.end();cur++) { - n++; - } int depth = OPT_GET("Limits/Undo Levels")->GetInt(); - while (n > depth) { - delete UndoStack.front(); + while ((int)UndoStack.size() > depth) { UndoStack.pop_front(); - n--; - } -} - -void AssFile::StackPop() { - bool addcopy = false; - wxString undodesc=""; - - - if (StackModified) { - undodesc=UndoStack.back()->undodescription; - delete UndoStack.back(); - UndoStack.pop_back(); - StackModified = false; - addcopy = true; } - if (!UndoStack.empty()) { - //delete top; - AssFile *undo = UndoStack.back(); - top->CompressForStack(); - top->undodescription = undodesc; - RedoStack.push_back(top); - top = undo; - UndoStack.pop_back(); - Popping = true; - } - - if (addcopy) { - StackPush(top->undodescription); - } + return commitId; } -void AssFile::StackRedo() { - bool addcopy = false; - if (StackModified) { - delete UndoStack.back(); - UndoStack.pop_back(); - StackModified = false; - addcopy = true; - } +void AssFile::Undo() { + if (UndoStack.size() <= 1) return; - if (!RedoStack.empty()) { - top->CompressForStack(); - UndoStack.push_back(top); - top = RedoStack.back(); - RedoStack.pop_back(); - Popping = true; - } - - if (addcopy) { - StackPush(top->undodescription); - } + RedoStack.push_back(AssFile()); + std::swap(RedoStack.back(), *this); + UndoStack.pop_back(); + *this = UndoStack.back(); } -void AssFile::StackClear() { - delete_clear(UndoStack); - delete_clear(RedoStack); +void AssFile::Redo() { + if (RedoStack.empty()) return; - Popping = false; + std::swap(*this, RedoStack.back()); + UndoStack.push_back(*this); + RedoStack.pop_back(); } -void AssFile::StackReset() { - StackClear(); - delete top; - top = new AssFile; - StackModified = false; +wxString AssFile::GetUndoDescription() const { + return IsUndoStackEmpty() ? "" : UndoStack.back().undoDescription; } -bool AssFile::IsUndoStackEmpty() { - if (StackModified) return (UndoStack.size() <= 1); - else return UndoStack.empty(); -} - -bool AssFile::IsRedoStackEmpty() { - return RedoStack.empty(); -} - -wxString AssFile::GetUndoDescription() { - return (IsUndoStackEmpty())?_T(""):(UndoStack.back())->undodescription; -} - -wxString AssFile::GetRedoDescription() { - return (IsRedoStackEmpty())?_T(""):(RedoStack.back())->undodescription; +wxString AssFile::GetRedoDescription() const { + return IsRedoStackEmpty() ? "" : RedoStack.back().undoDescription; } bool AssFile::CompStart(const AssDialogue* lft, const AssDialogue* rgt) { @@ -909,7 +870,3 @@ void AssFile::Sort(std::list &lst, CompFunc comp) { } AssFile *AssFile::top; -std::list AssFile::UndoStack; -std::list AssFile::RedoStack; -bool AssFile::Popping; -bool AssFile::StackModified; diff --git a/aegisub/src/ass_file.h b/aegisub/src/ass_file.h index 4457ba226..fb5113eff 100644 --- a/aegisub/src/ass_file.h +++ b/aegisub/src/ass_file.h @@ -62,26 +62,15 @@ typedef std::list::iterator entryIter; /// /// DOCME class AssFile { -private: - - /// DOCME - bool Modified; - - - /// DOCME - static std::list UndoStack; - - /// DOCME - static std::list RedoStack; - - /// DOCME - static bool StackModified; - static void StackClear(); - - wxString undodescription; + std::list UndoStack; + std::list RedoStack; + wxString undoDescription; + /// Revision counter for undo coalescing and modified state tracking + int commitId; + /// Last saved version of this file + int savedCommitId; public: - /// The lines in the file std::list Line; /// The filename of this file, if any @@ -95,12 +84,10 @@ public: ~AssFile(); /// Does the file have unsaved changes? - bool IsModified(); - /// @brief Flag the file as modified and push a copy onto the undo stack - /// @param desc Undo description - void FlagAsModified(wxString desc); + bool IsModified() const {return commitId != savedCommitId; }; /// Clear the file void Clear(); + /// Discard some parsed data to reduce the size of the undo stack void CompressForStack(); /// @brief Load default file @@ -119,6 +106,7 @@ public: /// @return Pointer to style or NULL AssStyle *GetStyle(wxString name); + void swap(AssFile &) throw(); /// @brief Load from a file /// @param file File name @@ -164,26 +152,23 @@ public: /// @param[out] outGroup Group it was actually added to; attachments do something strange here void AddLine(wxString data,wxString group,int &version,wxString *outGroup=NULL); - /// Pop subs from stack and set 'top' to it - static void StackPop(); - /// Redo action on stack - static void StackRedo(); - /// @brief Put a copy of 'top' on the stack - /// @param desc Undo message - static void StackPush(wxString desc); - /// Clear the stack. Do before loading new subtitles. - static void StackReset(); + /// @brief Flag the file as modified and push a copy onto the undo stack + /// @param desc Undo description + /// @param commitId Commit to amend rather than pushing a new commit + /// @return Unique identifier for the new undo group + int Commit(wxString desc, int commitId = -1); + /// @brief Undo the last set of changes to the file + void Undo(); + /// @brief Redo the last undone changes + void Redo(); /// Check if undo stack is empty - static bool IsUndoStackEmpty(); + bool IsUndoStackEmpty() const { return UndoStack.size() <= 1; }; /// Check if redo stack is empty - static bool IsRedoStackEmpty(); + bool IsRedoStackEmpty() const { return RedoStack.empty(); }; /// Get the description of the first undoable change - static wxString GetUndoDescription(); + wxString GetUndoDescription() const; /// Get the description of the first redoable change - static wxString GetRedoDescription(); - - /// Flags the stack as popping. You must unset this after popping - static bool Popping; + wxString GetRedoDescription() const; /// Current script file. It is "above" the stack. static AssFile *top; diff --git a/aegisub/src/audio_display.cpp b/aegisub/src/audio_display.cpp index 6c76f1ab2..e4126148e 100644 --- a/aegisub/src/audio_display.cpp +++ b/aegisub/src/audio_display.cpp @@ -1209,7 +1209,7 @@ void AudioDisplay::CommitChanges (bool nextLine) { // Update grid grid->editBox->Update(!karaoke->enabled); - grid->ass->FlagAsModified(_T("")); + grid->ass->Commit(_T("")); grid->CommitChanges(); karaoke->SetSelection(karaSelStart, karaSelEnd); blockUpdate = false; diff --git a/aegisub/src/auto4_lua_assfile.cpp b/aegisub/src/auto4_lua_assfile.cpp index 86de10394..345929330 100644 --- a/aegisub/src/auto4_lua_assfile.cpp +++ b/aegisub/src/auto4_lua_assfile.cpp @@ -1014,7 +1014,7 @@ namespace Automation4 { description = wxString(lua_tostring(L, 1), wxConvUTF8); lua_pop(L, 1); } - AssFile::top->FlagAsModified(description); + AssFile::top->Commit(description); laf->ass = AssFile::top; // make sure we're still working on the most recent undo point return 0; diff --git a/aegisub/src/dialog_attachments.cpp b/aegisub/src/dialog_attachments.cpp index 4889ef580..37b996fd3 100644 --- a/aegisub/src/dialog_attachments.cpp +++ b/aegisub/src/dialog_attachments.cpp @@ -174,7 +174,7 @@ DialogAttachments::~DialogAttachments() { } if (removed_any) { - AssFile::top->FlagAsModified(_("remove empty attachments sections")); + AssFile::top->Commit(_("remove empty attachments sections")); } } @@ -223,7 +223,7 @@ void DialogAttachments::OnAttachFont(wxCommandEvent &event) { AssFile::top->InsertAttachment(newAttach); } - AssFile::top->FlagAsModified(_("attach font file")); + AssFile::top->Commit(_("attach font file")); // Update UpdateList(); @@ -261,7 +261,7 @@ void DialogAttachments::OnAttachGraphics(wxCommandEvent &event) { AssFile::top->InsertAttachment(newAttach); } - AssFile::top->FlagAsModified(_("attach graphics file")); + AssFile::top->Commit(_("attach graphics file")); // Update UpdateList(); @@ -316,7 +316,7 @@ void DialogAttachments::OnDelete(wxCommandEvent &event) { i = listView->GetNextSelected(i); } - AssFile::top->FlagAsModified(_("remove attachment")); + AssFile::top->Commit(_("remove attachment")); // Update list UpdateList(); diff --git a/aegisub/src/dialog_fonts_collector.cpp b/aegisub/src/dialog_fonts_collector.cpp index 642f7ec0e..6270cbfed 100644 --- a/aegisub/src/dialog_fonts_collector.cpp +++ b/aegisub/src/dialog_fonts_collector.cpp @@ -514,7 +514,7 @@ void FontsCollectorThread::Collect() { // Modify file if it was attaching if (oper == 3 && someOk) { wxMutexGuiEnter(); - subs->FlagAsModified(_("font attachment")); + subs->Commit(_("font attachment")); collector->main->SubsGrid->CommitChanges(); wxMutexGuiLeave(); } diff --git a/aegisub/src/dialog_kara_timing_copy.cpp b/aegisub/src/dialog_kara_timing_copy.cpp index 909bb7c62..d616b6ac6 100644 --- a/aegisub/src/dialog_kara_timing_copy.cpp +++ b/aegisub/src/dialog_kara_timing_copy.cpp @@ -940,7 +940,7 @@ void DialogKanjiTimer::OnClose(wxCommandEvent &event) { line->Text = p.second; } if (modified) { - grid->ass->FlagAsModified(_("kanji timing")); + grid->ass->Commit(_("kanji timing")); grid->CommitChanges(); grid->UpdateMaps(); LinesToChange.clear(); diff --git a/aegisub/src/dialog_properties.cpp b/aegisub/src/dialog_properties.cpp index 07e2ccafa..e6e3d82ed 100644 --- a/aegisub/src/dialog_properties.cpp +++ b/aegisub/src/dialog_properties.cpp @@ -211,7 +211,7 @@ void DialogProperties::OnOK(wxCommandEvent &event) { count += SetInfoIfDifferent(_T("Collisions"),col[collision->GetSelection()]); count += SetInfoIfDifferent(_T("ScaledBorderAndShadow"),ScaleBorder->GetValue()? _T("yes") : _T("no")); - if (count) AssFile::top->FlagAsModified(_("property changes")); + if (count) AssFile::top->Commit(_("property changes")); EndModal(count?1:0); } diff --git a/aegisub/src/dialog_resample.cpp b/aegisub/src/dialog_resample.cpp index 9ade6a5c9..7e81fd147 100644 --- a/aegisub/src/dialog_resample.cpp +++ b/aegisub/src/dialog_resample.cpp @@ -321,7 +321,7 @@ void DialogResample::OnResample (wxCommandEvent &event) { subs->SetScriptInfo(_T("PlayResY"),wxString::Format(_T("%i"),y2)); // Flag as modified - subs->FlagAsModified(_("resolution resampling")); + subs->Commit(_("resolution resampling")); grid->CommitChanges(); grid->editBox->Update(); EndModal(0); diff --git a/aegisub/src/dialog_search_replace.cpp b/aegisub/src/dialog_search_replace.cpp index 4ce6500dd..9df698444 100644 --- a/aegisub/src/dialog_search_replace.cpp +++ b/aegisub/src/dialog_search_replace.cpp @@ -437,7 +437,7 @@ void SearchReplaceEngine::ReplaceNext(bool DoReplace) { } // Commit - grid->ass->FlagAsModified(_("replace")); + grid->ass->Commit(_("replace")); grid->CommitChanges(); } @@ -544,7 +544,7 @@ void SearchReplaceEngine::ReplaceAll() { // Commit if (count > 0) { - grid->ass->FlagAsModified(_("replace")); + grid->ass->Commit(_("replace")); grid->CommitChanges(); grid->editBox->Update(); wxMessageBox(wxString::Format(_("%i matches were replaced."),count)); diff --git a/aegisub/src/dialog_shift_times.cpp b/aegisub/src/dialog_shift_times.cpp index bdd28722b..52e89c745 100644 --- a/aegisub/src/dialog_shift_times.cpp +++ b/aegisub/src/dialog_shift_times.cpp @@ -311,7 +311,7 @@ void DialogShiftTimes::OnOK(wxCommandEvent &event) { OPT_SET("Tool/Shift Times/Direction")->SetBool(backward); // End dialog - grid->ass->FlagAsModified(_("shifting")); + grid->ass->Commit(_("shifting")); grid->CommitChanges(); grid->UpdateMaps(); grid->editBox->Update(); diff --git a/aegisub/src/dialog_spellchecker.cpp b/aegisub/src/dialog_spellchecker.cpp index 947c757f7..8355aba13 100644 --- a/aegisub/src/dialog_spellchecker.cpp +++ b/aegisub/src/dialog_spellchecker.cpp @@ -390,7 +390,7 @@ void DialogSpellChecker::Replace() { lastPos = wordStart + replaceWord->GetValue().Length(); // Commit - grid->ass->FlagAsModified(_("Spell check replace")); + grid->ass->Commit(_("Spell check replace")); grid->CommitChanges(); } diff --git a/aegisub/src/dialog_style_editor.cpp b/aegisub/src/dialog_style_editor.cpp index 76906b3a0..7e293401d 100644 --- a/aegisub/src/dialog_style_editor.cpp +++ b/aegisub/src/dialog_style_editor.cpp @@ -581,7 +581,7 @@ void DialogStyleEditor::Apply (bool apply,bool close) { *style = *work; style->UpdateData(); if (isLocal) { - AssFile::top->FlagAsModified(_("style change")); + AssFile::top->Commit(_("style change")); grid->CommitChanges(); } diff --git a/aegisub/src/dialog_style_manager.cpp b/aegisub/src/dialog_style_manager.cpp index 20642ddeb..093128e6d 100644 --- a/aegisub/src/dialog_style_manager.cpp +++ b/aegisub/src/dialog_style_manager.cpp @@ -576,7 +576,7 @@ void DialogStyleManager::OnCopyToCurrent (wxCommandEvent &) { for (list::iterator name = copied.begin(); name != copied.end(); ++name) { CurrentList->SetStringSelection(*name, true); } - grid->ass->FlagAsModified(_("style copy")); + grid->ass->Commit(_("style copy")); grid->CommitChanges(); wxCommandEvent dummy; OnCurrentChange(dummy); @@ -625,7 +625,7 @@ void DialogStyleManager::OnCurrentCopy (wxCommandEvent &) { } else delete temp; - grid->ass->FlagAsModified(_("style copy")); + grid->ass->Commit(_("style copy")); grid->CommitChanges(); UpdateMoveButtons(); } @@ -678,7 +678,7 @@ void DialogStyleManager::PasteToCurrent() { AssFile::top->InsertStyle(s); LoadCurrentStyles(AssFile::top); - grid->ass->FlagAsModified(_("style paste")); + grid->ass->Commit(_("style paste")); grid->CommitChanges(); } else @@ -822,7 +822,7 @@ void DialogStyleManager::OnCurrentDelete (wxCommandEvent &) { CurrentCopy->Enable(false); CurrentDelete->Enable(false); - grid->ass->FlagAsModified(_("style delete")); + grid->ass->Commit(_("style delete")); grid->CommitChanges(); } UpdateMoveButtons(); @@ -884,7 +884,7 @@ void DialogStyleManager::OnCurrentImport(wxCommandEvent &) { // Update if (modified) { LoadCurrentStyles(grid->ass); - grid->ass->FlagAsModified(_("style import")); + grid->ass->Commit(_("style import")); grid->CommitChanges(); } } @@ -1081,7 +1081,7 @@ void DialogStyleManager::MoveStyles(bool storage, int type) { } // Flag as modified - grid->ass->FlagAsModified(_("style move")); + grid->ass->Commit(_("style move")); grid->CommitChanges(); } diff --git a/aegisub/src/dialog_styling_assistant.cpp b/aegisub/src/dialog_styling_assistant.cpp index bbca46811..e21c0fa1b 100644 --- a/aegisub/src/dialog_styling_assistant.cpp +++ b/aegisub/src/dialog_styling_assistant.cpp @@ -169,7 +169,7 @@ wxDialog (parent, -1, _("Styling assistant"), wxDefaultPosition, wxDefaultSize, DialogStyling::~DialogStyling () { GetPosition(&lastx, &lasty); if (needCommit) { - grid->ass->FlagAsModified(_("style changes")); + grid->ass->Commit(_("style changes")); grid->CommitChanges(); } } @@ -232,7 +232,7 @@ void DialogStyling::SetStyle (wxString curName, bool jump) { // Update grid/subs grid->Refresh(false); if (PreviewCheck->IsChecked()) { - grid->ass->FlagAsModified(_("styling assistant")); + grid->ass->Commit(_("styling assistant")); grid->CommitChanges(); } else needCommit = true; @@ -264,7 +264,7 @@ void DialogStyling::OnActivate(wxActivateEvent &event) { // Dialog lost focus if (!event.GetActive()) { if (needCommit) { - grid->ass->FlagAsModified(_("styling assistant")); + grid->ass->Commit(_("styling assistant")); grid->CommitChanges(); needCommit = false; } diff --git a/aegisub/src/dialog_timing_processor.cpp b/aegisub/src/dialog_timing_processor.cpp index d27cb3396..390edd37b 100644 --- a/aegisub/src/dialog_timing_processor.cpp +++ b/aegisub/src/dialog_timing_processor.cpp @@ -542,6 +542,6 @@ void DialogTimingProcessor::Process() { } // Update grid - grid->ass->FlagAsModified(_("timing processor")); + grid->ass->Commit(_("timing processor")); grid->CommitChanges(); } diff --git a/aegisub/src/dialog_translation.cpp b/aegisub/src/dialog_translation.cpp index fd0f8afc2..7d77df93a 100644 --- a/aegisub/src/dialog_translation.cpp +++ b/aegisub/src/dialog_translation.cpp @@ -357,7 +357,7 @@ void DialogTranslation::OnTransBoxKey(wxKeyEvent &event) { // Update line cur->UpdateText(); cur->ClearBlocks(); - subs->FlagAsModified(_("translation assistant")); + subs->Commit(_("translation assistant")); grid->CommitChanges(); ((FrameMain*)main)->UpdateTitle(); UpdatePreview(); diff --git a/aegisub/src/frame_main.cpp b/aegisub/src/frame_main.cpp index eccd5a0d5..b644371e5 100644 --- a/aegisub/src/frame_main.cpp +++ b/aegisub/src/frame_main.cpp @@ -570,6 +570,7 @@ void FrameMain::InitMenu() { /// @brief Initialize contents void FrameMain::InitContents() { + AssFile::top = new AssFile; // Set a background panel StartupLog(_T("Create background panel")); Panel = new wxPanel(this,-1,wxDefaultPosition,wxDefaultSize,wxTAB_TRAVERSAL | wxCLIP_CHILDREN); @@ -590,8 +591,6 @@ void FrameMain::InitContents() { StartupLog(_T("Create subtitles grid")); SubsGrid = new SubtitlesGrid(this,Panel,-1,wxDefaultPosition,wxSize(600,100),wxWANTS_CHARS | wxSUNKEN_BORDER,_T("Subs grid")); BottomSizer->Add(SubsGrid,1,wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM,0); - StartupLog(_T("Reset undo stack")); - AssFile::StackReset(); videoBox->videoSlider->grid = SubsGrid; VideoContext::Get()->grid = SubsGrid; StartupLog(_T("Reset video zoom")); @@ -638,7 +637,6 @@ void FrameMain::DeInitContents() { SubsGrid->ClearMaps(); delete EditBox; delete videoBox; - AssFile::StackReset(); delete AssFile::top; HelpButton::ClearPages(); VideoContext::Get()->audio = NULL; @@ -708,7 +706,6 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) { // Proceed into loading SubsGrid->ClearMaps(); - AssFile::StackReset(); if (isFile) { AssFile::top->Load(filename,charset); SubsGrid->UpdateMaps(); @@ -1135,7 +1132,7 @@ void FrameMain::LoadVideo(wxString file,bool autoload) { // Always change script res SubsGrid->ass->SetScriptInfo(_T("PlayResX"), wxString::Format(_T("%d"), vidx)); SubsGrid->ass->SetScriptInfo(_T("PlayResY"), wxString::Format(_T("%d"), vidy)); - SubsGrid->ass->FlagAsModified(_("Change script resolution")); + SubsGrid->ass->Commit(_("Change script resolution")); SubsGrid->CommitChanges(); break; case 0: @@ -1350,8 +1347,8 @@ bool FrameMain::LoadList(wxArrayString list) { /// @brief Sets the descriptions for undo/redo void FrameMain::SetUndoRedoDesc() { - editMenu->SetHelpString(0,_T("Undo ")+AssFile::GetUndoDescription()); - editMenu->SetHelpString(1,_T("Redo ")+AssFile::GetRedoDescription()); + editMenu->SetHelpString(0,_T("Undo ")+AssFile::top->GetUndoDescription()); + editMenu->SetHelpString(1,_T("Redo ")+AssFile::top->GetRedoDescription()); } /// @brief Check if ASSDraw is available diff --git a/aegisub/src/frame_main_events.cpp b/aegisub/src/frame_main_events.cpp index baf014d06..d341cd9f8 100644 --- a/aegisub/src/frame_main_events.cpp +++ b/aegisub/src/frame_main_events.cpp @@ -435,16 +435,16 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) { else if (curMenu == editMenu) { // Undo state wxMenuItem *item; - wxString undo_text = _("&Undo") + wxString(_T(" ")) + AssFile::GetUndoDescription() + wxString(_T("\t")) + Hotkeys.GetText(_T("Undo")); + wxString undo_text = _("&Undo") + wxString(_T(" ")) + AssFile::top->GetUndoDescription() + wxString(_T("\t")) + Hotkeys.GetText(_T("Undo")); item = editMenu->FindItem(Menu_Edit_Undo); item->SetItemLabel(undo_text); - item->Enable(!AssFile::IsUndoStackEmpty()); + item->Enable(!AssFile::top->IsUndoStackEmpty()); // Redo state - wxString redo_text = _("&Redo") + wxString(_T(" ")) + AssFile::GetRedoDescription() + wxString(_T("\t")) + Hotkeys.GetText(_T("Redo")); + wxString redo_text = _("&Redo") + wxString(_T(" ")) + AssFile::top->GetRedoDescription() + wxString(_T("\t")) + Hotkeys.GetText(_T("Redo")); item = editMenu->FindItem(Menu_Edit_Redo); item->SetItemLabel(redo_text); - item->Enable(!AssFile::IsRedoStackEmpty()); + item->Enable(!AssFile::top->IsRedoStackEmpty()); // Copy/cut/paste wxArrayInt sels = SubsGrid->GetSelection(); @@ -1133,7 +1133,7 @@ void FrameMain::OnSnapToScene (wxCommandEvent &) { // Commit SubsGrid->editBox->Update(true); - SubsGrid->ass->FlagAsModified(_("snap to scene")); + SubsGrid->ass->Commit(_("snap to scene")); SubsGrid->CommitChanges(); } @@ -1160,7 +1160,7 @@ void FrameMain::OnShiftToFrame (wxCommandEvent &) { } // Commit - SubsGrid->ass->FlagAsModified(_("shift to frame")); + SubsGrid->ass->Commit(_("shift to frame")); SubsGrid->CommitChanges(); SubsGrid->editBox->Update(true,false); } @@ -1168,17 +1168,17 @@ void FrameMain::OnShiftToFrame (wxCommandEvent &) { /// @brief Undo void FrameMain::OnUndo(wxCommandEvent&) { VideoContext::Get()->Stop(); - AssFile::StackPop(); + AssFile::top->Undo(); + UpdateTitle(); SubsGrid->UpdateMaps(); - AssFile::Popping = false; } /// @brief Redo void FrameMain::OnRedo(wxCommandEvent&) { VideoContext::Get()->Stop(); - AssFile::StackRedo(); + AssFile::top->Redo(); + UpdateTitle(); SubsGrid->UpdateMaps(); - AssFile::Popping = false; } /// @brief Find @@ -1347,21 +1347,21 @@ void FrameMain::OnSelect (wxCommandEvent &) { /// @brief Sort subtitles by start time void FrameMain::OnSortStart (wxCommandEvent &) { AssFile::top->Sort(); - AssFile::top->FlagAsModified(_("sort")); + AssFile::top->Commit(_("sort")); SubsGrid->UpdateMaps(); SubsGrid->CommitChanges(); } /// @brief Sort subtitles by end time void FrameMain::OnSortEnd (wxCommandEvent &) { AssFile::top->Sort(AssFile::CompEnd); - AssFile::top->FlagAsModified(_("sort")); + AssFile::top->Commit(_("sort")); SubsGrid->UpdateMaps(); SubsGrid->CommitChanges(); } /// @brief Sort subtitles by style name void FrameMain::OnSortStyle (wxCommandEvent &) { AssFile::top->Sort(AssFile::CompStyle); - AssFile::top->FlagAsModified(_("sort")); + AssFile::top->Commit(_("sort")); SubsGrid->UpdateMaps(); SubsGrid->CommitChanges(); } diff --git a/aegisub/src/subs_edit_box.cpp b/aegisub/src/subs_edit_box.cpp index 9c243dd40..9b4b87171 100644 --- a/aegisub/src/subs_edit_box.cpp +++ b/aegisub/src/subs_edit_box.cpp @@ -573,7 +573,7 @@ void SubsEditBox::OnStyleChange(wxCommandEvent &event) { cur->Style = StyleBox->GetValue(); } } - grid->ass->FlagAsModified(_("style change")); + grid->ass->Commit(_("style change")); grid->CommitChanges(); grid->EndBatch(); } @@ -605,7 +605,7 @@ void SubsEditBox::OnActorChange(wxCommandEvent &event) { } // Update grid - grid->ass->FlagAsModified(_("actor change")); + grid->ass->Commit(_("actor change")); grid->CommitChanges(); grid->EndBatch(); } @@ -633,7 +633,7 @@ void SubsEditBox::OnLayerChange(wxSpinEvent &event) { } // Done - grid->ass->FlagAsModified(_("layer change")); + grid->ass->Commit(_("layer change")); grid->CommitChanges(); } @@ -660,7 +660,7 @@ void SubsEditBox::OnLayerEnter(wxCommandEvent &event) { } // Done - grid->ass->FlagAsModified(_("layer change")); + grid->ass->Commit(_("layer change")); grid->CommitChanges(); } @@ -746,7 +746,7 @@ void SubsEditBox::CommitTimes(bool start,bool end,bool fromStart,bool commit) { StartTime->Update(); EndTime->Update(); Duration->Update(); - grid->ass->FlagAsModified(_("modify times")); + grid->ass->Commit(_("modify times")); grid->CommitChanges(); int sel0 = grid->GetFirstSelRow(); audio->SetDialogue(grid,grid->GetDialogue(sel0),sel0); @@ -772,7 +772,7 @@ void SubsEditBox::OnMarginLChange(wxCommandEvent &event) { } } MarginL->SetValue(cur->GetMarginString(0,false)); - grid->ass->FlagAsModified(_("MarginL change")); + grid->ass->Commit(_("MarginL change")); grid->CommitChanges(); grid->EndBatch(); } @@ -795,7 +795,7 @@ void SubsEditBox::OnMarginRChange(wxCommandEvent &event) { } } MarginR->SetValue(cur->GetMarginString(1,false)); - grid->ass->FlagAsModified(_("MarginR change")); + grid->ass->Commit(_("MarginR change")); grid->CommitChanges(); grid->EndBatch(); } @@ -819,7 +819,7 @@ void SubsEditBox::OnMarginVChange(wxCommandEvent &event) { } } MarginV->SetValue(cur->GetMarginString(2,false)); - grid->ass->FlagAsModified(_("MarginV change")); + grid->ass->Commit(_("MarginV change")); grid->CommitChanges(); grid->EndBatch(); } @@ -841,7 +841,7 @@ void SubsEditBox::OnEffectChange(wxCommandEvent &event) { cur->Effect = Effect->GetValue(); } } - grid->ass->FlagAsModified(_("effect change")); + grid->ass->Commit(_("effect change")); grid->CommitChanges(); grid->EndBatch(); } @@ -862,7 +862,7 @@ void SubsEditBox::OnCommentChange(wxCommandEvent &event) { cur->Comment = CommentBox->GetValue(); } } - grid->ass->FlagAsModified(_("comment change")); + grid->ass->Commit(_("comment change")); grid->CommitChanges(); grid->EndBatch(); } @@ -945,7 +945,7 @@ void SubsEditBox::Commit(bool stay) { // Update file if (textNeedsCommit) { - grid->ass->FlagAsModified(_("editing")); + grid->ass->Commit(_("editing")); grid->CommitChanges(); } else if (StartTime->HasBeenModified() || EndTime->HasBeenModified()) { diff --git a/aegisub/src/subs_grid.cpp b/aegisub/src/subs_grid.cpp index 09b7b5718..9ed1a0bd5 100644 --- a/aegisub/src/subs_grid.cpp +++ b/aegisub/src/subs_grid.cpp @@ -427,7 +427,7 @@ void SubtitlesGrid::OnSplitByKaraoke (wxCommandEvent &event) { didSplit |= SplitLineByKaraoke(sels[i]); } if (didSplit) { - ass->FlagAsModified(_("splitting")); + ass->Commit(_("splitting")); CommitChanges(); } EndBatch(); @@ -692,7 +692,7 @@ void SubtitlesGrid::OnRecombine(wxCommandEvent &event) { } // Commit - ass->FlagAsModified(_("combining")); + ass->Commit(_("combining")); CommitChanges(); } @@ -848,7 +848,7 @@ void SubtitlesGrid::SwapLines(int n1,int n2) { std::swap(*dlg1, *dlg2); UpdateMaps(); - ass->FlagAsModified(_("swap lines")); + ass->Commit(_("swap lines")); CommitChanges(); } @@ -872,7 +872,7 @@ void SubtitlesGrid::InsertLine(AssDialogue *line,int n,bool after,bool update) { // Update if (update) { - ass->FlagAsModified(_("line insertion")); + ass->Commit(_("line insertion")); CommitChanges(); AdjustScrollbar(); } @@ -1005,7 +1005,7 @@ void SubtitlesGrid::PasteLines(int n,bool pasteOver) { // Commit UpdateMaps(); AdjustScrollbar(); - ass->FlagAsModified(_("paste")); + ass->Commit(_("paste")); CommitChanges(); // Set selection @@ -1055,7 +1055,7 @@ void SubtitlesGrid::DeleteLines(wxArrayInt target, bool flagModified) { UpdateMaps(); AdjustScrollbar(); if (flagModified) { - ass->FlagAsModified(_("delete")); + ass->Commit(_("delete")); CommitChanges(); } @@ -1118,7 +1118,7 @@ void SubtitlesGrid::JoinLines(int n1,int n2,bool concat) { // Delete remaining lines (this will auto commit) DeleteLines(GetRangeArray(n1+1,n2), false); - ass->FlagAsModified(_("join lines")); + ass->Commit(_("join lines")); CommitChanges(); // Select new line @@ -1160,7 +1160,7 @@ void SubtitlesGrid::AdjoinLines(int n1,int n2,bool setStart) { } // Commit - AssFile::top->FlagAsModified(_("adjoin")); + AssFile::top->Commit(_("adjoin")); CommitChanges(); } @@ -1210,7 +1210,7 @@ void SubtitlesGrid::JoinAsKaraoke(int n1,int n2) { // Delete remaining lines (this will auto commit) DeleteLines(GetRangeArray(n1+1,n2), false); - ass->FlagAsModified(_("join as karaoke")); + ass->Commit(_("join as karaoke")); CommitChanges(); // Select new line @@ -1330,7 +1330,7 @@ void SubtitlesGrid::SplitLine(int n,int pos,int mode,wxString textIn) { //editBox->SetToLine(n); // Commit - ass->FlagAsModified(_("split")); + ass->Commit(_("split")); CommitChanges(); } @@ -1439,7 +1439,7 @@ void SubtitlesGrid::SetSubsToVideo(bool start) { // Commit if (modified) { - ass->FlagAsModified(_("timing")); + ass->Commit(_("timing")); CommitChanges(); editBox->Update(true); } diff --git a/aegisub/src/visual_tool.cpp b/aegisub/src/visual_tool.cpp index 2527cec24..9bdbf3f03 100644 --- a/aegisub/src/visual_tool.cpp +++ b/aegisub/src/visual_tool.cpp @@ -266,7 +266,7 @@ void VisualTool::Commit(bool full, wxString message) { if (message.empty()) { message = _("visual typesetting"); } - grid->ass->FlagAsModified(message); + grid->ass->Commit(message); } grid->CommitChanges(false,!full); if (full)