4 # Copyright (C) 2010 Stefanos Harhalakis
6 # This file is part of wifieye.
8 # wifieye is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
13 # wifieye is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with wifieye. If not, see <http://www.gnu.org/licenses/>.
21 # $Id: 0.py 2265 2010-02-21 19:16:26Z v13 $
23 __version__ = "$Id: 0.py 2265 2010-02-21 19:16:26Z v13 $"
28 from hildondesktop import *
34 from portrait import FremantleRotation
36 from xdg.IconTheme import getIconPath
42 # Background surface for icons
46 # Fall-back to default/blue if not found or name==None
47 def getIcon(name, iconsize):
49 idef='tasklaunch_default_application'
51 # If name==None then use the default icon
52 if name==None or name=='':
57 ico=getIconPath(iname, iconsize)
59 # If not found then use the default icon
61 ico=getIconPath(idef, iconsize)
64 ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, iconsize, iconsize)
66 # On error use the default icon
67 ico=getIconPath(idef, iconsize)
68 ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, iconsize, iconsize)
69 print "Icon with unhandled format:", iname
73 class Icon(gobject.GObject):
74 def __init__(self, isconfig, config):
75 self.__gobject_init__()
77 self.isconfig=isconfig
101 def timePressed(self):
102 """ return how much time a button is pressed """
103 dt=time.time() - self.lastpress
107 def setApp(self, dt):
114 self.icon=dt['icon2']
116 self.clearAnimationCache()
119 def clearAnimationCache(self):
123 return(self.config.iconsize+self.config.iconspace)
125 def setAngle(self, angle):
126 """ Set the angle. Return True if the angle changed or False if it
127 didn't. The caller should invalidate the icon """
129 # The step in degrees
132 angle2=int(angle/step)*step
134 if angle2==self.angle:
139 # The caller should be responsible for redrawing.
140 # If we call invalidate() here there is the risk of having
141 # icons rotate individually using different angles
146 def mkbg(self, t_pressed):
147 """ Create the background of the icon and cache it as a global
148 variable among all icons and widget instances """
151 if iconbg!=None and t_pressed<=0.001:
154 w=self.config.iconsize + self.config.iconspace
155 s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
157 cr=gtk.gdk.CairoContext(cr0)
159 cr.set_source_rgba(0.1, 0.1, 0.1, 1)
163 if t_pressed>0.001 and \
164 (t_pressed <= self.presstime or self.ispressed):
165 t=1.0 * min(t_pressed, self.presstime) / self.presstime
168 cr.set_source_rgba(0, g, b, 0.7)
170 cr.set_source_rgba(0.3, 0.3, 0.3, 0.7)
174 x3=x + (self.config.iconspace/6)
175 y3=y + (self.config.iconspace/6)
178 w=self.config.iconsize+(self.config.iconspace*2/3)
181 cr.arc(x3+w-r, y3+r, r, pi*1.5, pi*2)
182 cr.arc(x3+w-r, y3+w-r, r, 0, pi*0.5)
183 cr.arc(x3+r, y3+w-r, r, pi*0.5, pi)
184 cr.arc(x3+r, y3+r, r, pi, pi*1.5)
197 def get_sthemebg(self, pressed):
198 """ Return the theme's background icon as a surface. Cache it. """
199 if not pressed and self.sthemebg1!=None:
200 return(self.sthemebg1)
201 if pressed and self.sthemebg2!=None:
202 return(self.sthemebg2)
204 fn="/etc/hildon/theme/images/"
206 fn+="ApplicationShortcutAppletPressed.png"
208 fn+="ApplicationShortcutApplet.png"
210 w=self.config.themebgsize
211 buf=gtk.gdk.pixbuf_new_from_file_at_size(fn, w, w)
212 s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
214 cr=gtk.gdk.CairoContext(cr0)
216 cr.set_source_pixbuf(buf, 0, 0)
227 """ Return the icon as a surface. Cache it. """
231 w=self.config.iconsize
232 s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
234 cr=gtk.gdk.CairoContext(cr0)
236 cr.set_source_pixbuf(self.icon, 0, 0)
243 def get_paint_icon(self):
244 """ Return the icon to paint as a surface. The icon is rotated
245 as needed. The result is cached. """
248 if self.timePressed() <= self.presstime or self.ispressed:
255 if not pressed and self.cached_icons.has_key(angle):
256 return(self.cached_icons[angle])
258 w=self.config.iconsize + self.config.iconspace
259 s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
261 cr=gtk.gdk.CairoContext(cr0)
263 # Paint the background
264 if self.config.getNoBg():
266 elif self.config.getThemeBg(): # Use theme bg
267 s2=self.get_sthemebg(pressed)
269 # have in mind the size difference of iconsize+iconspace with
270 # the fixed themebgsize
271 xy0=int((w-self.config.themebgsize)/2)
274 cr.set_source_surface(s2, xy0, xy0)
280 cr.set_source_surface(s2, 0, 0)
284 # If there is no icon then don't do anything more
286 # Get the icon as a surface (get_sicon() will cache the surface)
287 sicon=self.get_sicon()
289 # Width is the iconsize plus the empty border around the icon
290 #w=self.config.iconsize + self.config.iconspace
292 # This is used to locate the center of the surface
295 # This is the delta from the center where icons are drawn
296 dx2=int(self.config.iconsize/2)
300 # A transformation matrix with dx/dy set to point to the center
301 m=cairo.Matrix(1, 0, 0, 1, dx, dx)
303 # Transform degrees to rads
304 rot=-1 * pi * 2 * self.angle / 360
307 cr.set_source_surface(sicon, -dx2, -dx2) # Faster than pixbuf
308 # cr.set_source_pixbuf(icon2, -dx2, -dx2)
314 self.cached_icons[angle]=s
319 def draw(self, cr, x, y):
320 self.draw_queued=False
324 if self.icon==None and not self.isconfig:
328 s=self.get_paint_icon()
329 cr.set_source_surface(s, x, y)
336 def timerPressed(self):
337 # if not self.ispressed:
342 if self.timePressed()>self.presstime:
350 # Double-time: time for pressed and time for not-pressed
351 if time.time() - self.lastpress > self.presstime*2:
354 self.lastpress=time.time()
356 gobject.timeout_add(20, self.timerPressed)
359 dt=time.time() - self.lastpress
362 if dt<=self.presstime:
364 if self.clickcount==1:
366 elif self.clickcount==2:
367 self.emit('double-click')
368 if self.clickcount==3:
369 self.emit('tripple-click')
371 elif dt>self.presstime and dt<2:
372 self.emit('long-press')
377 def setWindow(self, window):
380 def invalidate(self, window=None):
393 self.draw_queued=True
394 w=self.config.iconsize + self.config.iconspace
395 rect=gdk.Rectangle(self.x, self.y, w, w)
396 gdk.Window.invalidate_rect(window, rect, True)
398 gobject.type_register(Icon)
399 signals=['click', 'double-click', 'tripple-click', 'long-press']
401 gobject.signal_new(s, Icon, gobject.SIGNAL_RUN_FIRST,
402 gobject.TYPE_NONE, ())
404 # vim: set ts=8 sts=4 sw=4 noet formatoptions=r ai nocindent: