Mercurial > fife-parpg
comparison engine/python/fife/extensions/pychan/tools.py @ 378:64738befdf3b
bringing in the changes from the build_system_rework branch in preparation for the 0.3.0 release. This commit will require the Jan2010 devkit. Clients will also need to be modified to the new way to import fife.
author | vtchill@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Mon, 11 Jan 2010 23:34:52 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
377:fe6fb0e0ed23 | 378:64738befdf3b |
---|---|
1 # -*- coding: utf-8 -*- | |
2 | |
3 # #################################################################### | |
4 # Copyright (C) 2005-2009 by the FIFE team | |
5 # http://www.fifengine.de | |
6 # This file is part of FIFE. | |
7 # | |
8 # FIFE is free software; you can redistribute it and/or | |
9 # modify it under the terms of the GNU Lesser General Public | |
10 # License as published by the Free Software Foundation; either | |
11 # version 2.1 of the License, or (at your option) any later version. | |
12 # | |
13 # This library is distributed in the hope that it will be useful, | |
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 # Lesser General Public License for more details. | |
17 # | |
18 # You should have received a copy of the GNU Lesser General Public | |
19 # License along with this library; if not, write to the | |
20 # Free Software Foundation, Inc., | |
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 # #################################################################### | |
23 | |
24 """ | |
25 Functional utilities designed for pychan use cases. | |
26 """ | |
27 | |
28 import exceptions | |
29 | |
30 ### Functools ### | |
31 | |
32 def applyOnlySuitable(func,*args,**kwargs): | |
33 """ | |
34 This nifty little function takes another function and applies it to a dictionary of | |
35 keyword arguments. If the supplied function does not expect one or more of the | |
36 keyword arguments, these are silently discarded. The result of the application is returned. | |
37 This is useful to pass information to callbacks without enforcing a particular signature. | |
38 """ | |
39 if hasattr(func,'im_func'): | |
40 code = func.im_func.func_code | |
41 varnames = code.co_varnames[1:code.co_argcount]#ditch bound instance | |
42 elif hasattr(func,'func_code'): | |
43 code = func.func_code | |
44 varnames = code.co_varnames[0:code.co_argcount] | |
45 elif hasattr(func,'__call__'): | |
46 func = func.__call__ | |
47 if hasattr(func,'im_func'): | |
48 code = func.im_func.func_code | |
49 varnames = code.co_varnames[1:code.co_argcount]#ditch bound instance | |
50 elif hasattr(func,'func_code'): | |
51 code = func.func_code | |
52 varnames = code.co_varnames[0:code.co_argcount] | |
53 | |
54 #http://docs.python.org/lib/inspect-types.html | |
55 if code.co_flags & 8: | |
56 return func(*args,**kwargs) | |
57 for name,value in kwargs.items(): | |
58 if name not in varnames: | |
59 del kwargs[name] | |
60 return func(*args,**kwargs) | |
61 | |
62 def callbackWithArguments(callback,*args,**kwargs): | |
63 """ | |
64 Curries a function with extra arguments to | |
65 create a suitable callback. | |
66 | |
67 If you don't know what this means, don't worry. | |
68 It is designed for the case where you need | |
69 different buttons to execute basically the same code | |
70 with different argumnets. | |
71 | |
72 Usage:: | |
73 # The target callback | |
74 def printStuff(text): | |
75 print text | |
76 # Mapping the events | |
77 gui.mapEvents({ | |
78 'buttonHello' : callbackWithArguments(printStuff,"Hello"), | |
79 'buttonBye' : callbackWithArguments(printStuff,"Adieu") | |
80 }) | |
81 """ | |
82 def real_callback(): | |
83 callback(*args,**kwargs) | |
84 return real_callback | |
85 | |
86 def attrSetCallback(**kwargs): | |
87 """ | |
88 Generates an event callback that sets attributes on the widget | |
89 it is called on. This is especially useful for mouseEntered/Exited | |
90 events - to create hover effects. | |
91 | |
92 It takes a set of keyword arguments. The keys are treated as attribute names, | |
93 which are then set to the corresponding value when the callback is called. | |
94 Some key names are treated special - see below. | |
95 | |
96 Usage - Example adapted from demo application:: | |
97 eventMap = { | |
98 'creditsLink' : showCreditsCallback, | |
99 'creditsLink/mouseEntered' : attrSetCallback( | |
100 text = "Show credits!", | |
101 background_color = (255,255,0,255), | |
102 do__adaptLayout=True), | |
103 'creditsLink/mouseExited' : attrSetCallback(text = "Credits"), | |
104 gui.mapEvents(eventMap) | |
105 | |
106 Now when the mouse enters the creditsLink (a Label in our case), the following code will be executed:: | |
107 #widget is the creditsLink - given to the event callback. | |
108 widget.text = "Show credits!" | |
109 widget.background_color = (255,255,0,255) | |
110 widget.adaptLayout() | |
111 | |
112 The C{do__adaptLayout} argument causes the method C{adaptLayout} to be called. | |
113 In fact any key starting with C{do__} results in such a method call. The order | |
114 of execution of such calls is undefined. | |
115 | |
116 Keys starting with an underscore raise a L{execptions.PrivateFunctionalityError}. | |
117 """ | |
118 do_calls = [] | |
119 | |
120 for name in kwargs.keys(): | |
121 if name.startswith("_"): | |
122 raise exceptions.PrivateFunctionalityError(name) | |
123 if name.startswith("do__"): | |
124 do_calls.append(name[4:]) | |
125 del kwargs[name] | |
126 | |
127 def attrSet_callback(widget=None): | |
128 for name,value in kwargs.items(): | |
129 setattr(widget,name,value) | |
130 for method_name in do_calls: | |
131 method = getattr(widget,method_name) | |
132 method() | |
133 return attrSet_callback | |
134 | |
135 def chainCallbacks(*args): | |
136 """ | |
137 Chains callbacks to be called one after the other. | |
138 | |
139 Example Usage:: | |
140 def print_event(event=0): | |
141 print event | |
142 def print_widget(widget=0): | |
143 print widget | |
144 callback = tools.chainCallbacks(doSomethingUseful, print_event, print_widget) | |
145 guiElement.capture(callback) | |
146 """ | |
147 callbacks = args | |
148 def chain_callback(event=0,widget=0): | |
149 for callback in callbacks: | |
150 applyOnlySuitable(callback, event=event, widget=widget) | |
151 return chain_callback | |
152 | |
153 def repeatALot(n = 1000): | |
154 """ | |
155 Internal decorator used to profile some pychan functions. | |
156 Only use with functions without side-effect. | |
157 | |
158 Usage:: | |
159 @repeatALot(n=10000) | |
160 def findChild(self,**kwargs): | |
161 ... | |
162 """ | |
163 def wrap_f(f): | |
164 def new_f(*args,**kwargs): | |
165 for i in xrange(n): | |
166 f(*args,**kwargs) | |
167 return f(*args,**kwargs) | |
168 return new_f | |
169 return wrap_f | |
170 | |
171 def this_is_deprecated(func,message=None): | |
172 if message is None: | |
173 message = repr(func) | |
174 def wrapped_func(*args,**kwargs): | |
175 print "PyChan: You are using the DEPRECATED functionality: %s" % message | |
176 return func(*args,**kwargs) | |
177 return wrapped_func |