Refactored a lot of code. Added a preliminary text window

Put configuration options for window so that the rendering is controlled
on initialization of window.

Improved clip function to only clip before the borders.

Added a border radius class for initializing separate border radii for
each corner.
This commit is contained in:
Joey Payne 2014-02-04 22:54:05 -07:00
commit 3a31732a14
5 changed files with 337 additions and 152 deletions

View file

@ -1,4 +1,4 @@
from jgui.surface.surface import *
from testclasses import *
import pygtk, gtk, gobject, cairo
from gtk import gdk

View file

@ -100,15 +100,67 @@ class Size(StructureBase):
other = Size.from_value(other)
return Size(self.width+other.width, self.height+other.height)
def __lt__(self, other):
other = Size.from_value(other)
return self.area() < other.area()
def __gt__(self, other):
other = Size.from_value(other)
return self.area() > other.area()
def __sub__(self, other):
other = Size.from_value(other)
return Size(self.width-other.width, self.height-other.height)
def __mul__(self, other):
if isinstance(other, (int, long, float)):
return Size(self.width*other, self.height*other)
def area(self):
return self.width*self.height
def __iter__(self):
yield self.width
yield self.height
class BorderRadius(StructureBase):
def __init__(self, *args, **kwargs):
values = self._parse_value(args)
self.topleft = kwargs.get('topleft', values[0])
self.topright = kwargs.get('topright', values[1])
self.bottomright = kwargs.get('bottomright', values[2])
self.bottomleft = kwargs.get('bottomleft', values[3])
def __iter__(self):
yield self.topleft
yield self.topright
yield self.bottomright
yield self.bottomleft
@classmethod
def _parse_value(cls, value):
f = lambda *args: args
try:
args = f(*value)
if len(args) == 1:
return args*4
if len(args) == 2:
return args*2
if len(args) == 3:
return [args[0], args[1], args[2], args[1]]
if len(args) == 4:
return args
except TypeError:
return [value]*4
return [0]*4
@classmethod
def from_value(cls, value):
return cls(*cls._parse_value(value))
class Color(StructureBase):
def __init__(self, r=0, g=0, b=0, a=1):
self.r = float(r)

View file

@ -1,6 +1,6 @@
import cairo
import math
from .structures import Size, Position, Rectangle, Color
from .structures import Size, Position, Rectangle, Color, BorderRadius
from ..events.events import WindowEventSource
debug = True
@ -13,10 +13,10 @@ class Surface(object):
self.context = cairo.Context(self.csurface)
else:
self.context = context
self.root_window = Window('root', Position(0,0), self.size, self.context)
self.root_window = Window('root', position=Position(0,0), size=self.size, context=self.context)
self.render_mouse = render_mouse
if self.render_mouse:
self.mouse_icon = Mouse('mouse', Position(0, 0), Size(12,20), self.context)
self.mouse_icon = Mouse('mouse', position=Position(0, 0), size=Size(12,20), context=self.context)
self.windows = [self.root_window, self.mouse_icon]
def setTopZero(self, context):
@ -59,14 +59,7 @@ class Surface(object):
for window in self.windows:
window.draw()
class TestSurface(Surface):
def __init__(self, *args, **kwargs):
super(TestSurface, self).__init__(*args, **kwargs)
self.root_window.add_child(MyWindow('child', Position(0,0), [500,200], self.context, draggable=True, resizable=True, min_size=Size(40,40)))
self.root_window.add_child(TestWindow('child2', Position(200,200), [200,200], self.context, draggable=True))
child3 = TestWindow('child3', Position(300,300), [200,200], self.context, draggable=True)
child3.add_child(TestWindow('child3-1', Position(10,10), [50,50], self.context, draggable=True))
self.root_window.add_child(child3)
class WindowSurface(object):
@ -82,7 +75,7 @@ class WindowSurface(object):
super(WindowSurface, self).__init__()
def draw_circle(self, position, size, color=(1,1,1), line_width=1.0, line_color=(0,0,0), start_angle=0.0, end_angle=360.0):
def draw_circle(self, position, size, color=(1,1,1,1), line_width=1.0, line_color=(0,0,0,1), start_angle=0.0, end_angle=360.0):
color = Color.from_value(color)
line_color = Color.from_value(line_color)
context = self.context
@ -107,12 +100,37 @@ class WindowSurface(object):
context.set_source_rgba(*line_color)
context.stroke()
def draw_lines(self, lines, line_color=(0,0,0,1), fill_color=(1,1,1,1), line_width=1, line_join='miter', line_cap='butt'):
def draw_text(self, text, position, size, color=(0,0,0,1), line_width=1.0, background_color=(1,1,1,0), fill_color=None):
color = Color.from_value(color)
background_color = Color.from_value(background_color)
position = Position.from_value(position)
size = Size.from_value(size)
context = self.context
width = size.width
height = size.height
context.set_line_width(line_width)
context.set_source_rgba(*color)
context.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
context.set_font_size(size.height)
extents = context.text_extents(text)
x,y = (self.position.x+position.x+2,
self.position.y+position.y+extents[3]+2)
context.move_to(x, y)
context.show_text(text)
def draw_lines(self, lines, line_color=(0,0,0,1), background_color=(1,1,1,1), line_width=1, line_join='miter', line_cap='butt'):
if lines:
line_color = Color.from_value(line_color)
background_color = Color.from_value(background_color)
context = self.context
start_pos = self.position + lines[0]
context.set_line_width(line_width)
context.move_to(int(start_pos.x), int(start_pos.y))
context.move_to(start_pos.x, start_pos.y)
for line in lines[1:]:
next_pos = self.position+line
context.line_to(next_pos.x, next_pos.y)
@ -125,17 +143,18 @@ class WindowSurface(object):
context.set_line_join(self.line_caps[line_cap])
except KeyError:
pass
context.set_source_rgba(*fill_color)
context.set_source_rgba(*background_color)
context.fill_preserve()
context.set_source_rgba(*line_color)
context.stroke()
def draw_rounded_rect(self, position, size, color=(1,1,1), line_width=1, line_color=(0,0,0), corner_radius=0, line_dashed=False, clip=False):
def draw_rounded_rect(self, position, size, background_color=(1,1,1), line_width=1, line_color=(0,0,0), corner_radius=0, line_dashed=False, clip=False):
position = Position.from_value(position)
size = Size.from_value(size)
color = Color.from_value(color)
background_color = Color.from_value(background_color)
line_color = Color.from_value(line_color)
corner_radius = BorderRadius.from_value(corner_radius)
context = self.context
radius = corner_radius
@ -144,23 +163,38 @@ class WindowSurface(object):
y = position.y + self.position.y
width = size.width
height = size.height
if clip: #clips the entire region so any child windows will be confined to the parent
context.arc(x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees)
context.arc(x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees)
context.arc(x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees)
context.arc(x + radius, y + radius, radius, 180 * degrees, 270 * degrees)
context.arc(x + width - radius.topright - line_width/2.0,
y + radius.topright + line_width/2.0,
radius.topright+self.border_width/2.0, -90 * degrees, 0 * degrees)
context.arc(x + width - radius.bottomright - line_width/2.0,
y + height - radius.bottomright - line_width/2.0,
radius.bottomright+self.border_width/2.0, 0 * degrees, 90 * degrees)
context.arc(x + radius.bottomleft + line_width/2.0,
y + height - radius.bottomleft - line_width/2.0,
radius.bottomleft+self.border_width/2.0, 90 * degrees, 180 * degrees)
context.arc(x + radius.topleft + line_width/2.0,
y + radius.topleft + line_width/2.0,
radius.topleft+self.border_width/2.0, 180 * degrees, 270 * degrees)
context.close_path()
context.clip()
context.new_path()
context.arc(x + width - radius - line_width/2.0, y + radius + line_width/2.0, radius, -90 * degrees, 0 * degrees)
context.arc(x + width - radius - line_width/2.0, y + height - radius - line_width/2.0, radius, 0 * degrees, 90 * degrees)
context.arc(x + radius + line_width/2.0, y + height - radius - line_width/2.0, radius, 90 * degrees, 180 * degrees)
context.arc(x + radius + line_width/2.0, y + radius + line_width/2.0, radius, 180 * degrees, 270 * degrees)
context.arc(x + width - radius.topright - line_width/2.0,
y + radius.topright + line_width/2.0,
radius.topright, -90 * degrees, 0 * degrees)
context.arc(x + width - radius.bottomright - line_width/2.0,
y + height - radius.bottomright - line_width/2.0,
radius.bottomright, 0 * degrees, 90 * degrees)
context.arc(x + radius.bottomleft + line_width/2.0,
y + height - radius.bottomleft - line_width/2.0,
radius.bottomleft, 90 * degrees, 180 * degrees)
context.arc(x + radius.topleft + line_width/2.0,
y + radius.topleft + line_width/2.0,
radius.topleft, 180 * degrees, 270 * degrees)
context.close_path()
context.set_source_rgba(*color)
context.set_source_rgba(*background_color)
context.fill_preserve()
context.set_source_rgba(*line_color)
context.set_line_width(line_width)
@ -170,9 +204,26 @@ class WindowSurface(object):
context.stroke()
context.restore()
if clip: #clips the entire region so any child windows will be confined to the parent
context.arc(x + width - radius.topright - line_width/2.0,
y + radius.topright + line_width/2.0,
radius.topright-self.border_width/2.0, -90 * degrees, 0 * degrees)
context.arc(x + width - radius.bottomright - line_width/2.0,
y + height - radius.bottomright - line_width/2.0,
radius.bottomright-self.border_width/2.0, 0 * degrees, 90 * degrees)
context.arc(x + radius.bottomleft + line_width/2.0,
y + height - radius.bottomleft - line_width/2.0,
radius.bottomleft-self.border_width/2.0, 90 * degrees, 180 * degrees)
context.arc(x + radius.topleft + line_width/2.0,
y + radius.topleft + line_width/2.0,
radius.topleft-self.border_width/2.0, 180 * degrees, 270 * degrees)
context.close_path()
context.clip()
def render(self):
if debug:
self.draw_rounded_rect([0,0], [self.size.width, self.size.height], color=(0,0,1,0.1), line_color=(0,0,1,0.4), line_width=1.5, corner_radius=2, line_dashed=True)
if debug and not self.ignore_debug:
self.draw_rounded_rect([0,0], [self.size.width, self.size.height], background_color=(0,0,1,0.1), line_color=(0,0,1,0.4), line_width=self.border_width+0.5, corner_radius=self.border_radius, line_dashed=True)
def draw(self):
if self.visible:
@ -184,35 +235,55 @@ class WindowSurface(object):
class Window(WindowEventSource, WindowSurface):
def __init__(self, name, position=None, size=None, context=None, draggable=False, resizable=False, **kwargs):
def __init__(self, name, **kwargs):
super(Window, self).__init__()
self.context = context
self._draggable = False
self._resizable = False
self.name = name
position = Position.from_value(kwargs.pop('position', Position()))
size = Size.from_value(kwargs.pop('size', Size()))
self.context = kwargs.pop('context', None)
self.min_size = kwargs.pop('min_size', Size(1,1))
self.corner_handle_size = kwargs.pop('corner_handle_size', Size(20, 20))
self.edge_handle_width = kwargs.pop('edge_handle_width', 10)
self.edge_handle_buffer = kwargs.pop('edge_handle_buffer', Size(5, 5))
self.border_width = kwargs.pop('border_width', 1)
self.border_color = Color.from_value(kwargs.pop('border_color', (0,0,0,0)))
self.background_color = Color.from_value(kwargs.pop('background_color', (0,0,0,0)))
self.border_radius = BorderRadius.from_value(kwargs.pop('border_radius', 1))
self.dashed_border = kwargs.pop('dashed_border', False)
self.clip_children = kwargs.pop('clip_children', False)
self.ignore_debug = kwargs.pop('ignore_debug', False)
self.rectangle = Rectangle(position, size)
self.children = []
self.min_size = kwargs.get('min_size', Size(1,1))
self.parent = None
self.mouse_pos = Position(-1, -1)
self.mouse_pos = Position(size.width/2, size.height/2)
self.mouse_diff = Position(0, 0)
self.mouse_in = False
self.mouse_hover = False
self.mouse_down = False
self.old_mouse_down = False
self.mouse_inputs = dict.fromkeys(self.mouse_button_down_events, False)
self.focused = False
self.visible = True
self.draggable = draggable
self._resizable = resizable
self.resizable = resizable
self.accept('mouse-move', self.process_mouse_move)
self.resizable = kwargs.pop('resizable', self._resizable)
self.draggable = kwargs.pop('draggable', self._draggable)
for key, value in kwargs.items():
setattr(self, key, value)
if self.draggable:
self.accept('mouse-left-drag', self.drag)
self.accept('mouse-left', self.click)
self.accept('mouse-left-up', self.click_up)
def render(self):
super(Window, self).render()
self.draw_rounded_rect([0,0], [self.size.width, self.size.height],
background_color=self.background_color,
line_color=self.border_color,
line_width=self.border_width,
corner_radius=self.border_radius,
line_dashed=self.dashed_border,
clip=self.clip_children)
@property
def resizable(self):
@ -220,12 +291,30 @@ class Window(WindowEventSource, WindowSurface):
@resizable.setter
def resizable(self, value):
self._resizable = value
if self._resizable:
if not self._resizable and value:
self.init_resize_handles()
elif not value and self._resizable:
self.remove_resize_handles()
self._resizable = value
def drag_handle(self, obj, mouse_pos):
pass
@property
def draggable(self):
return self._draggable
@draggable.setter
def draggable(self, value):
self._draggable = value
self.enable_drag(self._draggable)
def enable_drag(self, value):
if value:
self.accept('mouse-left-drag', self.drag)
self.accept('mouse-left', self.click)
self.accept('mouse-left-up', self.click_up)
else:
self.reject('mouse-left-drag', self.drag)
self.reject('mouse-left', self.click)
self.reject('mouse-left-up', self.click_up)
def drag_bottomright_handle(self, obj, mouse_pos):
diff = mouse_pos - self.mouse_diff
@ -322,10 +411,25 @@ class Window(WindowEventSource, WindowSurface):
self.mouse_diff.x = obj.position.x + self.handle_diff.x
def remove_resize_handles(self):
self.remove_child(self.top_handle)
self.remove_child(self.topleft_handle)
self.remove_child(self.topright_handle)
self.remove_child(self.left_handle)
self.remove_child(self.right_handle)
self.remove_child(self.bottom_handle)
self.remove_child(self.bottomright_handle)
self.remove_child(self.bottomleft_handle)
self.top_handle = None
self.topleft_handle = None
self.topright_handle = None
self.left_handle = None
self.right_handle = None
self.bottom_handle = None
self.bottomright_handle = None
self.bottomleft_handle = None
def init_resize_handles(self):
self.corner_handle_size = Size(20, 20)
self.edge_buffer = Size(10, 10)
self.edge_handle_width = 10
self.handle_diff = Position(0,0)
self.top_handle = Window('top_handle')
@ -372,7 +476,6 @@ class Window(WindowEventSource, WindowSurface):
self.vertical_edge_size = Size()
self.horizontal_edge_size = Size()
self.update_resize_handles()
self.add_child(self.top_handle)
self.add_child(self.topleft_handle)
self.add_child(self.topright_handle)
@ -381,9 +484,10 @@ class Window(WindowEventSource, WindowSurface):
self.add_child(self.bottom_handle)
self.add_child(self.bottomright_handle)
self.add_child(self.bottomleft_handle)
self.update_resize_handles()
def update_resize_handles(self):
buffer = self.edge_buffer
buffer = self.edge_handle_buffer
top = self.top_handle
topleft = self.topleft_handle
topright = self.topright_handle
@ -397,43 +501,43 @@ class Window(WindowEventSource, WindowSurface):
corner_handle_size = self.corner_handle_size
x, y = self.position.x, self.position.y
vertical_edge_size.width = self.size.width-2*corner_handle_size.width
vertical_edge_size.width = self.size.width - 2*corner_handle_size.width
vertical_edge_size.height = self.edge_handle_width
horizontal_edge_size.width = self.edge_handle_width
horizontal_edge_size.height = self.size.height-2*corner_handle_size.height
horizontal_edge_size.height = self.size.height - 2*corner_handle_size.height
top.position.x = x + corner_handle_size.width
top.position.y = y
top.size = vertical_edge_size
top.position.y = y - buffer.height
top.size = vertical_edge_size + [0, buffer.height]
topleft.position.x = x
topleft.position.y = y
topleft.size = corner_handle_size
topleft.position.x = x - buffer.width
topleft.position.y = y - buffer.height
topleft.size = corner_handle_size + buffer
topright.position.x = x + self.size.width-corner_handle_size.width
topright.position.y = y
topright.size = corner_handle_size
topright.position.x = x + self.size.width - corner_handle_size.width
topright.position.y = y - buffer.height
topright.size = corner_handle_size + buffer
bottom.position.x = x + corner_handle_size.width
bottom.position.y = y + self.size.height-vertical_edge_size.height
bottom.size = vertical_edge_size
bottom.position.y = y + self.size.height - vertical_edge_size.height
bottom.size = vertical_edge_size + [0, buffer.height]
bottomleft.position.x = x
bottomleft.position.y = y + self.size.height-corner_handle_size.height
bottomleft.size = corner_handle_size
bottomleft.position.x = x - buffer.width
bottomleft.position.y = y + self.size.height - corner_handle_size.height
bottomleft.size = corner_handle_size + buffer
bottomright.position.x = x + self.size.width-corner_handle_size.width
bottomright.position.y = y + self.size.height-corner_handle_size.height
bottomright.size = corner_handle_size
bottomright.size = corner_handle_size + buffer
right.position.x = x + self.size.width-horizontal_edge_size.width
right.position.y = y + corner_handle_size.height
right.size = horizontal_edge_size
right.size = horizontal_edge_size + [buffer.width, 0]
left.position.x = x
left.position.x = x - buffer.width
left.position.y = y + corner_handle_size.height
left.size = horizontal_edge_size
left.size = horizontal_edge_size + [buffer.width, 0]
def drag(self, obj, mouse_pos):
obj.position = mouse_pos - self.mouse_diff
@ -502,17 +606,17 @@ class Window(WindowEventSource, WindowSurface):
def grab_focus(self):
self.focused = True
if self.parent is not None:
children = self.parent.children[:]
children.remove(self)
children.append(self)
parent = self
#Reorder all the windows so that they are drawn on top
while parent is not None:
if parent.parent is not None:
children = parent.parent.children[:]
children.remove(parent)
children.append(parent)
self.parent.children = children
parent = self.parent
parent.parent.children = children
while parent is not None:
parent.grab_focus()
parent = parent.parent
parent = parent.parent
self.dispatch('focus', self)
@ -601,7 +705,7 @@ class Window(WindowEventSource, WindowSurface):
def add_child(self, child_window):
if child_window not in self.children:
child_window.parent = self
child_window.position = child_window.position + self.position
child_window.position = child_window.position + self.position + [self.border_width/2, self.border_width/2]
child_window.context = self.context
self.children.append(child_window)
@ -648,77 +752,6 @@ class Window(WindowEventSource, WindowSurface):
if self.resizable:
self.update_resize_handles()
class MyWindow(Window):
def render(self):
self.draw_rounded_rect([0,0], [self.size.width, self.size.height], line_width=2, corner_radius=3)
class TestWindow(Window):
def draw_test(self, position, size, color=(1,1,1), line_width=1, line_color=(0,0,0), corner_radius=0):
position = Position.from_value(position)
size = Size.from_value(size)
color = Color.from_value(color)
line_color = Color.from_value(line_color)
context = self.context
radius = corner_radius
degrees = math.pi / 180.0
x = position.x + self.position.x
y = position.y + self.position.y
width = size.width
height = size.height
context.new_sub_path()
context.set_source_rgba(0,0,1)
context.set_line_width(line_width)
context.arc(x + width - radius - line_width/2.0, y + radius + line_width/2.0, radius, -90 * degrees, -45 * degrees)
point = context.get_current_point()
context.stroke()
context.move_to(*point)
context.set_source_rgba(1,0,1)
context.set_line_width(10)
context.arc(x + width - radius - line_width/2.0, y + radius + line_width/2.0, radius, -45 * degrees, 0 * degrees)
context.line_to(x + width - line_width/2.0, y + height - radius - line_width/2.0)
context.arc(x + width - radius - line_width/2.0, y + height - radius - line_width/2.0, radius, 0 * degrees, 45 * degrees)
point = context.get_current_point()
context.stroke()
context.move_to(*point)
context.set_source_rgba(1,0,0)
context.set_line_width(line_width)
context.arc(x + width - radius - line_width/2.0, y + height - radius - line_width/2.0, radius, 45 * degrees, 90 * degrees)
context.line_to(x + radius + line_width/2.0, y + height - line_width/2.0)
context.arc(x + radius + line_width/2.0, y + height - radius - line_width/2.0, radius, 90 * degrees, 135 * degrees)
point = context.get_current_point()
context.stroke()
context.move_to(*point)
context.set_source_rgba(0,1,0)
context.set_line_width(line_width)
context.arc(x + radius + line_width/2.0, y + height - radius - line_width/2.0, radius, 135 * degrees, 180 * degrees)
context.line_to(x + line_width/2.0, y + radius + line_width/2.0)
context.arc(x + radius + line_width/2.0, y + radius + line_width/2.0, radius, 180 * degrees, 225 * degrees)
point = context.get_current_point()
context.stroke()
context.move_to(*point)
context.set_source_rgba(0,0,1)
context.set_line_width(line_width)
context.arc(x + radius + line_width/2.0, y + radius + line_width/2.0, radius, 225 * degrees, 270 * degrees)
context.line_to(x + width - radius - line_width/2.0, y + line_width/2.0)
context.stroke()
context.new_sub_path()
context.arc(x + width - radius - line_width/2.0, y + radius + line_width/2.0, radius, -90 * degrees, 0 * degrees)
context.arc(x + width - radius - line_width/2.0, y + height - radius - line_width/2.0, radius, 0 * degrees, 90 * degrees)
context.arc(x + radius + line_width/2.0, y + height - radius - line_width/2.0, radius, 90 * degrees, 180 * degrees)
context.arc(x + radius + line_width/2.0, y + radius + line_width/2.0, radius, 180 * degrees, 270 * degrees)
context.close_path()
context.set_source_rgba(*color)
context.fill()
def render(self):
self.draw_test([0,0], [self.size.width, self.size.height], corner_radius=10)
class Mouse(Window):
def __init__(self, *args, **kwargs):
super(Mouse, self).__init__(*args, **kwargs)
@ -734,3 +767,12 @@ class Mouse(Window):
def render(self):
self.draw_lines(self.lines, line_width=self.size.height/20)
class TextWindow(Window):
def __init__(self, name, text, *args, **kwargs):
super(TextWindow, self).__init__(name, *args, **kwargs)
self.text = text
def render(self):
super(TextWindow, self).render()
self.draw_text(self.text, [0,0], self.size)

View file

@ -8,7 +8,7 @@ import sys
from direct.showbase.ShowBase import ShowBase
from pandac.PandaModules import *
from jgui.surface.surface import *
from testclasses import *
class Test(ShowBase):
def __init__(self, width=1024, height=1024):

91
testclasses.py Normal file
View file

@ -0,0 +1,91 @@
from jgui.surface import Surface, Window, Position, Size, Color, TextWindow
import math
class TestSurface(Surface):
def __init__(self, *args, **kwargs):
super(TestSurface, self).__init__(*args, **kwargs)
my_win = Window('child',
position=[0,0],
size=[500,200],
draggable=True,
resizable=True,
min_size=Size(40,40),
border_width=5,
border_radius=[40,20],
border_color=(0,0,0),
background_color=(1,1,1),
clip_children=True,
ignore_debug=True)
my_win.add_child(TextWindow('text','Micro Bean.', position=[20,20], size=[100, 50]))
self.root_window.add_child(my_win)
self.root_window.add_child(TestWindow('child2', position=[200,200], size=[200,200], draggable=True))
child3 = TestWindow('child3', position=[300,300], size=[200,200], draggable=True)
child3.add_child(TestWindow('child3-1', position=[10,10], size=[50,50], draggable=True))
self.root_window.add_child(child3)
class TestWindow(Window):
def draw_test(self, position, size, color=(1,1,1), line_width=1, line_color=(0,0,0), corner_radius=0):
position = Position.from_value(position)
size = Size.from_value(size)
color = Color.from_value(color)
line_color = Color.from_value(line_color)
context = self.context
radius = corner_radius
degrees = math.pi / 180.0
x = position.x + self.position.x
y = position.y + self.position.y
width = size.width
height = size.height
context.new_sub_path()
context.set_source_rgba(0,0,1)
context.set_line_width(line_width)
context.arc(x + width - radius - line_width/2.0, y + radius + line_width/2.0, radius, -90 * degrees, -45 * degrees)
point = context.get_current_point()
context.stroke()
context.move_to(*point)
context.set_source_rgba(1,0,1)
context.set_line_width(10)
context.arc(x + width - radius - line_width/2.0, y + radius + line_width/2.0, radius, -45 * degrees, 0 * degrees)
context.line_to(x + width - line_width/2.0, y + height - radius - line_width/2.0)
context.arc(x + width - radius - line_width/2.0, y + height - radius - line_width/2.0, radius, 0 * degrees, 45 * degrees)
point = context.get_current_point()
context.stroke()
context.move_to(*point)
context.set_source_rgba(1,0,0)
context.set_line_width(line_width)
context.arc(x + width - radius - line_width/2.0, y + height - radius - line_width/2.0, radius, 45 * degrees, 90 * degrees)
context.line_to(x + radius + line_width/2.0, y + height - line_width/2.0)
context.arc(x + radius + line_width/2.0, y + height - radius - line_width/2.0, radius, 90 * degrees, 135 * degrees)
point = context.get_current_point()
context.stroke()
context.move_to(*point)
context.set_source_rgba(0,1,0)
context.set_line_width(line_width)
context.arc(x + radius + line_width/2.0, y + height - radius - line_width/2.0, radius, 135 * degrees, 180 * degrees)
context.line_to(x + line_width/2.0, y + radius + line_width/2.0)
context.arc(x + radius + line_width/2.0, y + radius + line_width/2.0, radius, 180 * degrees, 225 * degrees)
point = context.get_current_point()
context.stroke()
context.move_to(*point)
context.set_source_rgba(0,0,1)
context.set_line_width(line_width)
context.arc(x + radius + line_width/2.0, y + radius + line_width/2.0, radius, 225 * degrees, 270 * degrees)
context.line_to(x + width - radius - line_width/2.0, y + line_width/2.0)
context.stroke()
context.new_sub_path()
context.arc(x + width - radius - line_width/2.0, y + radius + line_width/2.0, radius, -90 * degrees, 0 * degrees)
context.arc(x + width - radius - line_width/2.0, y + height - radius - line_width/2.0, radius, 0 * degrees, 90 * degrees)
context.arc(x + radius + line_width/2.0, y + height - radius - line_width/2.0, radius, 90 * degrees, 180 * degrees)
context.arc(x + radius + line_width/2.0, y + radius + line_width/2.0, radius, 180 * degrees, 270 * degrees)
context.close_path()
context.set_source_rgba(*color)
context.fill()
def render(self):
self.draw_test([0,0], [self.size.width, self.size.height], corner_radius=20)