You can click buttons in the GUI!!11
[krufty_fps.git] / pygame_gui / DerGUI.py
blobda54d7b1ee79d9838f1d7215b760aa8fb5729b78
1 #!/usr/bin/python
3 import os, sys
4 from os import *
5 from os.path import *
7 from xml.dom.minidom import parse, parseString
9 from zipfile import *
11 import pygame
12 from pygame import *
14 import StringIO
16 import copy
18 FONT_NAME = 'serif'
19 FONT_SIZE = 30
20 FONT_COLOR = (255, 255, 255)
22 class GUISystem:
24 def __init__(self, gui_def, theme):
26 assert is_zipfile(theme)
27 assert exists(gui_def)
29 self.zipfile = ZipFile(theme)
31 self.definitions = self.parse_gui_def(gui_def)
33 pygame.init()
35 assert pygame.font.get_init()
37 self.the_font = pygame.font.SysFont(FONT_NAME, FONT_SIZE)
39 self.images = {}
41 assert self.getImages()
43 self.widgets = []
45 def parse_gui_def(self, gui_def):
46 results = {}
48 dom = parse(gui_def)
50 if dom.childNodes[0].nodeName == 'widgets':
52 widgets = {}
54 for node in dom.childNodes[0].childNodes:
56 image_list = []
58 if node.nodeName == 'images':
60 for sub_node in node.childNodes:
61 if sub_node.nodeName == 'image':
63 image = {'filename': '', name: ''}
65 for sub_sub_node in sub_node.childNodes:
67 if sub_sub_node.nodeName == 'filename':
68 image['filename'] = sub_sub_node.childNodes[0].nodeValue
69 if sub_sub_node.nodeName == 'name':
70 image['name'] = sub_sub_node.childNodes[0].nodeValue
72 if 'posix' in image:
73 del image['posix']
74 image_list.append(image)
76 results['image_list'] = image_list
78 if node.nodeName == 'widget':
80 widget = {}
82 widget['parameters'] = {}
83 widget['parts'] = {}
84 widget['behaviors'] = {}
86 for sub_node in node.childNodes:
87 if sub_node.nodeName == 'name' and len(sub_node.childNodes):
88 widget['name'] = sub_node.childNodes[0].nodeValue
90 if sub_node.nodeName == 'parameter':
92 parameter = {}
93 parameter['name'] = sub_node.attributes['name'].value
95 widget['parameters'][parameter['name']] = sub_node.attributes['default']
97 if sub_node.nodeName == 'part':
99 part_name = sub_node.getElementsByTagName('name')[0].childNodes[0].nodeValue
100 widget['parts'][part_name] = {}
102 for sub_sub_node in sub_node.childNodes:
104 if sub_sub_node.nodeName == 'type':
105 widget['parts'][part_name]['type'] = sub_sub_node.childNodes[0].nodeValue.encode()
107 if sub_sub_node.nodeName == 'source':
108 widget['parts'][part_name]['source'] = sub_sub_node.childNodes[0].nodeValue.encode()
110 if sub_sub_node.nodeName == 'position':
111 widget['parts'][part_name]['position'] = sub_sub_node.childNodes[0].nodeValue.encode()
113 if sub_sub_node.nodeName == 'size':
114 widget['parts'][part_name]['size'] = sub_sub_node.childNodes[0].nodeValue.encode()
116 if sub_node.nodeName == 'behavior':
118 event_type = sub_node.getElementsByTagName('on_event')[0].childNodes[0].nodeValue
119 the_do = sub_node.getElementsByTagName('do')[0].childNodes[0].nodeValue
121 widget['behaviors'][event_type] = the_do
123 widgets[widget['name']] = widget
125 results['widgets'] = widgets
127 return results
129 def getImages(self):
131 image_list = self.definitions['image_list']
132 name_list = []
134 name_list = self.zipfile.namelist()
136 for image in image_list:
138 if image['filename'] not in name_list:
139 return 0
141 else:
142 the_string_io = StringIO.StringIO()
143 print >>the_string_io, self.zipfile.read(image['filename'])
144 the_string_io.seek(0)
146 self.images[image['name']] = pygame.image.load(the_string_io).convert_alpha()
148 return 1
150 def event(self, the_event):
152 new_event = self.convertEvent(the_event)
154 if not new_event['type'].find('MOUSE') == -1:
156 for widget in self.widgets:
158 widget_rect = widget.getRect()
159 if widget_rect.collidepoint(new_event['data']['pos']):
160 if new_event['type'] != 'MOUSEMOTION':
161 self.focus = widget
162 self.focus.event(new_event)
163 else:
164 self.focus.event(new_event)
166 return
168 def convertEvent(self, e):
170 data = {}
172 if e.type == QUIT:
173 data['none'] = ''
175 if e.type == ACTIVEEVENT:
176 data['gain'] = e.gain
177 data['state'] = e.state
179 if e.type == KEYDOWN:
180 data['unicode'] = e.unicode
181 data['key'] = e.key
182 data['mod'] = e.mod
184 if e.type == KEYUP:
185 data['key'] = e.key
186 data['mod'] = e.mod
188 if e.type == MOUSEMOTION:
189 data['pos'] = e.pos
190 data['rel'] = e.rel
191 data['buttons'] = e.buttons
193 if e.type == MOUSEBUTTONUP:
194 data['pos'] = e.pos
195 data['button'] = e.button
197 if e.type == MOUSEBUTTONDOWN:
198 data['pos'] = e.pos
199 data['button'] = e.button
201 if e.type == JOYAXISMOTION:
202 data['joy'] = e.joy
203 data['axis'] = e.axis
204 data['value'] = e.value
206 if e.type == JOYBALLMOTION:
207 data['joy'] = e.joy
208 data['ball'] = e.ball
209 data['rel'] = e.rel
211 if e.type == JOYHATMOTION:
212 data['joy'] = e.joy
213 data['hat'] = e.hat
214 data['value'] = e.value
216 if e.type == JOYBUTTONUP:
217 data['joy'] = e.joy
218 data['button'] = e.button
220 if e.type == JOYBUTTONDOWN:
221 data['joy'] = e.joy
222 data['button'] = e.button
224 if e.type == VIDEORESIZE:
225 data['size'] = e.size
226 data['w'] = e.w
227 data['h'] = e.h
229 if e.type == VIDEOEXPOSE:
230 data['none'] = ''
232 if e.type == USEREVENT:
233 data['code'] = e.code
235 type = ''
237 if e.type == QUIT: type = "QUIT"
238 if e.type == ACTIVEEVENT: type = "ACTIVEEVENT"
239 if e.type == KEYDOWN: type = "KEYDOWN"
240 if e.type == KEYUP: type = "KEYUP"
241 if e.type == MOUSEMOTION : type = "MOUSEMOTION"
242 if e.type == MOUSEBUTTONUP: type = "MOUSEBUTTONUP"
243 if e.type == MOUSEBUTTONDOWN: type = "MOUSEBUTTONDOWN"
244 if e.type == JOYAXISMOTION: type = "JOYAXISMOTION"
245 if e.type == JOYBALLMOTION: type = "JOYBALLMOTION"
246 if e.type == JOYHATMOTION: type = "JOYHATMOTION"
247 if e.type == JOYBUTTONUP: type = "JOYBUTTONUP"
248 if e.type == JOYBUTTONDOWN: type = "JOYBUTTONDOWN"
249 if e.type == VIDEORESIZE: type = "VIDEORESIZE"
250 if e.type == VIDEOEXPOSE: type = "VIDEOEXPOSE"
251 if e.type == USEREVENT: type = "USEREVENT"
253 new_event = {}
255 new_event['type'] = type
256 new_event['data'] = data
258 return new_event
260 def draw(self, dest_surface):
262 for widget in self.widgets:
264 if widget.params['parameters']['visible']:
265 widget.draw(dest_surface)
267 return
269 def makeWidget(self, widget_name, params):
271 if self.definitions['widgets'].has_key(widget_name):
273 for param in self.definitions['widgets'][widget_name]['parameters']:
274 if not params.has_key(param):
275 if self.definitions['widgets'][widget_name][parameters][param] == 'kill':
276 print "GUISystem.makeWidget() Not all required parameters were passed."
277 assert 0
278 else:
279 params[param] = self.definitions['widgets'][widget_name][parameters][param]
281 new_params = copy.deepcopy(self.definitions['widgets'][widget_name])
282 new_params['parameters'] = params
284 the_widget = Widget(self, widget_name, new_params)
286 self.widgets.append(the_widget)
288 if len(self.widgets) == 1:
289 self.focus = the_widget
291 return the_widget
293 class Widget:
295 def __init__(self, the_gui_system, widget_name, params):
297 self.name = widget_name
298 self.params = params
299 self.the_gui_system = the_gui_system
301 assert self.params['parameters'].has_key('x')
302 assert self.params['parameters'].has_key('y')
304 if not self.params['parameters'].has_key('visible'):
305 self.params['parameters']['visible'] = 1
307 self.callbacks = {}
309 return
311 def move(self, (new_x, new_y)):
313 self.params['parameters']['x'], self.params['parameters']['y'] = new_x, new_y
315 return
317 def hide(self):
319 self.params['parameters']['visible'] = 0
321 return
323 def show(self):
325 self.params['parameters']['visible'] = 1
327 return
329 def connect(self, event, function, params={}):
331 self.callbacks[event] = {'function': function, 'params': params}
333 return
335 def getRect(self):
337 coords = (self.params['parameters']['x'], self.params['parameters']['y'])
338 dimensions = (self.params['parameters']['width'], self.params['parameters']['height'])
340 return pygame.Rect(coords, dimensions)
342 def event(self, the_event):
344 if self.params['behaviors'].has_key(the_event['type']):
346 the_value = self.params['behaviors'][the_event['type']]
348 exec(the_value)
350 return
352 def setPart(self, old_part, new_part):
354 self.params['parts'][old_part]['source'] = new_part
355 return
357 def raiseEvent(self, the_event, parameters={}):
359 if not self.callbacks.has_key(the_event):
360 return
362 the_function = self.callbacks[the_event]['function']
364 try:
365 the_function(self.callbacks[the_event]['params'], parameters)
366 except:
367 print "Widget.raiseEvent(): Error in callback."
369 return
371 def draw(self, dest_surface):
373 code = ''
375 for image in self.the_gui_system.images:
377 code = ''.join([code, '\n', image, ' = self.the_gui_system.images["', image, '"]'])
379 try:
380 exec(code)
381 except:
382 assert 0
384 for part in self.params['parts']:
386 if self.params['parts'][part]['type'] == 'text':
388 # here be dragons
389 try:
390 exec(''.join([part, ' = self.the_gui_system.the_font.render(self.params["parameters"][self.params["parts"][part]["source"]], FONT_SIZE, FONT_COLOR)\nthe_source =', part]))
391 except:
392 assert 0
394 width = self.params['parameters']['width']
395 height = self.params['parameters']['height']
397 position = eval(self.params['parts'][part]['position'])
398 size = eval(self.params['parts'][part]['size'])
400 position = [position[0], position[1]]
402 position[0] += self.params['parameters']['x']
403 position[1] += self.params['parameters']['y']
405 if self.params['parts'][part]['type'] == 'image':
407 if size[0] > 0 and size[1] > 0:
408 the_source = pygame.transform.scale(self.the_gui_system.images[self.params['parts'][part]['source']], size)
409 dest_surface.blit(the_source, position)
411 if self.params['parts'][part]['type'] == 'text':
413 dest_surface.blit(the_source, position, pygame.Rect((0, 0), size))
415 if self.params['parts'][part]['type'] == 'widget':
417 pass # implement nested widgets
419 return
421 # end