import cairo import clutter import gtk from cluttercairo import CairoTexture """ This element is a Clutter Group that displays as a rectangle of arbitary size with rounded corners. It is rendered using Cairo but maybe treated as per any other Clutter element """ class RoundedRectangle(clutter.Group): ARC_TO_BEZIER = 0.55228475 RADIUS = 5 MARGIN = 1 def __init__(self, width, height, colour = clutter.color_parse('Black')): clutter.Group.__init__(self) self.width = width self.height = height self.colour = colour margin = self.MARGIN radius = self.RADIUS #CairoTexture.__init__(self, width, height) #context = self.cairo_create() self.texture = CairoTexture(self.width, self.height) self.add(self.texture) self.texture.show() self.setup_rounded_context() self.refresh() def setup_rounded_context(self): # Round corners x = 0 + self.MARGIN y = 0 + self.MARGIN w = self.width - (self.MARGIN * 2) h = self.height - (self.MARGIN * 2) radius_x = self.RADIUS radius_y = self.RADIUS old_tex = self.texture self.texture = CairoTexture(self.width, self.height) self.add(self.texture) self.texture.show() self.remove(old_tex) context = self.texture.cairo_create() #Clear the texture #if not self.context is None: context.set_operator(cairo.OPERATOR_CLEAR) context.paint() context.set_operator(cairo.OPERATOR_OVER) """ Clip cairo texture with rounded rectangle. """ if radius_x > w - radius_x: radius_x = w / 2 if radius_y > h - radius_y: radius_y = h / 2 #approximate (quite close) the arc using a bezier curve c1 = self.ARC_TO_BEZIER * radius_x c2 = self.ARC_TO_BEZIER * radius_y context.new_path(); context.move_to ( x + radius_x, y) context.rel_line_to ( w - 2 * radius_x, 0.0) context.rel_curve_to ( c1, 0.0, radius_x, c2, radius_x, radius_y) context.rel_line_to ( 0, h - 2 * radius_y) context.rel_curve_to ( 0.0, c2, c1 - radius_x, radius_y, -radius_x, radius_y) context.rel_line_to ( -w + 2 * radius_x, 0) context.rel_curve_to ( -c1, 0, -radius_x, -c2, -radius_x, -radius_y) context.rel_line_to (0, -h + 2 * radius_y) context.rel_curve_to (0.0, -c2, radius_x - c1, -radius_y, radius_x, -radius_y) context.close_path() context.clip() #context = self.get_rounded_context(x ,y, w1, h1, radius, radius) self.ct = gtk.gdk.CairoContext(context) # Scale context area #wr = width / float(pixbuf.get_width()) #hr = height / float(pixbuf.get_height()) #context.scale(wr,hr) self.ct.rectangle( (0, 0, self.width, self.height) ) self.context = context #Set the colour self.context.set_source_rgb(self.colour.red, self.colour.green, self.colour.blue) def refresh(self): self.context.paint() del self.context # Update texture del self.ct def set_width(self, new_width): #self.texture.set_width(new_width) #self.texture.set_clip(0, 0, new_width, self.height) self.width = new_width self.setup_rounded_context() self.refresh() clutter.Group.set_width(self, new_width) def set_height(self, new_height): self.height = new_height self.setup_rounded_context() self.refresh() clutter.Group.set_height(self,new_height) def set_size(self, new_width, new_height): self.set_width(new_width) self.set_height(new_height) def set_color(self, new_colour): self.setup_rounded_context() self.colour = new_colour self.refresh() #self.texture.set_color(new_colour)