+ if ( !DoBeforeUpdate(skip) )
+ return false;
+
+ wxCHECK_MSG( m_gauge, false, "dialog should be fully created" );
+
+#ifdef __WXMSW__
+ value /= m_factor;
+#endif // __WXMSW__
+
+ wxASSERT_MSG( value <= m_maximum, wxT("invalid progress value") );
+
+ m_gauge->SetValue(value);
+
+ UpdateMessage(newmsg);
+
+ if ( (m_elapsed || m_remaining || m_estimated) && (value != 0) )
+ {
+ unsigned long elapsed;
+ unsigned long display_remaining;
+
+ UpdateTimeEstimates( value,
+ elapsed,
+ m_display_estimated,
+ display_remaining );
+
+ SetTimeLabel(elapsed, m_elapsed);
+ SetTimeLabel(m_display_estimated, m_estimated);
+ SetTimeLabel(display_remaining, m_remaining);
+ }
+
+ if ( value == m_maximum )
+ {
+ if ( m_state == Finished )
+ {
+ // ignore multiple calls to Update(m_maximum): it may sometimes be
+ // troublesome to ensure that Update() is not called twice with the
+ // same value (e.g. because of the rounding errors) and if we don't
+ // return now we're going to generate asserts below
+ return true;
+ }
+
+ // so that we return true below and that out [Cancel] handler knew what
+ // to do
+ m_state = Finished;
+ if( !HasPDFlag(wxPD_AUTO_HIDE) )
+ {
+ EnableClose();
+ DisableSkip();
+#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
+ EnableCloseButton();
+#endif // __WXMSW__
+
+ if ( newmsg.empty() )
+ {
+ // also provide the finishing message if the application didn't
+ m_msg->SetLabel(_("Done."));
+ }
+
+ // allow the window to repaint:
+ // NOTE: since we yield only for UI events with this call, there
+ // should be no side-effects
+ wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI);
+
+ // NOTE: this call results in a new event loop being created
+ // and to a call to ProcessPendingEvents() (which may generate
+ // unwanted re-entrancies).
+ (void)ShowModal();
+ }
+ else // auto hide
+ {
+ // reenable other windows before hiding this one because otherwise
+ // Windows wouldn't give the focus back to the window which had
+ // been previously focused because it would still be disabled
+ ReenableOtherWindows();
+
+ Hide();
+ }
+ }
+ else // not at maximum yet
+ {
+ DoAfterUpdate();
+ }
+
+ // update the display in case yielding above didn't do it
+ Update();
+
+ return m_state != Canceled;
+}
+
+bool wxGenericProgressDialog::Pulse(const wxString& newmsg, bool *skip)
+{
+ if ( !DoBeforeUpdate(skip) )
+ return false;
+
+ wxCHECK_MSG( m_gauge, false, "dialog should be fully created" );
+
+ // show a bit of progress
+ m_gauge->Pulse();
+
+ UpdateMessage(newmsg);
+
+ if (m_elapsed || m_remaining || m_estimated)
+ {
+ unsigned long elapsed = wxGetCurrentTime() - m_timeStart;
+
+ SetTimeLabel(elapsed, m_elapsed);
+ SetTimeLabel((unsigned long)-1, m_estimated);
+ SetTimeLabel((unsigned long)-1, m_remaining);
+ }
+
+ DoAfterUpdate();
+
+ return m_state != Canceled;
+}
+
+bool wxGenericProgressDialog::DoBeforeUpdate(bool *skip)
+{
+ // we have to yield because not only we want to update the display but
+ // also to process the clicks on the cancel and skip buttons
+ // NOTE: using YieldFor() this call shouldn't give re-entrancy problems
+ // for event handlers not interested to UI/user-input events.
+ wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT);
+
+ Update();
+
+ if ( m_skip && skip && !*skip )
+ {
+ *skip = true;
+ m_skip = false;
+ EnableSkip();
+ }
+
+ return m_state != Canceled;
+}
+
+void wxGenericProgressDialog::DoAfterUpdate()
+{
+ // allow the window to repaint:
+ // NOTE: since we yield only for UI events with this call, there
+ // should be no side-effects
+ wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI);