Block in wxMSW wxProgressDialog::Update(max) until the dialog is dismissed.
For consistency with the generic version and because it makes more sense than blocking in the dialog destructor (which is the only other alternative for the dialogs without wxPD_AUTO_HIDE to work), we should block in Update() when the maximal value is reached for dialogs without wxPD_AUTO_HIDE style until the dialog is dismissed. Document this behaviour even more clearly. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65507 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -62,7 +62,8 @@ public:
|
|||||||
Uncancelable = -1, // dialog can't be canceled
|
Uncancelable = -1, // dialog can't be canceled
|
||||||
Canceled, // can be cancelled and, in fact, was
|
Canceled, // can be cancelled and, in fact, was
|
||||||
Continue, // can be cancelled but wasn't
|
Continue, // can be cancelled but wasn't
|
||||||
Finished // finished, waiting to be removed from screen
|
Finished, // finished, waiting to be removed from screen
|
||||||
|
Dismissed // was closed by user after finishing
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@@ -29,9 +29,8 @@
|
|||||||
Causes the progress dialog to disappear from screen as soon as the
|
Causes the progress dialog to disappear from screen as soon as the
|
||||||
maximum value of the progress meter has been reached.
|
maximum value of the progress meter has been reached.
|
||||||
If this style is not present, the dialog will become a modal dialog
|
If this style is not present, the dialog will become a modal dialog
|
||||||
(see wxDialog::ShowModal) once the maximum value has been reached;
|
(see wxDialog::ShowModal) once the maximum value has been reached
|
||||||
this results in processing of pending events and may cause
|
and wait for the user to dismiss it.
|
||||||
unwanted re-entrancies.
|
|
||||||
@style{wxPD_SMOOTH}
|
@style{wxPD_SMOOTH}
|
||||||
Causes smooth progress of the gauge control (uses a wxGauge with the
|
Causes smooth progress of the gauge control (uses a wxGauge with the
|
||||||
@c wxGA_SMOOTH style).
|
@c wxGA_SMOOTH style).
|
||||||
@@ -173,6 +172,13 @@ public:
|
|||||||
dialog or ask the user for the confirmation and if the abort is not confirmed
|
dialog or ask the user for the confirmation and if the abort is not confirmed
|
||||||
the dialog may be resumed with Resume() function.
|
the dialog may be resumed with Resume() function.
|
||||||
|
|
||||||
|
If @a value is the maximum value for the dialog, the behaviour of the
|
||||||
|
function depends on whether @c wxPD_AUTO_HIDE was used when the dialog
|
||||||
|
was created. If it was, the dialog is hidden and the function returns
|
||||||
|
immediately. If it was not, the dialog becomes a modal dialog and waits
|
||||||
|
for the user to dismiss it, meaning that this function does not return
|
||||||
|
until this happens.
|
||||||
|
|
||||||
Notice that you may want to call Fit() to change the dialog size to
|
Notice that you may want to call Fit() to change the dialog size to
|
||||||
conform to the length of the new message if desired. The dialog does
|
conform to the length of the new message if desired. The dialog does
|
||||||
not do this automatically.
|
not do this automatically.
|
||||||
@@ -180,8 +186,6 @@ public:
|
|||||||
@param value
|
@param value
|
||||||
The new value of the progress meter. It should be less than or equal to
|
The new value of the progress meter. It should be less than or equal to
|
||||||
the maximum value given to the constructor.
|
the maximum value given to the constructor.
|
||||||
See @c wxPD_AUTO_HIDE style for more info about the behaviour of
|
|
||||||
wxProgressDialog when @a value is the maximum value given in the ctor.
|
|
||||||
@param newmsg
|
@param newmsg
|
||||||
The new messages for the progress dialog text, if it is
|
The new messages for the progress dialog text, if it is
|
||||||
empty (which is the default) the message is not changed.
|
empty (which is the default) the message is not changed.
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "wx/msw/private/msgdlg.h"
|
#include "wx/msw/private/msgdlg.h"
|
||||||
#include "wx/progdlg.h"
|
#include "wx/progdlg.h"
|
||||||
|
#include "wx/evtloop.h"
|
||||||
|
|
||||||
using namespace wxMSWMessageDialog;
|
using namespace wxMSWMessageDialog;
|
||||||
|
|
||||||
@@ -119,13 +120,37 @@ private:
|
|||||||
LONG_PTR dwRefData);
|
LONG_PTR dwRefData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
// A custom event loop which runs until the state of the dialog becomes
|
||||||
|
// "Dismissed".
|
||||||
|
class wxProgressDialogModalLoop : public wxEventLoop
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxProgressDialogModalLoop(wxProgressDialogSharedData& data)
|
||||||
|
: m_data(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void OnNextIteration()
|
||||||
|
{
|
||||||
|
wxCriticalSectionLocker locker(m_data.m_cs);
|
||||||
|
|
||||||
|
if ( m_data.m_state == wxProgressDialog::Dismissed )
|
||||||
|
Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxProgressDialogSharedData& m_data;
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxProgressDialogModalLoop);
|
||||||
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Helper functions
|
// Helper functions
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
// This function returns true if the progress dialog with the given style
|
// This function returns true if the progress dialog with the given style
|
||||||
// (combination of wxPD_XXX constants) needs the "Close" button and this button
|
// (combination of wxPD_XXX constants) needs the "Close" button and this button
|
||||||
// only, i.e. not a "Cancel" one.
|
// only, i.e. not a "Cancel" one.
|
||||||
@@ -324,53 +349,62 @@ bool wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
|
|||||||
#ifdef wxHAS_MSW_TASKDIALOG
|
#ifdef wxHAS_MSW_TASKDIALOG
|
||||||
if ( HasNativeProgressDialog() )
|
if ( HasNativeProgressDialog() )
|
||||||
{
|
{
|
||||||
wxCriticalSectionLocker locker(m_sharedData->m_cs);
|
|
||||||
|
|
||||||
// Do nothing in canceled state.
|
|
||||||
if ( !DoNativeBeforeUpdate(skip) )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
value /= m_factor;
|
|
||||||
|
|
||||||
wxASSERT_MSG( value <= m_maximum, wxT("invalid progress value") );
|
|
||||||
|
|
||||||
m_sharedData->m_value = value;
|
|
||||||
m_sharedData->m_notifications |= wxSPDD_VALUE_CHANGED;
|
|
||||||
|
|
||||||
if ( !newmsg.empty() )
|
|
||||||
{
|
{
|
||||||
m_message = newmsg;
|
wxCriticalSectionLocker locker(m_sharedData->m_cs);
|
||||||
m_sharedData->m_message = newmsg;
|
|
||||||
m_sharedData->m_notifications |= wxSPDD_MESSAGE_CHANGED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( m_sharedData->m_progressBarMarquee )
|
// Do nothing in canceled state.
|
||||||
{
|
if ( !DoNativeBeforeUpdate(skip) )
|
||||||
m_sharedData->m_progressBarMarquee = false;
|
return false;
|
||||||
m_sharedData->m_notifications |= wxSPDD_PBMARQUEE_CHANGED;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateExpandedInformation( value );
|
value /= m_factor;
|
||||||
|
|
||||||
// Has the progress bar finished?
|
wxASSERT_MSG( value <= m_maximum, wxT("invalid progress value") );
|
||||||
if ( value == m_maximum )
|
|
||||||
{
|
|
||||||
if ( m_state == Finished )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
|
m_sharedData->m_value = value;
|
||||||
|
m_sharedData->m_notifications |= wxSPDD_VALUE_CHANGED;
|
||||||
|
|
||||||
|
if ( !newmsg.empty() )
|
||||||
|
{
|
||||||
|
m_message = newmsg;
|
||||||
|
m_sharedData->m_message = newmsg;
|
||||||
|
m_sharedData->m_notifications |= wxSPDD_MESSAGE_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_sharedData->m_progressBarMarquee )
|
||||||
|
{
|
||||||
|
m_sharedData->m_progressBarMarquee = false;
|
||||||
|
m_sharedData->m_notifications |= wxSPDD_PBMARQUEE_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateExpandedInformation( value );
|
||||||
|
|
||||||
|
// If we didn't just reach the finish, all we have to do is to
|
||||||
|
// return true if the dialog wasn't cancelled and false otherwise.
|
||||||
|
if ( value != m_maximum || m_state == Finished )
|
||||||
|
return m_sharedData->m_state != Canceled;
|
||||||
|
|
||||||
|
|
||||||
|
// On finishing, the dialog without wxPD_AUTO_HIDE style becomes a
|
||||||
|
// modal one meaning that we must block here until the user
|
||||||
|
// dismisses it.
|
||||||
m_state = Finished;
|
m_state = Finished;
|
||||||
m_sharedData->m_state = Finished;
|
m_sharedData->m_state = Finished;
|
||||||
m_sharedData->m_notifications |= wxSPDD_FINISHED;
|
m_sharedData->m_notifications |= wxSPDD_FINISHED;
|
||||||
if( !HasPDFlag(wxPD_AUTO_HIDE) && newmsg.empty() )
|
if ( !HasPDFlag(wxPD_AUTO_HIDE) && newmsg.empty() )
|
||||||
{
|
{
|
||||||
// Provide the finishing message if the application didn't.
|
// Provide the finishing message if the application didn't.
|
||||||
m_message = _("Done.");
|
m_message = _("Done.");
|
||||||
m_sharedData->m_message = m_message;
|
m_sharedData->m_message = m_message;
|
||||||
m_sharedData->m_notifications |= wxSPDD_MESSAGE_CHANGED;
|
m_sharedData->m_notifications |= wxSPDD_MESSAGE_CHANGED;
|
||||||
}
|
}
|
||||||
}
|
} // unlock m_sharedData->m_cs
|
||||||
|
|
||||||
return m_sharedData->m_state != Canceled;
|
// We only get here when we need to wait for the dialog to terminate so
|
||||||
|
// do just this by running a custom event loop until the dialog is
|
||||||
|
// dismissed.
|
||||||
|
wxProgressDialogModalLoop loop(*m_sharedData);
|
||||||
|
loop.Run();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
#endif // wxHAS_MSW_TASKDIALOG
|
#endif // wxHAS_MSW_TASKDIALOG
|
||||||
|
|
||||||
@@ -774,6 +808,10 @@ void* wxProgressDialogTaskRunner::Entry()
|
|||||||
if ( FAILED(hr) )
|
if ( FAILED(hr) )
|
||||||
wxLogApiError( "TaskDialogIndirect", hr );
|
wxLogApiError( "TaskDialogIndirect", hr );
|
||||||
|
|
||||||
|
// If the main thread is waiting for us to exit inside the event loop in
|
||||||
|
// Update(), wake it up so that it checks our status again.
|
||||||
|
wxWakeUpIdle();
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -820,6 +858,11 @@ wxProgressDialogTaskRunner::TaskDialogCallbackProc
|
|||||||
case IDCANCEL:
|
case IDCANCEL:
|
||||||
if ( sharedData->m_state == wxProgressDialog::Finished )
|
if ( sharedData->m_state == wxProgressDialog::Finished )
|
||||||
{
|
{
|
||||||
|
// If the main thread is waiting for us, tell it that
|
||||||
|
// we're gone (and if it doesn't wait, it's harmless).
|
||||||
|
sharedData->m_state = wxProgressDialog::Dismissed;
|
||||||
|
|
||||||
|
// Let Windows close the dialog.
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user