From 03d1e1559c51d3e33828900bfb7ad8d5b9bc8a1c Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Sat, 18 Nov 2017 19:26:42 -0800 Subject: [PATCH] Add MappedType for wxMessageDialog::ButtonLabel, so MessageDialog methods can take either string or stock IDs. --- CHANGES.rst | 2 ++ etg/_core.py | 1 + etg/msgdlg.py | 27 +++++++--------- etgtools/extractors.py | 2 +- src/msgdlg_btnlabel.sip | 69 ++++++++++++++++++++++++++++++++++++++++ src/wxpy_api.sip | 2 +- unittests/test_msgdlg.py | 17 ++++++++++ 7 files changed, 102 insertions(+), 18 deletions(-) create mode 100644 src/msgdlg_btnlabel.sip diff --git a/CHANGES.rst b/CHANGES.rst index d9b6b91e..017e01f4 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -61,6 +61,8 @@ Changes in this release include the following: * Fix event type name in wx/lib/sheet.py (#613) +* The wx.MessageDialog methods which take ButtonLabel parameters are now able + to accept either strings or stock IDs. (#605, #276) diff --git a/etg/_core.py b/etg/_core.py index d06ee37a..c2f2d057 100644 --- a/etg/_core.py +++ b/etg/_core.py @@ -48,6 +48,7 @@ INCLUDES = [ # base and core stuff 'clntdatactnr', 'userdata', 'wxpybuffer', + 'msgdlg_btnlabel', 'stockgdi', 'longlong', diff --git a/etg/msgdlg.py b/etg/msgdlg.py index 3528d344..8e7f0e1a 100644 --- a/etg/msgdlg.py +++ b/etg/msgdlg.py @@ -11,6 +11,8 @@ import etgtools import etgtools.tweaker_tools as tools +from etgtools.extractors import ParamDef + import copy PACKAGE = "wx" @@ -40,23 +42,16 @@ def run(): module.addGlobalStr('wxMessageBoxCaptionStr', c) - # These argument types are actually ButtonLabel, but the class is a private - # helper. We will always be passing in strings, and ButtonLabel will implicitly - # convert. - # - # TODO: Add a mapped type for ButtonLabel that converts from a string or stock ID. See #276 - c.find('SetHelpLabel.help').type = 'const wxString&' - c.find('SetOKCancelLabels.ok').type = 'const wxString&' - c.find('SetOKCancelLabels.cancel').type = 'const wxString&' + # Several of the wxMessageDIalog methods take a + # wxMessageDialog::ButtonLabel parameter, which enables either a string or + # a Stock ID to be passed. To facilitate this same ability for Python the + # SIP types are changed to a custom type which is a MappedType which + # handles converting from the two types for us. See msgdlg_btnlabel.sip + c.find('ButtonLabel').ignore() + for item in c.allItems(): + if isinstance(item, ParamDef) and item.type == 'const ButtonLabel &': + item.type = 'const wxMessageDialogButtonLabel &' - c.find('SetOKLabel.ok').type = 'const wxString&' - - c.find('SetYesNoCancelLabels.yes').type = 'const wxString&' - c.find('SetYesNoCancelLabels.no').type = 'const wxString&' - c.find('SetYesNoCancelLabels.cancel').type = 'const wxString&' - - c.find('SetYesNoLabels.yes').type = 'const wxString&' - c.find('SetYesNoLabels.no').type = 'const wxString&' tools.fixTopLevelWindowClass(c) diff --git a/etgtools/extractors.py b/etgtools/extractors.py index 49fe036a..708edd84 100644 --- a/etgtools/extractors.py +++ b/etgtools/extractors.py @@ -155,7 +155,7 @@ class BaseDef(object): def findAll(self, name): """ - Search recursivly for items that have the given name. + Search recursively for items that have the given name. """ matches = list() for item in self.allItems(): diff --git a/src/msgdlg_btnlabel.sip b/src/msgdlg_btnlabel.sip new file mode 100644 index 00000000..dfae4366 --- /dev/null +++ b/src/msgdlg_btnlabel.sip @@ -0,0 +1,69 @@ +//-------------------------------------------------------------------------- +// Name: msgdlg_btnlabel.sip +// Purpose: A mapped type to allow auto-converting strings and ints +// to wxMessageDialog::ButtonLabel +// +// Author: Robin Dunn +// +// Created: 18-Nov-2017 +// Copyright: (c) 2017 by Total Control Software +// Licence: wxWindows license +//-------------------------------------------------------------------------- + +%ModuleHeaderCode + // Since the attributes of wxMessageDialogBase::ButtonLabel are declared + // const the implicitly generated copy ctor and assignment operator will + // cause compilation errors. Since the code generated for MappedTypes + // expects to be able to copy and assign objects (even though they are not + // really needed in this case) we need to use this little shim class so + // there is an explicit copy ctor and assignment operator. + + class wxMessageDialogButtonLabel : public wxMessageDialogBase::ButtonLabel + { + public: + wxMessageDialogButtonLabel() + : wxMessageDialogBase::ButtonLabel("") {} + + wxMessageDialogButtonLabel(int stockId) + : wxMessageDialogBase::ButtonLabel(stockId) {} + + wxMessageDialogButtonLabel(const wxString& label) + : wxMessageDialogBase::ButtonLabel(label) {} + + wxMessageDialogButtonLabel(const char *label) + : wxMessageDialogBase::ButtonLabel(label) {} + + wxMessageDialogButtonLabel(const wxMessageDialogButtonLabel& other) + : wxMessageDialogBase::ButtonLabel(other.GetAsString()) {} + + wxMessageDialogButtonLabel& operator=(const wxMessageDialogButtonLabel& other) + { return *this; } + }; +%End + +%MappedType wxMessageDialogButtonLabel +{ + %ConvertToTypeCode + // Code to test a PyObject for compatibility + if (!sipIsErr) { + return (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy) || wxPyInt_Check(sipPy)); + } + + // Code to create a new wxMessageDialogButtonLabel from the PyObject + wxMessageDialogButtonLabel* label; + if (PyBytes_Check(sipPy)) + label = new wxMessageDialogButtonLabel(PyBytes_AsString(sipPy)); + else if (PyUnicode_Check(sipPy)) + label = new wxMessageDialogButtonLabel(Py2wxString(sipPy)); + else + label = new wxMessageDialogButtonLabel(wxPyInt_AsLong(sipPy)); + + *sipCppPtr = label; + return sipGetState(sipTransferObj); + %End + + %ConvertFromTypeCode + Py_INCREF(Py_None); return Py_None; + %End + +}; diff --git a/src/wxpy_api.sip b/src/wxpy_api.sip index fdc14ff7..cd8089e7 100644 --- a/src/wxpy_api.sip +++ b/src/wxpy_api.sip @@ -30,7 +30,7 @@ static wxString i_Py2wxString(PyObject* source) { #if wxUSE_UNICODE_WCHAR == 0 -#error wxString converison can only handle WCHAR wxStrings currently +#error wxString conversion can only handle WCHAR wxStrings currently #endif PyErr_Clear(); PyObject* uni = source; diff --git a/unittests/test_msgdlg.py b/unittests/test_msgdlg.py index ee3808c5..b546e10c 100644 --- a/unittests/test_msgdlg.py +++ b/unittests/test_msgdlg.py @@ -52,6 +52,23 @@ class msgdlg_Tests(wtc.WidgetTestCase): wx.STAY_ON_TOP + def test_msgdlgLabels1(self): + dlg = wx.MessageDialog(None, 'Message', 'Caption') + dlg.SetHelpLabel('help') + dlg.SetOKCancelLabels('ok', 'cancel') + dlg.SetOKLabel('ok') + dlg.SetYesNoCancelLabels('yes', 'no', 'cancel') + dlg.SetYesNoLabels('yes', 'no') + + def test_msgdlgLabels2(self): + dlg = wx.MessageDialog(None, 'Message', 'Caption') + dlg.SetHelpLabel(wx.ID_HELP) + dlg.SetOKCancelLabels(wx.ID_OK, wx.ID_CANCEL) + dlg.SetOKLabel(wx.ID_OK) + dlg.SetYesNoCancelLabels(wx.ID_YES, wx.ID_NO, wx.ID_CANCEL) + dlg.SetYesNoLabels(wx.ID_YES, wx.ID_NO) + + def test_gmsgdlg1(self): dlg = wx.GenericMessageDialog(None, 'Message', 'Caption') wx.CallLater(250, dlg.EndModal, wx.ID_OK)