From: Marius Gedminas <marius@gedmin.as>
| ... | ... |
@@ -27,6 +27,7 @@ import sys |
| 27 | 27 |
import subprocess |
| 28 | 28 |
import math |
| 29 | 29 |
import colorsys |
| 30 |
+import time |
|
| 30 | 31 |
|
| 31 | 32 |
import gobject |
| 32 | 33 |
import gtk |
| ... | ... |
@@ -598,6 +599,70 @@ class XDotParser: |
| 598 | 599 |
return x, y |
| 599 | 600 |
|
| 600 | 601 |
|
| 602 |
+class Animation(object): |
|
| 603 |
+ |
|
| 604 |
+ step = 0.03 # seconds |
|
| 605 |
+ |
|
| 606 |
+ def __init__(self, dot_widget): |
|
| 607 |
+ self.dot_widget = dot_widget |
|
| 608 |
+ self.timeout_id = None |
|
| 609 |
+ |
|
| 610 |
+ def start(self): |
|
| 611 |
+ self.timeout_id = gobject.timeout_add(int(self.step * 1000), self.tick) |
|
| 612 |
+ |
|
| 613 |
+ def stop(self): |
|
| 614 |
+ self.dot_widget.animation = NoAnimation(self.dot_widget) |
|
| 615 |
+ if self.timeout_id is not None: |
|
| 616 |
+ gobject.source_remove(self.timeout_id) |
|
| 617 |
+ self.timeout_id = None |
|
| 618 |
+ |
|
| 619 |
+ def tick(self): |
|
| 620 |
+ self.stop() |
|
| 621 |
+ |
|
| 622 |
+ |
|
| 623 |
+class NoAnimation(Animation): |
|
| 624 |
+ |
|
| 625 |
+ def start(self): |
|
| 626 |
+ pass |
|
| 627 |
+ |
|
| 628 |
+ def stop(self): |
|
| 629 |
+ pass |
|
| 630 |
+ |
|
| 631 |
+ |
|
| 632 |
+class LinearAnimation(Animation): |
|
| 633 |
+ |
|
| 634 |
+ duration = 0.6 |
|
| 635 |
+ |
|
| 636 |
+ def start(self): |
|
| 637 |
+ self.started = time.time() |
|
| 638 |
+ Animation.start(self) |
|
| 639 |
+ |
|
| 640 |
+ def tick(self): |
|
| 641 |
+ t = (time.time() - self.started) / self.duration |
|
| 642 |
+ self.animate(max(0, min(t, 1))) |
|
| 643 |
+ return (t < 1) |
|
| 644 |
+ |
|
| 645 |
+ def animate(self, t): |
|
| 646 |
+ pass |
|
| 647 |
+ |
|
| 648 |
+ |
|
| 649 |
+class MoveToAnimation(LinearAnimation): |
|
| 650 |
+ |
|
| 651 |
+ def __init__(self, dot_widget, target_x, target_y): |
|
| 652 |
+ Animation.__init__(self, dot_widget) |
|
| 653 |
+ self.source_x = dot_widget.x |
|
| 654 |
+ self.source_y = dot_widget.y |
|
| 655 |
+ self.target_x = target_x |
|
| 656 |
+ self.target_y = target_y |
|
| 657 |
+ |
|
| 658 |
+ def animate(self, t): |
|
| 659 |
+ sx, sy = self.source_x, self.source_y |
|
| 660 |
+ tx, ty = self.target_x, self.target_y |
|
| 661 |
+ self.dot_widget.x = tx * t + sx * (1-t) |
|
| 662 |
+ self.dot_widget.y = ty * t + sy * (1-t) |
|
| 663 |
+ self.dot_widget.queue_draw() |
|
| 664 |
+ |
|
| 665 |
+ |
|
| 601 | 666 |
class DotWidget(gtk.DrawingArea): |
| 602 | 667 |
"""PyGTK widget that draws dot graphs.""" |
| 603 | 668 |
|
| ... | ... |
@@ -742,12 +807,9 @@ class DotWidget(gtk.DrawingArea): |
| 742 | 807 |
return True |
| 743 | 808 |
|
| 744 | 809 |
jump = self.get_jump(x, y) |
| 745 |
- x, y = self.window2graph(x, y) |
|
| 746 | 810 |
if jump is not None: |
| 747 | 811 |
jumpx, jumpy = jump |
| 748 |
- self.x += jumpx - x |
|
| 749 |
- self.y += jumpy - y |
|
| 750 |
- self.queue_draw() |
|
| 812 |
+ self.animate_to(jumpx, jumpy) |
|
| 751 | 813 |
return False |
| 752 | 814 |
|
| 753 | 815 |
def on_area_button_release(self, area, event): |
| ... | ... |
@@ -787,6 +849,10 @@ class DotWidget(gtk.DrawingArea): |
| 787 | 849 |
|
| 788 | 850 |
return True |
| 789 | 851 |
|
| 852 |
+ def animate_to(self, x, y): |
|
| 853 |
+ self.animation = MoveToAnimation(self, x, y) |
|
| 854 |
+ self.animation.start() |
|
| 855 |
+ |
|
| 790 | 856 |
def window2graph(self, x, y): |
| 791 | 857 |
rect = self.get_allocation() |
| 792 | 858 |
x -= 0.5*rect.width |