"""
This example demonstrates a simple drawing app. Useful for testing
canvas and its mouse events.
"""
from flexx import app, ui


class Drawing(ui.CanvasWidget):
    
    class JS:
        
        def init(self):
            super().init()
            self.ctx = self.canvas.getContext('2d')
        
        def on_mouse_move(self, *events):
            for ev in events:
                self.ctx.fillStyle = '#ff0'
                self.ctx.fillRect(ev.x-2, ev.y-2, 4, 4)
        
        def on_mouse_down(self, *events):
            for ev in events:
                self.ctx.fillStyle = '#f00'
                self.ctx.fillRect(ev.x-10, ev.y-10, 20, 20)
        
        def on_mouse_up(self, *events):
            for ev in events:
                self.ctx.fillStyle = '#00f'
                self.ctx.fillRect(ev.x-10, ev.y-10, 20, 20)


class Main(ui.Widget):
    """ Embed in larger widget to test offset.
    """
    
    CSS = """
    .flx-Widget { background: #aaf;}
    .flx-Drawing {background: #fff;}
    """
    
    def init(self):
        
        with ui.VBox():
            ui.Widget(flex=1)
            with ui.HBox(flex=2):
                ui.Widget(flex=1)
                Drawing(flex=2)
                ui.Widget(flex=1)
            ui.Widget(flex=1)


m = app.launch(Main, 'xul')
app.run()

@@ -302,16 +302,50 @@
 ('2d')%0D%0A
+            self._last_ev = None%0D%0A
         
@@ -338,32 +338,32 @@
 None%0D%0A        %0D%0A
-
         def on_m
@@ -432,37 +432,187 @@
             
-self.ctx.fill
+last_ev = self._last_ev%0D%0A                if 1 in ev.buttons and last_ev is not None:%0D%0A                    self.ctx.beginPath()%0D%0A                    self.ctx.stroke
 Style = '#ff
@@ -613,14 +613,18 @@
 = '#
-ff
+08
 0'%0D%0A
+    
     
@@ -648,38 +648,245 @@
 ctx.
-fillRect(ev.x-2, ev.y-2, 4, 4)
+lineWidth = 3%0D%0A                    self.ctx.lineCap = 'round'%0D%0A                    self.ctx.moveTo(*last_ev.pos)%0D%0A                    self.ctx.lineTo(*ev.pos)%0D%0A                    self.ctx.stroke()%0D%0A                    self._last_ev = ev
 %0D%0A  
@@ -959,32 +959,70 @@
  ev in events:%0D%0A
+                self.ctx.beginPath()%0D%0A
                 
@@ -1079,42 +1079,116 @@
 ctx.
-fillRect(ev.x-10, ev.y-10, 20, 20)
+arc(ev.pos%5B0%5D, ev.pos%5B1%5D, 3, 0, 6.2831)%0D%0A                self.ctx.fill()%0D%0A                self._last_ev = ev
 %0D%0A  
@@ -1259,32 +1259,70 @@
  ev in events:%0D%0A
+                self.ctx.beginPath()%0D%0A
                 
@@ -1379,42 +1379,114 @@
 ctx.
-fillRect(ev.x-10, ev.y-10
+arc(ev.pos%5B0%5D, ev.pos%5B1%5D, 3
 , 
-2
 0, 
-20)
+6.2831)%0D%0A                self.ctx.fill()%0D%0A            self._last_ev = None
 %0D%0A%0D%0A

Update drawing example