#include "wx/dcclient.h"
#include "wx/timer.h"
#include "wx/settings.h"
+ #include "wx/app.h"
#endif
#include "wx/progdlg.h"
+#include "wx/evtloop.h"
// ---------------------------------------------------------------------------
// macros
int maximum,
wxWindow *parent,
int style)
- : wxDialog(GetParentForModalDialog(parent), wxID_ANY, title),
+ : wxDialog(GetParentForModalDialog(parent, style), wxID_ANY, title),
m_skip(false),
m_delay(3),
m_hasAbortButton(false),
m_parentTop = wxGetTopLevelParent(parent);
- wxClientDC dc(this);
- dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
- wxCoord widthText = 0;
- dc.GetTextExtent(message, &widthText, NULL, NULL, NULL, NULL);
-
// top-level sizerTop
wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
bool
wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
{
+ if ( !DoBeforeUpdate(skip) )
+ return false;
+
wxASSERT_MSG( value == -1 || m_gauge, wxT("cannot update non existent dialog") );
#ifdef __WXMSW__
m_msg->SetLabel(_("Done."));
}
- wxYieldIfNeeded();
+ wxCHECK_MSG(wxEventLoopBase::GetActive(), false,
+ "wxProgressDialog::Update needs a running event loop");
+
+ // 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
}
else // not at maximum yet
{
- return DoAfterUpdate(skip);
+ DoAfterUpdate();
}
// update the display in case yielding above didn't do it
bool wxProgressDialog::Pulse(const wxString& newmsg, bool *skip)
{
+ if ( !DoBeforeUpdate(skip) )
+ return false;
+
wxASSERT_MSG( m_gauge, wxT("cannot update non existent dialog") );
// show a bit of progress
SetTimeLabel((unsigned long)-1, m_remaining);
}
- return DoAfterUpdate(skip);
+ DoAfterUpdate();
+
+ return m_state != Canceled;
}
-bool wxProgressDialog::DoAfterUpdate(bool *skip)
+bool wxProgressDialog::DoBeforeUpdate(bool *skip)
{
+ wxCHECK_MSG(wxEventLoopBase::GetActive(), false,
+ "wxProgressDialog::DoBeforeUpdate needs a running event loop");
+
// 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
- wxYieldIfNeeded();
+ // 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();
return m_state != Canceled;
}
+void wxProgressDialog::DoAfterUpdate()
+{
+ wxCHECK_RET(wxEventLoopBase::GetActive(),
+ "wxProgressDialog::DoAfterUpdate needs a running event loop");
+
+ // 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);
+}
+
void wxProgressDialog::Resume()
{
m_state = Continue;
return m_msg->GetLabel();
}
+void wxProgressDialog::SetRange(int maximum)
+{
+ wxASSERT_MSG(m_gauge, "The dialog should have been constructed with a range > 0");
+ wxASSERT_MSG(maximum > 0, "Invalid range");
+
+ m_gauge->SetRange(maximum);
+ m_maximum = maximum;
+
+#if defined(__WXMSW__) || defined(__WXPM__)
+ // we can't have values > 65,536 in the progress control under Windows, so
+ // scale everything down
+ m_factor = m_maximum / 65536 + 1;
+ m_maximum /= m_factor;
+#endif // __WXMSW__
+}
+
+
+bool wxProgressDialog::WasCancelled() const
+{
+ return m_hasAbortButton && m_state == Canceled;
+}
+
+bool wxProgressDialog::WasSkipped() const
+{
+ return m_hasSkipButton && m_skip;
+}
+
+
// ----------------------------------------------------------------------------
// event handlers
// ----------------------------------------------------------------------------
{
if ( HasFlag(wxPD_APP_MODAL) )
{
- delete m_winDisabler;
- m_winDisabler = (wxWindowDisabler *)NULL;
+ wxDELETE(m_winDisabler);
}
else
{
void wxProgressDialog::UpdateMessage(const wxString &newmsg)
{
+ wxCHECK_RET(wxEventLoopBase::GetActive(),
+ "wxProgressDialog::UpdateMessage needs a running event loop");
+
if ( !newmsg.empty() && newmsg != m_msg->GetLabel() )
{
m_msg->SetLabel(newmsg);
- Fit(); // adapt to the new label size
-
- wxYieldIfNeeded() ;
+ // 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);
}
}