11 # The parameters to pass to the function (as a list)
15 """Template object - base for all widgets.
17 <pre>Widget(**params)</pre>
19 <p>A number of optional params may be passed to the Widget initializer.</p>
22 <dt>decorate<dd>defaults to True. If true, will call <tt>theme.decorate(self)</tt> to allow the theme a chance to decorate the widget.
23 <dt>style<dd>a dict of style parameters.
24 <dt>x, y, width, height<dd>position and size parameters, passed along to style
25 <dt>align, valign<dd>alignment parameters, passed along to style
26 <dt>font, color, background<dd>other common parameters that are passed along to style
27 <dt>cls<dd>class name as used by Theme
28 <dt>name<dd>name of widget as used by Form. If set, will call <tt>form.add(self,name)</tt> to add the widget to the most recently created Form.
29 <dt>focusable<dd>True if this widget can receive focus via Tab, etc. Defaults to True.
30 <dt>disabled<dd>True of this widget is disabled. Defaults to False.
31 <dt>value<dd>initial value
34 <strong>Example - Creating your own Widget</strong>
35 <p>This example shows which methods are template methods.</p>
37 class Draw(gui.Widget):
39 #paint the pygame.Surface
43 #update the pygame.Surface and return the update rects
44 return [pygame.Rect(0,0,self.rect.w,self.rect.h)]
47 #handle the pygame.Event
50 def resize(self,width=None,height=None):
51 #return the width and height of this widget
56 # The name of the widget (or None if not defined)
59 def __init__(self
,**params
):
60 #object.Object.__init__(self)
62 params
.setdefault('decorate',True)
63 params
.setdefault('style',{})
64 params
.setdefault('focusable',True)
65 params
.setdefault('disabled',False)
67 self
.focusable
= params
['focusable']
68 self
.disabled
= params
['disabled']
70 self
.rect
= pygame
.Rect(params
.get('x',0),params
.get('y',0),params
.get('width',0),params
.get('height',0))
73 #some of this is a bit "theme-ish" but it is very handy, so these
74 #things don't have to be put directly into the style.
75 for att
in ('align','valign','x','y','width','height','color','font','background'):
76 if att
in params
: s
[att
] = params
[att
]
77 self
.style
= style
.Style(self
,s
)
80 if 'cls' in params
: self
.cls
= params
['cls']
83 self
.name
= params
['name']
84 if hasattr(form
.Form
,'form') and form
.Form
.form
!= None:
85 form
.Form
.form
.add(self
)
86 self
.form
= form
.Form
.form
87 if 'value' in params
: self
.value
= params
['value']
90 if params
['decorate'] != False:
91 if (not pguglobals
.app
):
92 # TODO - fix this somehow
94 print 'gui.widget: creating an App'
96 pguglobals
.app
.theme
.decorate(self
,params
['decorate'])
101 <pre>Widget.focus()</pre>
103 if getattr(self
,'container',None) != None:
104 if self
.container
.myfocus
!= self
: ## by Gal Koren
105 self
.container
.focus(self
)
110 <pre>Widget.blur()</pre>
112 if getattr(self
,'container',None) != None: self
.container
.blur(self
)
115 """Open this Widget as a modal dialog.
117 <pre>Widget.open()</pre>
119 #if getattr(self,'container',None) != None: self.container.open(self)
120 pguglobals
.app
.open(self
)
122 def close(self
, w
=None):
123 """Close this Widget (if it is a modal dialog.)
125 <pre>Widget.close()</pre>
127 #if getattr(self,'container',None) != None: self.container.close(self)
130 pguglobals
.app
.close(w
)
132 def resize(self
,width
=None,height
=None):
133 """Template method - return the size and width of this widget.
135 <p>Responsible for also resizing all sub-widgets.</p>
137 <pre>Widget.resize(width,height): return width,height</pre>
140 <dt>width<dd>suggested width
141 <dt>height<dd>suggested height
144 <p>If not overridden, will return self.style.width, self.style.height</p>
146 return self
.style
.width
, self
.style
.height
149 """Change the size of this widget.
151 <p>Calling this method will cause a resize on all the widgets,
152 including this one.</p>
154 <pre>Widget.chsize()</pre>
157 if not hasattr(self
,'_painted'): return
159 if not hasattr(self
,'container'): return
162 if pguglobals
.app
._chsize
:
164 pguglobals
.app
.chsize()
167 #if hasattr(app.App,'app'):
168 # w,h = self.rect.w,self.rect.h
169 # w2,h2 = self.resize()
170 # if w2 != w or h2 != h:
171 # app.App.app.chsize()
177 """Template method - update the surface
179 <pre>Widget.update(s): return list of pygame.Rect(s)</pre>
182 <dt>s<dd>pygame.Surface to update
185 <p>return - a list of the updated areas as pygame.Rect(s).</p>
190 """Template method - paint the surface
192 <pre>Widget.paint(s)</pre>
195 <dt>s<dd>pygame.Surface to paint
201 """Request a repaint of this Widget.
203 <pre>Widget.repaint()</pre>
205 if getattr(self
,'container',None) != None: self
.container
.repaint(self
)
206 def repaintall(self
):
207 """Request a repaint of all Widgets.
209 <pre>Widget.repaintall()</pre>
211 if getattr(self
,'container',None) != None: self
.container
.repaintall()
213 """Request a reupdate of this Widget
215 <pre>Widget.reupdate()</pre>
217 if getattr(self
,'container',None) != None: self
.container
.reupdate(self
)
219 """Pass focus to next Widget.
221 <p>Widget order determined by the order they were added to their container.</p>
223 <pre>Widget.next()</pre>
225 if getattr(self
,'container',None) != None: self
.container
.next(self
)
227 """Pass focus to previous Widget.
229 <p>Widget order determined by the order they were added to their container.</p>
231 <pre>Widget.previous()</pre>
234 if getattr(self
,'container',None) != None: self
.container
.previous(self
)
236 def get_abs_rect(self
):
237 """Get the absolute rect of this widget on the App screen
239 <pre>Widget.get_abs_rect(): return pygame.Rect</pre>
241 x
, y
= self
.rect
.x
, self
.rect
.y
242 x
+= self
._rect
_content
.x
243 y
+= self
._rect
_content
.y
244 c
= getattr(self
,'container',None)
248 if hasattr(c
,'_rect_content'):
249 x
+= c
._rect
_content
.x
250 y
+= c
._rect
_content
.y
251 c
= getattr(c
,'container',None)
252 return pygame
.Rect(x
, y
, self
.rect
.w
, self
.rect
.h
)
254 def connect(self
,code
,func
,*params
):
255 """Connect a event code to a callback function.
257 <p>There may be multiple callbacks per event code.</p>
259 <pre>Object.connect(code,fnc,value)</pre>
262 <dt>code<dd>event type [[gui-const]]
263 <dt>fnc<dd>callback function
264 <dt>*values<dd>values to pass to callback. Please note that callbacks may also have "magicaly" parameters. Such as:
266 <dt>_event<dd>receive the event
267 <dt>_code<dd>receive the event code
268 <dt>_widget<dd>receive the sending widget
272 <strong>Example</strong>
278 w.connect(gui.CLICK,onclick,'PGU Button Clicked')
281 if (not code
in self
.connects
):
282 self
.connects
[code
] = []
283 for cb
in self
.connects
[code
]:
284 if (cb
.func
== func
):
285 # Already connected to this callback function
287 # Wrap the callback function and add it to the list
288 cb
= SignalCallback()
291 self
.connects
[code
].append(cb
)
293 # Remove signal handlers from the given event code. If func is specified,
294 # only those handlers will be removed. If func is None, all handlers
296 def disconnect(self
, code
, func
=None):
297 if (not code
in self
.connects
):
300 # Remove all signal handlers
301 del self
.connects
[code
]
303 # Remove handlers that call 'func'
305 callbacks
= self
.connects
[code
]
306 while (n
< len(callbacks
)):
307 if (callbacks
[n
].func
== func
):
308 # Remove this callback
313 def send(self
,code
,event
=None):
314 """Send a code, event callback trigger.
316 <pre>Object.send(code,event=None)</pre>
319 <dt>code<dd>event code
323 if (not code
in self
.connects
):
325 # Trigger all connected signal handlers
326 for cb
in self
.connects
[code
]:
328 values
= list(cb
.params
)
330 nargs
= func
.func_code
.co_argcount
331 names
= list(func
.func_code
.co_varnames
)[:nargs
]
332 if hasattr(func
,'im_class'): names
.pop(0)
335 magic
= {'_event':event
,'_code':code
,'_widget':self
}
337 if name
in magic
.keys():
338 args
.append(magic
[name
])
340 args
.append(values
.pop(0))
347 if self
.disabled
: return
352 # if hasattr(app.App,'app'):
353 # app.App.app.events.append((self,e))
356 """Template method - called when an event is passed to this object.
358 <p>Please note that if you use an event, returning the value True
359 will stop parent containers from also using the event. (For example, if
360 your widget handles TABs or arrow keys, and you don't want those to
361 also alter the focus.)</p>
370 # Returns the top-level widget (usually the Desktop) by following the
371 # chain of 'container' references.
372 def get_toplevel(self
):
374 while (getattr(top
, "container", None)):