]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/progdlgg.cpp
Swap client data pointers in wxRearrangeList too.
[wxWidgets.git] / src / generic / progdlgg.cpp
index 94e1bed6f11c928c6d3855680c1a60c1d4a1071a..3c962a0f2e57920a1519adb0880e5c50f9718888 100644 (file)
     #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
@@ -97,7 +99,7 @@ wxProgressDialog::wxProgressDialog(const wxString& title,
                                    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),
@@ -137,11 +139,6 @@ wxProgressDialog::wxProgressDialog(const wxString& title,
 
     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);
 
@@ -311,6 +308,9 @@ wxProgressDialog::CreateLabel(const wxString& text, wxSizer *sizer)
 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__
@@ -401,8 +401,17 @@ wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
                 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
@@ -417,7 +426,7 @@ wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
     }
     else // not at maximum yet
     {
-        return DoAfterUpdate(skip);
+        DoAfterUpdate();
     }
 
     // update the display in case yielding above didn't do it
@@ -428,6 +437,9 @@ wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
 
 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
@@ -444,14 +456,21 @@ bool wxProgressDialog::Pulse(const wxString& newmsg, bool *skip)
         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();
 
@@ -465,6 +484,17 @@ bool wxProgressDialog::DoAfterUpdate(bool *skip)
     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;
@@ -506,6 +536,34 @@ wxString wxProgressDialog::GetMessage() const
     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
 // ----------------------------------------------------------------------------
@@ -577,8 +635,7 @@ void wxProgressDialog::ReenableOtherWindows()
 {
     if ( HasFlag(wxPD_APP_MODAL) )
     {
-        delete m_winDisabler;
-        m_winDisabler = (wxWindowDisabler *)NULL;
+        wxDELETE(m_winDisabler);
     }
     else
     {
@@ -664,13 +721,17 @@ void wxProgressDialog::EnableClose()
 
 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);
     }
 }