Properly handle apps without an icon or with an invalid one and fallback to blue.
[drlaunch] / src / icon.py
1 #!/usr/bin/env python
2 # coding=UTF-8
3
4 # Copyright (C) 2010 Stefanos Harhalakis
5 #
6 # This file is part of wifieye.
7 #
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.
12 #
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.
17 #
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/>.
20 #
21 # $Id: 0.py 2265 2010-02-21 19:16:26Z v13 $
22
23 __version__ = "$Id: 0.py 2265 2010-02-21 19:16:26Z v13 $"
24
25 import gtk
26 import gobject
27 import hildon
28 from hildondesktop import *
29 from gtk import gdk
30 from math import pi
31 import cairo
32 import time
33
34 from portrait import FremantleRotation
35 import launcher
36 from xdg.IconTheme import getIconPath
37
38
39 #import config
40 import apps
41
42 # Load an icon
43 # Fall-back to default/blue if not found or name==None
44 def getIcon(name, iconsize):
45     # Default icon
46     idef='tasklaunch_default_application'
47
48     # If name==None then use the default icon
49     if name==None or name=='':
50         iname=idef
51     else:
52         iname=name
53
54     ico=getIconPath(iname, iconsize)
55
56     # If not found then use the default icon
57     if ico==None:
58         ico=getIconPath(idef, iconsize)
59
60     ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, iconsize, iconsize)
61
62     return(ret)
63
64 class Icon(gobject.GObject):
65     def __init__(self, isconfig, config):
66         self.__gobject_init__()
67
68         self.isconfig=isconfig
69         self.config=config
70
71         self.name=None
72         self.icon=None
73         self.lastpress=0
74         self.ispressed=False
75
76         self.x=0
77         self.y=0
78
79         self.presstime=0.25
80
81         self.window=None
82
83         self.clickcount=0
84
85     def timePressed(self):
86         """ return how much time a button is pressed """
87         dt=time.time() - self.lastpress
88
89         return(dt)
90
91     def setApp(self, dt):
92         if dt==None:
93             self.name=None
94             self.icon=None
95         else:
96             self.name=dt['id']
97             self.icon=dt['icon2']
98         self.invalidate()
99
100     def getSize(self):
101         return(self.config.iconsize+self.config.iconspace)
102
103     def draw(self, cr, x, y, mode):
104         self.x=x
105         self.y=y
106
107         if self.icon==None and not self.isconfig:
108             return
109
110         cr.save()
111         cr.set_source_rgba(0.1, 0.1, 0.1, 1)
112         cr.set_line_width(5)
113
114         #if self.ispressed:
115         if self.timePressed() <= self.presstime or self.ispressed:
116             t=1.0 * min(self.timePressed(), self.presstime) / self.presstime
117             g=0.3+0.5*t
118             b=0.3+0.7*t
119             cr.set_source_rgba(0, g, b, 0.7)
120         else:
121             cr.set_source_rgba(0.3, 0.3, 0.3, 0.7)
122
123         x3=x + (self.config.iconspace/6)
124         y3=y + (self.config.iconspace/6)
125
126         r=10    # Radius
127         w=self.config.iconsize+(self.config.iconspace*2/3)
128
129         cr.move_to(x3+r, y3)
130         cr.arc(x3+w-r,  y3+r,   r,          pi*1.5, pi*2)
131         cr.arc(x3+w-r,  y3+w-r, r,          0,      pi*0.5)
132         cr.arc(x3+r,    y3+w-r, r,          pi*0.5, pi)
133         cr.arc(x3+r,    y3+r,   r,          pi,     pi*1.5)
134
135         cr.stroke_preserve()
136         cr.fill()
137         cr.clip()
138         cr.paint()
139         cr.restore()
140
141         if self.icon==None:
142             return
143
144         icon=self.icon
145
146         if mode=='l':
147             icon2=icon
148         else:
149             icon2=icon.rotate_simple(gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE)
150
151         cr.save()
152         x3=x + (self.config.iconspace/2)
153         y3=y + (self.config.iconspace/2)
154         cr.set_source_pixbuf(icon2, x3, y3)
155         cr.paint()
156         cr.restore()
157
158         return(False)
159
160     def timerPressed(self):
161 #       if not self.ispressed:
162 #           return(False)
163
164         self.invalidate()
165
166         if self.timePressed()>self.presstime:
167             ret=False
168         else:
169             ret=True
170
171         return(ret)
172
173     def doPress(self):
174         # Double-time: time for pressed and time for not-pressed
175         if time.time() - self.lastpress > self.presstime*2:
176             self.clickcount=0
177
178         self.lastpress=time.time()
179         self.ispressed=True
180         gobject.timeout_add(20, self.timerPressed)
181
182     def doRelease(self):
183         dt=time.time() - self.lastpress
184         self.ispressed=False
185         self.invalidate()
186         if dt<=self.presstime:
187             self.clickcount+=1
188             if self.clickcount==1:
189                 self.emit('click')
190             elif self.clickcount==2:
191                 self.emit('double-click')
192             if self.clickcount==3:
193                 self.emit('tripple-click')
194                 self.clickcount=0
195         elif dt>self.presstime and dt<2:
196             self.emit('long-press')
197
198     def doCancel(self):
199         self.ispressed=False
200
201     def invalidate(self, window=None):
202         if window==None:
203             window=self.window
204         else:
205             self.window=window
206         
207         if window==None:
208             return
209
210         w=self.config.iconsize + self.config.iconspace
211         rect=gdk.Rectangle(self.x, self.y, w, w)
212         gdk.Window.invalidate_rect(window, rect, True)
213
214 gobject.type_register(Icon)
215 signals=['click', 'double-click', 'tripple-click', 'long-press']
216 for s in signals:
217     gobject.signal_new(s, Icon, gobject.SIGNAL_RUN_FIRST,
218         gobject.TYPE_NONE, ())
219
220 # vim: set ts=8 sts=4 sw=4 noet formatoptions=r ai nocindent:
221