#!/usr/bin/env python
# coding=UTF-8
-#
+#
# Copyright (C) 2010 Stefanos Harhalakis
#
# This file is part of wifieye.
#import config
import apps
+# Background surface for icons
+iconbg=None
+
# Load an icon
# Fall-back to default/blue if not found or name==None
def getIcon(name, iconsize):
self.name=None
self.icon=None
+ self.sicon=None
self.lastpress=0
self.ispressed=False
self.angle=0
+ self.cached_icons={}
+
def timePressed(self):
""" return how much time a button is pressed """
dt=time.time() - self.lastpress
if dt==None:
self.name=None
self.icon=None
+ self.sicon=None
else:
self.name=dt['id']
self.icon=dt['icon2']
+ self.sicon=None
+ self.cached_icons={}
self.invalidate()
def getSize(self):
return(self.config.iconsize+self.config.iconspace)
def setAngle(self, angle):
- if self.angle==angle:
- print "Same angle"
- return
+ """ Set the angle. Return True if the angle changed or False if it
+ didn't. The caller should invalidate the icon """
+
+ # The step in degrees
+ step=15
+
+ angle2=int(angle/step)*step
- self.angle=angle
+ if angle2==self.angle:
+ return(False)
+
+ self.angle=angle2
# 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
+ return(True)
- if self.icon==None and not self.isconfig:
- return
+ def mkbg(self, t_pressed):
+ """ Create the background of the icon and cache it as a global
+ variable among all icons and widget instances """
+ global iconbg
- cr.save()
+ if iconbg!=None and t_pressed<=0.001:
+ return(iconbg)
+
+ w=self.config.iconsize + self.config.iconspace
+ s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
+ cr0=cairo.Context(s)
+ cr=gtk.gdk.CairoContext(cr0)
- cr.set_source_rgba(0.1, 0.1, 0.1, 1)
+ cr.set_source_rgba(0.1, 0.1, 0.1, 1)
cr.set_line_width(5)
#if self.ispressed:
- if self.timePressed() <= self.presstime or self.ispressed:
- t=1.0 * min(self.timePressed(), self.presstime) / self.presstime
+ if t_pressed>0.001 and \
+ (t_pressed <= self.presstime or self.ispressed):
+ t=1.0 * min(t_pressed, self.presstime) / self.presstime
g=0.3+0.5*t
b=0.3+0.7*t
cr.set_source_rgba(0, g, b, 0.7)
else:
cr.set_source_rgba(0.3, 0.3, 0.3, 0.7)
+ x=0
+ y=0
x3=x + (self.config.iconspace/6)
y3=y + (self.config.iconspace/6)
cr.fill()
cr.clip()
cr.paint()
- cr.restore()
+# cr.restore()
- if self.icon==None:
- return
+ if t_pressed<0.001:
+ iconbg=s
- icon=self.icon
+ return(s)
- icon2=icon
+ def get_sicon(self):
+ """ Return the icon as a surface. Cache it. """
+ if self.sicon!=None:
+ return(self.sicon)
-# Old method. Faster rotation but without support for rotation
-# animation
+ w=self.config.iconsize
+ s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
+ cr0=cairo.Context(s)
+ cr=gtk.gdk.CairoContext(cr0)
-# if mode=='l':
-# icon2=icon
-# else:
-# icon2=icon.rotate_simple(gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE)
+ cr.set_source_pixbuf(self.icon, 0, 0)
+ cr.paint()
-# 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()
+ self.sicon=s
+ return(s)
- # Width is the iconsize plus the empty border around the icon
- w=self.config.iconsize + self.config.iconspace
+ def get_paint_icon(self):
+ """ Return the icon to paint as a surface. The icon is rotated
+ as needed. The result is cached. """
+ angle=self.angle
- # This is used to locate the center of the surface
- dx=int(w/2)
+ if self.timePressed() <= self.presstime or self.ispressed:
+ t=self.timePressed()
+ pressed=True
+ else:
+ t=0
+ pressed=False
+
+ if not pressed and self.cached_icons.has_key(angle):
+ return(self.cached_icons[angle])
+
+ w=self.config.iconsize + self.config.iconspace
+ s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
+ cr0=cairo.Context(s)
+ cr=gtk.gdk.CairoContext(cr0)
+
+ # Paint the background
+ s2=self.mkbg(t)
+ cr.save()
+ cr.set_source_surface(s2, 0, 0)
+ cr.paint()
+ cr.restore()
+
+ # If there is no icon then don't do anything more
+ if self.icon!=None:
+ # Get the icon as a surface (get_sicon() will cache the surface)
+ sicon=self.get_sicon()
+
+ # 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)
+
+# cr.save()
- # This is the delta from the center where icons are drawn
- dx2=int(self.config.iconsize/2)
+ # A transformation matrix with dx/dy set to point to the center
+ m=cairo.Matrix(1, 0, 0, 1, dx, dx)
+ cr.set_matrix(m)
+ # Transform degrees to rads
+ rot=-1 * pi * 2 * self.angle / 360
+ cr.rotate(rot)
+ # Draw the icon
+ cr.set_source_surface(sicon, -dx2, -dx2) # Faster than pixbuf
+# cr.set_source_pixbuf(icon2, -dx2, -dx2)
+ cr.paint()
- # A surface to draw on
- t_s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
+# cr.restore()
- # And a context to draw
- t_cr0=cairo.Context(t_s)
- t_cr=gtk.gdk.CairoContext(t_cr0)
+ if not pressed:
+ self.cached_icons[angle]=s
- # 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()
+ return(s)
+
+
+ def draw(self, cr, x, y):
+ self.draw_queued=False
+ self.x=x
+ self.y=y
+
+ if self.icon==None and not self.isconfig:
+ return
- # Draw the rotated icon on the main cairo context
cr.save()
- cr.set_source_surface(t_s, x, y)
+ s=self.get_paint_icon()
+ cr.set_source_surface(s, x, y)
cr.paint()
+
cr.restore()
return(False)
window=self.window
else:
self.window=window
-
+
if window==None:
return