diff --git a/aegisub/src/dialog_progress.cpp b/aegisub/src/dialog_progress.cpp index ed840cc2d..8d37e7333 100644 --- a/aegisub/src/dialog_progress.cpp +++ b/aegisub/src/dialog_progress.cpp @@ -56,7 +56,7 @@ public: } void SetProgress(int64_t cur, int64_t max) { - Main().Async([=]{ dialog->gauge->SetValue(mid(0, double(cur) / max * 100, 100)); }); + Main().Async([=]{ dialog->SetProgress(mid(0, double(cur) / max * 300, 300)); }); } void Log(std::string const& str) { @@ -79,9 +79,11 @@ public: DialogProgress::DialogProgress(wxWindow *parent, wxString const& title_text, wxString const& message) : wxDialog(parent, -1, title_text, wxDefaultPosition, wxDefaultSize, wxBORDER_RAISED) , pulse_timer(GetEventHandler()) +, progress_current(0) +, progress_target(0) { title = new wxStaticText(this, -1, title_text, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE | wxST_NO_AUTORESIZE); - gauge = new wxGauge(this, -1, 100, wxDefaultPosition, wxSize(300,20)); + gauge = new wxGauge(this, -1, 300, wxDefaultPosition, wxSize(300,20)); text = new wxStaticText(this, -1, message, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE | wxST_NO_AUTORESIZE); cancel_button = new wxButton(this, wxID_CANCEL); log_output = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxSize(600, 240), wxTE_MULTILINE | wxTE_READONLY); @@ -160,6 +162,17 @@ void DialogProgress::OnShow(wxShowEvent&) { } void DialogProgress::OnIdle(wxIdleEvent&) { + if (progress_current != progress_target) { + using namespace std::chrono; + auto now = steady_clock::now(); + int ms = mid(0, duration_cast(now - progress_anim_start_time).count(), progress_anim_duration); + int dist = (progress_target - progress_anim_start_value) * ms / progress_anim_duration; + if (dist) { + progress_current = progress_anim_start_value + dist; + gauge->SetValue(progress_current); + } + } + if (!pending_log) return; if (log_output->IsEmpty()) { @@ -180,3 +193,16 @@ void DialogProgress::OnCancel(wxCommandEvent &) { cancel_button->Enable(false); cancel_button->SetLabelText(_("Cancelling...")); } + +void DialogProgress::SetProgress(int target) { + using namespace std::chrono; + + progress_anim_start_value = progress_current; + auto now = steady_clock::now(); + if (progress_target == 0) + progress_anim_duration = 1000; + else + progress_anim_duration = std::max(100, duration_cast(now - progress_anim_start_time).count() * 11 / 10); + progress_anim_start_time = now; + progress_target = target; +} diff --git a/aegisub/src/dialog_progress.h b/aegisub/src/dialog_progress.h index 52618d855..2dc3dc54c 100644 --- a/aegisub/src/dialog_progress.h +++ b/aegisub/src/dialog_progress.h @@ -17,6 +17,7 @@ /// @ingroup utility /// +#include #include #include @@ -43,11 +44,18 @@ class DialogProgress : public wxDialog, public agi::BackgroundRunner { wxTimer pulse_timer; wxString pending_log; + int progress_anim_start_value; + int progress_current; + int progress_target; + std::chrono::steady_clock::time_point progress_anim_start_time; + int progress_anim_duration; void OnShow(wxShowEvent&); void OnCancel(wxCommandEvent &); void OnIdle(wxIdleEvent&); + void SetProgress(int target); + public: /// Constructor /// @param parent Parent window of the dialog