Poodletooth-iLand/panda/python/Lib/site-packages/wx/lib/agw/pyprogress.py
2015-03-06 06:11:40 -06:00

917 lines
29 KiB
Python

# --------------------------------------------------------------------------------- #
# PYPROGRESS wxPython IMPLEMENTATION
#
# Andrea Gavana, @ 03 Nov 2006
# Latest Revision: 19 Dec 2012, 21.00 GMT
#
#
# TODO List
#
# 1. Do we support all the styles of wx.ProgressDialog in indeterminated mode?
#
# 2. Other ideas?
#
#
# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
# Write To Me At:
#
# andrea.gavana@maerskoil.com
# andrea.gavana@gmail.com
#
# Or, Obviously, To The wxPython Mailing List!!!
#
# Tags: phoenix-port, unittest, documented
#
# End Of Comments
# --------------------------------------------------------------------------------- #
"""
:class:`PyProgress` is similar to :class:`ProgressDialog` in indeterminated mode, but with a
different gauge appearance and a different spinning behavior.
Description
===========
:class:`PyProgress` is similar to :class:`ProgressDialog` in indeterminated mode, but with a
different gauge appearance and a different spinning behavior. The moving gauge
can be drawn with a single solid colour or with a shading gradient foreground.
The gauge background colour is user customizable.
The bar does not move always from the beginning to the end as in :class:`ProgressDialog`
in indeterminated mode, but spins cyclically forward and backward.
Other options include:
- Possibility to change the proportion between the spinning bar and the
entire gauge, so that the bar can be longer or shorter (the default is 20%);
- Modifying the number of steps the spinning bar performs before a forward
(or backward) loop reverses.
:class:`PyProgress` can optionally display a ``Cancel`` button, and a :class:`StaticText` which
outputs the elapsed time from the starting of the process.
Usage
=====
Usage example::
import wx
import wx.lib.agw.pyprogress as PP
# Our normal wxApp-derived class, as usual
app = wx.App(0)
dlg = PP.PyProgress(None, -1, "PyProgress Example",
"An Informative Message",
agwStyle=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME)
dlg.SetGaugeProportion(0.2)
dlg.SetGaugeSteps(50)
dlg.SetGaugeBackground(wx.WHITE)
dlg.SetFirstGradientColour(wx.WHITE)
dlg.SetSecondGradientColour(wx.BLUE)
max = 400
keepGoing = 1
count = 0
while keepGoing and count < max:
count += 1
wx.MilliSleep(30)
if count >= max // 2:
keepGoing = dlg.UpdatePulse("Half-time!")
else:
keepGoing = dlg.UpdatePulse()
dlg.Destroy()
app.MainLoop()
Supported Platforms
===================
:class:`PyProgress` has been tested on the following platforms:
* Windows (Windows XP);
* Linux Ubuntu (Dapper 6.06)
Window Styles
=============
This class supports the following window styles:
=================== =========== ==================================================
Window Styles Hex Value Description
=================== =========== ==================================================
``PD_CAN_ABORT`` 0x1 This flag tells the dialog that it should have a ``Cancel`` button which the user may press. If this happens, the next call to `Update` will return ``False``.
``PD_APP_MODAL`` 0x2 Make the progress dialog modal. If this flag is not given, it is only 'locally' modal - that is the input to the parent window is disabled, but not to the other ones.
``PD_AUTO_HIDE`` 0x4 Causes the progress dialog to disappear from screen as soon as the maximum value of the progress meter has been reached.
``PD_ELAPSED_TIME`` 0x8 This flag tells the dialog that it should show elapsed time (since creating the dialog).
=================== =========== ==================================================
Events Processing
=================
`No custom events are available for this class.`
License And Version
===================
:class:`PyProgress` is distributed under the wxPython license.
Latest Revision: Andrea Gavana @ 19 Dec 2012, 21.00 GMT
Version 0.5
"""
import wx
import time
# Some constants, taken straight from wx.ProgressDialog
Uncancelable = -1
""" Classifies the :class:`PyProgress` as "uncancelable". """
Canceled = 0
""" :class:`PyProgress` has been canceled. """
Continue = 1
""" :class:`PyProgress` can continue. """
Finished = 2
""" :class:`PyProgress` has finished. """
# Margins between gauge and text/button
LAYOUT_MARGIN = 8
""" Margins between gauge and text/button (in pixels). """
# PyProgress styles
PD_CAN_ABORT = wx.PD_CAN_ABORT
""" This flag tells the dialog that it should have a "Cancel" button which the user may press. If this happens, the next call to `Update()` will return ``False``. """
PD_APP_MODAL = wx.PD_APP_MODAL
""" Make the progress dialog modal. If this flag is not given, it is only 'locally' modal - that is the input to the parent window is disabled, but not to the other ones. """
PD_AUTO_HIDE = wx.PD_AUTO_HIDE
""" Causes the progress dialog to disappear from screen as soon as the maximum value of the progress meter has been reached. """
PD_ELAPSED_TIME = wx.PD_ELAPSED_TIME
""" This flag tells the dialog that it should show elapsed time (since creating the dialog). """
# ---------------------------------------------------------------------------- #
# Class ProgressGauge
# ---------------------------------------------------------------------------- #
class ProgressGauge(wx.Window):
""" This class provides a visual alternative for :class:`Gauge`."""
def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
size=(-1,30)):
"""
Default class constructor.
:param `parent`: parent window. Must not be ``None``;
:param `id`: window identifier. A value of -1 indicates a default value;
:param `pos`: the control position. A value of (-1, -1) indicates a default position,
chosen by either the windowing system or wxPython, depending on platform;
:param `size`: the control size. A value of (-1, -1) indicates a default size,
chosen by either the windowing system or wxPython, depending on platform.
"""
wx.Window.__init__(self, parent, id, pos, size, style=wx.SUNKEN_BORDER)
self._value = 0
self._steps = 50
self._pos = 0
self._current = 0
self._gaugeproportion = 0.2
self._firstGradient = wx.WHITE
self._secondGradient = wx.BLUE
self._background = wx.Brush(wx.WHITE)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
def GetFirstGradientColour(self):
""" Returns the first gradient colour. """
return self._firstGradient
def SetFirstGradientColour(self, colour):
"""
Sets the first gradient colour.
:param `colour`: a valid :class:`Colour` object.
"""
self._firstGradient = colour
self.Refresh()
def GetSecondGradientColour(self):
""" Returns the second gradient colour. """
return self._secondGradient
def SetSecondGradientColour(self, colour):
"""
Sets the second gradient colour.
:param `colour`: a valid :class:`Colour` object.
"""
self._secondGradient = colour
self.Refresh()
def GetGaugeBackground(self):
""" Returns the gauge background colour. """
return self._background
def SetGaugeBackground(self, colour):
"""
Sets the gauge background colour.
:param `colour`: a valid :class:`Colour` object.
"""
self._background = wx.Brush(colour)
def SetGaugeSteps(self, steps):
"""
Sets the number of steps the gauge performs before switching from
forward to backward (or vice-versa) movement.
:param `steps`: the number of steps the gauge performs before switching from
forward to backward (or vice-versa) movement.
"""
if steps <= 0:
raise Exception("ERROR:\n Gauge steps must be greater than zero. ")
if steps != self._steps:
self._steps = steps
def GetGaugeSteps(self):
"""
Returns the number of steps the gauge performs before switching from
forward to backward (or vice-versa) movement.
"""
return self._steps
def GetGaugeProportion(self):
"""
Returns the relative proportion between the sliding bar and the
whole gauge.
"""
return self._gaugeproportion
def SetGaugeProportion(self, proportion):
"""
Sets the relative proportion between the sliding bar and the
whole gauge.
:param `proportion`: a floating point number representing the relative
proportion between the sliding bar and the whole gauge.
"""
if proportion <= 0 or proportion >= 1:
raise Exception("ERROR:\n Gauge proportion must be between 0 and 1. ")
if proportion != self._gaugeproportion:
self._gaugeproportion = proportion
def OnEraseBackground(self, event):
"""
Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`ProgressGauge`.
:param `event`: a :class:`EraseEvent` event to be processed.
:note: This method is intentionally empty to reduce flicker.
"""
pass
def OnPaint(self, event):
"""
Handles the ``wx.EVT_PAINT`` event for :class:`ProgressGauge`.
:param `event`: a :class:`PaintEvent` event to be processed.
"""
dc = wx.BufferedPaintDC(self)
dc.SetBackground(self._background)
dc.Clear()
xsize, ysize = self.GetClientSize()
interval = xsize/float(self._steps)
self._pos = interval*self._value
status = self._current//(self._steps - int(self._gaugeproportion*xsize)//int(interval))
if status%2 == 0:
increment = 1
else:
increment = -1
self._value = self._value + increment
self._current = self._current + 1
self.DrawProgress(dc, xsize, ysize, increment)
def DrawProgress(self, dc, xsize, ysize, increment):
"""
Actually draws the sliding bar.
:param `dc`: an instance of :class:`DC`;
:param `xsize`: the width of the whole progress bar;
:param `ysize`: the height of the whole progress bar;
:param `increment`: a positive value if we are spinning from left to right,
a negative one if we are spinning from right to left.
"""
if increment > 0:
col1 = self.GetFirstGradientColour()
col2 = self.GetSecondGradientColour()
else:
col1 = self.GetSecondGradientColour()
col2 = self.GetFirstGradientColour()
interval = self._gaugeproportion*xsize
r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
rstep = float((r2 - r1)) / interval
gstep = float((g2 - g1)) / interval
bstep = float((b2 - b1)) / interval
rf, gf, bf = 0, 0, 0
dc.SetBrush(wx.TRANSPARENT_BRUSH)
for ii in range(int(self._pos), int(self._pos+interval)):
currCol = (r1 + rf, g1 + gf, b1 + bf)
dc.SetPen(wx.Pen(currCol, 2))
dc.DrawLine(ii, 1, ii, ysize-2)
rf = rf + rstep
gf = gf + gstep
bf = bf + bstep
def Update(self):
""" Updates the gauge with a new value. """
self.Refresh()
# ---------------------------------------------------------------------------- #
# Class PyProgress
# ---------------------------------------------------------------------------- #
class PyProgress(wx.Dialog):
"""
:class:`PyProgress` is similar to :class:`ProgressDialog` in indeterminated mode, but with a
different gauge appearance and a different spinning behavior. The moving gauge
can be drawn with a single solid colour or with a shading gradient foreground.
The gauge background colour is user customizable.
The bar does not move always from the beginning to the end as in :class:`ProgressDialog`
in indeterminated mode, but spins cyclically forward and backward.
"""
def __init__(self, parent=None, id=-1, title="", message="",
agwStyle=wx.PD_APP_MODAL|wx.PD_AUTO_HIDE):
"""
Default class constructor.
:param `parent`: parent window;
:param `id`: window identifier. A value of -1 indicates a default value;
:param `title`: dialog title to show in titlebar;
:param `message`: message displayed above the progress bar;
:param `style`: the dialog style. This can be a combination of the following bits:
=================== =========== ==================================================
Window Styles Hex Value Description
=================== =========== ==================================================
``PD_CAN_ABORT`` 0x1 This flag tells the dialog that it should have a ``Cancel`` button which the user may press. If this happens, the next call to `UpdatePulse` will return ``False``.
``PD_APP_MODAL`` 0x2 Make the progress dialog modal. If this flag is not given, it is only 'locally' modal - that is the input to the parent window is disabled, but not to the other ones.
``PD_AUTO_HIDE`` 0x4 Causes the progress dialog to disappear from screen as soon as the maximum value of the progress meter has been reached.
``PD_ELAPSED_TIME`` 0x8 This flag tells the dialog that it should show elapsed time (since creating the dialog).
=================== =========== ==================================================
"""
wx.Dialog.__init__(self, parent, id, title)
self._delay = 3
self._hasAbortButton = False
# we may disappear at any moment, let the others know about it
self.SetExtraStyle(self.GetExtraStyle()|wx.WS_EX_TRANSIENT)
self._hasAbortButton = (agwStyle & wx.PD_CAN_ABORT)
if wx.Platform == "__WXMSW__":
# we have to remove the "Close" button from the title bar then as it is
# confusing to have it - it doesn't work anyhow
# FIXME: should probably have a (extended?) window style for this
if not self._hasAbortButton:
self.EnableClose(False)
self._state = (self._hasAbortButton and [Continue] or [Uncancelable])[0]
self._parentTop = wx.GetTopLevelParent(parent)
dc = wx.ClientDC(self)
dc.SetFont(wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT))
widthText, dummy = dc.GetTextExtent(message)
sizer = wx.BoxSizer(wx.VERTICAL)
self._msg = wx.StaticText(self, wx.ID_ANY, message)
sizer.Add(self._msg, 0, wx.LEFT|wx.TOP, 2*LAYOUT_MARGIN)
sizeDlg = wx.Size()
sizeLabel = self._msg.GetSize()
sizeDlg.y = 2*LAYOUT_MARGIN + sizeLabel.y
self._gauge = ProgressGauge(self, -1)
sizer.Add(self._gauge, 0, wx.LEFT|wx.RIGHT|wx.TOP|wx.EXPAND, 2*LAYOUT_MARGIN)
sizeGauge = self._gauge.GetSize()
sizeDlg.y += 2*LAYOUT_MARGIN + sizeGauge.y
# create the estimated/remaining/total time zones if requested
self._elapsed = None
self._display_estimated = self._last_timeupdate = self._break = 0
self._ctdelay = 0
label = None
nTimeLabels = 0
if agwStyle & wx.PD_ELAPSED_TIME:
nTimeLabels += 1
self._elapsed = self.CreateLabel("Elapsed time : ", sizer)
if nTimeLabels > 0:
label = wx.StaticText(self, -1, "")
# set it to the current time
self._timeStart = int(time.time())
sizeDlg.y += nTimeLabels*(label.GetSize().y + LAYOUT_MARGIN)
label.Destroy()
sizeDlgModified = False
if wx.Platform == "__WXMSW__":
sizerFlags = wx.ALIGN_RIGHT|wx.ALL
else:
sizerFlags = wx.ALIGN_CENTER_HORIZONTAL|wx.BOTTOM|wx.TOP
if self._hasAbortButton:
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
self._btnAbort = wx.Button(self, -1, "Cancel")
self._btnAbort.Bind(wx.EVT_BUTTON, self.OnCancel)
# Windows dialogs usually have buttons in the lower right corner
buttonSizer.Add(self._btnAbort, 0, sizerFlags, LAYOUT_MARGIN)
if not sizeDlgModified:
sizeDlg.y += 2*LAYOUT_MARGIN + wx.Button.GetDefaultSize().y
if self._hasAbortButton:
sizer.Add(buttonSizer, 0, sizerFlags, LAYOUT_MARGIN )
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
self._agwStyle = agwStyle
self.SetSizerAndFit(sizer)
sizeDlg.y += 2*LAYOUT_MARGIN
# try to make the dialog not square but rectangular of reasonable width
sizeDlg.x = max(widthText, 4*sizeDlg.y//3)
sizeDlg.x *= 3
sizeDlg.x //= 2
self.SetClientSize(sizeDlg)
self.Centre(wx.CENTER|wx.BOTH)
if agwStyle & wx.PD_APP_MODAL:
self._winDisabler = wx.WindowDisabler(self)
else:
if self._parentTop:
self._parentTop.Disable()
self._winDisabler = None
self.ShowDialog()
self.Enable()
# this one can be initialized even if the others are unknown for now
# NB: do it after calling Layout() to keep the labels correctly aligned
if self._elapsed:
self.SetTimeLabel(0, self._elapsed)
self.evtloop = None
# This is causing the unittests to hang, investigate it later.
#if not wx.EventLoopBase.GetActive():
# self.evtloop = wx.GetApp().GetTraits().CreateEventLoop()
# wx.EventLoopBase.SetActive(self.evtloop)
self.Update()
def CreateLabel(self, text, sizer):
"""
Creates the :class:`StaticText` that holds the elapsed time label.
:param `text`: the dialog message to be displayed above the gauge;
:param `sizer`: the main :class:`BoxSizer` for :class:`PyProgress`.
"""
locsizer = wx.BoxSizer(wx.HORIZONTAL)
dummy = wx.StaticText(self, wx.ID_ANY, text)
label = wx.StaticText(self, wx.ID_ANY, "unknown")
if wx.Platform in ["__WXMSW__", "__WXMAC__"]:
# label and time centered in one row
locsizer.Add(dummy, 1, wx.ALIGN_LEFT)
locsizer.Add(label, 1, wx.ALIGN_LEFT|wx.LEFT, LAYOUT_MARGIN)
sizer.Add(locsizer, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.TOP, LAYOUT_MARGIN)
else:
# label and time to the right in one row
sizer.Add(locsizer, 0, wx.ALIGN_RIGHT|wx.RIGHT|wx.TOP, LAYOUT_MARGIN)
locsizer.Add(dummy)
locsizer.Add(label, 0, wx.LEFT, LAYOUT_MARGIN)
return label
# ----------------------------------------------------------------------------
# wxProgressDialog operations
# ----------------------------------------------------------------------------
def UpdatePulse(self, newmsg=""):
"""
Updates the dialog, setting the progress bar to the new value and, if given
changes the message above it. Returns ``True`` unless the ``Cancel`` button
has been pressed.
If ``False`` is returned, the application can either immediately destroy the
dialog or ask the user for the confirmation.
:param `newmsg`: The new messages for the progress dialog text, if it is
empty (which is the default) the message is not changed.
"""
self._gauge.Update()
if newmsg and newmsg != self._msg.GetLabel():
self._msg.SetLabel(newmsg)
wx.SafeYield()
if self._elapsed:
elapsed = int(time.time()) - self._timeStart
if self._last_timeupdate < elapsed:
self._last_timeupdate = elapsed
self.SetTimeLabel(elapsed, self._elapsed)
if self._state == Finished:
if not self._agwStyle & wx.PD_AUTO_HIDE:
self.EnableClose()
if newmsg == "":
# also provide the finishing message if the application didn't
self._msg.SetLabel("Done.")
wx.SafeYield()
self.ShowModal()
return False
else:
# 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
self.ReenableOtherWindows()
self.Hide()
# 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
wx.SafeYield()
return self._state != Canceled
def GetFirstGradientColour(self):
""" Returns the gauge first gradient colour. """
return self._gauge.GetFirstGradientColour()
def SetFirstGradientColour(self, colour):
"""
Sets the gauge first gradient colour.
:param `colour`: a valid :class:`Colour` object.
"""
self._gauge.SetFirstGradientColour(colour)
def GetSecondGradientColour(self):
""" Returns the gauge second gradient colour. """
return self._gauge.GetSecondGradientColour()
def SetSecondGradientColour(self, colour):
"""
Sets the gauge second gradient colour.
:param `colour`: a valid :class:`Colour` object.
"""
self._gauge.SetSecondGradientColour(colour)
def GetGaugeBackground(self):
""" Returns the gauge background colour. """
return self._gauge.GetGaugeBackground()
def SetGaugeBackground(self, colour):
"""
Sets the gauge background colour.
:param `colour`: a valid :class:`Colour` object.
"""
self._gauge.SetGaugeBackground(colour)
def SetGaugeSteps(self, steps):
"""
Sets the number of steps the gauge performs before switching from
forward to backward (or vice-versa) movement.
:param `steps`: the number of steps the gauge performs before switching from
forward to backward (or vice-versa) movement.
"""
self._gauge.SetGaugeSteps(steps)
def GetGaugeSteps(self):
"""
Returns the number of steps the gauge performs before switching from
forward to backward (or vice-versa) movement.
"""
return self._gauge.GetGaugeSteps()
def GetGaugeProportion(self):
"""
Returns the relative proportion between the sliding bar and the
whole gauge.
"""
return self._gauge.GetGaugeProportion()
def SetGaugeProportion(self, proportion):
"""
Sets the relative proportion between the sliding bar and the
whole gauge.
:param `proportion`: a floating point number representing the relative
proportion between the sliding bar and the whole gauge.
"""
self._gauge.SetGaugeProportion(proportion)
def ShowDialog(self, show=True):
"""
Show the dialog.
:param `show`: ``True`` to show the dialog and re-enable all the other windows,
``False`` otherwise.
"""
# 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
if not show:
self.ReenableOtherWindows()
return self.Show()
def GetAGWWindowStyleFlag(self):
"""
Returns the :class:`PyProgress` style.
:see: The :meth:`~PyProgress.__init__` method for a list of possible style flags.
"""
return self._agwStyle
# ----------------------------------------------------------------------------
# event handlers
# ----------------------------------------------------------------------------
def OnCancel(self, event):
"""
Handles the ``wx.EVT_BUTTON`` event for the dialog.
:param `event`: a :class:`CommandEvent` event to be processed.
:note: This method handles the ``Cancel`` button press.
"""
if self._state == Finished:
# this means that the count down is already finished and we're being
# shown as a modal dialog - so just let the default handler do the job
event.Skip()
else:
# request to cancel was received, the next time Update() is called we
# will handle it
self._state = Canceled
# update the buttons state immediately so that the user knows that the
# request has been noticed
self.DisableAbort()
# save the time when the dialog was stopped
self._timeStop = int(time.time())
self.ReenableOtherWindows()
def OnDestroy(self, event):
"""
Handles the ``wx.EVT_WINDOW_DESTROY`` event for :class:`PyProgress`.
:param `event`: a :class:`WindowDestroyEvent` event to be processed.
"""
if self.evtloop:
wx.EventLoopBase.SetActive(None)
self.ReenableOtherWindows()
event.Skip()
def OnClose(self, event):
"""
Handles the ``wx.EVT_CLOSE`` event for :class:`PyProgress`.
:param `event`: a :class:`CloseEvent` event to be processed.
"""
if self._state == Uncancelable:
# can't close this dialog
event.Veto()
elif self._state == Finished:
# let the default handler close the window as we already terminated
self.Hide()
event.Skip()
else:
# next Update() will notice it
self._state = Canceled
self.DisableAbort()
self._timeStop = int(time.time())
def ReenableOtherWindows(self):
""" Re-enables the other windows if using :class:`WindowDisabler`. """
if self._agwStyle & wx.PD_APP_MODAL:
if hasattr(self, "_winDisabler"):
del self._winDisabler
else:
if self._parentTop:
self._parentTop.Enable()
def SetTimeLabel(self, val, label=None):
"""
Sets the elapsed time label.
:param `val`: the elapsed time since the dialog was shown, in seconds;
:param `label`: the new message to display in the elapsed time text.
"""
if label:
hours = val//3600
minutes = (val%3600)//60
seconds = val%60
strs = ("%lu:%02lu:%02lu")%(hours, minutes, seconds)
if strs != label.GetLabel():
label.SetLabel(strs)
def EnableAbort(self, enable=True):
"""
Enables or disables the ``Cancel`` button.
:param `enable`: ``True`` to enable the ``Cancel`` button, ``False`` to disable it.
"""
if self._hasAbortButton:
if self._btnAbort:
self._btnAbort.Enable(enable)
def EnableClose(self, enable=True):
"""
Enables or disables the ``Close`` button.
:param `enable`: ``True`` to enable the ``Close`` button, ``False`` to disable it.
"""
if self._hasAbortButton:
if self._btnAbort:
self._btnAbort.Enable(enable)
self._btnAbort.SetLabel("Close")
self._btnAbort.Bind(wx.EVT_BUTTON, self.OnClose)
def DisableAbort(self):
""" Disables the ``Cancel`` button. """
self.EnableAbort(False)
if __name__ == '__main__':
import wx
# Our normal wxApp-derived class, as usual
app = wx.App(0)
dlg = PyProgress(None, -1, "PyProgress Example",
"An Informative Message",
agwStyle=wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME)
dlg.SetGaugeProportion(0.2)
dlg.SetGaugeSteps(50)
dlg.SetGaugeBackground(wx.WHITE)
dlg.SetFirstGradientColour(wx.WHITE)
dlg.SetSecondGradientColour(wx.BLUE)
max = 400
keepGoing = True
count = 0
while keepGoing and count < max:
count += 1
wx.MilliSleep(30)
if count >= max // 2:
keepGoing = dlg.UpdatePulse("Half-time!")
else:
keepGoing = dlg.UpdatePulse()
dlg.Destroy()
app.MainLoop()