Package screenlets :: Module drawing

[hide private]
[frames] | no frames]

# Source Code for Module screenlets.drawing

      1  # This application is released under the GNU General Public License
      2  # v3 (or, at your option, any later version). You can find the full
      3  # text of the license under http://www.gnu.org/licenses/gpl.txt.
      4  # By using, editing and/or distributing this software you agree to
      5  # the terms and conditions of this license.
      6  # Thank you for using free software!
      7
      8  # Screenlets Drawing Helder Fraga aka Whise <helder.fraga@hotmail.com>
      9
     10
     11  import gtk, cairo, pango, math
     12
     13 -class Drawing:
     14          """Contains static drawing functions."""
     15
     16          # ----------------------------------------------------------------------
     17          # Screenlet's Drawing functions
     18          # ----------------------------------------------------------------------
     19          p_context               = None          # PangoContext
     20          p_layout                = None          # PangoLayout
     21
     22 -        def get_text_width(self, ctx, text, font):
     23                  """Returns the pixel width of a given text"""
     24                  ctx.save()
     25                  if self.p_layout == None :
     26
     27                          self.p_layout = ctx.create_layout()
     28                  else:
     29
     30                          ctx.update_layout(self.p_layout)
     31                  if self.p_fdesc == None:self.p_fdesc = pango.FontDescription()
     32                  else: pass
     33                  self.p_fdesc.set_family_static(font)
     34                  self.p_layout.set_font_description(self.p_fdesc)
     35                  self.p_layout.set_text(text)
     36                  extents, lextents = self.p_layout.get_pixel_extents()
     37                  ctx.restore()
     38                  return extents[2]
     39
     40 -        def get_text_width(self, ctx, text, font):
     41                  """Returns the pixel width of a given text"""
     42                  ctx.save()
     43                  if self.p_layout == None :
     44
     45                          self.p_layout = ctx.create_layout()
     46                  else:
     47
     48                          ctx.update_layout(self.p_layout)
     49                  if self.p_fdesc == None:self.p_fdesc = pango.FontDescription()
     50                  else: pass
     51                  self.p_fdesc.set_family_static(font)
     52                  self.p_layout.set_font_description(self.p_fdesc)
     53                  self.p_layout.set_text(text)
     54                  extents, lextents = self.p_layout.get_pixel_extents()
     55                  ctx.restore()
     56                  return extents[2]
     57
     58 -        def get_text_line_count(self, ctx, text, font):
     59                  """Returns the line count of a given text"""
     60                  ctx.save()
     61                  if self.p_layout == None :
     62
     63                          self.p_layout = ctx.create_layout()
     64                  else:
     65
     66                          ctx.update_layout(self.p_layout)
     67                  if self.p_fdesc == None:self.p_fdesc = pango.FontDescription()
     68                  else: pass
     69                  self.p_fdesc.set_family_static(font)
     70                  self.p_layout.set_font_description(self.p_fdesc)
     71                  self.p_layout.set_text(text)
     72                  ctx.restore()
     73                  return self.p_layout.get_line_count()
     74
     75 -        def get_text_line(self, ctx, text, font, line):
     76                  """Returns a line of a given text"""
     77                  ctx.save()
     78                  if self.p_layout == None :
     79
     80                          self.p_layout = ctx.create_layout()
     81                  else:
     82
     83                          ctx.update_layout(self.p_layout)
     84                  if self.p_fdesc == None:self.p_fdesc = pango.FontDescription()
     85                  else: pass
     86                  self.p_fdesc.set_family_static(font)
     87                  self.p_layout.set_font_description(self.p_fdesc)
     88                  self.p_layout.set_text(text)
     89                  ctx.restore()
     90                  return self.p_layout.get_line(line)
     91
     92 -        def check_for_icon(self,icon):
     93                  try:
     94                          icontheme = gtk.icon_theme_get_default()
     95                          image = icontheme.load_icon (icon,32,32)
     96                          image = None
     97                          icontheme = None
     98                          return True
     99                  except:
    100                          return False
    101
    102 -        def draw_text(self, ctx, text, x, y,  font, size, width, allignment=pango.ALIGN_LEFT,alignment=None,justify = False,weight = 0, ellipsize = pango.ELLIPSIZE_NONE):
    103                  """Draws text"""
    104                  ctx.save()
    105                  ctx.translate(x, y)
    106                  if self.p_layout == None :
    107
    108                          self.p_layout = ctx.create_layout()
    109                  else:
    110
    111                          ctx.update_layout(self.p_layout)
    112                  if self.p_fdesc == None:self.p_fdesc = pango.FontDescription()
    113                  else: pass
    114                  self.p_fdesc.set_family_static(font)
    115                  self.p_fdesc.set_size(size * pango.SCALE)
    116                  self.p_fdesc.set_weight(weight)
    117                  self.p_layout.set_font_description(self.p_fdesc)
    118                  self.p_layout.set_width(width * pango.SCALE)
    119                  self.p_layout.set_alignment(allignment)
    120                  if alignment != None:self.p_layout.set_alignment(alignment)
    121                  self.p_layout.set_justify(justify)
    122                  self.p_layout.set_ellipsize(ellipsize)
    123                  self.p_layout.set_markup(text)
    124                  ctx.show_layout(self.p_layout)
    125                  ctx.restore()
    126
    127
    128 -        def draw_circle(self,ctx,x,y,width,height,fill=True):
    129                  """Draws a circule"""
    130                  ctx.save()
    131                  ctx.translate(x, y)
    132                  ctx.arc(width/2,height/2,min(height,width)/2,0,2*math.pi)
    133                  if fill:ctx.fill()
    134                  else: ctx.stroke()
    135                  ctx.restore()
    136
    137
    138 -        def draw_triangle(self,ctx,x,y,width,height,fill=True):
    139                  """Draws a circule"""
    140                  ctx.save()
    141                  ctx.translate(x, y)
    142                  ctx.move_to(width-(width/3), height/3)
    143                  ctx.line_to(width,height)
    144                  ctx.rel_line_to(-(width-(width/3)), 0)
    145                  ctx.close_path()
    146                  if fill:ctx.fill()
    147                  else: ctx.stroke()
    148                  ctx.restore()
    149
    150 -        def draw_line(self,ctx,start_x,start_y,end_x,end_y,line_width = 1,close=False,preserve=False):
    151                  """Draws a line"""
    152                  ctx.save()
    153                  ctx.move_to(start_x, start_y)
    154                  ctx.set_line_width(line_width)
    155                  ctx.rel_line_to(end_x, end_y)
    156                  if close : ctx.close_path()
    157                  if preserve: ctx.stroke_preserve()
    158                  else: ctx.stroke()
    159                  ctx.restore()
    160
    161 -        def draw_rectangle(self,ctx,x,y,width,height,fill=True):
    162                  """Draws a rectangle"""
    163                  ctx.save()
    164                  ctx.translate(x, y)
    165                  ctx.rectangle (0,0,width,height)
    166                  if fill:ctx.fill()
    167                  else: ctx.stroke()
    168                  ctx.restore()
    169
    170
    171 -        def draw_rectangle_advanced (self, ctx, x, y, width, height, rounded_angles=(0,0,0,0), fill=True, border_size=0, border_color=(0,0,0,1), shadow_size=0, shadow_color=(0,0,0,0.5)):
    172                  '''with this funktion you can create a rectangle in advanced mode'''
    173                  ctx.save()
    174                  ctx.translate(x, y)
    175                  s = shadow_size
    176                  w = width
    177                  h = height
    178                  rounded = rounded_angles
    179                  if shadow_size > 0:
    180                          ctx.save()
    181                          #top shadow
    182                          gradient = cairo.LinearGradient(0,s,0,0)
    183                          gradient.add_color_stop_rgba(0,*shadow_color)
    184                          gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0)
    185                          ctx.set_source(gradient)
    186                          ctx.rectangle(s+rounded[0],0, w-rounded[0]-rounded[1], s)
    187                          ctx.fill()
    188
    189                          #bottom
    190                          gradient = cairo.LinearGradient(0, s+h, 0, h+(s*2))
    191                          gradient.add_color_stop_rgba(0,*shadow_color)
    192                          gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0)
    193                          ctx.set_source(gradient)
    194                          ctx.rectangle(s+rounded[2], s+h, w-rounded[2]-rounded[3], s)
    195                          ctx.fill()
    196
    197                          #left
    198                          gradient = cairo.LinearGradient(s, 0, 0, 0)
    199                          gradient.add_color_stop_rgba(0,*shadow_color)
    200                          gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0)
    201                          ctx.set_source(gradient)
    202                          ctx.rectangle(0, s+rounded[0], s, h-rounded[0]-rounded[2])
    203                          ctx.fill()
    204
    205                          #right
    206                          gradient = cairo.LinearGradient(s+w, 0, (s*2)+w, 0)
    207                          gradient.add_color_stop_rgba(0,*shadow_color)
    208                          gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0)
    209                          ctx.set_source(gradient)
    210                          ctx.rectangle(s+w, s+rounded[1], s, h-rounded[1]-rounded[3])
    211                          ctx.fill()
    212                          ctx.restore
    213
    214                          #top-left
    215                          gradient = cairo.RadialGradient(s+rounded[0], s+rounded[0], rounded[0], s+rounded[0], s+rounded[0], s+rounded[0])
    216                          gradient.add_color_stop_rgba(0,*shadow_color)
    217                          gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0)
    218                          ctx.set_source(gradient)
    219                          ctx.new_sub_path()
    220                          ctx.arc(s,s,s, -math.pi, -math.pi/2)
    221                          ctx.line_to(s+rounded[0],0)
    222                          ctx.line_to(s+rounded[0],s)
    223                          ctx.arc_negative(s+rounded[0],s+rounded[0],rounded[0], -math.pi/2, math.pi)
    224                          ctx.line_to(0, s+rounded[0])
    225                          ctx.close_path()
    226                          ctx.fill()
    227
    228                          #top-right
    229                          gradient = cairo.RadialGradient(w+s-rounded[1], s+rounded[1], rounded[1], w+s-rounded[1], s+rounded[1], s+rounded[1])
    230                          gradient.add_color_stop_rgba(0,*shadow_color)
    231                          gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0)
    232                          ctx.set_source(gradient)
    233                          ctx.new_sub_path()
    234                          ctx.arc(w+s,s,s, -math.pi/2, 0)
    235                          ctx.line_to(w+(s*2), s+rounded[1])
    236                          ctx.line_to(w+s, s+rounded[1])
    237                          ctx.arc_negative(w+s-rounded[1], s+rounded[1], rounded[1], 0, -math.pi/2)
    238                          ctx.line_to(w+s-rounded[1], 0)
    239                          ctx.close_path()
    240                          ctx.fill()
    241
    242                          #bottom-left
    243                          gradient = cairo.RadialGradient(s+rounded[2], h+s-rounded[2], rounded[2], s+rounded[2], h+s-rounded[2], s+rounded[2])
    244                          gradient.add_color_stop_rgba(0,*shadow_color)
    245                          gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0)
    246                          ctx.set_source(gradient)
    247                          ctx.new_sub_path()
    248                          ctx.arc(s,h+s,s, math.pi/2, math.pi)
    249                          ctx.line_to(0, h+s-rounded[2])
    250                          ctx.line_to(s, h+s-rounded[2])
    251                          ctx.arc_negative(s+rounded[2], h+s-rounded[2], rounded[2], -math.pi, math.pi/2)
    252                          ctx.line_to(s+rounded[2], h+(s*2))
    253                          ctx.close_path()
    254                          ctx.fill()
    255
    256                          #bottom-right
    257                          gradient = cairo.RadialGradient(w+s-rounded[3], h+s-rounded[3], rounded[3], w+s-rounded[3], h+s-rounded[3], s+rounded[3])
    258                          gradient.add_color_stop_rgba(0,*shadow_color)
    259                          gradient.add_color_stop_rgba(1,shadow_color[0], shadow_color[1], shadow_color[2], 0)
    260                          ctx.set_source(gradient)
    261                          ctx.new_sub_path()
    262                          ctx.arc(w+s,h+s,s, 0, math.pi/2)
    263                          ctx.line_to(w+s-rounded[3], h+(s*2))
    264                          ctx.line_to(w+s-rounded[3], h+s)
    265                          ctx.arc_negative(s+w-rounded[3], s+h-rounded[3], rounded[3], math.pi/2, 0)
    266                          ctx.line_to((s*2)+w, s+h-rounded[3])
    267                          ctx.close_path()
    268                          ctx.fill()
    269                          ctx.restore()
    270
    271                          #the content starts here!
    272                          ctx.translate(s, s)
    273                  else:
    274                          ctx.translate(border_size, border_size)
    275
    276                  #and now the rectangle
    277                  if fill:
    278                          ctx.line_to(0, rounded[0])
    279                          ctx.arc(rounded[0], rounded[0], rounded[0], math.pi, -math.pi/2)
    280                          ctx.line_to(w-rounded[1], 0)
    281                          ctx.arc(w-rounded[1], rounded[1], rounded[1], -math.pi/2, 0)
    282                          ctx.line_to(w, h-rounded[3])
    283                          ctx.arc(w-rounded[3], h-rounded[3], rounded[3], 0, math.pi/2)
    284                          ctx.line_to(rounded[2], h)
    285                          ctx.arc(rounded[2], h-rounded[2], rounded[2], math.pi/2, -math.pi)
    286                          ctx.close_path()
    287                          ctx.fill()
    288
    289                  if border_size > 0:
    290                          ctx.save()
    291                          ctx.line_to(0, rounded[0])
    292                          ctx.arc(rounded[0], rounded[0], rounded[0], math.pi, -math.pi/2)
    293                          ctx.line_to(w-rounded[1], 0)
    294                          ctx.arc(w-rounded[1], rounded[1], rounded[1], -math.pi/2, 0)
    295                          ctx.line_to(w, h-rounded[3])
    296                          ctx.arc(w-rounded[3], h-rounded[3], rounded[3], 0, math.pi/2)
    297                          ctx.line_to(rounded[2], h)
    298                          ctx.arc(rounded[2], h-rounded[2], rounded[2], math.pi/2, -math.pi)
    299                          ctx.close_path()
    300                          ctx.set_source_rgba(*border_color)
    301                          ctx.set_line_width(border_size)
    302                          ctx.stroke()
    303                          ctx.restore()
    304                  ctx.restore()
    305
    306 -        def draw_rounded_rectangle(self,ctx,x,y,rounded_angle,width,height,round_top_left = True ,round_top_right = True,round_bottom_left = True,round_bottom_right = True, fill=True):
    307                  """Draws a rounded rectangle"""
    308                  ctx.save()
    309                  ctx.translate(x, y)
    310                  padding=0 # Padding from the edges of the window
    311                  rounded=rounded_angle # How round to make the edges 20 is ok
    312                  w = width
    313                  h = height
    314
    315                  # Move to top corner
    316                  ctx.move_to(0+padding+rounded, 0+padding)
    317
    318                  # Top right corner and round the edge
    319                  if round_top_right:
    320                          ctx.line_to(w-padding-rounded, 0+padding)
    321                          ctx.arc(w-padding-rounded, 0+padding+rounded, rounded, (math.pi/2 )+(math.pi) , 0)
    322                  else:
    323                          ctx.line_to(w-padding, 0+padding)
    324
    325                  # Bottom right corner and round the edge
    326                  if round_bottom_right:
    327                          ctx.line_to(w-padding, h-padding-rounded)
    328                          ctx.arc(w-padding-rounded, h-padding-rounded, rounded, 0, math.pi/2)
    329                  else:
    330                          ctx.line_to(w-padding, h-padding)
    331                  # Bottom left corner and round the edge.
    332                  if round_bottom_left:
    333                          ctx.line_to(0+padding+rounded, h-padding)
    334                          ctx.arc(0+padding+rounded, h-padding-rounded, rounded,math.pi/2, math.pi)
    335                  else:
    336                          ctx.line_to(0+padding, h-padding)
    337                  # Top left corner and round the edge
    338                  if round_top_left:
    339                          ctx.line_to(0+padding, 0+padding+rounded)
    340                          ctx.arc(0+padding+rounded, 0+padding+rounded, rounded, math.pi, (math.pi/2 )+(math.pi))
    341                  else:
    342                          ctx.line_to(0+padding, 0+padding)
    343                  # Fill in the shape.
    344                  if fill:ctx.fill()
    345                  else: ctx.stroke()
    346                  ctx.restore()
    347
    348 -        def draw_quadrant_shadow(self, ctx, x, y, from_r, to_r, quad, col):
    349                  gradient = cairo.RadialGradient(x,y,from_r,x,y,to_r)
    350                  gradient.add_color_stop_rgba(0,col[0],col[1],col[2],col[3])
    351                  gradient.add_color_stop_rgba(1,col[0],col[1],col[2],0)
    352                  ctx.set_source(gradient)
    353                  ctx.new_sub_path()
    354                  if quad==0: ctx.arc(x,y,to_r, -math.pi, -math.pi/2)
    355                  elif quad==1: ctx.arc(x,y,to_r, -math.pi/2, 0)
    356                  elif quad==2: ctx.arc(x,y,to_r, math.pi/2, math.pi)
    357                  elif quad==3: ctx.arc(x,y,to_r, 0, math.pi/2)
    358                  ctx.line_to(x,y)
    359                  ctx.close_path()
    360                  ctx.fill()
    361
    362          # side: 0 - left, 1 - right, 2 - top, 3 - bottom
    363 -        def draw_side_shadow(self, ctx, x, y, w, h, side, col):
    364                  gradient = None
    365                  if side==0:
    366                          gradient = cairo.LinearGradient(x+w,y,x,y)
    367                  elif side==1:
    368                          gradient = cairo.LinearGradient(x,y,x+w,y)
    369                  elif side==2:
    370                          gradient = cairo.LinearGradient(x,y+h,x,y)
    371                  elif side==3:
    372                          gradient = cairo.LinearGradient(x,y,x,y+h)
    373                  if gradient:
    374                          gradient.add_color_stop_rgba(0,col[0],col[1],col[2],col[3])
    375                          gradient.add_color_stop_rgba(1,col[0],col[1],col[2],0)
    376                          ctx.set_source(gradient)
    377                  ctx.rectangle(x,y,w,h)
    378                  ctx.fill()
    379
    380 -        def draw_shadow(self, ctx, x, y, w, h, shadow_size, col):
    381                  s = shadow_size
    382                  #r = self.layout.window.radius
    383                  r = s
    384                  rr = r+s
    385                  h = h-r
    386                  if h < 2*r: h = 2*r
    387
    388                  # TODO: Offsets [Will need to change all places doing
    389                  #       x+=shadow_size/2 or such to use the offsets then
    390                  ctx.save()
    391                  ctx.translate(x,y)
    392
    393                  # Top Left
    394                  self.draw_quadrant_shadow(ctx, rr, rr, 0, rr, 0, col)
    395                  # Left
    396                  self.draw_side_shadow(ctx, 0, rr, r+s, h-2*r, 0, col)
    397                  # Bottom Left
    398                  self.draw_quadrant_shadow(ctx, rr, h-r+s, 0, rr, 2, col)
    399                  # Bottom
    400                  self.draw_side_shadow(ctx, rr, h-r+s, w-2*r, s+r, 3, col)
    401                  # Bottom Right
    402                  self.draw_quadrant_shadow(ctx, w-r+s, h-r+s, 0, rr, 3, col)
    403                  # Right
    404                  self.draw_side_shadow(ctx, w-r+s, rr, s+r, h-2*r, 1, col)
    405                  # Top Right
    406                  self.draw_quadrant_shadow(ctx, w-r+s, rr, 0, rr, 1, col)
    407                  # Top
    408                  self.draw_side_shadow(ctx, rr, 0, w-2*r, s+r, 2, col)
    409
    410                  ctx.restore()
    411
    412
    413
    414 -        def get_image_size(self,pix):
    415                  """Gets a picture width and height"""
    416
    417                  pixbuf = gtk.gdk.pixbuf_new_from_file(pix)
    418                  iw = pixbuf.get_width()
    419                  ih = pixbuf.get_height()
    420                  puxbuf = None
    421                  return iw,ih
    422
    423 -        def draw_image(self,ctx,x,y, pix):
    424                  """Draws a picture from specified path"""
    425
    426                  ctx.save()
    427                  ctx.translate(x, y)
    428                  pixbuf = gtk.gdk.pixbuf_new_from_file(pix)
    429                  format = cairo.FORMAT_RGB24
    430                  if pixbuf.get_has_alpha():
    431                          format = cairo.FORMAT_ARGB32
    432
    433                  iw = pixbuf.get_width()
    434                  ih = pixbuf.get_height()
    435                  image = cairo.ImageSurface(format, iw, ih)
    436                  image = ctx.set_source_pixbuf(pixbuf, 0, 0)
    437
    438                  ctx.paint()
    439                  puxbuf = None
    440                  image = None
    441                  ctx.restore()
    442
    443 -        def draw_icon(self,ctx,x,y, pix,width=32,height=32):
    444                  """Draws a gtk icon """
    445
    446                  ctx.save()
    447                  ctx.translate(x, y)
    448                  icontheme = gtk.icon_theme_get_default()
    449                  image = icontheme.load_icon (pix,width,height)
    450                  ctx.set_source_pixbuf(image, 0, 0)
    451                  ctx.paint()
    452                  icontheme = None
    453                  image = None
    454                  ctx.restore()
    455
    456 -        def draw_scaled_image(self,ctx,x,y, pix, w, h):
    457                  """Draws a picture from specified path with a certain width and height"""
    458
    459                  ctx.save()
    460                  ctx.translate(x, y)
    461                  pixbuf = gtk.gdk.pixbuf_new_from_file(pix).scale_simple(w,h,gtk.gdk.INTERP_HYPER)
    462                  format = cairo.FORMAT_RGB24
    463                  if pixbuf.get_has_alpha():
    464                          format = cairo.FORMAT_ARGB32
    465
    466                  iw = pixbuf.get_width()
    467                  ih = pixbuf.get_height()
    468                  image = cairo.ImageSurface(format, iw, ih)
    469
    470                  matrix = cairo.Matrix(xx=iw/w, yy=ih/h)
    471                  image = ctx.set_source_pixbuf(pixbuf, 0, 0)
    472                  if image != None :image.set_matrix(matrix)
    473                  ctx.paint()
    474                  puxbuf = None
    475                  image = None
    476                  ctx.restore()
    477