Mercurial > MadButterfly
comparison pyink/frameline.py @ 1153:5abf419d66e5
Refactory methods of state awared drawing to frameline_draw_state
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Mon, 27 Dec 2010 15:37:03 +0800 |
parents | d333baa702a9 |
children | 1c9ef65c74b2 |
comparison
equal
deleted
inserted
replaced
1152:d333baa702a9 | 1153:5abf419d66e5 |
---|---|
269 win.draw_line(gc, line_x1, 1, line_x2, 1) | 269 win.draw_line(gc, line_x1, 1, line_x2, 1) |
270 win.draw_line(gc, line_x1, w_h - 2, line_x2, w_h - 2) | 270 win.draw_line(gc, line_x1, w_h - 2, line_x2, w_h - 2) |
271 pass | 271 pass |
272 pass | 272 pass |
273 | 273 |
274 ## Show frame status of a layer | 274 |
275 # | 275 ## \brief Drawing frameline according state of a frameline. |
276 # \section frameline_sigs Signals | 276 # |
277 # - 'frame-button-pree' for user press on a frame. | 277 # Thsi class calls methods of class frameline_draw to drawing frameline. But, |
278 # - callback(widget, frame_idx, button) | 278 # this class is state awared. It according states of an instance to determines |
279 # | 279 # calling methods and arguments. This class decorates methods of |
280 # All methos that change state of the frameline, must call methods to update | 280 # frameline_draw class according states of an instance. |
281 # the screen. | 281 # |
282 # | 282 # This classs reading state of a frameline, but it does not change and control |
283 class frameline(frameline_draw): | 283 # states. The deriving classes are responsible to change and control states. |
284 _sig_frame_but_press = None | 284 # |
285 | 285 class frameline_draw_state(frameline_draw): |
286 # tween types | 286 # tween types |
287 TWEEN_TYPE_NONE = 0 | 287 TWEEN_TYPE_NONE = 0 |
288 TWEEN_TYPE_MOVE = 1 | 288 TWEEN_TYPE_MOVE = 1 |
289 TWEEN_TYPE_SHAPE = 2 | 289 TWEEN_TYPE_SHAPE = 2 |
290 | 290 |
291 FRAME_BUT_PRESS = 'frame-button-press' | 291 def __init__(self, num_frames): |
292 | 292 frameline_draw.__init__(self) |
293 def __new__(clz, *args): | 293 |
294 fl_obj = frameline_draw.__new__(clz, *args) | |
295 | |
296 if not clz._sig_frame_but_press: | |
297 but_press = gobject.signal_new(frameline.FRAME_BUT_PRESS, | |
298 frameline._type, | |
299 gobject.SIGNAL_RUN_FIRST, | |
300 gobject.TYPE_NONE, | |
301 (gobject.TYPE_INT, | |
302 gobject.TYPE_INT)) | |
303 clz._sig_frame_but_press = but_press | |
304 pass | |
305 return fl_obj | |
306 | |
307 def __init__(self, num_frames=20): | |
308 self.connect('button-press-event', self._press_hdl) | |
309 self.connect('expose-event', self._fl_expose) | |
310 self.connect('motion-notify-event', self._motion_hdl) | |
311 self._num_frames = num_frames | 294 self._num_frames = num_frames |
312 self._keys = [] | 295 self._keys = [] |
313 self._active_frame = -1 | 296 self._active_frame = -1 |
314 self._last_hover = -1 # frame index of last hover | |
315 self._drawing = False | 297 self._drawing = False |
316 pass | |
317 | |
318 def __len__(self): | |
319 return self._num_frames | |
320 | |
321 def _find_keyframe(self, idx): | |
322 key_indic = [key.idx for key in self._keys] | |
323 key_pos = key_indic.index(idx) | |
324 return key_pos | |
325 | |
326 def _find_keyframe_floor(self, frame_idx): | |
327 pos = 0 | |
328 keys = [key.idx for key in self._keys] | |
329 keys.append(frame_idx) | |
330 keys.sort() | |
331 keys.reverse() | |
332 pos = (len(keys) - 1) - keys.index(frame_idx) - 1 | |
333 return pos | |
334 | |
335 ## \brief Find the range a continous tween. | |
336 # | |
337 def _find_tween_range(self, key_pos): | |
338 key = self._keys[key_pos] | |
339 if not (key.left_tween or key.right_tween): | |
340 raise ValueError, 'the keyframe is not in a tween' | |
341 | |
342 # | |
343 # Initialize tween type and first_pos | |
344 # | |
345 if key.right_tween: | |
346 tween_type = key.right_tween_type | |
347 first_pos = key_pos | |
348 else: | |
349 # key.left_tween is True since the key is in a tween. | |
350 first_pos = key_pos -1 | |
351 key = self._keys[first_pos] | |
352 tween_type = key.right_tween_type | |
353 pass | |
354 | |
355 # | |
356 # Find first_pos | |
357 # | |
358 while first_pos and key.left_tween: | |
359 right_pos = first_pos - 1 | |
360 right_key = self._keys[right_pos] | |
361 if right_key.right_tween_type != tween_type: | |
362 break | |
363 first_pos = right_pos | |
364 key = right_key | |
365 pass | |
366 | |
367 # | |
368 # Find last_pos | |
369 # | |
370 max_pos = len(self._keys) - 1 | |
371 last_pos = key_pos | |
372 key = self._keys[last_pos] | |
373 while last_pos < max_pos and self._keys[last_pos].right_tween: | |
374 if key.right_tween_type != tween_type: | |
375 break | |
376 last_pos = last_pos + 1 | |
377 key = self._keys[last_pos] | |
378 pass | |
379 | |
380 return first_pos, last_pos | |
381 | |
382 def _press_hdl(self, widget, event): | |
383 frame = event.x / self._frame_width | |
384 but = event.button | |
385 self.emit(frameline.FRAME_BUT_PRESS, frame, but) | |
386 pass | |
387 | |
388 def hide_hover(self): | |
389 if self._active_frame != self._last_hover: | |
390 self._draw_normal_frame(self._last_hover) | |
391 pass | |
392 pass | 298 pass |
393 | |
394 def _motion_hdl(self, widget, event): | |
395 frame_idx = int(event.x / self._frame_width) | |
396 if self._last_hover != -1: | |
397 self._draw_frame(self._last_hover) | |
398 if self._last_hover == self._active_frame: | |
399 self._draw_active_frame() | |
400 pass | |
401 pass | |
402 | |
403 if frame_idx < self._num_frames and frame_idx >= 0: | |
404 self._draw_hover_frame(frame_idx) | |
405 if self._last_hover == self._active_frame: | |
406 self._draw_active_frame() | |
407 pass | |
408 self._last_hover = frame_idx | |
409 else: | |
410 self._last_hover = -1 | |
411 pass | |
412 pass | |
413 | |
414 def _fl_expose(self, widget, event): | |
415 win = self.window | |
416 x, y, w, h, depth = win.get_geometry() | |
417 if not hasattr(self, '_gc'): | |
418 self._gc = gtk.gdk.GC(win) | |
419 # | |
420 # register for button press event | |
421 # | |
422 emask = win.get_events() | |
423 emask = emask | gtk.gdk.BUTTON_PRESS_MASK | \ | |
424 gtk.gdk.POINTER_MOTION_MASK | |
425 win.set_events(emask) | |
426 self._drawing = True | |
427 pass | |
428 self.update() | |
429 pass | |
430 | 299 |
431 def _draw_keyframe(self, frame_idx): | 300 def _draw_keyframe(self, frame_idx): |
432 # Only keyframes that is not right-side of NONE type tween should be | 301 # Only keyframes that is not right-side of NONE type tween should be |
433 # draw. | 302 # draw. |
434 pos = self._find_keyframe(frame_idx) | 303 pos = self._find_keyframe(frame_idx) |
555 def _draw_hover_frame(self, frame_idx): | 424 def _draw_hover_frame(self, frame_idx): |
556 if not self._drawing: | 425 if not self._drawing: |
557 return | 426 return |
558 self._draw_hover(frame_idx) | 427 self._draw_hover(frame_idx) |
559 pass | 428 pass |
429 | |
430 ## \brief Start future drawing actions | |
431 # | |
432 def start_drawing(self): | |
433 if not hasattr(self, '_gc'): | |
434 win = self.window | |
435 self._gc = gtk.gdk.GC(win) | |
436 # | |
437 # register for button press event | |
438 # | |
439 emask = win.get_events() | |
440 emask = emask | gtk.gdk.BUTTON_PRESS_MASK | \ | |
441 gtk.gdk.POINTER_MOTION_MASK | |
442 win.set_events(emask) | |
443 pass | |
444 self._drawing = True | |
445 pass | |
446 | |
447 ## \brief Stop any future drawing actions | |
448 # | |
449 # When doing massive udpate, to stop drawing the screen make | |
450 # application more effecient. The screen is updated by calling | |
451 # update() method after massive update and calliing start_drawing(). | |
452 # | |
453 def stop_drawing(self): | |
454 self._drawing = False | |
455 pass | |
456 pass | |
457 | |
458 | |
459 ## Show frame status of a layer | |
460 # | |
461 # \section frameline_sigs Signals | |
462 # - 'frame-button-pree' for user press on a frame. | |
463 # - callback(widget, frame_idx, button) | |
464 # | |
465 # All methos that change state of the frameline, must call methods to update | |
466 # the screen. | |
467 # | |
468 class frameline(frameline_draw_state): | |
469 _sig_frame_but_press = None | |
470 | |
471 FRAME_BUT_PRESS = 'frame-button-press' | |
472 | |
473 def __new__(clz, *args): | |
474 fl_obj = frameline_draw_state.__new__(clz, *args) | |
475 | |
476 if not clz._sig_frame_but_press: | |
477 but_press = gobject.signal_new(frameline.FRAME_BUT_PRESS, | |
478 frameline._type, | |
479 gobject.SIGNAL_RUN_FIRST, | |
480 gobject.TYPE_NONE, | |
481 (gobject.TYPE_INT, | |
482 gobject.TYPE_INT)) | |
483 clz._sig_frame_but_press = but_press | |
484 pass | |
485 return fl_obj | |
486 | |
487 def __init__(self, num_frames=20): | |
488 frameline_draw_state.__init__(self, num_frames) | |
489 | |
490 self.connect('button-press-event', self._press_hdl) | |
491 self.connect('expose-event', self._fl_expose) | |
492 self.connect('motion-notify-event', self._motion_hdl) | |
493 self._last_hover = -1 # frame index of last hover | |
494 pass | |
495 | |
496 def __len__(self): | |
497 return self._num_frames | |
498 | |
499 def _find_keyframe(self, idx): | |
500 key_indic = [key.idx for key in self._keys] | |
501 key_pos = key_indic.index(idx) | |
502 return key_pos | |
503 | |
504 def _find_keyframe_floor(self, frame_idx): | |
505 pos = 0 | |
506 keys = [key.idx for key in self._keys] | |
507 keys.append(frame_idx) | |
508 keys.sort() | |
509 keys.reverse() | |
510 pos = (len(keys) - 1) - keys.index(frame_idx) - 1 | |
511 return pos | |
512 | |
513 ## \brief Find the range a continous tween. | |
514 # | |
515 def _find_tween_range(self, key_pos): | |
516 key = self._keys[key_pos] | |
517 if not (key.left_tween or key.right_tween): | |
518 raise ValueError, 'the keyframe is not in a tween' | |
519 | |
520 # | |
521 # Initialize tween type and first_pos | |
522 # | |
523 if key.right_tween: | |
524 tween_type = key.right_tween_type | |
525 first_pos = key_pos | |
526 else: | |
527 # key.left_tween is True since the key is in a tween. | |
528 first_pos = key_pos -1 | |
529 key = self._keys[first_pos] | |
530 tween_type = key.right_tween_type | |
531 pass | |
532 | |
533 # | |
534 # Find first_pos | |
535 # | |
536 while first_pos and key.left_tween: | |
537 right_pos = first_pos - 1 | |
538 right_key = self._keys[right_pos] | |
539 if right_key.right_tween_type != tween_type: | |
540 break | |
541 first_pos = right_pos | |
542 key = right_key | |
543 pass | |
544 | |
545 # | |
546 # Find last_pos | |
547 # | |
548 max_pos = len(self._keys) - 1 | |
549 last_pos = key_pos | |
550 key = self._keys[last_pos] | |
551 while last_pos < max_pos and self._keys[last_pos].right_tween: | |
552 if key.right_tween_type != tween_type: | |
553 break | |
554 last_pos = last_pos + 1 | |
555 key = self._keys[last_pos] | |
556 pass | |
557 | |
558 return first_pos, last_pos | |
559 | |
560 def _press_hdl(self, widget, event): | |
561 frame = event.x / self._frame_width | |
562 but = event.button | |
563 self.emit(frameline.FRAME_BUT_PRESS, frame, but) | |
564 pass | |
565 | |
566 def hide_hover(self): | |
567 if self._active_frame != self._last_hover: | |
568 self._draw_normal_frame(self._last_hover) | |
569 pass | |
570 pass | |
571 | |
572 def _motion_hdl(self, widget, event): | |
573 frame_idx = int(event.x / self._frame_width) | |
574 if self._last_hover != -1: | |
575 self._draw_frame(self._last_hover) | |
576 if self._last_hover == self._active_frame: | |
577 self._draw_active_frame() | |
578 pass | |
579 pass | |
580 | |
581 if frame_idx < self._num_frames and frame_idx >= 0: | |
582 self._draw_hover_frame(frame_idx) | |
583 if self._last_hover == self._active_frame: | |
584 self._draw_active_frame() | |
585 pass | |
586 self._last_hover = frame_idx | |
587 else: | |
588 self._last_hover = -1 | |
589 pass | |
590 pass | |
591 | |
592 def _fl_expose(self, widget, event): | |
593 win = self.window | |
594 self.start_drawing() | |
595 self.update() | |
596 pass | |
560 | 597 |
561 def set_tween_type(self, frame_idx, tween_type): | 598 def set_tween_type(self, frame_idx, tween_type): |
562 pos = self._find_keyframe(frame_idx) | 599 pos = self._find_keyframe(frame_idx) |
563 key = self._keys[pos] | 600 key = self._keys[pos] |
564 assert key.right_tween | 601 assert key.right_tween |
568 | 605 |
569 self._draw_active_frame() | 606 self._draw_active_frame() |
570 pass | 607 pass |
571 | 608 |
572 def update(self): | 609 def update(self): |
573 if not self._drawing: | |
574 return | |
575 | |
576 win = self.window | |
577 x, y, w, h, depth = win.get_geometry() | |
578 self._draw_all_frames() | 610 self._draw_all_frames() |
579 self._draw_active_frame() | 611 self._draw_active_frame() |
580 pass | 612 pass |
581 | 613 |
582 ## Add a key frame | 614 ## Add a key frame |
641 pass | 673 pass |
642 | 674 |
643 ## Tween the key frame specified by an index and the key frame at right. | 675 ## Tween the key frame specified by an index and the key frame at right. |
644 # | 676 # |
645 # \see http://www.entheosweb.com/Flash/shape_tween.asp | 677 # \see http://www.entheosweb.com/Flash/shape_tween.asp |
646 def tween(self, idx, tween_type=TWEEN_TYPE_NONE): | 678 def tween(self, idx, tween_type=frameline_draw_state.TWEEN_TYPE_NONE): |
647 pos = self._find_keyframe(idx) | 679 pos = self._find_keyframe(idx) |
648 key = self._keys[pos] | 680 key = self._keys[pos] |
649 | 681 |
650 try: | 682 try: |
651 right_key = self._keys[pos + 1] | 683 right_key = self._keys[pos + 1] |
720 self._active_frame = -1 | 752 self._active_frame = -1 |
721 pass | 753 pass |
722 | 754 |
723 def set_num_frames(self, num): | 755 def set_num_frames(self, num): |
724 self._num_frames = num | 756 self._num_frames = num |
725 self._ | |
726 pass | 757 pass |
727 | 758 |
728 def reset(self): | 759 def reset(self): |
729 self._keys = [] | 760 self._keys = [] |
730 self._active_frame = -1 | 761 self._active_frame = -1 |
731 self._draw_all_frames() | 762 self._draw_all_frames() |
732 pass | |
733 | |
734 ## \brief Start future drawing actions | |
735 # | |
736 def start_drawing(self): | |
737 self._drawing = True | |
738 pass | |
739 | |
740 ## \brief Stop any future drawing actions | |
741 # | |
742 # When doing massive udpate, to stop drawing the screen make | |
743 # application more effecient. The screen is updated by calling | |
744 # update() method after massive update and calliing start_drawing(). | |
745 # | |
746 def stop_drawing(self): | |
747 self._drawing = False | |
748 pass | 763 pass |
749 pass | 764 pass |
750 | 765 |
751 if __name__ == '__main__': | 766 if __name__ == '__main__': |
752 window = gtk.Window(gtk.WINDOW_TOPLEVEL) | 767 window = gtk.Window(gtk.WINDOW_TOPLEVEL) |