home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / python2.4 / site-packages / serpentine / gdkpiechart.py < prev    next >
Encoding:
Python Source  |  2006-08-23  |  6.9 KB  |  246 lines

  1. # Copyright (C) 2005 Tiago Cogumbreiro <cogumbreiro@users.sf.net>
  2. #
  3. # This library is free software; you can redistribute it and/or
  4. # modify it under the terms of the GNU Library General Public
  5. # License as published by the Free Software Foundation; either
  6. # version 2 of the License, or (at your option) any later version.
  7. #
  8. # This library is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11. # Library General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU Library General Public
  14. # License along with this library; if not, write to the
  15. # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  16. # Boston, MA 02111-1307, USA.
  17. #
  18. # Authors: Tiago Cogumbreiro <cogumbreiro@users.sf.net>
  19.  
  20. import gobject
  21. import gtk.gdk
  22. import gtk
  23. import math
  24. import os
  25.  
  26. from gtk import DrawingArea
  27. from math import cos, sin
  28. from weakref import ref
  29. from cairopiechart import CairoPieChart
  30.  
  31. _CIRCLE = 360 * 64
  32.  
  33.  
  34. class GdkPieChart (DrawingArea):
  35.     def __init__ (self, values, getter):
  36.         DrawingArea.__init__ (self)
  37.         self.gc = None
  38.         self.width = 0
  39.         self.height = 0
  40.         self.selected = []
  41.         self.total = 0
  42.         self.offset = 1
  43.         self.getter = getter
  44.         self.values = values
  45.         self.connect ("size-allocate", self.__on_size_allocate)
  46.         self.connect ("expose-event", self.__on_expose_event)
  47.         self.connect ("realize", self.__on_realize)
  48.     
  49.     def __on_realize (self, widget):
  50.         style = self.get_style ()
  51.         self.border_gc         = style.dark_gc[gtk.STATE_NORMAL]
  52.         self.transparent_gc    = style.bg_gc[gtk.STATE_NORMAL]
  53.         self.background_gc     = style.mid_gc[gtk.STATE_NORMAL]
  54.         self.slice_gc          = style.base_gc[gtk.STATE_NORMAL]
  55.         self.selected_slice_gc = style.base_gc[gtk.STATE_SELECTED]
  56.     
  57.     def __on_size_allocate (self, widget, allocation):
  58.         self.width = allocation.width
  59.         self.height = allocation.height
  60.     
  61.     def draw_slice (self, gc, offset, aperture):
  62.         self.window.draw_arc (
  63.             gc,
  64.             True,
  65.             0, # x
  66.             0, # y
  67.             self.radius, # width
  68.             self.radius, # height
  69.             offset,
  70.             aperture,
  71.         )
  72.     
  73.     def draw_circle (self, gc):
  74.         self.draw_slice (gc, 0, _CIRCLE)
  75.         
  76.     def __on_expose_event (self, widget, event):
  77.         offset = 0
  78.         
  79.         # Reset the selected index
  80.         selected_slices = []
  81.         index = 0
  82.         
  83.         # Get the real total
  84.         total = 0
  85.         for v in self.values:
  86.             total  += self.getter (v)
  87.         # Check if the gauge is filled    
  88.         filled = total >= self.total
  89.         
  90.         self.draw_circle (self.background_gc)
  91.         
  92.         ratio = _CIRCLE / float (self.total)
  93.         
  94.         for value in self.values:
  95.             # Get the angle aperture
  96.             angle = int (self.getter (value) * ratio)
  97.             
  98.             if index in self.selected:
  99.                 #color = self.selected_color
  100.                 selected_slices.append ((offset, angle))
  101.                 
  102.             elif not filled:
  103.                 self.draw_slice (self.slice_gc, offset, angle)
  104.                 
  105.             offset += angle
  106.             index += 1
  107.         
  108.         # When everything is filled we just paint a slice circle
  109.         if filled:
  110.             # Draw the border
  111.             self.draw_circle (self.slice_gc)
  112.         
  113.         for offset, angle in selected_slices:
  114.             self.draw_slice (self.selected_slice_gc, offset, angle)
  115.         
  116.         # Draw the little dial
  117.         r = int (self.radius / 4)
  118.         dx = self.radius/2 - r/2
  119.         self.window.draw_arc (
  120.             self.transparent_gc,
  121.             True,
  122.             dx,    # x
  123.             dx,    # y
  124.             r,
  125.             r,
  126.             0,
  127.             _CIRCLE
  128.         )
  129.         # Draw inner dial border
  130.         self.window.draw_arc (
  131.             self.border_gc,
  132.             False,
  133.             dx,    # x
  134.             dx,    # y
  135.             r,
  136.             r,
  137.             0,
  138.             _CIRCLE
  139.         )
  140.  
  141.         
  142.         # Draw the border
  143.         self.window.draw_arc (
  144.             self.border_gc,
  145.             False,
  146.             0,
  147.             0,
  148.             self.radius,
  149.             self.radius,
  150.             0,
  151.             _CIRCLE
  152.         )
  153.     
  154.     def get_radius (self):
  155.         return min (self.width, self.height) - self.offset
  156.  
  157.     radius = property (get_radius)
  158.     
  159.  
  160.  
  161. # Use the correct widget renderer
  162. if hasattr(gtk.gdk.Drawable, "cairo_create") or os.environ.get("SERP_USE_GDK", "") != "yes": 
  163.     PieChart = CairoPieChart
  164. else:
  165.     PieChart = GdkPieChart
  166.  
  167. class SerpentineUsage (object):
  168.     def __init__ (self, parent):
  169.         self.__parent = ref (parent)
  170.         self.__overflow = False
  171.         
  172.         self.widget = PieChart (values = self.parent.source,
  173.                                    getter = lambda value: value['duration'])
  174.         self.widget.total = self.parent.disc_size
  175.         # Register as a GtkMusicList listener
  176.         self.parent.source.listeners.append (self)
  177.         # Register as a AudioMastering listener
  178.         self.parent.listeners.append (self)
  179.     
  180.     # Basic properties
  181.     def get_parent (self):
  182.         return self.__parent()
  183.     parent = property (get_parent)
  184.     
  185.     def __set_overflow (self, is_overflow):
  186.         self.widget.filled = is_overflow
  187.         self.__is_overflow = is_overflow
  188.     
  189.     def __get_overflow (self):
  190.         return self.__overflow
  191.     
  192.     overflow = property (__get_overflow, __set_overflow)
  193.     # Clean up references
  194.     del __set_overflow, __get_overflow
  195.     
  196.     # GtkMusicList listener
  197.     def on_contents_changed (self, *args):
  198.         self.widget.queue_draw ()
  199.         self.__update ()
  200.         
  201.     def on_musics_added (self, e, rows):
  202.         self.widget.queue_draw ()
  203.         self.__update ()
  204.     
  205.     on_musics_removed = on_musics_added
  206.     
  207.     def __update (self):
  208.         self.overflow = self.widget.total < self.parent.source.total_duration
  209.     
  210.     # AudioMasterer listener
  211.     def on_selection_changed (self, e):
  212.         if not self.overflow:
  213.             self.widget.selected = self.parent.get_selected ()
  214.             self.widget.queue_draw ()
  215.     
  216.     def on_disc_size_changed (self, e):
  217.         self.widget.total = self.parent.disc_size
  218.         self.__update ()
  219.         self.widget.queue_draw ()
  220.         
  221.  
  222. if __name__ == '__main__':
  223.     import gtk
  224.     
  225.     def cb (widget):
  226.         widget.selected += 1
  227.         widget.selected %= len (widget.values)
  228.         widget.queue_draw ()
  229.         return True
  230.     
  231.     w = gtk.Window (gtk.WINDOW_TOPLEVEL)
  232.     vals = [dict(value=v) for v in [10, 3, 5]]
  233.     pie = GdkPieChart (vals)
  234.     pie.values = vals
  235.     total = 0
  236.     for v in vals:
  237.         total += v['value']
  238.     pie.total = total #* 2
  239.     pie.selected = [1]
  240.     pie.show ()
  241.     w.add (pie)
  242.     w.show ()
  243.     w.connect ("delete-event", gtk.main_quit)
  244.     gobject.timeout_add (250, cb, pie)
  245.     gtk.main ()
  246.