Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/turtlewidget.py
blob: 4bcf0eb746640c3031dd1252fe27cb5f037e0b13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
"""
TurtleWidget is defined in this module, see its documentation.
"""

import time
import Queue
import math

from gi.repository import Gtk, Gdk, GObject
import cairo

from vector import Vector
from my_turtle import *
import misc.dumpqueue as dumpqueue
from misc.fromresourcefolder import from_resource_folder

BITMAP_X = 1200
BITMAP_Y = 900

class TurtleWidget(Gtk.DrawingArea):
    """
    A Gtk Drawing Area widget to display the turtle and all the drawings that
    it made.
    """
    def __init__(self,turtle_queue):
        Gtk.DrawingArea.__init__(self)

        #self.BACKGROUND_COLOR = wx.Colour(212,208,200)
        self.TURTLE_IMAGE = cairo.ImageSurface.create_from_png(from_resource_folder("turtle.png"))
        self.turtle_w = self.TURTLE_IMAGE.get_width()
        self.turtle_h = self.TURTLE_IMAGE.get_height()
        self.turtle = Turtle()

        self.count = 0
        #bitmap=self.bitmap=wx.EmptyBitmapRGBA(2000,1200,BACKGROUND_COLOR[0],BACKGROUND_COLOR[1],BACKGROUND_COLOR[2],255) # todo: Change to something smarter?
        #self.bitmap = wx.EmptyBitmap(*BITMAP_SIZE)
        self.bitmap = cairo.ImageSurface(cairo.FORMAT_RGB24, BITMAP_X, BITMAP_Y)
        self.connect("draw", self.on_paint)
        GObject.timeout_add(30, self.on_idle)
        #GObject.idle_add(self.on_idle)

        #self.Bind(wx.EVT_SIZE,self.on_size)

        self.turtle_queue = turtle_queue

        self.idle_block = False

    def on_paint(self, widget, cr):
        """
        Paint event handler. Reads the turtle reports and draws graphics
        accordingly.
        """
        # Translate to (0, 0) is in the center
        w = self.get_allocation().width
        h = self.get_allocation().height

        cxt = cairo.Context(self.bitmap) # The drawing context for the bitmap
        cxt.translate(w/2, h/2)

        turtle_reports=dumpqueue.dump_queue(self.turtle_queue)
        for turtle_report in turtle_reports:
            if turtle_report.pen_down is True:
                cxt.set_source_rgb(*self.turtle.rgb_color)
                cxt.set_line_width(self.turtle.width)
                cxt.move_to(*(-self.turtle.pos))
                cxt.line_to(*(-turtle_report.pos))
            #if turtle_report.clear is True:
            #    brush=wx.Brush("black")
            #    dc.SetBackground(brush)
            #    dc.Clear()
            self.turtle = turtle_report
        cxt.stroke()

        if len(turtle_reports) > 0:
            pass
            #self.queue_draw()

        # Draw the bitmap
        cr.set_source_surface(self.bitmap, 0, 0)
        cr.paint()

        if self.turtle.visible:
            p = -self.turtle.pos
            x = p[0] + w/2
            y = p[1] + h/2
            cr.translate(x, y)
            cr.rotate(math.radians(self.turtle.orientation - 180))
            cr.translate(-x, -y)
            cr.set_source_surface(self.TURTLE_IMAGE, x - self.turtle_w/2, y - self.turtle_h/2)
            cr.paint()


        # Draw the turtle:
        #if self.turtle.visible:
        #    new_pos = top_left_corner + from_my_pos(self.turtle.pos)
        #    draw_bitmap_to_dc_rotated(dc, self.TURTLE_IMAGE, from_my_angle(self.turtle.orientation), new_pos)
        #dc.Destroy()



    def on_idle(self,e=None):
        """
        Idle event handler. Checks whether there are any
        pending turtle reports, and if there are tells the widget
        to process them.
        """
        if self.idle_block==True: return True

        if not self.turtle_queue.empty(): self.queue_draw()
        return True
        #wx.CallLater(30,self._clear_idle_block_and_do) # Should make the delay customizable?
        #self.idle_block=True
        

    def _clear_idle_block_and_do(self):
        self.idle_block=False
        event=wx.PyEvent()
        event.SetEventType(wx.wxEVT_IDLE)
        wx.PostEvent(self,event)

    def on_size(self,e=None):
        self.Refresh()



def draw_bitmap_to_dc_rotated( dc, bitmap, angle , point):
    """
    Rotate a bitmap and write it to the supplied device context.
    """
    img = bitmap.ConvertToImage()
    img_centre = wx.Point( img.GetWidth()/2.0, img.GetHeight()/2.0 )
    img = img.Rotate( angle, img_centre , interpolating=True)
    new_point=Vector(point)-Vector(img.GetSize())/2
    dc.DrawBitmapPoint( img.ConvertToBitmap(), new_point,useMask=True )