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
35 #from xdg.IconTheme import getIconPath
37 from config import dump
41 from icons import Icons
43 #def getIcon(name, iconsize):
44 # ico=getIconPath(name, iconsize)
45 # ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, iconsize, iconsize)
49 # IconGrid is the main class that implements tha drawing of the grid
50 # However, since it will be used both by the desktop plugin and the
51 # configuration window, it cannot derive either gtk.Widget or HomePluginItem.
52 # It is created here in a way that will allow it to work on both cases
53 # and it is inherited by appropriate classes (one for the plugin and one
54 # for the config widget)
56 #class IconGrid(gtk.Widget, FremantleRotation):
58 def __init__(self, isconfig=False):
59 # self.__gobject_init__()
60 # gtk.Widget.__init__(self)
66 self.isconfig=isconfig
69 self.lasticon=None # The last icon that got selected
71 self.draw_pending=False
75 # If this is False then animations are forcefully disabled
76 self.do_animations=True
78 self.angle_timer_start=0
80 # Duration of the rotation effect
81 self.rotation_time=0.8
83 # Whether we're in CSSU's h-d portrait mode
84 self.cssuportrait=False
86 # Force modechange, even when mode doesn't change
87 self.force_modechange=False
94 def do_realize(self, config):
102 print "WTF??????????????????????"
107 self.icons=Icons(self.isconfig, self.config)
109 #self.icons.set_parent(self)
111 self.setSize(config.getMaxSize())
114 def do_unrealize(self):
115 # print "ig-unrealize"
121 def connect(self, what, *args):
122 if what in Icon.gsignals.keys():
123 ret=self.icons.connect(what, *args)
125 ret=gobject.GObject.connect(self, what, *args)
126 #ret=super(IconGrid, self).connect(what, *args)
130 def setSize(self, size):
132 self.icons.setSize(size)
135 ret=self.icons.getSize()
138 def setCSSUPortrait(self, cssuportrait):
139 if self.cssuportrait==cssuportrait:
140 # print "same portrait"
143 self.cssuportrait=cssuportrait
144 self.force_modechange=True
146 # TODO: Remove default value from cssuportrait
147 def setMode(self, mode):
148 if self.mode==mode and not self.force_modechange:
153 self.force_modechange=False
155 if not isinstance(self, gtk.Widget):
161 v=self.get_property('is-on-current-desktop')
165 self.draw_pending=True
169 if do_draw and self.config.getAnimate() and self.do_animations \
170 and not self.cssuportrait:
172 # Don't start another timer
173 # Instead adjust the time start to produce a nice effect ;-)
174 if self.angle_timer_start==0:
175 self.angle_timer_start=time.time()
176 gobject.timeout_add(20, self.timerAngle)
178 dt=time.time()-self.angle_timer_start
179 da=90.0*dt/self.rotation_time
182 dt2=da2*self.rotation_time/90.0
183 self.angle_timer_start=time.time()-dt2
185 if self.mode=='l' or self.cssuportrait:
193 def disableAnimation(self):
194 self.do_animations=False
196 def enableAnimation(self):
197 self.do_animations=True
199 def setAnimationEnable(self, value):
201 self.enableAnimation()
203 self.disableAnimation()
205 def timerAngle(self):
206 if self.angle_timer_start==0:
207 self.angle_timer_start=time.time()-0.05
209 dt=time.time()-self.angle_timer_start
211 da=90.0*dt/self.rotation_time
227 if self.setAngle(angle):
231 self.angle_timer_start=0
235 def iconAt(self, x, y):
236 """ Get icon at coordinates x,y. X and Y are in pixels """
238 w=self.config.getIconSizeFull()
240 if self.cssuportrait:
242 y2=self.size[1] - int(x/w) - 1
243 elif self.mode=='l' or self.config.getIndiv():
247 x2=self.size[1] - int(y/w) - 1
250 # print "%d,%d -> %d,%d" % (int(x/w), int(y/w), x2, y2), \
251 # self.cssuportrait, self.mode
257 ret=self.icons.get(x,y)
261 def _draw(self, cr, event):
262 self.draw_pending=False
264 w=self.config.getIconSizeFull()
265 for x,y in self.icons:
266 x2=(self.size[1]-y-1) * self.config.getIconSizeFull()
267 y2=x * self.config.getIconSizeFull()
268 if self.cssuportrait:
269 # What we do here is:
270 # We map the x,y of icons to x,y on the screen.
271 # x,y of icons is the x,y as if there is no desktop rotation
272 # and we're in landscape mode
274 # After that, iconAt() will work properly. It's a kind of
275 # double effort but it works nice
276 x2=(self.size[1]-y-1) * self.config.getIconSizeFull()
277 y2=x * self.config.getIconSizeFull()
278 elif not self.cssuportrait and \
279 (self.mode=='l' or self.config.getIndiv()):
280 #x2=x * (self.config.iconsize + self.config.iconspace)
281 #y2=y * (self.config.iconsize + self.config.iconspace)
282 x2=x * self.config.getIconSizeFull()
283 y2=y * self.config.getIconSizeFull()
285 #x2=y * (self.config.iconsize + self.config.iconspace)
286 #y2=(self.size[1]-x-1) * \
287 # (self.config.iconsize + self.config.iconspace)
288 x2=y * self.config.getIconSizeFull()
289 y2=(self.size[1]-x-1) * self.config.getIconSizeFull()
291 # Only repaint the needed icons
292 rect=gdk.Rectangle(x2, y2, w, w)
293 t=rect.intersect(event.area)
294 if t.width==0 and t.height==0 and False:
297 ico=self.icons.get(x,y)
301 print "No icon for %d, %d (%d, %d)!" % (x,y, x2, y2)
303 def setAngle(self, angle):
304 """ Return True/False indicating that angle has changed """
307 #print "angle:", angle, self.mode
309 for x,y in self.icons:
310 ic=self.icons.get(x,y)
312 if ic.setAngle(angle):
317 def clearAnimationCache(self):
318 """ Clear animation cache, freeing memory """
319 for x,y in self.icons:
320 ic=self.icons.get(x,y)
322 ic.clearAnimationCache()
324 def clearBgCache(self):
325 """ Clear backgrounds cache """
326 for x,y in self.icons:
327 ic=self.icons.get(x,y)
331 def do_expose_event(self, event):
332 cr=self.window.cairo_create()
334 cr.rectangle(event.area.x, event.area.y,
335 event.area.width, event.area.height)
339 if not self.init_done:
340 self.icons.setWindow(self.window)
343 # print "expose:", event.area.x, event.area.y, event.area.width, \
346 self._draw(cr, event)
348 def setLastIcon(self, icon):
349 if icon==self.lasticon:
352 if self.lasticon!=None:
353 self.lasticon.doCancel()
354 self.lasticon.invalidate(self.window)
357 def do_button_press_event(self, event):
358 icon=self.iconAt(event.x, event.y)
361 # rect=gdk.Rectangle(event.x,event.y,1,1)
362 # rect=gdk.Rectangle(0, 0, 100, 100)
364 icon.invalidate(self.window)
365 self.setLastIcon(icon)
367 # gdk.Window.invalidate_rect(self.window, rect, True)
371 def do_button_release_event(self, event):
372 if self.lasticon!=None:
373 self.lasticon.invalidate(self.window)
374 self.lasticon.doRelease()
376 self.setLastIcon(None)
380 def do_leave_notify_event(self, event):
381 self.setLastIcon(None)
384 def do_pproperty_notify_event(self, event):
385 icon=self.iconAt(event.x, event.y)
389 icon.invalidate(self.window)
392 def do_motion_notify_event(self, event):
393 icon=self.iconAt(event.x, event.y)
394 if self.lasticon==icon:
397 self.setLastIcon(None)
399 icon.invalidate(self.window)
402 def do_button_press_event_old(self, event):
403 if event.type==gdk.BUTTON_PRESS:
412 def do_event1(self, event):
413 print "event:", event, event.type
415 def reloadIcons(self):
419 # def on_orientation_changed(self, orientation):
420 # print "orch:", orientation
424 class IconGridWidget(IconGrid, gtk.Widget):
425 def __init__(self, isconfig, config, animation=True):
426 IconGrid.__init__(self, isconfig)
427 gtk.Widget.__init__(self)
429 # This must be called before do_realize
430 self.setAnimationEnable(animation)
434 IconGrid.do_realize(self, self.config)
436 self.setSize(self.size)
443 def setSize(self, size):
444 IconGrid.setSize(self, size)
446 w=self.size[0] * self.config.getIconSizeFull()
447 h=self.size[1] * self.config.getIconSizeFull()
449 self.set_size_request(w, h)
453 self.clearAnimationCache()
455 self.setSize(self.size)
456 self.icons.resizeMax()
459 def do_realize(self):
460 # print "igw-realize"
461 screen=self.get_screen()
462 self.set_colormap(screen.get_rgba_colormap())
463 self.set_app_paintable(True)
465 self.set_flags(self.flags() | gtk.REALIZED)
467 self.window=gdk.Window(
468 self.get_parent_window(),
469 width=self.allocation.width,
470 height=self.allocation.height,
471 window_type=gdk.WINDOW_CHILD,
472 wclass=gdk.INPUT_OUTPUT,
473 event_mask=self.get_events() | gdk.EXPOSURE_MASK
474 | gdk.BUTTON_PRESS_MASK
475 | gdk.BUTTON_RELEASE_MASK
476 | gdk.BUTTON_MOTION_MASK
477 | gdk.POINTER_MOTION_MASK
478 | gdk.POINTER_MOTION_HINT_MASK
479 | gdk.ENTER_NOTIFY_MASK
480 | gdk.LEAVE_NOTIFY_MASK )
482 self.window.set_user_data(self)
484 # No matter what the pygtk widget demo says, this is NOT CORRECT!!!
485 # Don't call style.attach(self.window) or else the program will crash
486 # after some time! It seems that there is a style already.
487 # If we want to use the style the we use get_style() instead.
488 # This one was very hard to solve. Thanks to gnome2-globalmenu guys.
489 # It was solved by looking the commit 2666:
491 # svn diff -r2665:2666 http://gnome2-globalmenu.googlecode.com/svn/trunk
492 # which solved cse 490:
493 # http://code.google.com/p/gnome2-globalmenu/issues/detail?id=490
494 # self.style.attach(self.window)
495 style=self.get_style()
497 # style.set_background(self.window, gtk.STATE_NORMAL)
498 self.window.move_resize(*self.allocation)
500 # self.pixmap, mask = gtk.gdk.pixmap_create_from_xpm_d(
501 # self.window, self.style.bg[gtk.STATE_NORMAL], STAR_PIXMAP)
503 # self.gc = self.style.fg_gc[gtk.STATE_NORMAL]
505 #HomePluginItem.do_realize(self)
507 # screen=self.get_screen()
508 # self.set_colormap(screen.get_rgba_colormap())
509 # self.set_app_paintable(True)
511 def do_unrealize(self):
512 # print "igw-unrealize", self
513 IconGrid.do_unrealize(self)
514 self.window.destroy()
515 self.window.set_user_data(None)
517 def do_expose_event(self, event):
518 cr=self.window.cairo_create()
520 cr.rectangle(event.area.x, event.area.y,
521 event.area.width, event.area.height)
524 style=self.get_style()
525 col=style.bg[gtk.STATE_NORMAL]
526 cr.set_source_color(col)
529 IconGrid.do_expose_event(self, event)
531 #gobject.type_register(IconGrid)
532 gobject.type_register(IconGridWidget)
535 # vim: set ts=8 sts=4 sw=4 noet formatoptions=r ai nocindent: