mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2025-12-15 17:20:07 +01:00
Merge pull request #1201 from RobinD42/fix-issue1198
Fix access to members of transient wx.VisualAttributes
(cherry picked from commit d6324a0578)
This commit is contained in:
@@ -61,7 +61,10 @@ Changes in this release include the following:
|
||||
|
||||
* Fix the use of the output parameter in HtmlWindow.OnOpeningURL the same way
|
||||
it was fixed in HtmlWindowInterface.OnHTMLOpeningURL. (#1068)
|
||||
|
||||
|
||||
* Fixed a crashing bug when using a member of a transient wx.VisualAttributes
|
||||
object. Also set the attributes to be read-only to simplify the fix. (#1198).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ def run():
|
||||
|
||||
|
||||
c = module.find('wxProgressDialog')
|
||||
tools.fixWindowClass(c)
|
||||
|
||||
# Copy methods from the generic to the native class. This is needed
|
||||
# because none of the methods are declared in the interface files, and
|
||||
@@ -59,6 +58,7 @@ def run():
|
||||
not item.isDtor):
|
||||
c.addItem(copy.deepcopy(item))
|
||||
|
||||
tools.fixWindowClass(c)
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
|
||||
@@ -35,6 +35,29 @@ def run():
|
||||
# Tweak the parsed meta objects in the module object as needed for
|
||||
# customizing the generated code and docstrings.
|
||||
|
||||
c = module.find('wxVisualAttributes')
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
# Mark the stucture memebers as read-only, and make copies of the values
|
||||
# when fetching them. This is to protect against cases where the
|
||||
# VisualAttributes object is transient and may be GC'd while we still are
|
||||
# using a reference to a C++ member value.
|
||||
c.find('colBg').noSetter = True
|
||||
c.find('colBg').getCode = """\
|
||||
wxColour* clr = new wxColour(sipCpp->colBg);
|
||||
sipPy = wxPyConstructObject((void*)clr, "wxColour", true);
|
||||
"""
|
||||
c.find('colFg').noSetter = True
|
||||
c.find('colFg').getCode = """\
|
||||
wxColour* clr = new wxColour(sipCpp->colFg);
|
||||
sipPy = wxPyConstructObject((void*)clr, "wxColour", true);
|
||||
"""
|
||||
c.find('font').noSetter = True
|
||||
c.find('font').getCode = """\
|
||||
wxFont* font = new wxFont(sipCpp->font);
|
||||
sipPy = wxPyConstructObject((void*)font, "wxFont", true);
|
||||
"""
|
||||
|
||||
|
||||
c = module.find('wxWindow')
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
module.addGlobalStr('wxPanelNameStr', c)
|
||||
|
||||
@@ -206,6 +206,7 @@ class VariableDef(BaseDef):
|
||||
self.definition = ''
|
||||
self.argsString = ''
|
||||
self.pyInt = False
|
||||
self.noSetter = False
|
||||
self.__dict__.update(**kw)
|
||||
if element is not None:
|
||||
self.extract(element)
|
||||
@@ -247,6 +248,8 @@ class MemberVarDef(VariableDef):
|
||||
super(MemberVarDef, self).__init__()
|
||||
self.isStatic = False
|
||||
self.protection = 'public'
|
||||
self.getCode = ''
|
||||
self.setCode = ''
|
||||
self.__dict__.update(kw)
|
||||
if element is not None:
|
||||
self.extract(element)
|
||||
|
||||
@@ -569,7 +569,19 @@ from .%s import *
|
||||
if memberVar.ignored:
|
||||
return
|
||||
stream.write('%s%s %s' % (indent, memberVar.type, memberVar.name))
|
||||
stream.write('%s;\n\n' % self.annotate(memberVar))
|
||||
stream.write(self.annotate(memberVar))
|
||||
if memberVar.getCode or memberVar.setCode:
|
||||
stream.write('\n%s{\n' % (indent,))
|
||||
if memberVar.getCode:
|
||||
stream.write('%s%%GetCode\n' % (indent))
|
||||
stream.write(nci(memberVar.getCode, len(indent)+4))
|
||||
stream.write('%s%%End\n' % (indent))
|
||||
if memberVar.setCode:
|
||||
stream.write('%s%%SetCode\n' % (indent))
|
||||
stream.write(nci(memberVar.setCode, len(indent)+4))
|
||||
stream.write('%s%%End\n' % (indent))
|
||||
stream.write('%s}' % (indent,))
|
||||
stream.write(';\n\n')
|
||||
|
||||
|
||||
def generateProperty(self, prop, stream, indent):
|
||||
@@ -979,6 +991,8 @@ from .%s import *
|
||||
if isinstance(item, extractors.VariableDef):
|
||||
if item.pyInt:
|
||||
annotations.append('PyInt')
|
||||
if item.noSetter:
|
||||
annotations.append('NoSetter')
|
||||
|
||||
if isinstance(item, extractors.TypedefDef):
|
||||
if item.noTypeName:
|
||||
|
||||
@@ -261,17 +261,27 @@ def fixWindowClass(klass, hideVirtuals=True, ignoreProtected=True):
|
||||
removeVirtuals(klass)
|
||||
addWindowVirtuals(klass)
|
||||
|
||||
if not klass.findItem('GetClassDefaultAttributes'):
|
||||
klass.addItem(extractors.WigCode("""\
|
||||
static wxVisualAttributes
|
||||
GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
|
||||
"""))
|
||||
|
||||
if not ignoreProtected:
|
||||
for item in klass.allItems():
|
||||
if isinstance(item, extractors.MethodDef) and item.protection == 'protected':
|
||||
item.ignore(False)
|
||||
|
||||
fixDefaultAttributesMethods(klass)
|
||||
|
||||
|
||||
def fixDefaultAttributesMethods(klass):
|
||||
if not klass.findItem('GetClassDefaultAttributes'):
|
||||
m = extractors.MethodDef(
|
||||
type='wxVisualAttributes', name='GetClassDefaultAttributes',
|
||||
isStatic=True, protection='public',
|
||||
items=[extractors.ParamDef(
|
||||
type='wxWindowVariant', name='variant', default='wxWINDOW_VARIANT_NORMAL')]
|
||||
)
|
||||
klass.addItem(m)
|
||||
|
||||
if klass.findItem('GetDefaultAttributes'):
|
||||
klass.find('GetDefaultAttributes').mustHaveApp()
|
||||
klass.find('GetClassDefaultAttributes').mustHaveApp()
|
||||
|
||||
|
||||
def fixTopLevelWindowClass(klass, hideVirtuals=True, ignoreProtected=True):
|
||||
@@ -308,6 +318,8 @@ def fixTopLevelWindowClass(klass, hideVirtuals=True, ignoreProtected=True):
|
||||
if isinstance(item, extractors.MethodDef) and item.protection == 'protected':
|
||||
item.ignore(False)
|
||||
|
||||
fixDefaultAttributesMethods(klass)
|
||||
|
||||
|
||||
|
||||
def fixSizerClass(klass):
|
||||
|
||||
@@ -137,6 +137,31 @@ class WindowTests(wtc.WidgetTestCase):
|
||||
wx.DLG_PNT
|
||||
|
||||
|
||||
def test_vizattrs1(self):
|
||||
w = wx.Window(self.frame, -1, (10,10), (50,50))
|
||||
a = w.GetClassDefaultAttributes()
|
||||
assert isinstance(a.colBg, wx.Colour)
|
||||
assert isinstance(a.colFg, wx.Colour)
|
||||
assert isinstance(a.font, wx.Font)
|
||||
|
||||
|
||||
def test_vizattrs2(self):
|
||||
w = wx.Window(self.frame, -1, (10,10), (50,50))
|
||||
assert isinstance(w.GetClassDefaultAttributes().colBg, wx.Colour)
|
||||
assert isinstance(w.GetClassDefaultAttributes().colFg, wx.Colour)
|
||||
assert isinstance(w.GetClassDefaultAttributes().font, wx.Font)
|
||||
|
||||
|
||||
def test_vizattrs3(self):
|
||||
w = wx.Window(self.frame, -1, (10,10), (50,50))
|
||||
a = w.GetClassDefaultAttributes()
|
||||
with self.assertRaises(AttributeError):
|
||||
a.colBg = wx.Colour('blue')
|
||||
with self.assertRaises(AttributeError):
|
||||
a.colFg = wx.Colour('blue')
|
||||
with self.assertRaises(AttributeError):
|
||||
a.font = wx.NORMAL_FONT
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user