]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/tools/pywxrc.py
Added gtk dirdlg
[wxWidgets.git] / wxPython / wx / tools / pywxrc.py
1 #----------------------------------------------------------------------
2 # Name: wx.tools.pywxrc
3 # Purpose: XML resource compiler
4 #
5 # Author: Robin Dunn
6 # Based on wxrc.cpp by Vaclav Slavik, Eduardo Marques
7 # Ported to Python in order to not require yet another
8 # binary in wxPython distributions
9 #
10 # Massive rework by Eli Golovinsky
11 #
12 # RCS-ID: $Id$
13 # Copyright: (c) 2004 by Total Control Software, 2000 Vaclav Slavik
14 # Licence: wxWindows license
15 #----------------------------------------------------------------------
16
17 """
18 pywxrc -- Python XML resource compiler
19
20 Usage: python pywxrc.py -h
21 python pywxrc.py <resource.xrc> [-e] [-o filename]
22
23 -h, --help show help message
24 -e, --embed embed resources in output file
25 -o, --output output filename, or - for stdout
26 """
27
28 import sys, os, getopt, glob, re
29 import xml.dom.minidom as minidom
30 import wx
31 import wx.xrc
32
33 #----------------------------------------------------------------------
34
35 class PythonTemplates:
36 FILE_HEADER = """\
37 # This file was automatically generated by pywxrc, do not edit by hand.
38
39 import wx
40 import wx.xrc as xrc
41
42 __res = None
43
44 def get_resources():
45 \"\"\" This function provides access to the XML resources in this module.\"\"\"
46 global __res
47 if __res == None:
48 __init_resources()
49 return __res
50
51 """
52
53 CLASS_HEADER = """\
54 class %(windowName)sBase(wx.%(windowClass)s):
55 def PreCreate(self):
56 \"\"\" This function is called during the class's initialization.
57
58 Override it for custom setup before the window is created usually to
59 set additional window styles using SetWindowStyle() and SetExtraStyle().\"\"\"
60 pass
61
62 def __init__(self, parent):
63 # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation)
64 pre = wx.Pre%(windowClass)s()
65 get_resources().LoadOn%(windowClass)s(pre, parent, "%(windowName)s")
66 self.PreCreate()
67 self.PostCreate(pre)
68
69 # Define variables for the controls
70 """
71
72 CREATE_WIDGET_VAR = """\
73 self.%(widgetName)s = xrc.XRCCTRL(self, \"%(widgetName)s\")
74 """
75
76 INIT_RESOURE_HEADER = """\
77 # -------------------------------------------------------------
78 # ------------------------ Resource data ----------------------
79 # -------------------------------------------------------------
80
81 def __init_resources():
82 """
83
84 LOAD_RES_FILE = """\
85 global __res
86 __res = xrc.XmlResource('%(resourceFilename)s')
87 """
88
89 FILE_AS_STRING = """\
90 %(filename)s = '''\\
91 %(fileData)s'''
92
93
94 """
95
96 PREPARE_MEMFS = """\
97 # Load all the strings as memory files
98
99 wx.FileSystem.AddHandler(wx.MemoryFSHandler())
100 """
101
102 ADD_FILE_TO_MEMFS = """\
103 wx.MemoryFSHandler.AddFile('XRC/%(memoryPath)s/%(filename)s', %(filename)s)
104 """
105
106 LOAD_RES_MEMFS = """\
107 global __res
108 __res = xrc.EmptyXmlResource()
109 __res.Load('memory:XRC/%(memoryPath)s/%(resourceFilename)s')
110 """
111
112 #----------------------------------------------------------------------
113
114 class XmlResourceCompiler:
115
116 templates = PythonTemplates()
117
118 """This class generates Python code from XML resource files (XRC)."""
119
120 def MakePythonModule(self, resourceFilename, outputFilename, embedResources=False):
121 if outputFilename == "-":
122 outputFile = sys.stdout
123 else:
124 try:
125 outputFile = open(outputFilename, "wt")
126 except IOError:
127 raise IOError("Can't write output to '%s'" % outputFilename)
128
129 resourceDocument = minidom.parse(resourceFilename)
130 print >>outputFile, self.templates.FILE_HEADER
131 print >>outputFile, self.GenerateClasses(resourceDocument)
132
133 if embedResources:
134 print >>outputFile, self.GenerateInitResourcesEmbedded(resourceFilename, resourceDocument)
135 else:
136 print >>outputFile, self.GenerateInitResourcesFile(resourceFilename, resourceDocument)
137
138 #-------------------------------------------------------------------
139
140 def GenerateClasses(self, resourceDocument):
141 outputList = []
142
143 resource = resourceDocument.firstChild
144 topWindows = [e for e in resource.childNodes
145 if e.nodeType == e.ELEMENT_NODE and e.tagName == "object"]
146
147 # Generate a class for each top-window object (Frame, Panel, Dialog, etc.)
148 for topWindow in topWindows:
149 windowClass = topWindow.getAttribute("class")
150 windowClass = re.sub("^wx", "", windowClass)
151 windowName = topWindow.getAttribute("name")
152 outputList.append(self.templates.CLASS_HEADER % locals())
153
154 # Generate a variable for each control, and standard event handlers
155 # for standard controls.
156 for widget in topWindow.getElementsByTagName("object"):
157 widgetClass = widget.getAttribute("class")
158 widgetClass = re.sub("^wx", "", widgetClass)
159 widgetName = widget.getAttribute("name")
160 if (widgetName != "" and widgetClass != "" and
161 widgetClass not in
162 ['tool', 'unknown', 'notebookpage',
163 'separator', 'sizeritem', 'MenuItem']):
164 outputList.append(self.templates.CREATE_WIDGET_VAR % locals())
165 outputList.append('\n\n')
166
167 return "".join(outputList)
168
169 #-------------------------------------------------------------------
170
171 def GenerateInitResourcesEmbedded(self, resourceFilename, resourceDocument):
172 outputList = []
173
174 outputList.append(self.templates.INIT_RESOURE_HEADER)
175
176 files = []
177
178 resourcePath = os.path.split(resourceFilename)[0]
179 memoryPath = self.GetMemoryFilename(os.path.splitext(os.path.split(resourceFilename)[1])[0])
180 resourceFilename = self.GetMemoryFilename(os.path.split(resourceFilename)[1])
181
182 self.ReplaceFilenamesInXRC(resourceDocument.firstChild, files, resourcePath)
183
184 filename = resourceFilename
185 fileData = resourceDocument.toxml()
186 outputList.append(self.templates.FILE_AS_STRING % locals())
187
188 for f in files:
189 filename = self.GetMemoryFilename(f)
190 fileData = self.FileToString(os.path.join(resourcePath, f))
191 outputList.append(self.templates.FILE_AS_STRING % locals())
192
193 outputList.append(self.templates.PREPARE_MEMFS % locals())
194
195 for f in [resourceFilename] + files:
196 filename = self.GetMemoryFilename(f)
197 outputList.append(self.templates.ADD_FILE_TO_MEMFS % locals())
198
199 outputList.append(self.templates.LOAD_RES_MEMFS % locals())
200
201 return "".join(outputList)
202
203 #-------------------------------------------------------------------
204
205 def GenerateInitResourcesFile(self, resourceFilename, resourceDocument):
206 outputList = []
207 outputList.append(self.templates.INIT_RESOURE_HEADER)
208 outputList.append(self.templates.LOAD_RES_FILE % locals())
209 return "".join(outputList)
210
211 #-------------------------------------------------------------------
212
213 def GetMemoryFilename(self, filename):
214 # Remove special chars from the filename
215 return re.sub(r"[^A-Za-z0-9_]", "_", filename)
216
217 #-------------------------------------------------------------------
218
219 def FileToString(self, filename):
220 outputList = []
221
222 buffer = open(filename, "rb").read()
223 fileLen = len(buffer)
224
225 linelng = 0
226 for i in xrange(fileLen):
227 s = buffer[i]
228 c = ord(s)
229 if s == '\n':
230 tmp = s
231 linelng = 0
232 elif c < 32 or c > 127 or s == "'":
233 tmp = "\\x%02x" % c
234 elif s == "\\":
235 tmp = "\\\\"
236 else:
237 tmp = s
238
239 if linelng > 70:
240 linelng = 0
241 outputList.append("\\\n")
242
243 outputList.append(tmp)
244 linelng += len(tmp)
245
246 return "".join(outputList)
247
248 #-------------------------------------------------------------------
249
250 def NodeContainsFilename(self, node):
251 """ Does 'node' contain filename information at all? """
252
253 # Any bitmaps:
254 if node.nodeName == "bitmap":
255 return True
256
257 if node.nodeName == "icon":
258 return True
259
260 # URLs in wxHtmlWindow:
261 if node.nodeName == "url":
262 return True
263
264 # wxBitmapButton:
265 parent = node.parentNode
266 if parent.__class__ != minidom.Document and \
267 parent.getAttribute("class") == "wxBitmapButton" and \
268 (node.nodeName == "focus" or node.nodeName == "disabled" or
269 node.nodeName == "selected"):
270 return True
271
272 # wxBitmap or wxIcon toplevel resources:
273 if node.nodeName == "object":
274 klass = node.getAttribute("class")
275 if klass == "wxBitmap" or klass == "wxIcon":
276 return True
277
278 return False
279
280 #-------------------------------------------------------------------
281
282 def ReplaceFilenamesInXRC(self, node, files, resourcePath):
283 """ Finds all files mentioned in resource file, e.g. <bitmap>filename</bitmap>
284 and replaces them with the memory filenames.
285
286 Fills a list of the filenames found."""
287
288 # Is 'node' XML node element?
289 if node is None: return
290 if node.nodeType != minidom.Document.ELEMENT_NODE: return
291
292 containsFilename = self.NodeContainsFilename(node);
293
294 for n in node.childNodes:
295
296 if (containsFilename and
297 (n.nodeType == minidom.Document.TEXT_NODE or
298 n.nodeType == minidom.Document.CDATA_SECTION_NODE)):
299
300 filename = n.nodeValue
301 memoryFilename = self.GetMemoryFilename(filename)
302 n.nodeValue = memoryFilename
303
304 if filename not in files:
305 files.append(filename)
306
307 # Recurse into children
308 if n.nodeType == minidom.Document.ELEMENT_NODE:
309 self.ReplaceFilenamesInXRC(n, files, resourcePath);
310
311 #---------------------------------------------------------------------------
312
313 def main(args):
314 resourceFilename = ""
315 outputFilename = ""
316 embedResources = False
317
318 try:
319 opts, args = getopt.gnu_getopt(args, "heo:", "help embed output=".split())
320 except getopt.GetoptError:
321 print __doc__
322 sys.exit(1)
323
324 # If there is no input file argument, show help and exit
325 if args:
326 resourceFilename = args[0]
327 else:
328 print __doc__
329 sys.exit(1)
330
331 # Parse options and arguments
332 for opt, val in opts:
333 if opt in ["-h", "--help"]:
334 print __doc__
335 sys.exit(1)
336
337 if opt in ["-o", "--output"]:
338 outputFilename = val
339
340 if opt in ["-e", "--embed"]:
341 embedResources = True
342
343 if outputFilename is None or outputFilename == "":
344 outputFilename = os.path.splitext(resourceFilename)[0] + "_xrc.py"
345
346 comp = XmlResourceCompiler()
347
348 try:
349 comp.MakePythonModule(resourceFilename, outputFilename, embedResources)
350 except IOError, e:
351 print >>sys.stderr, "%s." % str(e)
352 else:
353 if outputFilename != "-":
354 print >>sys.stderr, "Resources written to %s." % outputFilename
355
356 if __name__ == "__main__":
357 main(sys.argv[1:])
358