]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/wxpTag.py
Patch from Will Sadkin:
[wxWidgets.git] / wxPython / wx / lib / wxpTag.py
1 #----------------------------------------------------------------------
2 # Name: wxPython.lib.wxpTag
3 # Purpose: A wxHtmlTagHandler that knows how to build and place
4 # wxPython widgets onto web pages.
5 #
6 # Author: Robin Dunn
7 #
8 # Created: 13-Sept-1999
9 # RCS-ID: $Id$
10 # Copyright: (c) 1999 by Total Control Software
11 # Licence: wxWindows license
12 #----------------------------------------------------------------------
13 # 12/13/2003 - Jeff Grimmett (grimmtooth@softhome.net)
14 #
15 # o Updated for V2.5 compatability
16 #
17
18 '''
19 wxPython.lib.wxpTag
20
21 This module contains a wxHtmlTagHandler that knows how to build
22 and place wxPython widgets onto wxHtmlWindow web pages.
23
24 You don\'t need to use anything in this module directly, just
25 importing it will create the tag handler and add it to any
26 wxHtmlWinParsers created from that time forth.
27
28 Tags of the following form are recognised:
29
30 <WXP class="classname" [module="modulename"] [width="num"] [height="num"]>
31 <PARAM name="parameterName" value="parameterValue>
32 ...
33 </WXP>
34
35 where modulename is the name of a module (possibly in package
36 notation) to import and classname is the name of a class in that
37 module to create an instance of. If the module tag-attribute is not
38 given or is an empty string, then wx is used. The width and height
39 attributes are expected to be integers and will be passed to the
40 __init__ method of the class as a wxSize object named size. However,
41 if the width attribute ends with the percent (%) symbol then the value
42 will be used as a percentage of the available width and the
43 wxHtmlWindow will manage the size.
44
45 The name-value pairs in all the nested PARAM tags are packaged up as
46 strings into a python dictionary and passed to the __init__ method of
47 the class as keyword arguments. This means that they are all
48 accessible from the __init__ method as regular parameters, or you use
49 the special Python **kw syntax in your __init__ method to get the
50 dictionary directly.
51
52 Some parameter values are special and if they are present then they will
53 be converted from strings to alternate datatypes. They are:
54
55 id If the value of id can be converted to an integer, it will
56 be. Otherwise it is assumed to be the name of an integer
57 variable in the module.
58
59 colours Any value of the form "#123ABC" will automatically be
60 converted to a wxColour object.
61
62 Py Types Any value begining with "(", "[" or "{" are expected to
63 be a Python tuple, list, or dictionary and eval()
64 will be used to convert them to that type. If the
65 eval() fails then the original string value will be
66 preserved.
67
68 wx Types Any value begining with "wx" is expected to be an attempt
69 to create a wxPython object, such as a wxSize, etc.
70 The eval() will be used to try and construct the
71 object and if it fails then the original string value
72 will be used instead.
73
74 An example:
75
76 <wxp module="wx" class="Button">
77 <param name="label" value="Click here">
78 <param name="id" value="ID_OK">
79 </wxp>
80
81 Both the begining and ending WXP tags are required.
82
83 In the future support will be added for another tag that can be
84 embedded between the two begining and ending WXP tags and will
85 facilitate calling methods of the widget to help initialize it.
86 Additionally, support may be added to fetch the module from a web
87 server as is done with java applets.
88
89 '''
90 #----------------------------------------------------------------------
91
92 import types
93
94 import wx
95 import wx.html
96
97
98 #----------------------------------------------------------------------
99
100 WXPTAG = 'WXP'
101 PARAMTAG = 'PARAM'
102
103 #----------------------------------------------------------------------
104
105 class wxpTagHandler(wx.html.HtmlWinTagHandler):
106 def __init__(self):
107 wx.html.HtmlWinTagHandler.__init__(self)
108 self.ctx = None
109
110 def GetSupportedTags(self):
111 return WXPTAG+','+PARAMTAG
112
113
114 def HandleTag(self, tag):
115 name = tag.GetName()
116 if name == WXPTAG:
117 return self.HandleWxpTag(tag)
118 elif name == PARAMTAG:
119 return self.HandleParamTag(tag)
120 else:
121 raise ValueError, 'unknown tag: ' + name
122
123
124 def HandleWxpTag(self, tag):
125 # create a new context object
126 self.ctx = _Context()
127
128 # find and import the module
129 modName = ''
130 if tag.HasParam('MODULE'):
131 modName = tag.GetParam('MODULE')
132 if modName:
133 self.ctx.classMod = _my_import(modName)
134 else:
135 self.ctx.classMod = wx
136
137 # find and verify the class
138 if not tag.HasParam('CLASS'):
139 raise AttributeError, "WXP tag requires a CLASS attribute"
140
141 className = tag.GetParam('CLASS')
142 self.ctx.classObj = getattr(self.ctx.classMod, className)
143 if type(self.ctx.classObj) not in [ types.ClassType, types.TypeType]:
144 raise TypeError, "WXP tag attribute CLASS must name a class"
145
146 # now look for width and height
147 width = -1
148 height = -1
149 if tag.HasParam('WIDTH'):
150 width = tag.GetParam('WIDTH')
151 if width[-1] == '%':
152 self.ctx.floatWidth = int(width[:-1], 0)
153 width = self.ctx.floatWidth
154 else:
155 width = int(width)
156 if tag.HasParam('HEIGHT'):
157 height = int(tag.GetParam('HEIGHT'))
158 self.ctx.kwargs['size'] = wx.Size(width, height)
159
160 # parse up to the closing tag, and gather any nested Param tags.
161 self.ParseInner(tag)
162
163 # create the object
164 parent = self.GetParser().GetWindow()
165 if parent:
166 obj = apply(self.ctx.classObj,
167 (parent,),
168 self.ctx.kwargs)
169 obj.Show(True)
170
171 # add it to the HtmlWindow
172 self.GetParser().GetContainer().InsertCell(
173 wx.html.HtmlWidgetCell(obj, self.ctx.floatWidth))
174 self.ctx = None
175
176 return True
177
178
179 def HandleParamTag(self, tag):
180 if not tag.HasParam('NAME'):
181 return False
182
183 name = tag.GetParam('NAME')
184 value = ""
185 if tag.HasParam('VALUE'):
186 value = tag.GetParam('VALUE')
187
188 # check for a param named 'id'
189 if name == 'id':
190 theID = -1
191 try:
192 theID = int(value)
193 except ValueError:
194 theID = getattr(self.ctx.classMod, value)
195 value = theID
196
197
198 # check for something that should be evaluated
199 elif value and value[0] in '[{(' or value[:2] == 'wx':
200 saveVal = value
201 try:
202 value = eval(value, self.ctx.classMod.__dict__)
203 except:
204 value = saveVal
205
206 # convert to wx.Colour
207 elif value and value[0] == '#':
208 try:
209 red = int('0x'+value[1:3], 16)
210 green = int('0x'+value[3:5], 16)
211 blue = int('0x'+value[5:], 16)
212 value = wx.Color(red, green, blue)
213 except:
214 pass
215
216 if self.ctx:
217 self.ctx.kwargs[str(name)] = value
218 return False
219
220
221 #----------------------------------------------------------------------
222 # just a place to hold some values
223 class _Context:
224 def __init__(self):
225 self.kwargs = {}
226 self.width = -1
227 self.height = -1
228 self.classMod = None
229 self.classObj = None
230 self.floatWidth = 0
231
232
233 #----------------------------------------------------------------------
234 # Function to assist with importing packages
235 def _my_import(name):
236 mod = __import__(name)
237 components = name.split('.')
238 for comp in components[1:]:
239 mod = getattr(mod, comp)
240 return mod
241
242
243 #----------------------------------------------------------------------
244 # Function to parse a param string (of the form 'item=value item2="value etc"'
245 # and creates a dictionary
246 def _param2dict(param):
247 i = 0; j = 0; s = len(param); d = {}
248 while 1:
249 while i<s and param[i] == " " : i = i+1
250 if i>=s: break
251 j = i
252 while j<s and param[j] != "=": j=j+1
253 if j+1>=s:
254 break
255 word = param[i:j]
256 i=j+1
257 if (param[i] == '"'):
258 j=i+1
259 while j<s and param[j] != '"' : j=j+1
260 if j == s: break
261 val = param[i+1:j]
262 elif (param[i] != " "):
263 j=i+1
264 while j<s and param[j] != " " : j=j+1
265 val = param[i:j]
266 else:
267 val = ""
268 i=j+1
269 d[word] = val
270 return d
271
272 #----------------------------------------------------------------------
273
274
275
276 wx.html.HtmlWinParser_AddTagHandler(wxpTagHandler)