Mercurial > MadButterfly
comparison pyink/frameline.py @ 944:b0edd13779ee
Implement a frameline widget
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Tue, 16 Nov 2010 12:12:21 +0800 |
parents | |
children | 8db3dd03508f |
comparison
equal
deleted
inserted
replaced
943:82321f404b5f | 944:b0edd13779ee |
---|---|
1 import pygtk | |
2 pygtk.require("2.0") | |
3 import gtk | |
4 import gtk.gdk | |
5 import gobject | |
6 | |
7 def color_to_rgb(v): | |
8 return (((v >> 16) & 0xff) * 65535 / 0xff, | |
9 ((v >> 8) & 0xff) * 65535 / 0xff, | |
10 (v & 0xff) * 65535 / 0xff) | |
11 | |
12 class keyframe(object): | |
13 def __init__(self, frame_idx): | |
14 self.idx = frame_idx | |
15 self.left_tween = False | |
16 self.right_tween = False | |
17 self.right_tween_type = 0 | |
18 pass | |
19 pass | |
20 | |
21 ## Show frame status of a layer | |
22 # | |
23 class frameline(gtk.DrawingArea): | |
24 _type_id = 0 | |
25 _frame_width = 10 # Width for each frame is 10 pixels | |
26 _select_color = 0xee2222 # color of border of selected frame | |
27 _key_mark_color = 0x000000 # color of marks for key frames. | |
28 _key_mark_sz = 4 # width and height of a key frame mark | |
29 _tween_color = 0x000000 # color of tween line | |
30 _tween_bgcolors = [0x80ff80, 0xff8080] # bg colors of tween frames | |
31 # Colors for normal frames | |
32 _normal_bgcolors = [0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xcccccc] | |
33 _normal_border = 0xaaaaaa # border color of normal frames. | |
34 _active_border = 0xff3030 # border color of an active frame | |
35 | |
36 def __new__(clz, *args): | |
37 if not frameline._type_id: | |
38 frameline._type_id = gobject.type_register(frameline) | |
39 pass | |
40 fl_obj = gobject.new(frameline._type_id) | |
41 return fl_obj | |
42 | |
43 def __init__(self, num_frames=20): | |
44 self.connect('expose_event', self._fl_expose) | |
45 self._num_frames = num_frames | |
46 self._keys = [] | |
47 self._active_frame = -1 | |
48 pass | |
49 | |
50 def _fl_expose(self, widget, event): | |
51 print 'Expose %s' % (repr(event)) | |
52 win = self.window | |
53 x, y, w, h, depth = win.get_geometry() | |
54 print ' Geometry of window: %dx%d+%d+%d' % (w, h, x, y) | |
55 self.update() | |
56 pass | |
57 | |
58 def _draw_tween(self, first_key, last_key): | |
59 win = self.window | |
60 w_x, w_y, w_w, w_h, depth = win.get_geometry() | |
61 | |
62 # | |
63 # Get background color of a tween | |
64 # | |
65 bg_idx = first_key.right_tween_type | |
66 bg_color_v = self._tween_bgcolors[bg_idx] | |
67 bg_color_rgb = color_to_rgb(bg_color_v) | |
68 bg_color = gtk.gdk.Color(*bg_color_rgb) | |
69 | |
70 gc = self._gc | |
71 gc.set_rgb_fg_color(bg_color) | |
72 | |
73 draw_x = first_key.idx * self._frame_width + 1 | |
74 draw_w = (last_key.idx - first_key.idx + 1) * self._frame_width - 1 | |
75 | |
76 win.draw_rectangle(gc, True, draw_x, 0, draw_w, w_h) | |
77 pass | |
78 | |
79 def _draw_frame(self, idx): | |
80 win = self.window | |
81 w_x, w_y, w_w, w_h, depth = win.get_geometry() | |
82 | |
83 gc = self._gc | |
84 bg_idx = idx % len(self._normal_bgcolors) | |
85 rgb = color_to_rgb(self._normal_bgcolors[bg_idx]) | |
86 color = gtk.gdk.Color(*rgb) | |
87 gc.set_rgb_fg_color(color) | |
88 | |
89 f_x = self._frame_width * idx | |
90 win.draw_rectangle(gc, True, f_x + 1, 0, self._frame_width, w_h) | |
91 next_f_x = f_x + self._frame_width | |
92 | |
93 border_rgb = color_to_rgb(self._normal_border) | |
94 border_color = gtk.gdk.Color(*border_rgb) | |
95 gc.set_rgb_fg_color(border_color) | |
96 gc.set_line_attributes(1, gtk.gdk.LINE_SOLID, | |
97 gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER) | |
98 win.draw_line(gc, next_f_x, 0, next_f_x, w_h) | |
99 pass | |
100 | |
101 def _draw_frames(self): | |
102 win = self.window | |
103 gc = gtk.gdk.GC(win) | |
104 self._gc = gc | |
105 | |
106 i = 0 | |
107 key_i = 0 | |
108 try: | |
109 key = self._keys[key_i] | |
110 except IndexError: | |
111 key = keyframe(self._num_frames) | |
112 pass | |
113 num_frames = self._num_frames | |
114 while i < num_frames: | |
115 if key.idx == i: | |
116 # | |
117 # Skip tween keys | |
118 # | |
119 first_tween_key = key | |
120 while key.idx == i or key.left_tween: | |
121 last_tween_key = key | |
122 key_i = key_i + 1 | |
123 try: | |
124 key = self._keys[key_i] | |
125 except IndexError: | |
126 key = keyframe(self._num_frames) | |
127 pass | |
128 pass | |
129 | |
130 if first_tween_key != last_tween_key: | |
131 self._draw_tween(first_tween_key, last_tween_key) | |
132 | |
133 i = last_tween_key.idx + 1 | |
134 pass | |
135 else: | |
136 self._draw_frame(i) | |
137 i = i + 1 | |
138 pass | |
139 pass | |
140 pass | |
141 | |
142 def _draw_keyframes(self): | |
143 win = self.window | |
144 w_x, w_y, w_w, w_h, depth = win.get_geometry() | |
145 | |
146 color_v = self._key_mark_color | |
147 color_rgb = color_to_rgb(color_v) | |
148 color = gtk.gdk.Color(*color_rgb) | |
149 | |
150 gc = self._gc | |
151 gc.set_rgb_fg_color(color) | |
152 | |
153 for key in self._keys: | |
154 mark_sz = self._key_mark_sz | |
155 mark_x = int((key.idx + 0.5) * self._frame_width - mark_sz / 2) | |
156 mark_y = w_h * 2 / 3 - mark_sz / 2 | |
157 | |
158 win.draw_rectangle(gc, True, mark_x, mark_y, mark_sz, mark_sz) | |
159 pass | |
160 pass | |
161 | |
162 def _draw_active(self): | |
163 win = self.window | |
164 w_x, w_y, w_w, w_h, depth = win.get_geometry() | |
165 | |
166 color_v = self._active_border | |
167 color_rgb = color_to_rgb(color_v) | |
168 color = gtk.gdk.Color(*color_rgb) | |
169 | |
170 gc = self._gc | |
171 gc.set_rgb_fg_color(color) | |
172 | |
173 idx = self._active_frame | |
174 line_x1 = idx * self._frame_width | |
175 line_x2 = line_x1 + self._frame_width | |
176 | |
177 win.draw_line(gc, line_x1, 0, line_x1, w_h) | |
178 win.draw_line(gc, line_x2, 0, line_x2, w_h) | |
179 pass | |
180 | |
181 def update(self): | |
182 win = self.window | |
183 x, y, w, h, depth = win.get_geometry() | |
184 | |
185 self._draw_frames() | |
186 self._draw_keyframes() | |
187 if self._active_frame != -1: | |
188 self._draw_active() | |
189 pass | |
190 pass | |
191 | |
192 def add_keyframe(self, idx): | |
193 key_indic = [key.idx for key in self._keys] | |
194 if idx in key_indic: | |
195 return | |
196 | |
197 key_indic.append(idx) | |
198 key_indic.sort() | |
199 insert_pos = key_indic.index(idx) | |
200 | |
201 key = keyframe(idx) | |
202 self._keys[insert_pos:insert_pos] = [key] | |
203 if insert_pos > 0 and self._keys[insert_pos - 1].right_tween: | |
204 key.left_tween = True | |
205 pass | |
206 if insert_pos < (len(self._keys) - 1) and \ | |
207 self._keys[insert_pos + 1].left_tween: | |
208 key.right_tween = True | |
209 pass | |
210 pass | |
211 | |
212 ## Tween the key frame specified by an index and the frame at right. | |
213 # | |
214 # \see http://www.entheosweb.com/Flash/shape_tween.asp | |
215 def tween(self, idx, _type=0): | |
216 key_indic = [key.idx for key in self._keys] | |
217 pos = key_indic.index(idx) | |
218 key = self._keys[pos] | |
219 | |
220 try: | |
221 right_key = self._keys[pos + 1] | |
222 except IndexError: | |
223 raise ValueError, 'No right key frame' | |
224 | |
225 key.right_tween = True | |
226 right_key.left_tween = True | |
227 key.right_tween_type = _type | |
228 pass | |
229 | |
230 ## Set active frame | |
231 # | |
232 # The active frame is the frame that is working on. | |
233 # | |
234 def active_frame(self, idx): | |
235 if idx < 0 or idx >= self._num_frames: | |
236 raise IndexError, 'value of index (%d) is out of range' % (idx) | |
237 | |
238 self._active_frame = idx | |
239 pass | |
240 | |
241 def deactive(self): | |
242 self._active_frame = -1 | |
243 pass | |
244 | |
245 def set_num_frames(self, num): | |
246 self._num_frames = num | |
247 pass | |
248 | |
249 def __len__(self): | |
250 return self._num_frames | |
251 pass | |
252 | |
253 if __name__ == '__main__': | |
254 window = gtk.Window(gtk.WINDOW_TOPLEVEL) | |
255 fl = frameline(40) | |
256 fl.set_size_request(300, 30) | |
257 fl.add_keyframe(3) | |
258 fl.add_keyframe(9) | |
259 fl.add_keyframe(15) | |
260 fl.add_keyframe(20) | |
261 fl.tween(3) | |
262 fl.tween(15, 1) | |
263 fl.active_frame(15) | |
264 print 'num of frames: %d' % (len(fl)) | |
265 | |
266 window.add(fl) | |
267 fl.show() | |
268 window.show() | |
269 gtk.main() | |
270 pass |