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 )
|