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