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

1603 lines
64 KiB
Python

# --------------------------------------------------------------------------------- #
# GENERICMESSAGEDIALOG wxPython IMPLEMENTATION
#
# Andrea Gavana, @ 07 October 2008
# Latest Revision: 19 Dec 2012, 21.00 GMT
#
#
# TODO List
#
# 1) ?
#
#
# For all kind of problems, requests of enhancements and bug reports, please
# write to me at:
#
# andrea.gavana@gmail.com
# andrea.gavana@maerskoil.com
#
# Or, obviously, to the wxPython mailing list!!!
#
# Tags: phoenix-port, unittest, documented, py3-port
#
# End Of Comments
# --------------------------------------------------------------------------------- #
"""
This class is a possible, fancy replacement for :class:`MessageDialog`.
Description
===========
This class represents a dialog that shows a single or multi-line message,
with a choice of ``OK``, ``Yes``, ``No``, ``Cancel`` and ``Help`` buttons. It is a possible
replacement for the standard :class:`MessageDialog`, with these extra functionalities:
* Possibility to modify the dialog position;
* Custom themed generic bitmap & text buttons;
* Support for normal and extended message (in different fonts);
* Custom labels for the ``OK``, ``Yes``, ``No``, ``Cancel`` and ``Help`` buttons;
* Custom icons for the ``OK``, ``Yes``, ``No``, ``Cancel`` and ``Help`` buttons;
* Possibility to set an icon to the dialog;
* More visibility to the button getting the focus;
* Support for Aqua buttons or Gradient buttons instead of themed ones (see :class:`~lib.agw.aquabutton.AquaButton`
and :class:`~lib.agw.gradientbutton.GradientButton`);
* Possibility to automatically wrap long lines of text;
* Good old Python code :-D .
And a lot more. Check the demo for an almost complete review of the functionalities.
Usage
=====
Usage example::
import wx
import wx.lib.agw.genericmessagedialog as GMD
# Our normal wxApp-derived class, as usual
app = wx.App(0)
main_message = "Hello world! I am the main message."
dlg = GMD.GenericMessageDialog(None, main_message, "A Nice Message Box",
agwStyle=wx.ICON_INFORMATION | wx.OK)
dlg.ShowModal()
dlg.Destroy()
app.MainLoop()
Supported Platforms
===================
:class:`GenericMessageDialog` has been tested on the following platforms:
* Windows (Windows XP).
Window Styles
=============
This class supports the following window styles:
=========================== =========== ==================================================
Window Styles Hex Value Description
=========================== =========== ==================================================
``GMD_DEFAULT`` 0x0 Uses generic buttons.
``GMD_USE_AQUABUTTONS`` 0x20 Uses :mod:`lib.agw.aquabutton` buttons instead of generic buttons.
``GMD_USE_GRADIENTBUTTONS`` 0x40 Uses :mod:`lib.agw.gradientbutton` buttons instead of generic buttons.
=========================== =========== ==================================================
The styles above are mutually exclusive. The style chosen above can be combined with a
bitlist containing flags chosen from the following:
=========================== =========== ==================================================
Window Styles Hex Value Description
=========================== =========== ==================================================
``wx.OK`` 0x4 Shows an ``OK`` button.
``wx.CANCEL`` 0x10 Shows a ``Cancel`` button.
``wx.YES_NO`` 0xA Show ``Yes`` and ``No`` buttons.
``wx.YES_DEFAULT`` 0x0 Used with ``wx.YES_NO``, makes ``Yes`` button the default - which is the default behaviour.
``wx.NO_DEFAULT`` 0x80 Used with ``wx.YES_NO``, makes ``No`` button the default.
``wx.ICON_EXCLAMATION`` 0x100 Shows an exclamation mark icon.
``wx.ICON_HAND`` 0x200 Shows an error icon.
``wx.ICON_ERROR`` 0x200 Shows an error icon - the same as ``wx.ICON_HAND``.
``wx.ICON_QUESTION`` 0x400 Shows a question mark icon.
``wx.ICON_INFORMATION`` 0x800 Shows an information icon.
=========================== =========== ==================================================
Events Processing
=================
`No custom events are available for this class.`
License And Version
===================
:class:`GenericMessageDialog` is distributed under the wxPython license.
Latest Revision: Andrea Gavana @ 19 Dec 2012, 21.00 GMT
Version 0.8
"""
import wx
import wx.lib.wordwrap as wordwrap
import wx.lib.buttons as buttons
from wx.lib.embeddedimage import PyEmbeddedImage
# To use AquaButtons or GradientButtons instead of wx.lib.buttons
import wx.lib.agw.aquabutton as AB
import wx.lib.agw.gradientbutton as GB
# GenericMessageDialog styles
GMD_DEFAULT = 0
""" Uses generic buttons. """
GMD_USE_AQUABUTTONS = 32
""" Uses :mod:`lib.agw.aquabutton` buttons instead of generic buttons. """
GMD_USE_GRADIENTBUTTONS = 64
""" Uses :mod:`lib.agw.gradientbutton` buttons instead of generic buttons. """
# Avoid 2.9 errors
BUTTON_SIZER_FLAGS = wx.OK | wx.CANCEL | wx.YES | wx.NO | wx.HELP | wx.NO_DEFAULT
""" Flag used to mask the :class:`GenericMessageDialog` AGW-specific style. """
_ = wx.GetTranslation
_cancel = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAA1dJ"
"REFUOI11019oEwccB/Dv3eUuyZ2XpfljsmJ7JY01KZYWty6bdMwnp1X34JNS5sPAsmYruOnL"
"3kTGcPg6Bdkexqql4EPdBuKbVG0xLmpoWjbW0D+S1Jg24RJzuSR3l58PtpsI/l5/fB5+3x9f"
"AEDc7VauhMP3prq7q9+1t5/AW+aiLB+ZDocrU6HQk4tAFAC4s8Gg0uVyXTsZiw190Nsr6JnM"
"kZAkrd6rVtOv4wuyfLS/rW3y6Oioq2tgILiRyXy4v1yexU979yaKIyNEiQRRsUjG2Bjddrtr"
"532+k9v4B1kevu33l+vnzhFtbBAtL9OLS5douq9v0eZ1OPo8Xi8gSUClAls8jk+qVad148bP"
"33s8TcY0K32mOTV07JhsP3UKKJUAy8IORYF3584erodopaGqh7qzWYEJBgGGgW3fPrQ/eyY0"
"5uePewzjxIGDB0U5HgcsC1BV0MOH+GtiojF/9+433P1qNd1pGCvs5uawUijwbDAIWBZsAwPw"
"5nJsRyBgc8fjYLZwK5lE6uZN88Hc3LdfmeYVDgDu12oLXUSrxvPnw8r6uo3z+cAQwRGJQOzv"
"B0sEKhZhJRJI3rplJlKpM+OWdRkAuO2gZnQ93UO02CgUjr9bLHKCzweGZcGYJqhchp5I4NGd"
"O9bjpaUvxol+2Xa211/FAKolSa0XySSq+TzYYBAAYGkaUKnA5LgWA6hvmP//PKgokx9tbspq"
"Pg8NgL61c0gSJL8f73R04O9KRV9Mp0+PtlrX/zvhgigO749GJ4dKJVc9l0MTgAVAZBg4BQEk"
"SeCcTjAAOhWF5/3+w7FsdvkPogXuR7f7s/d6eycPqKqrubKC+hZ28DxydnurzHFWwG5niefB"
"CALYVgu7wmGe2toOfby2lrVFIpFrn9brcmNpCU0ALIAdooiMw9FI1etfkmGUbaY5EXY4JIth"
"YAIw1tcxODgoEcddZeua9rQqCGB5HgwA0e3GmsdjPtH1s1/Xar+ON5vTi6p6+qmm6U5JAksE"
"VhBQbzahl0p57n1Nm9kQxVhXINAucxzSLpeZLBTOxHX98nbAfxItxMrlVV4UD+/q7OTJ58Pc"
"7Ow/uVTq81c1FYTo76HQo5k9expXnc6xt9X5OsuOPIhGtZndu//9DYgBwEt1gHq0YITgmAAA"
"AABJRU5ErkJggg==")
#----------------------------------------------------------------------
_error = PyEmbeddedImage(
"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")
#----------------------------------------------------------------------
_help = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAtxJ"
"REFUOI2lk81LFHEYx5+ZndnWnV0bt8z2TYKpxYsdwpBWA62w2rxIdOgmdPAvCOnqMSiig2SB"
"lVmeAhEsJt02SNdcXZXC1HYT3SRWXLd1HHdmduf3ezqUgrjQoef08MDzeZ7v8wLwn8aUCn69"
"fNntWl9vsrrdR4pra2lDEN5Xf/qU/ScgMjR09PTjxw/sLS03+YYGFmw2QF0Hc2KisJXL9Sxf"
"uNAZDAa1koBIJHJcFMUxKZOR+EwGVhHBQIQT5eVgzedBb26GX6o6kc1mL9XV1eV389hdxzU+"
"/tzpdErfnU6IiaIunD+/6Gm5MhkXhLEvXm+6QAiUT02d87W1PTygY76pqT4jipjq6EBZlrfz"
"eW1S1/U5TdPnVFWLxuOzTz7L8s5GfT2mRZEkPB7/vg7sq6vXiKLAyswMSNKpJUIIFosUCSEM"
"pdQhSVJdQlXDRlUVmIrCWnO5q7sADgCAFgp+k1LQ/X4wjAKqO1qOs7B2lmVtCMBQgmYqlVo+"
"K0mAlAItFj37OqAMkzMBwC8IIMvvOGISq6YZRUXVthQlvzX6fnSnoqJiAbNZMAHAtFi29wEM"
"QYgQAODDYQj4jqfu37+3MTYeLZuNz1r7XjyHvme9ou3QoY5iNArkT8GP+4Y43dPDL9rtiW+h"
"EC7FYnRhYeFee3t7sLa29szw8HAg/ObNYGsohK+fPsXk9etRRNxb/54T6+0NHm5oCPMcZyt2"
"dQEbCCBbVbXDpNMOY2AANi9ehLsrK+Dz+e52d3d3lrzE6enpRlc8/pKV5WpEBCQEkFJASqGw"
"ubn4qrn5dmxm5lFlZWV/f3//HYZh8MAvDLW22k86HDfsktTEWK3H6Pb2T3V+fvRHIjEYSiYN"
"j8cTqKmp+WCxWG6NjIy8LfVMjNvtLlMUxWGapgMRbYhoRUT+79AJAHA8z6e8Xu8mVwKAjY2N"
"RiwWo6qqaqZpcoQQy65clmUJx3Gmy+Uykslk4TdmSW8/+y1ZpAAAAABJRU5ErkJggg==")
#----------------------------------------------------------------------
_information = PyEmbeddedImage(
"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")
#----------------------------------------------------------------------
_no = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAelJ"
"REFUOI21ksFL03EYxj/fX1tuWEtxW0ZulbbpKYutIYM6CIFEimh2CUFIKKhLpxCKSPwDunSI"
"IOgQSh48dq5DB9EiVik/NaHBYrRm5HTG2u/pMAsTiRb0nJ735X0e3vfhhf+FC4dpT/WioWY6"
"/8ngfT8reoXsXtYBd1XigTDnc/frJeW18iigoSOMAOavxEehZm4QOYXHymRmVV6b1PIlFPFy"
"cKf5Xdsb9gD3gtdisdlcn3n+LEXm017inRniSx+iD5eY2D5vbS2uNBP8coDLnuRd46kpUiqV"
"8O0p4YqNETrOudONxP9ocP0Y0y13uoAyTU0W+fxXmkIWsEF4pIsHSZ4CNTsa3G4n4TvjPkTd"
"MPARv3+VbDZHJLIBpGFfD3Vn3Q1XW+lnS6A/iZnrw2mb7AYruRmNmJ7+TCJRC2wAa+DMsHDx"
"BdEJGoD8rw2W+7gRvuUCyw8sAPMUCm8ZH39NNpsC5gEbLC+hmy6enGLst/PfDSKpVdJJSR2S"
"OjQ1dUKRSESjo1FJbZJaJIUlBWQPIyAAwJseZuQYSQFJ+yU1SmpUWUHZi34Vv9VL8kmqleSR"
"tFsSetnNIuB2GbDtQcWMexWMwRgLpM3dHNKOU6FykASq1OvfSQNes3mL31vdv5tiJdl8FZqd"
"8QO3F9ZRFEVpTAAAAABJRU5ErkJggg==")
#----------------------------------------------------------------------
_ok = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAjdJ"
"REFUOI2tksFLk3Ecxp+97975vmuve1dWuiUTNIy1JlsLpkZG0aXLbv0B0aVDUMfVQTp0jJpF"
"EHl5LxUZgZcuQjAID4KUyWwyEU3d9m7O5d733dze97dfB1siJSn1nJ/P5+ELX+Afwx6YuAMB"
"AVgwjcaBBdIovP2eyKMLPYNdM+7kNKZA9i3gR+ENCeF4Hx+8VigVBgrKWrXKGp/2JeCfwhsW"
"Q/HTQiCaVTOYUiZtDuoMQqefrc1S9+uOEGNSRzqd+4j72/c1l4OOQNwn+aOFWg5TdBJEIKbH"
"dI9zHLMt6H3lHrjScfU5x3DSmOXNrVUUxwFQ6S3vDdh9cZ/zTHSz8R0pMguGMKaRMuX5peQ9"
"ZULPW8+PnB286L78zH/M76/DwCYtjSTefaAOQZjpEDofn5J8UR0qViqLoCpLql+IXFzS72IC"
"eQCwssR2NFfOtNXsFZx09SLkDnfSlsYTluUy7a3Hz6mWMrLGKswiJaV0WS6Uyr9gAGC7It0L"
"WrWYm99K9VdcqugSD8Pd6nG6RNeJCq9ZstwqNL1CMl/z8npdiRkPd2AAYJcTy41FcSVZt+lK"
"na9FaLspCg4ehDew3qJgs6qStUxerhItlr+h74KB5iPNgVZuGkm6QpQWmy3i8AoiY7dA1XTy"
"LZuVGYHGZi8t/gbvCABgDFS7vpVEgSgS29bv5CR7XtmQjxxyxt77En+Edwt+Svpua3MbRT5T"
"a9QXPGL7gxc9L/eE98wwHWaG6JD1783/kB9qTvueLt8LjwAAAABJRU5ErkJggg==")
#----------------------------------------------------------------------
_question = PyEmbeddedImage(
"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"
"AElFTkSuQmCC")
#----------------------------------------------------------------------
_reassign = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAcRJ"
"REFUKJGdj01Ik3Ecxz///565KcvkcUwedtiWRFRUprTAxxZLq0MRzBy5IIoShF5cp6BLBF16"
"oU4RnQK7BC2WtEOLGLJkvdGbBzOFEqpLRXhYbZLu+XWwt3Mf+B4/H/gqFlkOnAU+AGFgDlgJ"
"zABBIC0ij5RSAoDH485lr52SocHdMv7giqR6e2SyeFn2JLrlWf6SWIHGj4VCoRXAAGhb17Yz"
"urFTFnSTevn4KYnePqamp0j17+Xzl3esWdseFJFlwFsDQGmD4KrtyvzkZf/h05w/18GOXScw"
"dA2UG9/tNwALADqTySQrlW/kcncYyd5ia3w9kZYaN65fpVwu43Y5gKCUUgA6mUzePHRwQIpj"
"BZY2NXD0eBq7qwNrySxjo/eo1Ry01vzGABhKDyjmRsCoh9nvUP2KUZnm7pMJujZv41f8r5A+"
"sk9ejWaVUddAIh4httrF5HuLwWMnsawWHMf5I+hSqWQXSzPqwvBzuvvPcHF4gvuvG1nReYBw"
"OML8/A9EBBERAMO27YexWIzohnY8dS7GX/TRuilFfEsP1WoFr7cen8+H/vcIUAmFQmKappim"
"Kc3NfvH7FxcIBASQfD4f5X/4CVPZn52VDH4mAAAAAElFTkSuQmCC")
#----------------------------------------------------------------------
_warning = PyEmbeddedImage(
"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"
"7HCEfEAAAAAASUVORK5CYII=")
#----------------------------------------------------------------------
_yes = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAjdJ"
"REFUOI2tksFLk3Ecxp+97975vmuve1dWuiUTNIy1JlsLpkZG0aXLbv0B0aVDUMfVQTp0jJpF"
"EHl5LxUZgZcuQjAID4KUyWwyEU3d9m7O5d733dze97dfB1siJSn1nJ/P5+ELX+Afwx6YuAMB"
"AVgwjcaBBdIovP2eyKMLPYNdM+7kNKZA9i3gR+ENCeF4Hx+8VigVBgrKWrXKGp/2JeCfwhsW"
"Q/HTQiCaVTOYUiZtDuoMQqefrc1S9+uOEGNSRzqd+4j72/c1l4OOQNwn+aOFWg5TdBJEIKbH"
"dI9zHLMt6H3lHrjScfU5x3DSmOXNrVUUxwFQ6S3vDdh9cZ/zTHSz8R0pMguGMKaRMuX5peQ9"
"ZULPW8+PnB286L78zH/M76/DwCYtjSTefaAOQZjpEDofn5J8UR0qViqLoCpLql+IXFzS72IC"
"eQCwssR2NFfOtNXsFZx09SLkDnfSlsYTluUy7a3Hz6mWMrLGKswiJaV0WS6Uyr9gAGC7It0L"
"WrWYm99K9VdcqugSD8Pd6nG6RNeJCq9ZstwqNL1CMl/z8npdiRkPd2AAYJcTy41FcSVZt+lK"
"na9FaLspCg4ehDew3qJgs6qStUxerhItlr+h74KB5iPNgVZuGkm6QpQWmy3i8AoiY7dA1XTy"
"LZuVGYHGZi8t/gbvCABgDFS7vpVEgSgS29bv5CR7XtmQjxxyxt77En+Edwt+Svpua3MbRT5T"
"a9QXPGL7gxc9L/eE98wwHWaG6JD1783/kB9qTvueLt8LjwAAAABJRU5ErkJggg==")
class StdDialogButtonSizer(wx.BoxSizer):
""" wxWidgets standard dialog button sizer. """
def __init__(self):
""" Default class constructor. """
wx.BoxSizer.__init__(self, wx.HORIZONTAL)
self._buttonAffirmative = None
self._buttonApply = None
self._buttonNegative = None
self._buttonCancel = None
self._buttonHelp = None
def AddButton(self, mybutton):
"""
Add a button to the sizer.
:param `mybutton`: the button to add.
"""
buttonId = mybutton.GetId()
if buttonId in [wx.ID_OK, wx.ID_YES, wx.ID_SAVE]:
self._buttonAffirmative = mybutton
elif buttonId == wx.ID_APPLY:
self._buttonApply = mybutton
elif buttonId == wx.ID_NO:
self._buttonNegative = mybutton
elif buttonId in [wx.ID_CANCEL, wx.ID_CLOSE]:
self._buttonCancel = mybutton
elif buttonId in [wx.ID_HELP, wx.ID_CONTEXT_HELP]:
self._buttonHelp = mybutton
def SetAffirmativeButton(self, button):
"""
Sets the affirmative button.
:param `button`: the button to set as affirmative one.
"""
self._buttonAffirmative = button
def SetNegativeButton(self, button):
"""
Sets the negative button.
:param `button`: the button to set as negative one.
"""
self._buttonNegative = button
def SetCancelButton(self, button):
"""
Sets the cancel button.
:param `button`: the button to set as cancel one.
"""
self._buttonCancel = button
def Realize(self):
""" Realizes the sizer depending on the platform. """
if wx.Platform == "__WXMAC__":
self.Add((0, 0), 0, wx.LEFT, 6)
if self._buttonHelp:
self.Add(self._buttonHelp, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 6)
if self._buttonNegative:
# HIG POLICE BULLETIN - destructive buttons need extra padding
# 24 pixels on either side
self.Add(self._buttonNegative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 12)
# extra whitespace between help/negative and cancel/ok buttons
self.Add((0, 0), 1, wx.EXPAND, 0)
if self._buttonCancel:
self.Add(self._buttonCancel, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 6)
# Cancel or help should be default
# self._buttonCancel.SetDefaultButton()
# Ugh, Mac doesn't really have apply dialogs, so I'll just
# figure the best place is between Cancel and OK
if self._buttonApply:
self.Add(self._buttonApply, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 6)
if self._buttonAffirmative:
self.Add(self._buttonAffirmative, 0, wx.ALIGN_CENTRE | wx.LEFT, 6)
if self._buttonAffirmative.GetId() == wx.ID_SAVE:
# these buttons have set labels under Mac so we should use them
self._buttonAffirmative.SetLabel(_("Save"))
if self._buttonNegative:
self._buttonNegative.SetLabel(_("Don't Save"))
# Extra space around and at the right
self.Add((12, 24))
elif wx.Platform == "__WXGTK__":
self.Add((0, 0), 0, wx.LEFT, 9)
if self._buttonHelp:
self.Add(self._buttonHelp, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 3)
# extra whitespace between help and cancel/ok buttons
self.Add((0, 0), 1, wx.EXPAND, 0)
if self._buttonNegative:
self.Add(self._buttonNegative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 3)
# according to HIG, in explicit apply windows the order is:
# [ Help Apply Cancel OK ]
if self._buttonApply:
self.Add(self._buttonApply, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 3)
if self._buttonCancel:
self.Add(self._buttonCancel, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 3)
# Cancel or help should be default
# self._buttonCancel.SetDefaultButton()
if self._buttonAffirmative:
self.Add(self._buttonAffirmative, 0, wx.ALIGN_CENTRE | wx.LEFT, 6)
elif wx.Platform == "__WXMSW__":
# Windows
# center-justify buttons
self.Add((0, 0), 1, wx.EXPAND, 0)
if self._buttonAffirmative:
self.Add(self._buttonAffirmative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonAffirmative.ConvertDialogToPixels(wx.Size(2, 0)).x)
if self._buttonNegative:
self.Add(self._buttonNegative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonNegative.ConvertDialogToPixels(wx.Size(2, 0)).x)
if self._buttonCancel:
self.Add(self._buttonCancel, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonCancel.ConvertDialogToPixels(wx.Size(2, 0)).x)
if self._buttonApply:
self.Add(self._buttonApply, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonApply.ConvertDialogToPixels(wx.Size(2, 0)).x)
if self._buttonHelp:
self.Add(self._buttonHelp, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonHelp.ConvertDialogToPixels(wx.Size(2, 0)).x)
self.Add((0, 0), 1, wx.EXPAND, 0)
else:
# GTK+1 and any other platform
if self._buttonHelp:
self.Add(self._buttonHelp, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonHelp.ConvertDialogToPixels(wx.Size(4, 0)).x)
# extra whitespace between help and cancel/ok buttons
self.Add((0, 0), 1, wx.EXPAND, 0)
if self._buttonApply:
self.Add(self._buttonApply, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonApply.ConvertDialogToPixels(wx.Size(4, 0)).x)
if self._buttonAffirmative:
self.Add(self._buttonAffirmative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonAffirmative.ConvertDialogToPixels(wx.Size(4, 0)).x)
if self._buttonNegative:
self.Add(self._buttonNegative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonNegative.ConvertDialogToPixels(wx.Size(4, 0)).x)
if self._buttonCancel:
self.Add(self._buttonCancel, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonCancel.ConvertDialogToPixels(wx.Size(4, 0)).x)
# Cancel or help should be default
# self._buttonCancel.SetDefaultButton()
class GenericMessageDialog(wx.Dialog):
"""
Main class implementation, :class:`GenericMessageDialog` is a possible replacement
for the standard :class:`MessageDialog`.
"""
def __init__(self, parent, message, caption, agwStyle,
pos=wx.DefaultPosition, size=wx.DefaultSize,
style=wx.DEFAULT_DIALOG_STYLE|wx.WANTS_CHARS,
wrap=-1):
"""
Default class constructor. Use :meth:`~GenericMessageDialog.ShowModal` to show the dialog.
:param `parent`: the :class:`GenericMessageDialog` parent (if any);
:param `message`: the message in the main body of the dialog;
:param `caption`: the dialog title;
:param `agwStyle`: the AGW-specific dialog style; it can be one of the
following bits:
=========================== =========== ==================================================
Window Styles Hex Value Description
=========================== =========== ==================================================
``GMD_DEFAULT`` 0 Uses normal generic buttons
``GMD_USE_AQUABUTTONS`` 0x20 Uses :class:`~lib.agw.aquabutton.AquaButton` buttons instead of generic buttons.
``GMD_USE_GRADIENTBUTTONS`` 0x40 Uses :class:`~lib.agw.gradientbutton.GradientButton` buttons instead of generic buttons.
=========================== =========== ==================================================
The styles above are mutually exclusive. The style chosen above can be combined with a
bitlist containing flags chosen from the following:
=========================== =========== ==================================================
Window Styles Hex Value Description
=========================== =========== ==================================================
``wx.OK`` 0x4 Shows an ``OK`` button.
``wx.CANCEL`` 0x10 Shows a ``Cancel`` button.
``wx.YES_NO`` 0xA Show ``Yes`` and ``No`` buttons.
``wx.YES_DEFAULT`` 0x0 Used with ``wx.YES_NO``, makes ``Yes`` button the default - which is the default behaviour.
``wx.NO_DEFAULT`` 0x80 Used with ``wx.YES_NO``, makes ``No`` button the default.
``wx.ICON_EXCLAMATION`` 0x100 Shows an exclamation mark icon.
``wx.ICON_HAND`` 0x200 Shows an error icon.
``wx.ICON_ERROR`` 0x200 Shows an error icon - the same as ``wx.ICON_HAND``.
``wx.ICON_QUESTION`` 0x400 Shows a question mark icon.
``wx.ICON_INFORMATION`` 0x800 Shows an information icon.
=========================== =========== ==================================================
:param `pos`: the dialog position on screen;
:param `size`: the dialog size;
:param `style`: the underlying :class:`Dialog` style;
:param `wrap`: if set greater than zero, wraps the string in `message` so that
every line is at most `wrap` pixels long.
:note: Notice that not all styles are compatible: only one of ``wx.OK`` and ``wx.YES_NO`` may be
specified (and one of them must be specified) and at most one default button style can be used
and it is only valid if the corresponding button is shown in the message box.
"""
wx.Dialog.__init__(self, parent, wx.ID_ANY, caption, pos, size, style)
self._message = message
self._agwStyle = agwStyle
self._wrap = wrap
# The extended message placeholder
self._extendedMessage = ''
# Labels for the buttons, initially empty meaning that the defaults should
# be used, use GetYes/No/OK/CancelLabel() to access them
self._yes = self._no = self._ok = self._cancel = self._help = ''
# Icons for the buttons, initially empty meaning that the defaults should
# be used, use GetYes/No/OK/CancelBitmap() to access them
self._yesBitmap = self._noBitmap = self._okBitmap = self._cancelBitmap = self._helpBitmap = None
self._created = False
def CreateMessageDialog(self):
""" Actually creates the :class:`GenericMessageDialog`, just before showing it on screen. """
message = self.GetMessage()
topsizer = wx.BoxSizer(wx.VERTICAL)
icon_text = wx.BoxSizer(wx.HORIZONTAL)
case = self._agwStyle & wx.ICON_MASK
if case == wx.ICON_ERROR:
bitmap = _error
elif case == wx.ICON_INFORMATION:
bitmap = _information
elif case == wx.ICON_WARNING:
bitmap = _warning
elif case == wx.ICON_QUESTION:
bitmap = _question
# Populate the sizers...
icon = wx.StaticBitmap(self, -1, bitmap.GetBitmap())
icon_text.Add(icon, 0, wx.ALIGN_CENTER_HORIZONTAL)
textsizer = wx.BoxSizer(wx.VERTICAL)
# We want to show the main message in a different font to make it stand
# out if the extended message is used as well. This looks better and is
# more consistent with the native dialogs under MSW and GTK.
if self._extendedMessage.strip():
boldFont = self.GetFont().Larger().MakeBold()
if self._wrap > 0:
message = self.WrapMessage(message, self._wrap, boldFont)
msgSizer = self.CreateTextSizer(message)
for index in range(len(msgSizer.GetChildren())):
msgSizer.GetItem(index).GetWindow().SetFont(boldFont)
textsizer.Add(msgSizer, wx.SizerFlags().Border(wx.BOTTOM, 20))
lowerMessage = self.GetExtendedMessage()
else: # no extended message
lowerMessage = message
if self._wrap > 0:
lowerMessage = self.WrapMessage(lowerMessage, self._wrap)
textsizer.Add(self.CreateTextSizer(lowerMessage))
icon_text.Add(textsizer, 1, wx.ALIGN_CENTER | wx.LEFT, 10)
topsizer.Add(icon_text, 1, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 10)
center_flag = wx.EXPAND
if self._agwStyle & wx.YES_NO:
center_flag |= wx.ALIGN_CENTRE
sizerBtn = self.CreateSeparatedButtonSizer(self._agwStyle & BUTTON_SIZER_FLAGS)
if sizerBtn:
topsizer.Add(sizerBtn, 0, center_flag | wx.ALL, 10)
self.SetAutoLayout(True)
self.SetSizer(topsizer)
topsizer.SetSizeHints(self)
topsizer.Fit(self)
size = self.GetSize()
if size.x < size.y*3//2:
size.x = size.y*3//2
self.SetSize(size)
self.Layout()
self.Centre(wx.BOTH)
self.Bind(wx.EVT_BUTTON, self.OnYes, id=wx.ID_YES)
self.Bind(wx.EVT_BUTTON, self.OnOk, id=wx.ID_OK)
self.Bind(wx.EVT_BUTTON, self.OnNo, id=wx.ID_NO)
self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL)
self.Bind(wx.EVT_BUTTON, self.OnHelp, id=wx.ID_HELP)
for child in self.GetChildren():
if isinstance(child, wx.lib.buttons.ThemedGenBitmapTextButton) or \
isinstance(child, AB.AquaButton) or isinstance(child, GB.GradientButton):
# Handles the key down for the buttons...
child.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
if isinstance(child, wx.lib.buttons.ThemedGenBitmapTextButton):
child.SetUseFocusIndicator(False)
self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigation)
self.SwitchFocus()
def EndDialog(self, rc):
"""
Ends the :class:`GenericMessageDialog` life. This will be done differently depending on
the dialog modal/non-modal behaviour.
:param `rc`: one of the ``wx.ID_YES``, ``wx.ID_NO``, ``wx.ID_OK``, ``wx.ID_CANCEL`` constants.
:note: the `rc` parameter is unused if the dialog is not modal.
"""
if self.IsModal():
self.EndModal(rc)
else:
self.Hide()
def OnYes(self, event):
""" :class:`GenericMessageDialog` had received a ``wx.ID_YES`` answer. """
self.EndDialog(wx.ID_YES)
def OnOk(self, event):
""" :class:`GenericMessageDialog` had received a ``wx.ID_OK`` answer. """
self.EndDialog(wx.ID_OK)
def OnNo(self, event):
""" :class:`GenericMessageDialog` had received a ``wx.ID_NO`` answer. """
self.EndDialog(wx.ID_NO)
def OnCancel(self, event):
""" :class:`GenericMessageDialog` had received a ``wx.ID_CANCEL`` answer. """
# Allow cancellation via ESC/Close button except if
# only YES and NO are specified.
if self._agwStyle & wx.YES_NO != wx.YES_NO or self._agwStyle & wx.CANCEL:
self.EndDialog(wx.ID_CANCEL)
def OnHelp(self, event):
""" :class:`GenericMessageDialog` had received a ``wx.ID_HELP`` answer. """
self.EndDialog(wx.ID_HELP)
def OnKeyDown(self, event):
"""
Handles the ``wx.EVT_KEY_DOWN`` event for :class:`GenericMessageDialog`.
:param `event`: a :class:`KeyEvent` event to be processed.
"""
key = event.GetKeyCode()
if key == wx.WXK_ESCAPE:
self.OnCancel(None)
ids = []
for child in self.GetChildren():
if isinstance(child, wx.lib.buttons.ThemedGenBitmapTextButton) or \
isinstance(child, AB.AquaButton) or isinstance(child, GB.GradientButton):
ids.append(child.GetId())
if key in [ord("y"), ord("Y")] and wx.ID_YES in ids:
self.OnYes(None)
elif key in [ord("n"), ord("N")] and wx.ID_NO in ids:
self.OnNo(None)
elif key in [ord("c"), ord("C")] and wx.ID_CANCEL in ids:
self.OnCancel(None)
elif key in [ord("o"), ord("O")] and wx.ID_OK in ids:
self.OnOk(None)
elif key in [ord("h"), ord("H")] and wx.ID_HELP in ids:
self.OnHelp(None)
event.Skip()
def OnNavigation(self, event):
"""
Handles the ``wx.EVT_NAVIGATION_KEY`` event for :class:`GenericMessageDialog`.
:param `event`: a :class:`NavigationKeyEvent` event to be processed.
"""
# Switch the focus between buttons...
if wx.GetKeyState(wx.WXK_LEFT) or wx.GetKeyState(wx.WXK_RIGHT) or \
wx.GetKeyState(wx.WXK_DOWN) or wx.GetKeyState(wx.WXK_UP) or \
wx.GetKeyState(wx.WXK_NUMPAD_LEFT) or wx.GetKeyState(wx.WXK_NUMPAD_RIGHT) or \
wx.GetKeyState(wx.WXK_NUMPAD_DOWN) or wx.GetKeyState(wx.WXK_NUMPAD_UP) or \
event.IsFromTab():
event.Skip()
wx.CallAfter(self.SwitchFocus)
return
button = wx.Window.FindFocus()
buttonId = button.GetId()
self.EndDialog(buttonId)
def SwitchFocus(self):
""" Switch focus between buttons. """
current = wx.Window.FindFocus()
font = self.GetFont()
boldFont = wx.Font(font.GetPointSize(), font.GetFamily(), font.GetStyle(), wx.BOLD,
font.GetUnderlined(), font.GetFaceName())
for child in self.GetChildren():
if isinstance(child, wx.lib.buttons.ThemedGenBitmapTextButton) or \
isinstance(child, AB.AquaButton) or isinstance(child, GB.GradientButton):
if child == current:
# Set a bold font for the current focused button
child.SetFont(boldFont)
else:
# Restore the other buttons...
child.SetFont(font)
child.Refresh()
def CreateButtonSizer(self, flags):
"""
Creates a sizer with standard buttons.
:param `flags`: a bit list of the following flags:
================= ========= ==========================
Flags Hex Value Description
================= ========= ==========================
``wx.YES`` 0x2 Show a ``Yes`` button
``wx.OK`` 0x4 Show an ``OK`` button
``wx.NO`` 0x8 Show a ``No`` button
``wx.CANCEL`` 0x10 Show a ``Cancel`` button
``wx.NO_DEFAULT`` 0x80 Used with ``wx.YES`` and ``wx.NO``, makes ``No`` button the default
``wx.HELP`` 0x8000 Show a ``Help`` button
================= ========= ==========================
:note: The sizer lays out the buttons in a manner appropriate to the platform.
"""
sizer = self.CreateStdDialogButtonSizer(flags)
return sizer
def CreateSeparatedButtonSizer(self, flags):
"""
Creates a sizer with standard buttons using :meth:`~GenericMessageDialog.CreateButtonSizer` separated
from the rest of the dialog contents by a horizontal :class:`StaticLine`.
:param `flags`: the button sizer flags.
:see: :meth:`~GenericMessageDialog.CreateButtonSizer` for a list of valid flags.
"""
sizer = self.CreateButtonSizer(flags)
# Mac Human Interface Guidelines recommend not to use static lines as
# grouping elements
if wx.Platform != "__WXMAC__":
topsizer = wx.BoxSizer(wx.VERTICAL)
topsizer.Add(wx.StaticLine(self), wx.SizerFlags().Expand().DoubleBorder(wx.BOTTOM))
topsizer.Add(sizer, wx.SizerFlags().Expand())
sizer = topsizer
return sizer
def CreateStdDialogButtonSizer(self, flags):
"""
Creates a :class:`StdDialogButtonSizer` with standard buttons.
:param `flags`: the button sizer flags.
:see: :meth:`~GenericMessageDialog.CreateButtonSizer` for a list of valid flags.
:note: The sizer lays out the buttons in a manner appropriate to the platform.
"""
sizer = StdDialogButtonSizer()
no = yes = ok = None
if flags & wx.OK:
# Remove unwanted flags...
flags &= ~(wx.YES | wx.NO | wx.NO_DEFAULT)
if self._agwStyle & GMD_USE_AQUABUTTONS:
klass = AB.AquaButton
elif self._agwStyle & GMD_USE_GRADIENTBUTTONS:
klass = GB.GradientButton
else:
klass = buttons.ThemedGenBitmapTextButton
if flags & wx.OK:
ok = klass(self, wx.ID_OK, self.GetCustomOKBitmap(), self.GetCustomOKLabel())
sizer.AddButton(ok)
if flags & wx.CANCEL:
cancel = klass(self, wx.ID_CANCEL, self.GetCustomCancelBitmap(), self.GetCustomCancelLabel())
sizer.AddButton(cancel)
if flags & wx.YES:
yes = klass(self, wx.ID_YES, self.GetCustomYesBitmap(), self.GetCustomYesLabel())
sizer.AddButton(yes)
if flags & wx.NO:
no = klass(self, wx.ID_NO, self.GetCustomNoBitmap(), self.GetCustomNoLabel())
sizer.AddButton(no)
if flags & wx.HELP:
help = klass(self, wx.ID_HELP, self.GetCustomHelpBitmap(), self.GetCustomHelpLabel())
sizer.AddButton(help)
if flags & wx.NO_DEFAULT:
if no:
no.SetDefault()
no.SetFocus()
else:
if ok:
ok.SetDefault()
ok.SetFocus()
elif yes:
yes.SetDefault()
yes.SetFocus()
if flags & wx.OK:
self.SetAffirmativeId(wx.ID_OK)
elif flags & wx.YES:
self.SetAffirmativeId(wx.ID_YES)
sizer.Realize()
return sizer
def GetDefaultYesLabel(self):
"""
Returns the default label for the ``Yes`` button.
:note: this method may be overridden to provide different defaults for the
default button labels.
.. versionadded:: 0.9.3
"""
return _("Yes")
def GetDefaultNoLabel(self):
"""
Returns the default label for the ``No`` button.
:note: this method may be overridden to provide different defaults for the
default button labels.
.. versionadded:: 0.9.3
"""
return _("No")
def GetDefaultOKLabel(self):
"""
Returns the default label for the ``OK`` button.
:note: this method may be overridden to provide different defaults for the
default button labels.
.. versionadded:: 0.9.3
"""
return _("OK")
def GetDefaultCancelLabel(self):
"""
Returns the default label for the ``Cancel`` button.
:note: this method may be overridden to provide different defaults for the
default button labels.
.. versionadded:: 0.9.3
"""
return _("Cancel")
def GetDefaultHelpLabel(self):
"""
Returns the default label for the ``Help`` button.
:note: this method may be overridden to provide different defaults for the
default button labels.
.. versionadded:: 0.9.3
"""
return _("Help")
def GetCustomOKLabel(self):
"""
If a custom label has been used for the ``OK`` button, this method will return
it as a string. Otherwise, the default one (as defined in :meth:`~GenericMessageDialog.GetDefaultOKLabel`)
is returned.
.. versionadded:: 0.9.3
"""
return (self._ok and [self._ok] or [self.GetDefaultOKLabel()])[0]
def GetCustomYesLabel(self):
"""
If a custom label has been used for the ``Yes`` button, this method will return
it as a string. Otherwise, the default one (as defined in :meth:`~GenericMessageDialog.GetDefaultYesLabel`)
is returned.
.. versionadded:: 0.9.3
"""
return (self._yes and [self._yes] or [self.GetDefaultYesLabel()])[0]
def GetCustomNoLabel(self):
"""
If a custom label has been used for the ``No`` button, this method will return
it as a string. Otherwise, the default one (as defined in :meth:`~GenericMessageDialog.GetDefaultNoLabel`)
is returned.
.. versionadded:: 0.9.3
"""
return (self._no and [self._no] or [self.GetDefaultNoLabel()])[0]
def GetCustomCancelLabel(self):
"""
If a custom label has been used for the ``Cancel`` button, this method will return
it as a string. Otherwise, the default one (as defined in :meth:`~GenericMessageDialog.GetDefaultCancelLabel`)
is returned.
.. versionadded:: 0.9.3
"""
return (self._cancel and [self._cancel] or [self.GetDefaultCancelLabel()])[0]
def GetCustomHelpLabel(self):
"""
If a custom label has been used for the ``Help`` button, this method will return
it as a string. Otherwise, the default one (as defined in :meth:`~GenericMessageDialog.GetDefaultHelpLabel`)
is returned.
.. versionadded:: 0.9.3
"""
return (self._help and [self._help] or [self.GetDefaultHelpLabel()])[0]
# Customization of the message box buttons
def SetYesNoLabels(self, yes, no):
"""
Overrides the default labels of the ``Yes`` and ``No`` buttons.
:param `yes`: the new label for the ``Yes`` button;
:param `no`: the new label for the ``No`` button.
Typically, if the function was used successfully, the main dialog message may need to be changed, e.g.::
main_message = "Hello world! I am the main message."
dlg = GenericMessageDialog(None, main_message, "A Nice Message Box",
agwStyle=wx.ICON_INFORMATION | wx.OK)
if dlg.SetYesNoLabels(_("&Quit"), _("&Don't quit")):
dlg.SetMessage(_("What do you want to do?"))
else: # buttons have standard "Yes"/"No" values, so rephrase the question
dlg.SetMessage(_("Do you really want to quit?"))
.. versionadded:: 0.9.3
"""
self._yes, self._no = yes, no
return True
def SetYesNoCancelLabels(self, yes, no, cancel):
"""
Overrides the default labels of the ``Yes`` and ``No`` buttons.
:param `yes`: the new label for the ``Yes`` button;
:param `no`: the new label for the ``No`` button;
:param `cancel`: the new label for the ``Cancel`` button.
:see: The remarks in the :meth:`~GenericMessageDialog.SetYesNoLabels` documentation.
.. versionadded:: 0.9.3
"""
self._yes, self._no, self._cancel = yes, no, cancel
return True
def SetOKLabel(self, ok):
"""
Overrides the default label of the ``OK`` button.
:param `ok`: the new label for the ``OK`` button.
:see: The remarks in the :meth:`~GenericMessageDialog.SetYesNoLabels` documentation.
.. versionadded:: 0.9.3
"""
self._ok = ok
return True
def SetOKCancelLabels(self, ok, cancel):
"""
Overrides the default labels of the ``OK`` and ``Cancel`` buttons.
:param `ok`: the new label for the ``OK`` button;
:param `cancel`: the new label for the ``Cancel`` button.
:see: The remarks in the :meth:`~GenericMessageDialog.SetYesNoLabels` documentation.
.. versionadded:: 0.9.3
"""
self._ok, self._cancel = ok, cancel
return True
def SetHelpLabel(self, help):
"""
Overrides the default label of the ``Help`` button.
:param `help`: the new label for the ``Help`` button.
:see: The remarks in the :meth:`~GenericMessageDialog.SetYesNoLabels` documentation.
.. versionadded:: 0.9.3
"""
self._help = help
return True
# Test if any custom labels were set
def HasCustomLabels(self):
"""
Returns ``True`` if any of the buttons have a non-default label.
.. versionadded:: 0.9.3
"""
for label in [self._ok, self._no, self._yes, self._cancel, self._help]:
if label.strip():
return True
return False
def GetDefaultYesBitmap(self):
"""
Returns the default icon for the ``Yes`` button.
:note: this method may be overridden to provide different defaults for the
default button icons.
.. versionadded:: 0.9.3
"""
return _yes.GetBitmap()
def GetDefaultNoBitmap(self):
"""
Returns the default icon for the ``No`` button.
:note: this method may be overridden to provide different defaults for the
default button icons.
.. versionadded:: 0.9.3
"""
return _no.GetBitmap()
def GetDefaultOKBitmap(self):
"""
Returns the default icon for the ``OK`` button.
:note: this method may be overridden to provide different defaults for the
default button icons.
.. versionadded:: 0.9.3
"""
return _ok.GetBitmap()
def GetDefaultCancelBitmap(self):
"""
Returns the default icon for the ``Cancel`` button.
:note: this method may be overridden to provide different defaults for the
default button icons.
.. versionadded:: 0.9.3
"""
return _cancel.GetBitmap()
def GetDefaultHelpBitmap(self):
"""
Returns the default icon for the ``Help`` button.
:note: this method may be overridden to provide different defaults for the
default button icons.
.. versionadded:: 0.9.3
"""
return _help.GetBitmap()
def GetCustomOKBitmap(self):
"""
If a custom icon has been used for the ``OK`` button, this method will return
it as an instance of :class:`Bitmap`. Otherwise, the default one (as defined in
:meth:`~GenericMessageDialog.GetDefaultOKBitmap`) is returned.
.. versionadded:: 0.9.3
"""
return (self._okBitmap and [self._okBitmap] or [self.GetDefaultOKBitmap()])[0]
def GetCustomYesBitmap(self):
"""
If a custom icon has been used for the ``Yes`` button, this method will return
it as an instance of :class:`Bitmap`. Otherwise, the default one (as defined in
:meth:`~GenericMessageDialog.GetDefaultYesBitmap`) is returned.
.. versionadded:: 0.9.3
"""
return (self._yesBitmap and [self._yesBitmap] or [self.GetDefaultYesBitmap()])[0]
def GetCustomNoBitmap(self):
"""
If a custom icon has been used for the ``No`` button, this method will return
it as an instance of :class:`Bitmap`. Otherwise, the default one (as defined in
:meth:`~GenericMessageDialog.GetDefaultNoBitmap`) is returned.
.. versionadded:: 0.9.3
"""
return (self._noBitmap and [self._noBitmap] or [self.GetDefaultNoBitmap()])[0]
def GetCustomCancelBitmap(self):
"""
If a custom icon been used for the ``Cancel`` button, this method will return
it as an instance of :class:`Bitmap`. Otherwise, the default one (as defined in
:meth:`~GenericMessageDialog.GetDefaultCancelBitmap`) is returned.
.. versionadded:: 0.9.3
"""
return (self._cancelBitmap and [self._cancelBitmap] or [self.GetDefaultCancelBitmap()])[0]
def GetCustomHelpBitmap(self):
"""
If a custom icon has been used for the ``Help`` button, this method will return
it as an instance of :class:`Bitmap`. Otherwise, the default one (as defined in
:meth:`~GenericMessageDialog.GetDefaultHelpBitmap`) is returned.
.. versionadded:: 0.9.3
"""
return (self._helpBitmap and [self._helpBitmap] or [self.GetDefaultHelpBitmap()])[0]
# Customization of the message box buttons icons
def SetYesNoBitmaps(self, yesBitmap, noBitmap):
"""
Overrides the default icons of the ``Yes`` and ``No`` buttons.
:param `yesBitmap`: the new icon for the ``Yes`` button, an instance of :class:`Bitmap`;
:param `noBitmap`: the new icon for the ``No`` button, an instance of :class:`Bitmap`.
.. versionadded:: 0.9.3
"""
self._yesBitmap, self._noBitmap = yesBitmap, noBitmap
return True
def SetYesNoCancelBitmaps(self, yesBitmap, noBitmap, cancelBitmap):
"""
Overrides the default icons of the ``Yes`` and ``No`` buttons.
:param `yesBitmap`: the new icon for the ``Yes`` button, an instance of :class:`Bitmap`;
:param `noBitmap`: the new icon for the ``No`` button, an instance of :class:`Bitmap`;
:param `cancelBitmap`: the new icon for the ``Cancel`` button, an instance of :class:`Bitmap`.
.. versionadded:: 0.9.3
"""
self._yesBitmap, self._noBitmap, self._cancelBitmap = yesBitmap, noBitmap, cancelBitmap
return True
def SetOKBitmap(self, okBitmap):
"""
Overrides the default icon of the ``OK`` button.
:param `yesBitmap`: the new icon for the ``OK`` button, an instance of :class:`Bitmap`;
.. versionadded:: 0.9.3
"""
self._okBitmap = okBitmap
return True
def SetOKCancelBitmaps(self, okBitmap, cancelBitmap):
"""
Overrides the default icons of the ``OK`` and ``Cancel`` buttons.
:param `okBitmap`: the new icon for the ``OK`` button, an instance of :class:`Bitmap`;
:param `cancelBitmap`: the new icon for the ``Cancel`` button, an instance of :class:`Bitmap`.
.. versionadded:: 0.9.3
"""
self._okBitmap, self._cancelBitmap = okBitmap, cancelBitmap
return True
def SetHelpBitmap(self, helpBitmap):
"""
Overrides the default icon of the ``Help`` button.
:param `helpBitmap`: the new icon for the ``Help`` button, an instance of :class:`Bitmap`.
.. versionadded:: 0.9.3
"""
self._helpBitmap = helpBitmap
return True
# Test if any custom icons were set
def HasCustomBitmaps(self):
"""
Returns ``True`` if any of the buttons have a non-default icons.
.. versionadded:: 0.9.3
"""
for icon in [self._okBitmap, self._noBitmap, self._yesBitmap,
self._cancelBitmap, self._helpBitmap]:
if icon is not None:
return True
return False
def WrapMessage(self, message, wrap, font=None):
"""
Wraps the input message to multi lines so that the resulting new message
is at most `wrap` pixels wide.
:param `message`: the original input message;
:param `wrap`: wraps the string in `message` so that every line is at most
`wrap` pixels long;
:param `font`: if not ``None``, it should be an instance of :class:`Font` to be
used to measure and then wrap the input `message`.
:return: a new message wrapped at maximum `wrap` pixels wide.
:todo: Estabilish if wrapping all messages by default is a better idea than
provide a keyword parameter to :class:`GenericMessageDialog`. A default maximum
line width might be the wxMac one, at 360 pixels.
"""
dc = wx.ClientDC(self)
if font is None:
dc.SetFont(self.GetFont())
else:
dc.SetFont(font)
newMessage = wordwrap.wordwrap(message, wrap, dc, False)
return newMessage
def ShowModal(self):
"""
Shows the dialog, returning one of ``wx.ID_OK``, ``wx.ID_CANCEL``, ``wx.ID_YES``,
``wx.ID_NO`` or ``wx.ID_HELP``.
:note: Notice that this method returns the identifier of the button which was
clicked unlike the :class:`MessageBox` () function.
:note: Reimplemented from :class:`Dialog`.
"""
if not self._created:
self._created = True
self.CreateMessageDialog()
return wx.Dialog.ShowModal(self)
def GetCaption(self):
"""
Returns the main caption (the title) for :class:`GenericMessageDialog`.
.. versionadded:: 0.9.3
"""
return self.GetTitle()
def SetMessage(self, message):
"""
Sets the message shown by the dialog.
:param `message`: a string representing the main :class:`GenericMessageDialog` message.
.. versionadded:: 0.9.3
"""
self._message = message
def GetMessage(self):
"""
Returns a string representing the main :class:`GenericMessageDialog` message.
.. versionadded:: 0.9.3
"""
return self._message
def SetExtendedMessage(self, extendedMessage):
"""
Sets the extended message for the dialog: this message is usually an extension of the
short message specified in the constructor or set with :meth:`~GenericMessageDialog.SetMessage`.
If it is set, the main message appears highlighted and this message appears beneath
it in normal font.
:param `extendedMessage`: a string representing the extended :class:`GenericMessageDialog` message.
.. versionadded:: 0.9.3
"""
self._extendedMessage = extendedMessage
def GetExtendedMessage(self):
"""
Returns a string representing the extended :class:`GenericMessageDialog` message.
.. versionadded:: 0.9.3
"""
return self._extendedMessage
def GetMessageDialogStyle(self):
"""
Returns the AGW-specific window style for :class:`GenericMessageDialog`.
.. versionadded:: 0.9.3
"""
return self._agwStyle
# To combine the separate main and extended messages in a single string
def GetFullMessage(self):
"""
Returns a string representing the combination of the main :class:`GenericMessageDialog`
message and the extended message, separated by an empty line.
.. versionadded:: 0.9.3
"""
msg = self._message
if self._extendedMessage.strip():
msg += '\n\n' + self._extendedMessage
return msg
if __name__ == '__main__':
import wx
# Our normal wxApp-derived class, as usual
app = wx.App(0)
main_message = "Hello world! I am the main message."
dlg = GenericMessageDialog(None, main_message, "A Nice Message Box",
agwStyle=wx.ICON_INFORMATION|wx.OK)
dlg.ShowModal()
dlg.Destroy()
app.MainLoop()