forked from mia/Aegisub
Improve the negative-duration-avoiding behavior of the time edit boxes
Save the initial start and end times of lines before adjusting them to avoid negative line durations, so that if further changes to the edit boxes make the adjustment unneccesary the original values can be restored. This Fixes the problem where changing a line visible from frames 800-900 to 800-901 would actually result in 90-901, due to the end frame briefly being 90. Originally committed to SVN as r6741.
This commit is contained in:
parent
252351b7da
commit
8f3b027881
2 changed files with 46 additions and 23 deletions
|
@ -288,6 +288,8 @@ wxRadioButton *SubsEditBox::MakeRadio(wxString const& text, bool start, wxString
|
||||||
void SubsEditBox::OnCommit(int type) {
|
void SubsEditBox::OnCommit(int type) {
|
||||||
wxEventBlocker blocker(this);
|
wxEventBlocker blocker(this);
|
||||||
|
|
||||||
|
initialTimes.clear();
|
||||||
|
|
||||||
if (type == AssFile::COMMIT_NEW || type & AssFile::COMMIT_STYLES) {
|
if (type == AssFile::COMMIT_NEW || type & AssFile::COMMIT_STYLES) {
|
||||||
wxString style = StyleBox->GetValue();
|
wxString style = StyleBox->GetValue();
|
||||||
StyleBox->Clear();
|
StyleBox->Clear();
|
||||||
|
@ -384,6 +386,7 @@ void SubsEditBox::OnActiveLineChanged(AssDialogue *new_line) {
|
||||||
}
|
}
|
||||||
void SubsEditBox::OnSelectedSetChanged(const Selection &, const Selection &) {
|
void SubsEditBox::OnSelectedSetChanged(const Selection &, const Selection &) {
|
||||||
sel = c->selectionController->GetSelectedSet();
|
sel = c->selectionController->GetSelectedSet();
|
||||||
|
initialTimes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsEditBox::UpdateFrameTiming(agi::vfr::Framerate const& fps) {
|
void SubsEditBox::UpdateFrameTiming(agi::vfr::Framerate const& fps) {
|
||||||
|
@ -423,6 +426,8 @@ void SubsEditBox::SetSelectedRows(setter set, T value, wxString desc, int type,
|
||||||
commitId = c->ass->Commit(desc, type, (amend && desc == lastCommitType) ? commitId : -1, sel.size() == 1 ? *sel.begin() : 0);
|
commitId = c->ass->Commit(desc, type, (amend && desc == lastCommitType) ? commitId : -1, sel.size() == 1 ? *sel.begin() : 0);
|
||||||
file_changed_slot.Unblock();
|
file_changed_slot.Unblock();
|
||||||
lastCommitType = desc;
|
lastCommitType = desc;
|
||||||
|
lastTimeCommitType = -1;
|
||||||
|
initialTimes.clear();
|
||||||
undoTimer.Start(10000, wxTIMER_ONE_SHOT);
|
undoTimer.Start(10000, wxTIMER_ONE_SHOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,35 +441,48 @@ void SubsEditBox::CommitText(wxString desc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsEditBox::CommitTimes(TimeField field) {
|
void SubsEditBox::CommitTimes(TimeField field) {
|
||||||
if (ByFrame->GetValue())
|
|
||||||
Duration->SetFrame(EndTime->GetFrame() - StartTime->GetFrame() + 1);
|
|
||||||
else
|
|
||||||
Duration->SetTime(EndTime->GetTime() - StartTime->GetTime());
|
|
||||||
|
|
||||||
// Update lines
|
|
||||||
for (Selection::iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
for (Selection::iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
||||||
AssDialogue *d = *cur;
|
AssDialogue *d = *cur;
|
||||||
|
|
||||||
|
if (!initialTimes.count(d))
|
||||||
|
initialTimes[d] = std::make_pair(d->Start, d->End);
|
||||||
|
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case TIME_START:
|
case TIME_START:
|
||||||
d->Start = StartTime->GetTime();
|
initialTimes[d].first = d->Start = StartTime->GetTime();
|
||||||
if (d->Start > d->End)
|
d->End = std::max(d->Start, initialTimes[d].second);
|
||||||
d->End = d->Start;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIME_END:
|
case TIME_END:
|
||||||
d->End = EndTime->GetTime();
|
initialTimes[d].second = d->End = EndTime->GetTime();
|
||||||
if (d->Start > d->End)
|
d->Start = std::min(d->End, initialTimes[d].first);
|
||||||
d->Start = d->End;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIME_DURATION:
|
case TIME_DURATION:
|
||||||
if (ByFrame->GetValue())
|
if (ByFrame->GetValue())
|
||||||
d->End = c->videoController->TimeAtFrame(c->videoController->FrameAtTime(d->Start, agi::vfr::START) + Duration->GetFrame(), agi::vfr::END);
|
d->End = c->videoController->TimeAtFrame(c->videoController->FrameAtTime(d->Start, agi::vfr::START) + Duration->GetFrame(), agi::vfr::END);
|
||||||
else
|
else
|
||||||
d->End = d->Start + Duration->GetTime();
|
d->End = d->Start + Duration->GetTime();
|
||||||
|
initialTimes[d].second = d->End;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timeCommitId[field] = c->ass->Commit(_("modify times"), AssFile::COMMIT_DIAG_TIME, timeCommitId[field], sel.size() == 1 ? *sel.begin() : 0);
|
StartTime->SetTime(line->Start);
|
||||||
|
EndTime->SetTime(line->End);
|
||||||
|
|
||||||
|
if (ByFrame->GetValue())
|
||||||
|
Duration->SetFrame(EndTime->GetFrame() - StartTime->GetFrame() + 1);
|
||||||
|
else
|
||||||
|
Duration->SetTime(EndTime->GetTime() - StartTime->GetTime());
|
||||||
|
|
||||||
|
if (field != lastTimeCommitType)
|
||||||
|
commitId = -1;
|
||||||
|
|
||||||
|
lastTimeCommitType = field;
|
||||||
|
file_changed_slot.Block();
|
||||||
|
commitId = c->ass->Commit(_("modify times"), AssFile::COMMIT_DIAG_TIME, commitId, sel.size() == 1 ? *sel.begin() : 0);
|
||||||
|
file_changed_slot.Unblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsEditBox::OnSize(wxSizeEvent &evt) {
|
void SubsEditBox::OnSize(wxSizeEvent &evt) {
|
||||||
|
@ -530,20 +548,14 @@ void SubsEditBox::OnLayerEnter(wxCommandEvent &) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsEditBox::OnStartTimeChange(wxCommandEvent &) {
|
void SubsEditBox::OnStartTimeChange(wxCommandEvent &) {
|
||||||
if (StartTime->GetTime() > EndTime->GetTime()) EndTime->SetTime(StartTime->GetTime());
|
|
||||||
CommitTimes(TIME_START);
|
CommitTimes(TIME_START);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsEditBox::OnEndTimeChange(wxCommandEvent &) {
|
void SubsEditBox::OnEndTimeChange(wxCommandEvent &) {
|
||||||
if (StartTime->GetTime() > EndTime->GetTime()) StartTime->SetTime(EndTime->GetTime());
|
|
||||||
CommitTimes(TIME_END);
|
CommitTimes(TIME_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsEditBox::OnDurationChange(wxCommandEvent &) {
|
void SubsEditBox::OnDurationChange(wxCommandEvent &) {
|
||||||
if (ByFrame->GetValue())
|
|
||||||
EndTime->SetFrame(StartTime->GetFrame() + Duration->GetFrame() - 1);
|
|
||||||
else
|
|
||||||
EndTime->SetTime(StartTime->GetTime() + Duration->GetTime());
|
|
||||||
CommitTimes(TIME_DURATION);
|
CommitTimes(TIME_DURATION);
|
||||||
}
|
}
|
||||||
void SubsEditBox::OnMarginLChange(wxCommandEvent &) {
|
void SubsEditBox::OnMarginLChange(wxCommandEvent &) {
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
///
|
///
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <wx/panel.h>
|
#include <wx/panel.h>
|
||||||
|
@ -50,6 +51,7 @@ namespace agi { struct Context; }
|
||||||
struct AssColor;
|
struct AssColor;
|
||||||
class AssDialogue;
|
class AssDialogue;
|
||||||
class AssStyle;
|
class AssStyle;
|
||||||
|
class AssTime;
|
||||||
class SubsTextEditCtrl;
|
class SubsTextEditCtrl;
|
||||||
class TimeEdit;
|
class TimeEdit;
|
||||||
class wxButton;
|
class wxButton;
|
||||||
|
@ -118,14 +120,23 @@ class SubsEditBox : public wxPanel, protected SelectionListener<AssDialogue> {
|
||||||
/// @param desc Undo description to use
|
/// @param desc Undo description to use
|
||||||
void CommitText(wxString desc);
|
void CommitText(wxString desc);
|
||||||
|
|
||||||
/// Move to the next line, creating it if needed
|
/// Last commit ID for undo coalescing
|
||||||
void NextLine();
|
|
||||||
|
|
||||||
int timeCommitId[3];
|
|
||||||
int commitId;
|
int commitId;
|
||||||
|
|
||||||
|
/// Last used commit message to avoid coalescing different types of changes
|
||||||
wxString lastCommitType;
|
wxString lastCommitType;
|
||||||
|
|
||||||
|
/// Last field to get a time commit, as they all have the same commit message
|
||||||
|
int lastTimeCommitType;
|
||||||
|
|
||||||
|
/// Timer to stop coalescing changes after a break with no edits
|
||||||
wxTimer undoTimer;
|
wxTimer undoTimer;
|
||||||
|
|
||||||
|
/// The start and end times of the selected lines without changes made to
|
||||||
|
/// avoid negative durations, so that they can be restored if future changes
|
||||||
|
/// eliminate the negative durations
|
||||||
|
std::map<AssDialogue *, std::pair<AssTime, AssTime> > initialTimes;
|
||||||
|
|
||||||
// Constructor helpers
|
// Constructor helpers
|
||||||
wxTextCtrl *MakeMarginCtrl(wxString const& tooltip, void (SubsEditBox::*handler)(wxCommandEvent&));
|
wxTextCtrl *MakeMarginCtrl(wxString const& tooltip, void (SubsEditBox::*handler)(wxCommandEvent&));
|
||||||
TimeEdit *MakeTimeCtrl(bool end, wxString const& tooltip, void (SubsEditBox::*handler)(wxCommandEvent&));
|
TimeEdit *MakeTimeCtrl(bool end, wxString const& tooltip, void (SubsEditBox::*handler)(wxCommandEvent&));
|
||||||
|
|
Loading…
Reference in a new issue