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
37 from sig import Disconnector
42 # Background surface for icons
48 # Fall-back to default/blue if not found or name==None
49 def getIcon(name, iconsize):
51 idef='tasklaunch_default_application'
53 # If name==None then use the default icon
54 if name==None or name=='':
59 ico=getIconPath(iname, iconsize)
61 # If not found then use the default icon
63 ico=getIconPath(idef, iconsize)
66 ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, iconsize, iconsize)
68 # On error use the default icon
69 ico=getIconPath(idef, iconsize)
70 ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, iconsize, iconsize)
71 print "Icon with unhandled format:", iname
75 class Icon(Disconnector, gobject.GObject):
76 #class Icon(gtk.Widget, Disconnector):
78 __v_t=(gobject.SIGNAL_RUN_FIRST | gobject.SIGNAL_ACTION,
79 gobject.TYPE_NONE, ())
83 'double-click': __v_t,
84 'tripple-click': __v_t,
90 def __init__(self, isconfig, config):
91 # self.__gobject_init__()
92 gobject.GObject.__init__(self)
93 # gtk.Widget.__init__(self)
94 Disconnector.__init__(self)
96 self.isconfig=isconfig
118 self.draw_queued=False
126 def timePressed(self):
127 """ return how much time a button is pressed """
128 dt=time.time() - self.lastpress
133 self.clearAnimationCache()
137 def setApp(self, dt):
143 self.appname=dt['id']
144 self.icon=dt['icon2']
146 self.clearAnimationCache()
150 def clearAnimationCache(self):
153 def clearBgCache(self):
154 global iconbg, sthemebg1, sthemebg2
161 return(self.config.getIconSizeFull())
162 # return(self.config.iconsize+self.config.iconspace)
164 def setAngle(self, angle):
165 """ Set the angle. Return True if the angle changed or False if it
166 didn't. The caller should invalidate the icon """
168 # The step in degrees
171 angle2=int(angle/step)*step
173 if angle2==self.angle:
178 # The caller should be responsible for redrawing.
179 # If we call invalidate() here there is the risk of having
180 # icons rotate individually using different angles
185 def mkbg(self, t_pressed):
186 """ Create the background of the icon and cache it as a global
187 variable among all icons and widget instances """
190 if iconbg!=None and t_pressed<=0.001:
194 s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
196 cr=gtk.gdk.CairoContext(cr0)
198 cr.set_source_rgba(0.1, 0.1, 0.1, 1)
202 if t_pressed>0.001 and \
203 (t_pressed <= self.presstime or self.ispressed):
204 t=1.0 * min(t_pressed, self.presstime) / self.presstime
207 cr.set_source_rgba(0, g, b, 0.7)
209 cr.set_source_rgba(0.3, 0.3, 0.3, 0.7)
213 x3=x + (self.config.iconmargin)
214 y3=y + (self.config.iconmargin)
217 w=self.config.iconsize+(self.config.iconpadding*2)
220 cr.arc(x3+w-r, y3+r, r, pi*1.5, pi*2)
221 cr.arc(x3+w-r, y3+w-r, r, 0, pi*0.5)
222 cr.arc(x3+r, y3+w-r, r, pi*0.5, pi)
223 cr.arc(x3+r, y3+r, r, pi, pi*1.5)
236 def get_sthemebg(self, pressed):
237 """ Return the theme's background icon as a surface. Cache it. """
238 global sthemebg1, sthemebg2
240 if not pressed and sthemebg1!=None:
242 if pressed and sthemebg2!=None:
245 fn="/etc/hildon/theme/images/"
247 fn+="ApplicationShortcutAppletPressed.png"
249 fn+="ApplicationShortcutApplet.png"
251 w=self.config.iconsize + (self.config.iconpadding*2)
252 buf=gtk.gdk.pixbuf_new_from_file_at_size(fn, w, w)
253 s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
255 cr=gtk.gdk.CairoContext(cr0)
257 cr.set_source_pixbuf(buf, 0, 0)
268 """ Return the icon as a surface. Cache it. """
272 w=self.config.iconsize
273 s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
275 cr=gtk.gdk.CairoContext(cr0)
277 cr.set_source_pixbuf(self.icon, 0, 0)
284 def get_paint_icon(self):
285 """ Return the icon to paint as a surface. The icon is rotated
286 as needed. The result is cached. """
289 if self.timePressed() <= self.presstime or self.ispressed:
296 if not pressed and self.cached_icons.has_key(angle):
297 return(self.cached_icons[angle])
299 w=self.config.getIconSizeFull()
300 s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
302 cr=gtk.gdk.CairoContext(cr0)
304 # Paint the background
305 if self.config.getNoBg():
307 elif self.config.getThemeBg(): # Use theme bg
308 s2=self.get_sthemebg(pressed)
310 # have in mind the size difference of iconsize+iconspace with
311 # the fixed themebgsize
312 #xy0=int((w-self.config.themebgsize)/2)
313 #xy0=int((w-self.config.iconsize)/2)
314 xy0=self.config.iconmargin
317 cr.set_source_surface(s2, xy0, xy0)
323 cr.set_source_surface(s2, 0, 0)
327 # If there is no icon then don't do anything more
329 # Get the icon as a surface (get_sicon() will cache the surface)
330 sicon=self.get_sicon()
332 # Width is the iconsize plus the empty border around the icon
333 #w=self.config.iconsize + self.config.iconspace
335 # This is used to locate the center of the surface
338 # This is the delta from the center where icons are drawn
339 dx2=int(self.config.iconsize/2)
343 # A transformation matrix with dx/dy set to point to the center
344 m=cairo.Matrix(1, 0, 0, 1, dx, dx)
346 # Transform degrees to rads
347 rot=-1 * pi * 2 * self.angle / 360
350 cr.set_source_surface(sicon, -dx2, -dx2) # Faster than pixbuf
351 # cr.set_source_pixbuf(icon2, -dx2, -dx2)
357 self.cached_icons[angle]=s
362 def draw(self, cr, x, y):
363 self.draw_queued=False
367 if self.icon==None and not self.isconfig:
371 s=self.get_paint_icon()
372 cr.set_source_surface(s, x, y)
379 def timerPressed(self):
380 # if not self.ispressed:
385 if self.timePressed()>self.presstime:
393 # Double-time: time for pressed and time for not-pressed
394 if time.time() - self.lastpress > self.presstime*2:
397 self.lastpress=time.time()
399 gobject.timeout_add(20, self.timerPressed)
402 dt=time.time() - self.lastpress
405 if dt<=self.presstime:
407 if self.clickcount==1:
409 # print "emit click", self
410 elif self.clickcount==2:
411 self.emit('double-click')
412 if self.clickcount==3:
413 self.emit('tripple-click')
415 elif dt>self.presstime and dt<2:
416 self.emit('long-press')
422 def setWindow(self, window):
425 def invalidate(self, window=None):
438 self.draw_queued=True
440 rect=gdk.Rectangle(self.x, self.y, w, w)
441 gdk.Window.invalidate_rect(window, rect, True)
443 #gobject.type_register(Icon)
444 #signals=['click', 'double-click', 'tripple-click', 'long-press']
446 # gobject.signal_new(s, Icon, gobject.SIGNAL_RUN_FIRST | \
447 # gobject.SIGNAL_ACTION, gobject.TYPE_NONE, ())
449 # vim: set ts=8 sts=4 sw=4 noet formatoptions=r ai nocindent: