mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-29 06:32:40 -06:00
1603 lines
64 KiB
Python
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()
|
|
|