Merge lp:~codeforger/simplegc/simplegc into lp:simplegc
- simplegc
- Merge into trunk
Proposed by
Sam Bull
Status: | Merged |
---|---|
Merged at revision: | 274 |
Proposed branch: | lp:~codeforger/simplegc/simplegc |
Merge into: | lp:simplegc |
Diff against target: |
996 lines (+713/-62) 9 files modified
example/test_lists.py (+68/-0) sgc/__init__.py (+6/-0) sgc/widgets/base_widget.py (+3/-0) sgc/widgets/button.py (+13/-16) sgc/widgets/composite/dialogs.py (+98/-0) sgc/widgets/lists.py (+383/-0) sgc/widgets/menu.py (+19/-12) sgc/widgets/opengl.py (+121/-32) sgc/widgets/radio_button.py (+2/-2) |
To merge this branch: | bzr merge lp:~codeforger/simplegc/simplegc |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sam Bull | Needs Fixing | ||
Review via email: mp+115960@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Sam Bull (dreamsorcerer) wrote : | # |
My mistake, conflicts are with newer trunk. Resolve the conflicts, and also revert helloworld.py (this is for one of the tutorials, put you example code into test.py), _locals.py, base_widget.py, menu.py, radio_button.py.
Revision history for this message
Michael Rochester (codeforger) wrote : | # |
This merge also contains the new button style I invented, would you like me to revert that too?
lp:~codeforger/simplegc/simplegc
updated
- 273. By Michael Rochester
-
merge
- 274. By Michael Rochester
-
merge
- 275. By Michael Rochester
-
moved test code to test.py
- 276. By Michael Rochester
-
reverted /example/
helloworld. py - 277. By Michael Rochester
-
fixed my idiocy with test.py
- 278. By Michael Rochester
-
removed matrix.py as requested
Revision history for this message
Sam Bull (dreamsorcerer) wrote : | # |
> This merge also contains the new button style I invented, would you like me to
> revert that too?
Yes please.
lp:~codeforger/simplegc/simplegc
updated
- 279. By Michael Rochester
-
reverted button.py to the old buttons style
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'example/test_lists.py' |
2 | --- example/test_lists.py 1970-01-01 00:00:00 +0000 |
3 | +++ example/test_lists.py 2012-07-21 12:53:18 +0000 |
4 | @@ -0,0 +1,68 @@ |
5 | +import sgc |
6 | +from sgc.locals import * |
7 | + |
8 | +import pygame |
9 | +from pygame.locals import * |
10 | + |
11 | +pygame.display.init() |
12 | +pygame.font.init() |
13 | + |
14 | +screen = sgc.surface.Screen((640,480)) |
15 | + |
16 | +clock = pygame.time.Clock() |
17 | + |
18 | +lst = sgc._List(width=(100),pos=(10,10),multi_selection=True,content=("hello","world","nice","to","meet","you")) |
19 | +lst.add(0) |
20 | + |
21 | +mullst = sgc._MultiList(pos=(10,150),columnwidth=(150,150),content=(["hello","world"],["nice","to"],["meet","you"])) |
22 | +mullst.add(0) |
23 | + |
24 | +listb = sgc.ListBox((100,100),pos=(150,10),multi_selection=True,content=("hello","world","nice","to","meet","you")) |
25 | +listb.add(0) |
26 | + |
27 | +list2 = sgc.ListBox((100,100),pos=(300,10),header="head",content=("hello","world","nice","to","meet","you")) |
28 | +list2.add(0) |
29 | + |
30 | +data = (["Hello","12Mb","30/06/2012"], |
31 | + ["World","15Mb","30/06/2012"], |
32 | + ["Nice","123Kb","19/06/2012"], |
33 | + ["To","1.2Gb","29/06/2012"], |
34 | + ["Meet","12Mb","25/06/2012"], |
35 | + ["You","6Mb","30/06/2012"]) |
36 | + |
37 | + |
38 | +mullist = sgc.MultiListBox((200,100), pos=(370,150), columnwidth=(150,50,100), content=data) |
39 | +mullist.add(0) |
40 | + |
41 | +head = ("Name","Size","Modified") |
42 | + |
43 | +mullist2 = sgc.MultiListBox((100,100), pos=(100,300), multi_selection=True, header=head, columnwidth=(150,150,150), content=data) |
44 | +mullist2.add(0) |
45 | + |
46 | +def print_attr(): |
47 | + x = mullist2.selected_text |
48 | + print x |
49 | + |
50 | +def print_pos(): |
51 | + x = mullist2.selected_pos |
52 | + print x |
53 | + |
54 | +btn = sgc.Button(pos=(300,400), label="get attr") |
55 | +btn.on_click = print_attr |
56 | +btn.add(0) |
57 | + |
58 | +btn2 = sgc.Button(pos=(300,300), label="get pos") |
59 | +btn2.on_click = print_pos |
60 | +btn2.add(0) |
61 | + |
62 | +while True: |
63 | + time = clock.tick(30) |
64 | + |
65 | + for event in pygame.event.get(): |
66 | + sgc.event(event) |
67 | + if event.type == QUIT: |
68 | + exit() |
69 | + |
70 | + screen.fill((200,200,200)) |
71 | + sgc.update(time) |
72 | + pygame.display.flip() |
73 | |
74 | === modified file 'sgc/__init__.py' |
75 | --- sgc/__init__.py 2012-07-19 13:33:13 +0000 |
76 | +++ sgc/__init__.py 2012-07-21 12:53:18 +0000 |
77 | @@ -21,12 +21,18 @@ |
78 | from widgets.boxes import VBox, HBox |
79 | from widgets.button import Button |
80 | from widgets.container import Container |
81 | +from widgets.composite.dialogs import DialogSaveQuit |
82 | from widgets.dialog import Dialog |
83 | from widgets.fps_counter import FPSCounter |
84 | from widgets.input_box import InputBox |
85 | from widgets.label import Label |
86 | +from widgets.lists import MultiListBox |
87 | +from widgets.lists import ListBox |
88 | +from widgets.lists import _List |
89 | +from widgets.lists import _MultiList |
90 | from widgets.menu import Menu |
91 | from widgets.radio_button import Radio |
92 | from widgets.scroll_box import ScrollBox |
93 | from widgets.settings import Keys |
94 | from widgets.switch import Switch |
95 | + |
96 | |
97 | === modified file 'sgc/widgets/base_widget.py' |
98 | --- sgc/widgets/base_widget.py 2012-07-18 09:38:26 +0000 |
99 | +++ sgc/widgets/base_widget.py 2012-07-21 12:53:18 +0000 |
100 | @@ -237,6 +237,9 @@ |
101 | return surf |
102 | elif isinstance(surf, str): |
103 | return pygame.image.load(surf).convert_alpha() |
104 | + elif isinstance(surf, opengl.OpenGLImage): |
105 | + self._custom_image = True |
106 | + return surf |
107 | |
108 | # Create base images |
109 | self._custom_image = False |
110 | |
111 | === modified file 'sgc/widgets/button.py' |
112 | --- sgc/widgets/button.py 2012-06-16 11:01:51 +0000 |
113 | +++ sgc/widgets/button.py 2012-07-21 12:53:18 +0000 |
114 | @@ -58,16 +58,15 @@ |
115 | # Clear previous renderings |
116 | del self._settings["label"][1:] |
117 | label = self._settings["label"][0].split("\n") |
118 | - f = Font["widget"] |
119 | - h = f.get_ascent() |
120 | for count, line in enumerate(label): |
121 | - lbl = Simple(f.render(line, True, self._settings["label_col"])) |
122 | + lbl = Simple(Font["widget"].render(line, True, |
123 | + self._settings["label_col"])) |
124 | self._settings["label"].append(lbl) |
125 | - y = (self.rect.h - (h * len(label)) + f.get_descent()) / 2 + \ |
126 | - (h * count) |
127 | + y = (self.rect.h - (lbl.rect.h * len(label))) / 2 + \ |
128 | + (lbl.rect.h * count) |
129 | lbl.rect.midtop = (self.rect.w/2, y) |
130 | |
131 | - def _draw_base(self, draw): |
132 | + def _draw(self, draw): |
133 | # Frames around edge of button |
134 | x = min(self.image.get_size()) / 8 |
135 | self._frame_lt = ((0,0), (self.rect.w,0), (self.rect.w-x,x), |
136 | @@ -81,18 +80,16 @@ |
137 | cols["over"] = [min(c*1.1, 255) for c in self._settings["col"]] |
138 | cols["down"] = [c*0.8 for c in self._settings["col"]] |
139 | for img in cols: |
140 | - self._images[img].fill(cols[img]) |
141 | - # Draw a frame around the edges of the button |
142 | - frame_lt_c = [min(c*1.3,255) for c in cols[img]] |
143 | - frame_rb_c = [c*0.8 for c in cols[img]] |
144 | - draw.polygon(self._images[img], frame_lt_c, self._frame_lt) |
145 | - draw.polygon(self._images[img], frame_rb_c, self._frame_rb) |
146 | - |
147 | - def _draw_final(self, draw): |
148 | - for img in self._images.values(): |
149 | + if not self._custom_image: |
150 | + self._images[img].fill(cols[img]) |
151 | + # Draw a frame around the edges of the button |
152 | + frame_lt_c = [min(c*1.3,255) for c in cols[img]] |
153 | + frame_rb_c = [c*0.8 for c in cols[img]] |
154 | + draw.polygon(self._images[img], frame_lt_c, self._frame_lt) |
155 | + draw.polygon(self._images[img], frame_rb_c, self._frame_rb) |
156 | # Blit label onto button |
157 | for line in self._settings["label"][1:]: |
158 | - img.blit(line.image, line.pos) |
159 | + self._images[img].blit(line.image, line.pos) |
160 | self._draw_button() |
161 | |
162 | def on_click(self): |
163 | |
164 | === added directory 'sgc/widgets/composite' |
165 | === added file 'sgc/widgets/composite/__init__.py' |
166 | === added file 'sgc/widgets/composite/dialogs.py' |
167 | --- sgc/widgets/composite/dialogs.py 1970-01-01 00:00:00 +0000 |
168 | +++ sgc/widgets/composite/dialogs.py 2012-07-21 12:53:18 +0000 |
169 | @@ -0,0 +1,98 @@ |
170 | +#!/usr/bin/env python |
171 | + |
172 | +# Copyright (C) 2012 Michael Rochester |
173 | + |
174 | +""" |
175 | +Dialog composite widgets. A list of predefined common dialogs |
176 | + |
177 | +""" |
178 | +import sgc |
179 | +from sgc.locals import * |
180 | + |
181 | +from ..dialog import * |
182 | + |
183 | +class DialogSaveQuit (Dialog): |
184 | + """ |
185 | + This dialog is designed to be called when a user tries to quit without saving. |
186 | + It will emmit 2 GUI events: 'quit' and 'save'. |
187 | + If the final option 'cancel' is selected, the dialog will remove its self. |
188 | + """ |
189 | + def _config(self, **kwargs): |
190 | + """ |
191 | + doctitle: ``str`` The text that will be used as the documents Title. |
192 | + """ |
193 | + if "init" in kwargs: |
194 | + self.lbl = sgc.Label(pos=(10,10),text="The document has not been saved.\nWould you like to save the changes before quitting?", col=(20,20,20)) |
195 | + self.btn_save = sgc.Button(pos=(200,100), label="Save") |
196 | + self.btn_save.on_click = self.send_save |
197 | + self.btn_quit = sgc.Button((200,50), pos=(0,100), label="Close without saving") |
198 | + self.btn_quit.on_click = self.send_quit |
199 | + self.btn_cancel = sgc.Button(pos=(310,100), label="Cancel") |
200 | + self.btn_cancel.on_click = self.send_cancel |
201 | + contain = sgc.Container(pos=(0,0), widgets=[self.lbl,self.btn_quit,self.btn_cancel,self.btn_save] ) |
202 | + |
203 | + kwargs["widget"] = contain; |
204 | + kwargs["title"]="Save changes?" |
205 | + sgc.Dialog._config(self,**kwargs) |
206 | + if "doctitle" in kwargs: |
207 | + self.lbl.text = "The document \"" + kwargs["doctitle"] + "\" has not been saved.\nWould you like to save the changes before quitting?" |
208 | + def send_quit(self): |
209 | + ev = pygame.event.Event(GUI, {"gui_type": "quit", |
210 | + "widget_type": self.__class__, |
211 | + "widget":self}) |
212 | + pygame.event.post(ev) |
213 | + |
214 | + def send_save(self): |
215 | + ev = pygame.event.Event(GUI, {"gui_type": "save", |
216 | + "widget_type": self.__class__, |
217 | + "widget":self}) |
218 | + pygame.event.post(ev) |
219 | + def send_cancel(self): |
220 | + ev = pygame.event.Event(GUI, {"gui_type": "cancel", |
221 | + "widget_type": self.__class__, |
222 | + "widget":self}) |
223 | + pygame.event.post(ev) |
224 | + |
225 | +class DialogSave (Dialog): |
226 | + """ |
227 | + This dialog is designed to be called when a user tries to quit without saving. |
228 | + It will emmit 2 GUI events: 'quit' and 'save'. |
229 | + If the final option 'cancel' is selected, the dialog will remove its self. |
230 | + """ |
231 | + def _config(self, **kwargs): |
232 | + """ |
233 | + doctitle: ``str`` The text that will be used as the documents Title. |
234 | + """ |
235 | + if "init" in kwargs: |
236 | + self.lbl = sgc.Label(pos=(10,10),text="The document has not been saved.\nWould you like to save the changes before quitting?", col=(20,20,20)) |
237 | + self.btn_save = sgc.Button(pos=(200,100), label="Save") |
238 | + self.btn_save.on_click = self.send_save |
239 | + self.btn_quit = sgc.Button((200,50), pos=(0,100), label="Close without saving") |
240 | + self.btn_quit.on_click = self.send_quit |
241 | + self.btn_cancel = sgc.Button(pos=(310,100), label="Cancel") |
242 | + self.btn_cancel.on_click = self.send_cancel |
243 | + contain = sgc.Container(pos=(0,0), widgets=[self.lbl,self.btn_quit,self.btn_cancel,self.btn_save] ) |
244 | + |
245 | + kwargs["widget"] = contain; |
246 | + kwargs["title"]="Save changes?" |
247 | + sgc.Dialog._config(self,**kwargs) |
248 | + if "doctitle" in kwargs: |
249 | + self.lbl.text = "The document \"" + kwargs["doctitle"] + "\" has not been saved.\nWould you like to save the changes before quitting?" |
250 | + def send_quit(self): |
251 | + ev = pygame.event.Event(GUI, {"gui_type": "quit", |
252 | + "widget_type": self.__class__, |
253 | + "widget":self}) |
254 | + pygame.event.post(ev) |
255 | + |
256 | + def send_save(self): |
257 | + ev = pygame.event.Event(GUI, {"gui_type": "save", |
258 | + "widget_type": self.__class__, |
259 | + "widget":self}) |
260 | + pygame.event.post(ev) |
261 | + def send_cancel(self): |
262 | + ev = pygame.event.Event(GUI, {"gui_type": "cancel", |
263 | + "widget_type": self.__class__, |
264 | + "widget":self}) |
265 | + pygame.event.post(ev) |
266 | + |
267 | + |
268 | |
269 | === added file 'sgc/widgets/lists.py' |
270 | --- sgc/widgets/lists.py 1970-01-01 00:00:00 +0000 |
271 | +++ sgc/widgets/lists.py 2012-07-21 12:53:18 +0000 |
272 | @@ -0,0 +1,383 @@ |
273 | +#!/usr/bin/env python |
274 | + |
275 | +# Copyright (C) 2012 Michael Rochester |
276 | + |
277 | +import sgc |
278 | +from sgc.locals import * |
279 | + |
280 | +import pygame.mouse |
281 | +from pygame.locals import * |
282 | + |
283 | +from _locals import * |
284 | +from base_widget import Simple |
285 | + |
286 | +class _List(Simple): |
287 | + |
288 | + _can_focus = True |
289 | + _settings_default = {"col": (118, 45, 215), |
290 | + "font": Font["widget"], |
291 | + "padding": 3,"offset": 0,"width":None, |
292 | + "mult": False} |
293 | + |
294 | + |
295 | + def _config(self,**kwargs): |
296 | + self.anchor = False |
297 | + if "multi_selection" in kwargs: |
298 | + self._settings["mult"] = kwargs["multi_selection"] |
299 | + if "padding" in kwargs: |
300 | + self._settings["padding"] = kwargs["padding"] |
301 | + if "init" in kwargs: |
302 | + self.color = (118, 45, 215) |
303 | + self.contain = sgc.Container(border=self._settings["padding"]) |
304 | + self.lbls=[] |
305 | + self.selected=[] |
306 | + if "col" in kwargs: |
307 | + self.color = kwargs["col"] |
308 | + if "font" in kwargs: |
309 | + self._settings["font"] = kwargs["font"] |
310 | + if "width" in kwargs: |
311 | + self._settings["width"] = kwargs["width"] |
312 | + if "content" in kwargs: |
313 | + self.content = kwargs["content"] |
314 | + self.texth = self._settings["font"].get_ascent()+\ |
315 | + self._settings["font"].get_descent()+\ |
316 | + (self._settings["padding"]*2) |
317 | + p=0 |
318 | + for string in kwargs["content"]: |
319 | + lbl = sgc.Label(pos=(0,p),col=(10,10,10),text=string, |
320 | + font=self._settings["font"]) |
321 | + p+=self.texth |
322 | + self.lbls.append(lbl) |
323 | + self.contain.config(widgets=self.lbls) |
324 | + if not hasattr(self, "image"): |
325 | + self._create_base_images((self.contain.image.get_width() if |
326 | + self._settings["width"] == None else self._settings["width"] |
327 | + ,self.contain.image.get_height())) |
328 | + |
329 | + def _event(self, event): |
330 | + if event.type == MOUSEBUTTONDOWN and event.button == 1: |
331 | + sel = self.colide_item(event.pos) |
332 | + if sel > 0 and sel < len(self.content)+1: |
333 | + if (pygame.key.get_mods() & KMOD_CTRL and self._settings["mult"]): |
334 | + |
335 | + if sel in self.selected: |
336 | + self.selected.remove(sel) |
337 | + else: |
338 | + self.selected.append(sel) |
339 | + elif (pygame.key.get_mods() & KMOD_SHIFT |
340 | + and self._settings["mult"] and self.anchor): |
341 | + self.selected=[] |
342 | + for new in range(abs(self.anchor-sel)+1): |
343 | + self.selected.append(new+(min(self.anchor,sel))) |
344 | + else: |
345 | + self.anchor = sel |
346 | + self.selected = [sel] |
347 | + |
348 | + def update(self, time): |
349 | + draw = self.get_draw() |
350 | + |
351 | + self.contain.update(time) |
352 | + self.image.fill((255,255,255)) |
353 | + |
354 | + for sel in self.selected: |
355 | + w = (self.image.get_width()) |
356 | + selection = Simple((w, self.texth)) |
357 | + selection.pos = (0,(sel-1)*self.texth+self._settings["padding"]) |
358 | + selection.image.fill(self.color) |
359 | + selection.image.set_alpha(100) |
360 | + self.image.blit(selection.image, selection.pos) |
361 | + self.image.blit(self.contain.image,(0,0)) |
362 | + self.image.blit(self._images["image"],(0,0)) |
363 | + |
364 | + def colide_item(self,pos): |
365 | + pos = pos[1]-self.rect_abs.y |
366 | + return ((pos-self._settings["padding"])/self.texth)+1 |
367 | + |
368 | + def _focus_enter(self, focus): |
369 | + self.color = self._settings["col"] |
370 | + |
371 | + def _focus_exit(self): |
372 | + self.color = (179,179,179) |
373 | + |
374 | + @property |
375 | + def selected_text(self): |
376 | + return [self.content[x-1] for x in self.selected] |
377 | + |
378 | + @property |
379 | + def selected_pos(self): |
380 | + return [x-1 for x in self.selected] |
381 | + |
382 | +class ListBox(Simple): |
383 | + |
384 | + _can_focus = True |
385 | + _default_size = (100,100) |
386 | + _settings_default = {"headfont": Font["widget"], |
387 | + "offset": 0} |
388 | + |
389 | + def _config(self,**kwargs): |
390 | + if "header" in kwargs: |
391 | + self._settings["header"] = kwargs["header"] |
392 | + self._settings["offset"] = self._settings["headfont"].get_ascent()+\ |
393 | + self._settings["headfont"].get_descent()+6 |
394 | + if "init" in kwargs: |
395 | + self.list = _List(width=self.image.get_width()) |
396 | + self.scroll = sgc.ScrollBox((self.rect.w,self.rect.h-self._settings["offset"]),pos=(0,self._settings["offset"]),widget=self.list) |
397 | + self.scroll._parent = self |
398 | + self.list.config(**kwargs) |
399 | + self.scroll.config(widget=self.list,**kwargs) |
400 | + |
401 | + def _draw(self,draw): |
402 | + if "header" in self._settings: |
403 | + lbl = sgc.Label(pos=(0,0),col=(10,10,10), |
404 | + text=self._settings["header"], |
405 | + font=self._settings["headfont"]) |
406 | + self._images["image"].blit(lbl.image,(3,1)) |
407 | + draw.line(self._images["image"],(150,150,150), |
408 | + (1,self._settings["offset"]), |
409 | + (self.image.get_width()-2,self._settings["offset"])) |
410 | + |
411 | + draw.line(self._images["image"],(150,150,150), |
412 | + (1,0),(self.image.get_width()-2,0)) |
413 | + draw.line(self._images["image"],(150,150,150), |
414 | + (1,self.image.get_height()-1), |
415 | + (self.image.get_width()-2,self.image.get_height()-1)) |
416 | + draw.line(self._images["image"],(150,150,150), |
417 | + (0,1),(0,self.image.get_height()-2)) |
418 | + draw.line(self._images["image"],(150,150,150), |
419 | + (self.image.get_width()-1,1), |
420 | + (self.image.get_width()-1,self.image.get_height()-2)) |
421 | + |
422 | + def _event(self, event): |
423 | + self.scroll._event(event) |
424 | + |
425 | + def update(self, time): |
426 | + self.scroll.update(time) |
427 | + self.image.fill((255,255,255)) |
428 | + self.image.blit(self.scroll.image,(0,self._settings["offset"])) |
429 | + self.image.blit(self._images["image"],(0,0)) |
430 | + |
431 | + def _focus_enter(self, focus): |
432 | + self.scroll._focus_enter(focus) |
433 | + |
434 | + def _focus_exit(self): |
435 | + self.scroll._focus_exit() |
436 | + |
437 | + @property |
438 | + def selected_text(self): |
439 | + return [x for x in self.list.selected_text] |
440 | + |
441 | + @property |
442 | + def selected_pos(self): |
443 | + return [x for x in self.list.selected] |
444 | + |
445 | + |
446 | +class _MultiList(_List): |
447 | + |
448 | + _can_focus = True |
449 | + _settings_default = {"col": (118, 45, 215), |
450 | + "font": Font["widget"], |
451 | + "padding": 3,"offset": 0, |
452 | + "mult": False,"colwid":False} |
453 | + |
454 | + |
455 | + def _config(self,**kwargs): |
456 | + self.anchor = False |
457 | + if "multi_selection" in kwargs: |
458 | + self._settings["mult"] = kwargs["multi_selection"] |
459 | + if "padding" in kwargs: |
460 | + self._settings["padding"] = kwargs["padding"] |
461 | + if "init" in kwargs: |
462 | + self.color = (118, 45, 215) |
463 | + self.lbls=[] |
464 | + self.selected=[] |
465 | + if "col" in kwargs: |
466 | + self.color = kwargs["col"] |
467 | + if "font" in kwargs: |
468 | + self._settings["font"] = kwargs["font"] |
469 | + if "columnwidth" in kwargs: |
470 | + self._settings["colwid"] = kwargs["columnwidth"] |
471 | + if "content" in kwargs: |
472 | + |
473 | + self.columns = [] |
474 | + self.content = kwargs["content"] |
475 | + self.texth = self._settings["font"].get_ascent()+\ |
476 | + self._settings["font"].get_descent()+\ |
477 | + (self._settings["padding"]*2) |
478 | + w = [] |
479 | + for x in range(len(kwargs["content"][0])): |
480 | + labels = [] |
481 | + p=0 |
482 | + for y in range(len(kwargs["content"])): |
483 | + lbl = sgc.Label(pos=(0,p),col=(10,10,10),text=kwargs["content"][y][x], |
484 | + font=self._settings["font"]) |
485 | + p+=self.texth |
486 | + labels.append(lbl) |
487 | + w.append(lbl) |
488 | + self.lbls.append(labels) |
489 | + if self._settings["colwid"]: |
490 | + column = sgc.Container((self._settings["colwid"][x],len(kwargs["content"])*self.texth),widgets=labels) |
491 | + else: |
492 | + column = sgc.Container(widgets=labels) |
493 | + self.columns.append(column) |
494 | + |
495 | + self.contain = sgc.HBox(border=self._settings["padding"],widgets=self.columns) |
496 | + self.rect.w = self.contain.rect.w |
497 | + self.rect.h = self.contain.rect.h |
498 | + if not hasattr(self, "image"): |
499 | + self._create_base_images((self.contain.image.get_width() |
500 | + ,self.contain.image.get_height())) |
501 | + |
502 | + @property |
503 | + def selected_text(self): |
504 | + return [self.content[x-1] for x in self.selected] |
505 | + |
506 | + @property |
507 | + def selected_pos(self): |
508 | + return [x-1 for x in self.selected] |
509 | + |
510 | +class MultiListBox(ListBox): |
511 | + |
512 | + _can_focus = True |
513 | + _default_size = (100,100) |
514 | + _settings_default = {"headfont": Font["widget"], |
515 | + "offset": 0,"colwid": 100,"header":None} |
516 | + |
517 | + |
518 | + def _config(self,**kwargs): |
519 | + if "content" in kwargs: |
520 | + self.content = kwargs["content"] |
521 | + if "columnwidth" in kwargs: |
522 | + self.colpos=[0] |
523 | + self._settings["colwid"] = [c for c in kwargs["columnwidth"]] |
524 | + for x in range(len(kwargs["columnwidth"])): |
525 | + self.colpos.append((self.colpos[x]+self._settings["colwid"][x])) |
526 | + if "header" in kwargs: |
527 | + self._settings["header"] = kwargs["header"] |
528 | + self._settings["offset"] = self._settings["headfont"].get_ascent()+\ |
529 | + self._settings["headfont"].get_descent()+6 |
530 | + |
531 | + |
532 | + if "init" in kwargs: |
533 | + strings = pygame.cursors.sizer_x_strings |
534 | + cursor = pygame.cursors.compile(strings) |
535 | + size = (len(strings[0]), len(strings)) |
536 | + hotspot = (size[0]/2, size[1]/2) |
537 | + self._cursor = (size, hotspot) + cursor |
538 | + self._cursor_set = False |
539 | + |
540 | + self.move = False |
541 | + self.mouse = False |
542 | + self.resize = False |
543 | + self.list = _MultiList() |
544 | + self.scroll = sgc.ScrollBox((self.rect.w,self.rect.h-self._settings["offset"]),pos=(0,self._settings["offset"]),widget=self.list) |
545 | + self.scroll._parent = self |
546 | + if self._settings["colwid"] != 100: |
547 | + kwargs["columnwidth"] = self._settings["colwid"] |
548 | + if "content" not in kwargs: |
549 | + kwargs["content"]=self.content |
550 | + self.list.config(**kwargs) |
551 | + if "init" in kwargs: |
552 | + self.scroll.config(widget=self.list,**kwargs) |
553 | + |
554 | + def _draw(self,draw): |
555 | + |
556 | + if self._settings["header"]: |
557 | + self.header = sgc.Simple((self.colpos[-1]+10,self._settings["offset"])) |
558 | + for p, header in enumerate(self._settings["header"]): |
559 | + lbl = sgc.Label((self._settings["colwid"][p],self._settings["offset"]),pos=(0,0), |
560 | + text=header, |
561 | + col=(10,10,10), |
562 | + |
563 | + font=self._settings["headfont"]) |
564 | + draw.rect(self.header.image,(255,255,255),((self.colpos[p],0),(self.colpos[p]+self._settings["colwid"][p],self._settings["offset"])),0) |
565 | + self.header.image.blit(lbl.image,(self.colpos[p]+6*p+3,1)) |
566 | + draw.line(self.header.image,(150,150,150), |
567 | + (self.colpos[p]+6*(p),0), |
568 | + (self.colpos[p]+6*(p),self._settings["offset"])) |
569 | + |
570 | + |
571 | + draw.line(self._images["image"],(150,150,150), |
572 | + (1,0),(self.image.get_width()-2,0)) |
573 | + draw.line(self._images["image"],(150,150,150), |
574 | + (1,self.image.get_height()-1), |
575 | + (self.image.get_width()-2,self.image.get_height()-1)) |
576 | + draw.line(self._images["image"],(150,150,150), |
577 | + (0,1),(0,self.image.get_height()-2)) |
578 | + draw.line(self._images["image"],(150,150,150), |
579 | + (self.image.get_width()-1,1), |
580 | + (self.image.get_width()-1,self.image.get_height()-2)) |
581 | + self.image.fill((255,0,0)) |
582 | + |
583 | + def _event(self, event): |
584 | + if (event.type == MOUSEBUTTONDOWN and event.button == 1 |
585 | + and (self.collidehead(event.pos)is not False)): |
586 | + self.move = self.collidehead(event.pos) |
587 | + self.mouse = event.pos[0] |
588 | + elif event.type == MOUSEBUTTONUP: |
589 | + if self.resize is not False and self.mouse is not False: |
590 | + self.scroll = sgc.ScrollBox((self.rect.w,self.rect.h-self._settings["offset"]),pos=(0,self._settings["offset"]),widget=self.list) |
591 | + self.scroll._parent = self |
592 | + self.mouse = False |
593 | + self.resize = False |
594 | + elif event.type == MOUSEMOTION: |
595 | + if self.collidehead(event.pos) is False and self._cursor_set==True: |
596 | + self._remove_cursor() |
597 | + self._cursor_set = False |
598 | + elif self.collidehead(event.pos) is not False and self._cursor_set==False: |
599 | + self._set_cursor(*self._cursor) |
600 | + self._cursor_set = True |
601 | + if self.resize is not False and self.mouse is not False: |
602 | + dif = event.pos[0] - self.mouse |
603 | + self.mouse = event.pos[0] |
604 | + self._settings["colwid"][self.move]+=dif |
605 | + if self._settings["colwid"][self.move] < 0: |
606 | + self._settings["colwid"][self.move] = 0 |
607 | + self.config(columnwidth=self._settings["colwid"], content=self.content) |
608 | + self.list._create_base_images((self.list.rect.w, self.list.rect.h)) |
609 | + elif self.mouse is not False: |
610 | + if abs(event.pos[0] - self.mouse) > 4: |
611 | + self.resize = True |
612 | + self.scroll._event(event) |
613 | + |
614 | + def collidehead(self,pos): |
615 | + for p, x in enumerate(self.colpos[1:],1): |
616 | + if (pos[0]-self.pos_abs[0]>=self.scroll._settings["widget"].pos[0]+x+6*p-2 and |
617 | + pos[0]-self.pos_abs[0]<=self.scroll._settings["widget"].pos[0]+x+6*p+2 and |
618 | + pos[1] < self.pos_abs[1]+self._settings["offset"] and |
619 | + pos[1] > self.pos_abs[1]): |
620 | + return p-1 |
621 | + return False |
622 | + |
623 | + def update(self, time): |
624 | + self.scroll.update(time) |
625 | + self.image.fill((255,255,255)) |
626 | + self.image.blit(self.scroll.image,(0,self._settings["offset"])) |
627 | + if self._settings["header"]: |
628 | + self.image.blit(self.header.image,(self.scroll._settings["widget"].pos[0],0)) #MAYBE A HACK, PROBABLY |
629 | + self.image.blit(self._images["image"],(0,0)) |
630 | + |
631 | + def _focus_enter(self, focus): |
632 | + self.scroll._focus_enter(focus) |
633 | + |
634 | + def _focus_exit(self): |
635 | + self.scroll._focus_exit() |
636 | + |
637 | + @property |
638 | + def selected_text(self): |
639 | + return [x for x in self.list.selected_text] |
640 | + |
641 | + @property |
642 | + def selected_pos(self): |
643 | + return [x for x in self.list.selected] |
644 | + |
645 | + |
646 | + |
647 | + |
648 | + |
649 | + |
650 | + |
651 | + |
652 | + |
653 | + |
654 | + |
655 | + |
656 | |
657 | === modified file 'sgc/widgets/menu.py' |
658 | --- sgc/widgets/menu.py 2012-07-18 11:56:10 +0000 |
659 | +++ sgc/widgets/menu.py 2012-07-21 12:53:18 +0000 |
660 | @@ -120,18 +120,24 @@ |
661 | widgets.append(div) |
662 | # Widget |
663 | elif item[0].startswith("w:"): |
664 | - args = item[1] |
665 | - name = args.pop("name", None) |
666 | - try: |
667 | - # Try to load existing widget |
668 | - widget = eval(item[0][2:]) |
669 | - except NameError: |
670 | - # Try to import custom widget |
671 | - parts = item[0][2:].rpartition(".") |
672 | - mod = __import__(parts[0]) |
673 | - widget = getattr(mod, parts[2]) |
674 | - widget = widget(**args) |
675 | - if name: self._dict[name] = widget |
676 | + args = self._get_args(item[1:]) |
677 | + name = args.pop("name") |
678 | + f = args.pop("func") if ("func" in args) else None |
679 | + if item[0].endswith("input_box"): |
680 | + widget = input_box.InputBox(**args) |
681 | + elif item[0].endswith("button"): |
682 | + if "surf" in args: |
683 | + args["surf"] = eval(args["surf"]) |
684 | + widget = button.Button(**args) |
685 | + elif item[0].endswith("radio"): |
686 | + if "surf" in args: |
687 | + args["surf"] = eval(args["surf"]) |
688 | + widget = radio_button.Radio(**args) |
689 | + elif item[0].endswith("label"): |
690 | + widget = label.Label(**args) |
691 | + self._dict[name] = widget |
692 | + if f: widget.on_click = self._funcs[f] |
693 | + widget.name = name |
694 | widgets.append(widget) |
695 | # Function |
696 | elif item[0].startswith("f:"): |
697 | @@ -176,6 +182,7 @@ |
698 | def update(self, time): |
699 | menu = self._menus[self._curr_menu] |
700 | menu.update(time) |
701 | + self.image.fill(0) # Hack for OpenGL |
702 | if self._old_menu is not None: |
703 | self.image.blit(self._menus[self._old_menu].image, (0,0)) |
704 | menu.image.set_alpha(menu._fade) |
705 | |
706 | === modified file 'sgc/widgets/opengl.py' |
707 | --- sgc/widgets/opengl.py 2011-09-22 09:41:10 +0000 |
708 | +++ sgc/widgets/opengl.py 2012-07-21 12:53:18 +0000 |
709 | @@ -1,9 +1,9 @@ |
710 | #!/usr/bin/env python |
711 | |
712 | -# Copyright (C) 2011 Sam Bull |
713 | +# Copyright (C) 2011-2012 Sam Bull |
714 | |
715 | """ |
716 | -Base widget, all widgets inherit from this. |
717 | +OpenGL functions. |
718 | |
719 | """ |
720 | |
721 | @@ -11,10 +11,11 @@ |
722 | from OpenGL.GL import * |
723 | import FTGL |
724 | |
725 | -from ..surface import SurfaceBase |
726 | - |
727 | - |
728 | -class OpenGLImage(SurfaceBase): |
729 | +from _locals import * |
730 | +from matrix import Matrix |
731 | + |
732 | + |
733 | +class OpenGLImage(): |
734 | """ |
735 | Class used to emulate the interface of Surface for OpenGL drawing. |
736 | |
737 | @@ -28,39 +29,49 @@ |
738 | self._lock = False |
739 | self.display_list = [] |
740 | self._children = [] |
741 | - if parent: |
742 | - self._parent = parent # Parent surface used for _abs |
743 | - else: |
744 | - self._parent = self._default_screen |
745 | + self.matrix = Matrix() |
746 | + self._parent = parent # Parent surface used for _abs |
747 | |
748 | - self._rect = Rect((0,0), (0,0)) |
749 | + self.rect = Rect((0,0), (0,0)) |
750 | if isinstance(surf, (tuple,list)): |
751 | - self._rect.size = surf |
752 | + self.rect.size = surf |
753 | elif isinstance(surf, OpenGLFont): |
754 | - self._rect.size = (surf.size) |
755 | + self.rect.size = (surf.size) |
756 | self.display_list.extend(surf.display_list) |
757 | elif isinstance(surf, OpenGLImage): |
758 | - self._rect = surf._rect |
759 | + self.matrix = surf.matrix.copy() |
760 | + self.rect = Rect(surf.rect) |
761 | self._a = surf._a |
762 | - self.display_list = surf.display_list |
763 | - self._children = surf._children |
764 | + self.display_list = surf.display_list[:] |
765 | + for child in surf._children: |
766 | + self.blit(child.copy()) |
767 | |
768 | - def blit(self, surf, pos=None): |
769 | + def blit(self, surf, pos=None, area=None): |
770 | assert isinstance(surf, OpenGLImage) |
771 | if surf not in self._children: |
772 | if pos is not None: surf.pos = pos |
773 | + surf.rect.topleft = surf.pos |
774 | surf._parent = self |
775 | self._children.append(surf) |
776 | |
777 | def draw(self): |
778 | glLoadIdentity() |
779 | - if self.rect.w <= self._parent.rect.w and \ |
780 | - self.rect.h <= self._parent.rect.h: |
781 | + if self._parent: |
782 | + r = self._parent.rect |
783 | + else: |
784 | + r = Rect(0,0,10000,10000) |
785 | + if self.rect.w <= r.w and self.rect.h <= r.h: |
786 | # Mask the area, so nothing is drawn outside surface area. |
787 | - bottom = self._default_screen.h - self.rect_abs.bottom |
788 | + bottom = 480 - self.rect_abs.bottom # Screen height... |
789 | glScissor(self.rect_abs.x, bottom, |
790 | self.rect.w+1, self.rect.h+1) |
791 | glTranslatef(self.pos_abs[0], self.pos_abs[1], 0) |
792 | + if not isinstance(self.matrix, (list, tuple)): |
793 | + glMultMatrixf(self.matrix.to_opengl()) |
794 | + else: |
795 | + for m in self.matrix: |
796 | + glMultMatrixf(m.to_opengl()) |
797 | + |
798 | for dl,col in self.display_list: |
799 | if col is not None: glColor(col[0], col[1], col[2], self.a) |
800 | glCallList(dl) |
801 | @@ -73,7 +84,7 @@ |
802 | # Clear the surface |
803 | self.display_list = [] |
804 | self._children = [] |
805 | - rect = Rect((0,0), self.size) |
806 | + rect = Rect((0,0), self.rect.size) |
807 | if col != 0: |
808 | col = [c/255. for c in col] |
809 | dl = glGenLists(1) |
810 | @@ -86,7 +97,13 @@ |
811 | return OpenGLImage(self) |
812 | |
813 | def get_size(self): |
814 | - return self.size |
815 | + return self.rect.size |
816 | + |
817 | + def get_height(self): |
818 | + return self.rect.h |
819 | + |
820 | + def get_width(self): |
821 | + return self.rect.w |
822 | |
823 | def set_alpha(self, alpha): |
824 | self._a = alpha/255. |
825 | @@ -127,7 +144,7 @@ |
826 | self._lock = False |
827 | |
828 | def replace(self, surf, **kwargs): |
829 | - self._rect.size = surf.size |
830 | + self.rect.size = surf.size |
831 | self.display_list = surf.display_list[:] |
832 | self._children = surf._children[:] |
833 | |
834 | @@ -136,7 +153,33 @@ |
835 | if self._a is not None: |
836 | return self._a |
837 | else: |
838 | - return self._parent.a |
839 | + if self._parent: |
840 | + return self._parent.a |
841 | + else: |
842 | + return 1 |
843 | + |
844 | + @property |
845 | + def rect_abs(self): |
846 | + if self._parent is None: |
847 | + return self.rect |
848 | + else: |
849 | + p_abs = self._parent.pos_abs |
850 | + p = (self.rect.x + p_abs[0], self.rect.y + p_abs[1]) |
851 | + return Rect(p, self.rect.size) |
852 | + |
853 | + @property |
854 | + def pos(self): |
855 | + return self.rect.topleft |
856 | + @pos.setter |
857 | + def pos(self, value): |
858 | + self.rect.topleft = value |
859 | + @property |
860 | + def pos_abs(self): |
861 | + if self._parent is None: |
862 | + return self.rect.topleft |
863 | + else: |
864 | + p_abs = self._parent.pos_abs |
865 | + return (self.rect.x + p_abs[0], self.rect.y + p_abs[1]) |
866 | |
867 | # --- Dummy methods. Ignore. --- |
868 | |
869 | @@ -152,17 +195,27 @@ |
870 | to an OpenGLImage object in the same manner as pygame.Font. |
871 | |
872 | """ |
873 | - def __init__(self, font, size): |
874 | + def __init__(self, font, size=16): |
875 | + self.rect = Rect(0,0,0,0) |
876 | self._children = [] |
877 | - self.font = FTGL.TextureFont(font) |
878 | - self.font.FaceSize(16) |
879 | - self.y_offset = self.font.line_height * .75 |
880 | + self.matrix = Matrix() |
881 | + self.display_list = [] |
882 | + if isinstance(font, OpenGLFont): |
883 | + self.font = font.font |
884 | + self.y_offset = font.y_offset |
885 | + self.size = font.size |
886 | + else: |
887 | + self.font = FTGL.TextureFont(font) # BufferFont |
888 | + self.font.FaceSize(size) |
889 | + self.y_offset = self.font.line_height * .75 |
890 | |
891 | def render(self, text, antialias, color, background=None): |
892 | + temp = OpenGLImage((self.font.Advance(text.encode()), self.font.line_height)) |
893 | text = text.encode() |
894 | col = [c/255. for c in color] |
895 | dl = glGenLists(1) |
896 | self.size = (self.font.Advance(text), self.font.line_height) |
897 | + self.rect = Rect((0,0), self.size) |
898 | glNewList(dl, GL_COMPILE) |
899 | glPushMatrix() |
900 | # Flip text right way up |
901 | @@ -173,16 +226,33 @@ |
902 | self.font.Render(text) |
903 | glPopMatrix() |
904 | glEndList() |
905 | - self.display_list = [(dl, col)] |
906 | - return self |
907 | + temp.display_list = [(dl, col)] |
908 | + return temp |
909 | + |
910 | + def get_linesize(self): |
911 | + """TODO""" |
912 | + return self.rect.h |
913 | + |
914 | + def get_ascent(self): |
915 | + """TODO""" |
916 | + return self.rect.h-4 |
917 | + |
918 | + def get_descent(self): |
919 | + """TODO""" |
920 | + return -4 |
921 | + |
922 | + def metrics(self, text): |
923 | + """TODO""" |
924 | + return [(0,0,0,0,10) for c in text] |
925 | |
926 | class Draw(): |
927 | """ |
928 | Class to emulate the pygame.draw module. |
929 | - Functions should work in the same manner. |
930 | + Functions should work in the same manner, except where otherwise stated. |
931 | |
932 | """ |
933 | def rect(self, surf, col, rect, width=0): |
934 | + rect = Rect(rect) |
935 | col = [c/255. for c in col] |
936 | dl = glGenLists(1) |
937 | glNewList(dl, GL_COMPILE) |
938 | @@ -220,6 +290,8 @@ |
939 | for v in pointlist: |
940 | glVertex(v) |
941 | glEnd() |
942 | + else: |
943 | + raise NotImplementedError |
944 | glEndList() |
945 | surf.display_list.append((dl, col)) |
946 | |
947 | @@ -235,10 +307,18 @@ |
948 | glVertex(pos) |
949 | glEnd() |
950 | glDisable(GL_POINT_SMOOTH) |
951 | - glPointSize() |
952 | + #glPointSize() |
953 | + else: |
954 | + raise NotImplementedError |
955 | glEndList() |
956 | surf.display_list.append((dl, col)) |
957 | |
958 | + def ellipse(self, surf, col, rect, width=0): |
959 | + raise NotImplementedError |
960 | + |
961 | + def arc(self, surf, col, rect, start_angle, stop_angle, width=1): |
962 | + raise NotImplementedError |
963 | + |
964 | def line(self, surf, col, start_pos, end_pos, width=1): |
965 | col = [c/255. for c in col] |
966 | dl = glGenLists(1) |
967 | @@ -251,5 +331,14 @@ |
968 | glEndList() |
969 | surf.display_list.append((dl, col)) |
970 | |
971 | + def lines(self, surf, col, closed, pointlist, width=1): |
972 | + raise NotImplementedError |
973 | + |
974 | + def aaline(self, surf, col, startpos, endpos, blend=1): |
975 | + raise NotImplementedError |
976 | + |
977 | + def aalines(self, surf, col, closed, pointlist, blend=1): |
978 | + raise NotImplementedError |
979 | + |
980 | # Export Draw functions |
981 | draw = Draw() |
982 | |
983 | === modified file 'sgc/widgets/radio_button.py' |
984 | --- sgc/widgets/radio_button.py 2012-06-19 20:41:57 +0000 |
985 | +++ sgc/widgets/radio_button.py 2012-07-21 12:53:18 +0000 |
986 | @@ -73,8 +73,8 @@ |
987 | draw.circle(self._images["image"], (255,255,255), pos, r) |
988 | draw.circle(self._images["over"], self._settings["col"], pos, r) |
989 | # Border circles |
990 | - draw.circle(self._images["image"], (0,0,1), pos, r, 1) |
991 | - draw.circle(self._images["over"], (0,0,1), pos, r, 1) |
992 | + draw.circle(self._images["image"], (0,0,1), pos, r) |
993 | + draw.circle(self._images["over"], (0,0,1), pos, r) |
994 | |
995 | def _draw_active(self, draw, image): |
996 | # Central dot for 'active' state |
Unresolved conflicts that should never have been committed.
Remove extra line breaks added into multiple files.
Remove matrix.py and revert opengl.py.