1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
"""
Code generator functions for CustomWidget objects
@copyright: 2002-2007 Alberto Griggio
@copyright: 2016 Carsten Grohmann
@copyright: 2017-2021 Dietmar Schwertberger
@license: MIT (see LICENSE.txt) - THIS PROGRAM COMES WITH NO WARRANTY
"""
import logging, common, config
import wcodegen
def format_ctor_arguments(arguments, parent, id, size):
"""Format constructor arguments; returns a list
arguments: Constructor arguments (list)
parent: Parent widget (string or unicode)
id: Widget ID e.g. wxID_ANY
size: Widget size 'width, height'"""
vSize = size.split(',')
for i in range(len(arguments)):
if arguments[i] == '$parent':
arguments[i] = parent
elif arguments[i] == '$id':
arguments[i] = id
elif arguments[i] == '$width':
arguments[i] = vSize[0]
elif arguments[i] == '$height':
arguments[i] = vSize[1]
return arguments
class PythonCustomWidgetGenerator(wcodegen.PythonWidgetCodeWriter):
def get_code(self, widget):
if self.codegen.preview and (not widget.show_preview or not config.preferences.allow_custom_widgets):
# if this CustomWidget refers to another class in the same wxg
# file, use that for the preview
return self.get_code_preview(widget)
self.codegen.have_extracode = True
id_name, id = self.codegen.generate_code_id(widget)
parent = widget.get_parent_window2(self.codegen)
if parent.IS_SIZER:
parent_access = '%s.GetStaticBox()' % self.format_widget_access(parent)
elif not parent.IS_CLASS:
parent_access = 'self.%s' % parent.name
else:
parent_access = 'self'
init = []
if id_name: init.append(id_name)
arguments = format_ctor_arguments( widget.arguments, parent_access, id, widget.size)
ctor = widget.custom_ctor.strip() or widget.instance_class
widget_access = self.format_widget_access(widget)
init.append( '%s = %s(%s)\n' % (widget_access, ctor, ", ".join(arguments)) )
init += self.codegen.generate_code_common_properties(widget)
return init, []
def get_code_preview(self, widget):
parent = widget.get_parent_window2(self.codegen)
if parent.IS_SIZER:
parent_access = '%s.GetStaticBox()' % self.format_widget_access(parent)
elif not parent.IS_CLASS:
parent_access = 'self.%s' % parent.name
else:
parent_access = 'self'
init = []
append = init.append
append('self.%s = wx.Window(%s, -1, style=wx.FULL_REPAINT_ON_RESIZE)\n' % (widget.name, parent_access))
if widget.check_prop('size'):
append( self.codegen.generate_code_size(widget) )
else:
# set a minimum size
append( self.codegen.generate_code_size(widget, "10, 10") )
on_paint_code = """\
def self_%s_on_paint(event):
widget = self.%s
dc = wx.PaintDC(widget)
dc.SetBrush(wx.WHITE_BRUSH)
dc.SetPen(wx.BLACK_PEN)
dc.SetBackground(wx.WHITE_BRUSH)
dc.Clear()
w, h = widget.GetClientSize()
dc.DrawLine(0, 0, w, h)
dc.DrawLine(w, 0, 0, h)
text = 'Custom Widget: %s'
tw, th = dc.GetTextExtent(text)
x = (w - tw)//2
y = (h - th)//2
dc.SetPen(wx.ThePenList.FindOrCreatePen(wx.BLACK, 0, wx.TRANSPARENT))
dc.DrawRectangle(x-1, y-1, tw+2, th+2)
dc.DrawText(text, x, y)
""" % ((widget.name,) * 3)
for line in on_paint_code.splitlines():
append(line + '\n')
append( 'self.%s.Bind(wx.EVT_PAINT, self_%s_on_paint)\n' % (widget.name, widget.name) )
append( 'self.%s.Bind(wx.EVT_ERASE_BACKGROUND, lambda event: None)\n' % widget.name )
return init, []
class CppCustomWidgetGenerator(wcodegen.CppWidgetCodeWriter):
def get_code(self, widget):
id_name, id = self.codegen.generate_code_id(widget)
if id_name:
ids = [id_name]
else:
ids = []
parent = widget.get_parent_window2(self.codegen)
if parent.IS_SIZER:
parent_access = '%s->GetStaticBox()' % self.format_widget_access(parent)
elif not parent.IS_CLASS:
parent_access = '%s' % parent.name
else:
parent_access = 'this'
arguments = format_ctor_arguments( widget.arguments, parent_access, id, widget.size )
ctor = widget.custom_ctor.strip() or ('new ' + widget.instance_class)
init = [ '%s = %s(%s);\n' % (widget.name, ctor, ", ".join(arguments)) ]
init += self.codegen.generate_code_common_properties(widget)
return init, ids, []
def xrc_code_generator(obj):
xrcgen = common.code_writers['XRC']
class CustomXrcObject(xrcgen.DefaultXrcObject):
# return value for xrc_code_generator
def write(self, outfile, ntabs, properties=None):
if properties is None: properties = {}
# first, fix the class:
self.subclass = self.klass = obj.instance_class
# delete the custom constructor property
properties['custom_ctor'] = None
# then, the attributes:
args_p = self.widget.properties['arguments']
if args_p.is_active() and args_p.value!=args_p.default_value:
for arg in args_p.value:
arg = arg[0].strip()
if arg in ("$parent", "$id"): continue
try:
name, val = [s.strip() for s in arg.split(':', 1)]
except Exception:
# show malformed arguments
logging.warning('Ignore malformed argument "%s" for "%s". Argument format should be: name:value',
arg, self.klass )
continue
properties[name] = val
properties["arguments"] = None
xrcgen.DefaultXrcObject.write(self, outfile, ntabs, properties)
return CustomXrcObject(obj)
def initialize():
klass = 'CustomWidget'
common.class_names[klass] = klass
common.register('python', klass, PythonCustomWidgetGenerator(klass) )
common.register('C++', klass, CppCustomWidgetGenerator(klass) )
common.register('XRC', klass, xrc_code_generator )
|