Added animation for icon rotation.
authorStefanos Harhalakis <v13@v13.gr>
Mon, 2 Aug 2010 21:46:34 +0000 (21:46 +0000)
committerStefanos Harhalakis <v13@v13.gr>
Mon, 2 Aug 2010 21:46:34 +0000 (21:46 +0000)
src/icon.py
src/icongrid.py
src/icons.py

index aafe320..df559cc 100755 (executable)
@@ -82,6 +82,8 @@ class Icon(gobject.GObject):
 
        self.clickcount=0
 
+       self.angle=0
+
     def timePressed(self):
        """ return how much time a button is pressed """
        dt=time.time() - self.lastpress
@@ -100,7 +102,20 @@ class Icon(gobject.GObject):
     def getSize(self):
        return(self.config.iconsize+self.config.iconspace)
 
-    def draw(self, cr, x, y, mode):
+    def setAngle(self, angle):
+       if self.angle==angle:
+           print "Same angle"
+           return
+
+       self.angle=angle
+
+       # The caller should be responsible for redrawing.
+       # If we call invalidate() here there is the risk of having
+       # icons rotate individually using different angles
+#      self.invalidate()
+
+    def draw(self, cr, x, y):
+       self.draw_queued=False
        self.x=x
        self.y=y
 
@@ -108,6 +123,7 @@ class Icon(gobject.GObject):
            return
 
        cr.save()
+
        cr.set_source_rgba(0.1, 0.1, 0.1, 1)
        cr.set_line_width(5)
 
@@ -143,15 +159,54 @@ class Icon(gobject.GObject):
 
        icon=self.icon
 
-       if mode=='l':
-           icon2=icon
-       else:
-           icon2=icon.rotate_simple(gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE)
+       icon2=icon
+
+# Old method. Faster rotation but without support for rotation
+# animation
+
+#      if mode=='l':
+#          icon2=icon
+#      else:
+#          icon2=icon.rotate_simple(gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE)
+
+#      cr.save()
+#      x3=x + (self.config.iconspace/2)
+#      y3=y + (self.config.iconspace/2)
+#      cr.set_source_pixbuf(icon2, x3, y3)
+#
+#      cr.paint()
+#      cr.restore()
 
+
+       # Width is the iconsize plus the empty border around the icon
+       w=self.config.iconsize + self.config.iconspace
+
+       # This is used to locate the center of the surface
+       dx=int(w/2)
+
+       # This is the delta from the center where icons are drawn
+       dx2=int(self.config.iconsize/2)
+
+       # A surface to draw on
+       t_s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
+
+       # And a context to draw
+       t_cr0=cairo.Context(t_s)
+       t_cr=gtk.gdk.CairoContext(t_cr0)
+
+       # A transformation matrix with dx/dy set to point to the center
+       m=cairo.Matrix(1, 0, 0, 1, dx, dx)
+       t_cr.set_matrix(m)
+       # Transform degrees to rads
+       rot=-1 * pi * 2 * self.angle / 360
+       t_cr.rotate(rot)
+       # Draw the icon
+       t_cr.set_source_pixbuf(icon2, -dx2, -dx2)
+       t_cr.paint()
+
+       # Draw the rotated icon on the main cairo context
        cr.save()
-       x3=x + (self.config.iconspace/2)
-       y3=y + (self.config.iconspace/2)
-       cr.set_source_pixbuf(icon2, x3, y3)
+       cr.set_source_surface(t_s, x, y)
        cr.paint()
        cr.restore()
 
@@ -198,6 +253,9 @@ class Icon(gobject.GObject):
     def doCancel(self):
        self.ispressed=False
 
+    def setWindow(self, window):
+       self.window=window
+
     def invalidate(self, window=None):
        if window==None:
            window=self.window
@@ -207,6 +265,10 @@ class Icon(gobject.GObject):
        if window==None:
            return
 
+       if self.draw_queued:
+           print "queued"
+           return
+       self.draw_queued=True
        w=self.config.iconsize + self.config.iconspace
        rect=gdk.Rectangle(self.x, self.y, w, w)
        gdk.Window.invalidate_rect(window, rect, True)
index ffe098d..0278dde 100755 (executable)
@@ -51,6 +51,8 @@ class IconGrid(object):       #(gobject.GObject):
     def __init__(self, isconfig=False):
 #      self.__gobject_init__()
 
+       self.init_done=False
+
        self.size=(0,0)
 
        self.isconfig=isconfig
@@ -60,6 +62,8 @@ class IconGrid(object):       #(gobject.GObject):
 
        self.draw_pending=False
 
+       self.mode=None
+
     def do_realize(self, config):
        self.config=config
 
@@ -83,18 +87,60 @@ class IconGrid(object):     #(gobject.GObject):
        return(ret)
 
     def setMode(self, mode):
+       if self.mode==mode:
+           print "same mode"
+           return
+
        self.mode=mode
        if not isinstance(self, gtk.Widget):
            return
 
+       do_draw=False
+
        try:
            v=self.get_property('is-on-current-desktop')
            if v:
-               self.queue_draw()
+               do_draw=True
            else:
                self.draw_pending=True
        except TypeError:
-           self.queue_draw()
+           do_draw=True
+
+       if do_draw:
+           #self.queue_draw()
+           self.angle_timer_start=time.time()
+           gobject.timeout_add(20, self.timerAngle)
+
+    def timerAngle(self):
+       self.queue_draw()
+
+       if self.angle_timer_start==0:
+           self.angle_timer_start=time.time()
+
+       dt=time.time()-self.angle_timer_start
+
+       da=90.0*dt/0.5
+
+       if self.mode=='l':
+           angle=90-da
+       else:
+           angle=da
+
+       if angle>=90:
+           angle=90
+           ret=False
+       elif angle<0:
+           angle=0
+           ret=False
+       else:
+           ret=True
+
+       self.setAngle(angle)
+
+       if ret==False:
+           self.angle_timer_start=0
+
+       return(ret)
 
     def iconAt(self, x, y):
        """ Get icon at coordinates x,y. X and Y are in pixels """
@@ -137,7 +183,12 @@ class IconGrid(object):    #(gobject.GObject):
                continue
 
            ico=self.icons.get(x,y)
-           ico.draw(cr, x2, y2, self.mode)
+           ico.draw(cr, x2, y2)
+
+    def setAngle(self, angle):
+       for x,y in self.icons:
+           ic=self.icons.get(x,y)
+           ic.setAngle(angle)
 
     def do_expose_event(self, event):
        cr=self.window.cairo_create()
@@ -147,6 +198,10 @@ class IconGrid(object):    #(gobject.GObject):
 
        cr.clip()
 
+       if not self.init_done:
+           self.icons.setWindow(self.window)
+           self.init_done=True
+
        self._draw(cr, event)
 
     def setLastIcon(self, icon):
index 015273b..3f663d7 100755 (executable)
@@ -116,6 +116,13 @@ class Icons(gobject.GObject):
     def getSize(self):
        return(self.size)
 
+    def setWindow(self, win):
+       """ Set the window for all icons """
+
+       for i in self.icons:
+           ic=self.icons[i]
+           ic.setWindow(win)
+
     def signalLongpress(self, icon):
        #print "signalLongpress()", icon
        self.emit('long-press', icon)