vim line
[drlaunch] / src / icon.py
index 2982bf3..c4ea529 100755 (executable)
@@ -34,13 +34,15 @@ import time
 from portrait import FremantleRotation
 import launcher
 from xdg.IconTheme import getIconPath
-
+from sig import Disconnector
 
 #import config
 import apps
 
 # Background surface for icons
 iconbg=None
+sthemebg1=None
+sthemebg2=None
 
 # Load an icon
 # Fall-back to default/blue if not found or name==None
@@ -60,18 +62,41 @@ def getIcon(name, iconsize):
     if ico==None:
        ico=getIconPath(idef, iconsize)
 
-    ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, iconsize, iconsize)
+    try:
+       ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, iconsize, iconsize)
+    except:
+       # On error use the default icon
+       ico=getIconPath(idef, iconsize)
+       ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, iconsize, iconsize)
+       print "Icon with unhandled format:", iname
 
     return(ret)
 
-class Icon(gobject.GObject):
+class Icon(Disconnector, gobject.GObject):
+#class Icon(gtk.Widget, Disconnector):
+
+    __v_t=(gobject.SIGNAL_RUN_FIRST | gobject.SIGNAL_ACTION,
+           gobject.TYPE_NONE, ())
+
+    gsignals={
+       'click':            __v_t,
+       'double-click':     __v_t,
+       'tripple-click':    __v_t,
+       'long-press':       __v_t,
+       }
+
+    __gsignals__=gsignals
+
     def __init__(self, isconfig, config):
-       self.__gobject_init__()
+#      self.__gobject_init__()
+       gobject.GObject.__init__(self)
+#      gtk.Widget.__init__(self)
+       Disconnector.__init__(self)
 
        self.isconfig=isconfig
        self.config=config
 
-       self.name=None
+       self.appname=None
        self.icon=None
         self.sicon=None
        self.lastpress=0
@@ -82,7 +107,7 @@ class Icon(gobject.GObject):
 
        self.presstime=0.25
 
-       self.window=None
+       self.window_=None
 
        self.clickcount=0
 
@@ -90,29 +115,51 @@ class Icon(gobject.GObject):
 
        self.cached_icons={}
 
+       self.draw_queued=False
+
+       #print "icon-init"
+
+    def __del__(self):
+       #print "icon-del"
+       pass
+
     def timePressed(self):
        """ return how much time a button is pressed """
        dt=time.time() - self.lastpress
 
        return(dt)
 
+    def reload(self):
+       self.clearAnimationCache()
+       self.clearBgCache()
+       self.invalidate()
+
     def setApp(self, dt):
        if dt==None:
-           self.name=None
+           self.appname=None
            self.icon=None
            self.sicon=None
        else:
-           self.name=dt['id']
+           self.appname=dt['id']
            self.icon=dt['icon2']
            self.sicon=None
        self.clearAnimationCache()
+       self.clearBgCache()
        self.invalidate()
 
     def clearAnimationCache(self):
        self.cached_icons={}
 
+    def clearBgCache(self):
+       global iconbg, sthemebg1, sthemebg2
+
+       iconbg=None
+       sthemebg1=None
+       sthemebg2=None
+
     def getSize(self):
-       return(self.config.iconsize+self.config.iconspace)
+       return(self.config.getIconSizeFull())
+       # return(self.config.iconsize+self.config.iconspace)
 
     def setAngle(self, angle):
        """ Set the angle. Return True if the angle changed or False if it
@@ -143,7 +190,7 @@ class Icon(gobject.GObject):
         if iconbg!=None and t_pressed<=0.001:
             return(iconbg)
 
-        w=self.config.iconsize + self.config.iconspace
+       w=self.getSize()
        s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
        cr0=cairo.Context(s)
        cr=gtk.gdk.CairoContext(cr0)
@@ -163,11 +210,11 @@ class Icon(gobject.GObject):
 
         x=0
         y=0
-       x3=x + (self.config.iconspace/6)
-       y3=y + (self.config.iconspace/6)
+       x3=x + (self.config.iconmargin)
+       y3=y + (self.config.iconmargin)
 
        r=10    # Radius
-       w=self.config.iconsize+(self.config.iconspace*2/3)
+       w=self.config.iconsize+(self.config.iconpadding*2)
 
        cr.move_to(x3+r, y3)
        cr.arc(x3+w-r,  y3+r,   r,          pi*1.5, pi*2)
@@ -186,6 +233,37 @@ class Icon(gobject.GObject):
 
         return(s)
 
+    def get_sthemebg(self, pressed):
+       """ Return the theme's background icon as a surface. Cache it. """
+       global sthemebg1, sthemebg2
+
+       if not pressed and sthemebg1!=None:
+           return(sthemebg1)
+       if pressed and sthemebg2!=None:
+           return(sthemebg2)
+
+       fn="/etc/hildon/theme/images/"
+       if pressed:
+           fn+="ApplicationShortcutAppletPressed.png"
+       else:
+           fn+="ApplicationShortcutApplet.png"
+
+       w=self.config.iconsize + (self.config.iconpadding*2)
+       buf=gtk.gdk.pixbuf_new_from_file_at_size(fn, w, w)
+       s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
+       cr0=cairo.Context(s)
+       cr=gtk.gdk.CairoContext(cr0)
+
+       cr.set_source_pixbuf(buf, 0, 0)
+       cr.paint()
+
+       if not pressed:
+           sthemebg1=s
+       else:
+           sthemebg2=s
+
+       return(s)
+
     def get_sicon(self):
        """ Return the icon as a surface. Cache it. """
        if self.sicon!=None:
@@ -218,13 +296,28 @@ class Icon(gobject.GObject):
        if not pressed and self.cached_icons.has_key(angle):
            return(self.cached_icons[angle])
 
-        w=self.config.iconsize + self.config.iconspace
+        w=self.config.getIconSizeFull()
        s=cairo.ImageSurface(cairo.FORMAT_ARGB32, w, w)
        cr0=cairo.Context(s)
        cr=gtk.gdk.CairoContext(cr0)
 
        # Paint the background
-       if not self.config.getNoBg():
+       if self.config.getNoBg():
+           pass
+       elif self.config.getThemeBg():  # Use theme bg
+           s2=self.get_sthemebg(pressed)
+
+           # have in mind the size difference of iconsize+iconspace with
+           # the fixed themebgsize
+           #xy0=int((w-self.config.themebgsize)/2)
+           #xy0=int((w-self.config.iconsize)/2)
+           xy0=self.config.iconmargin
+
+           cr.save()
+           cr.set_source_surface(s2, xy0, xy0)
+           cr.paint()
+           cr.restore()
+       else:
            s2=self.mkbg(t)
            cr.save()
            cr.set_source_surface(s2, 0, 0)
@@ -313,6 +406,7 @@ class Icon(gobject.GObject):
            self.clickcount+=1
            if self.clickcount==1:
                self.emit('click')
+#              print "emit click", self
            elif self.clickcount==2:
                self.emit('double-click')
            if self.clickcount==3:
@@ -320,18 +414,19 @@ class Icon(gobject.GObject):
                self.clickcount=0
        elif dt>self.presstime and dt<2:
            self.emit('long-press')
+#          print "Emit lp"
 
     def doCancel(self):
        self.ispressed=False
 
     def setWindow(self, window):
-       self.window=window
+       self.window_=window
 
     def invalidate(self, window=None):
        if window==None:
-           window=self.window
+           window=self.window_
        else:
-           self.window=window
+           self.window_=window
 
        if window==None:
            return
@@ -341,15 +436,15 @@ class Icon(gobject.GObject):
            return
 
        self.draw_queued=True
-       w=self.config.iconsize + self.config.iconspace
+       w=self.getSize()
        rect=gdk.Rectangle(self.x, self.y, w, w)
        gdk.Window.invalidate_rect(window, rect, True)
 
-gobject.type_register(Icon)
-signals=['click', 'double-click', 'tripple-click', 'long-press']
-for s in signals:
-    gobject.signal_new(s, Icon, gobject.SIGNAL_RUN_FIRST,
-       gobject.TYPE_NONE, ())
+#gobject.type_register(Icon)
+#signals=['click', 'double-click', 'tripple-click', 'long-press']
+#for s in signals:
+#    gobject.signal_new(s, Icon, gobject.SIGNAL_RUN_FIRST | \
+#      gobject.SIGNAL_ACTION, gobject.TYPE_NONE, ())
 
 # vim: set ts=8 sts=4 sw=4 noet formatoptions=r ai nocindent: