Example #1
0
class TurtleWidget(CanvasWidget):
    def newTKWidget(self, parent, hOptions):
        return super().newTKWidget(parent, hOptions)

    def initialize(self, hOptions):
        self.screen = TurtleScreen(self.tkWidget)
        self.tkTurtle = RawTurtle(self.screen)
        self.screen.mode('world')

        self.tkTurtle.setheading(90)

        if 'speed' in hOptions:
            self.curSpeed = int(hOptions['speed'])
        else:
            self.curSpeed = 1
        self.lSaveStack = []  # stack to save/restore state on

    def setBounds(self, xmin, ymin, xmax, ymax, padding=15):
        width = xmax - xmin
        height = ymax - ymin
        if (width > height):
            halfdiff = (width - height) / 2
            ymin -= halfdiff
            ymax += halfdiff
        else:
            halfdiff = (height - width) / 2
            xmin -= halfdiff
            xmax += halfdiff
        self.screen.setworldcoordinates(
            xmin - padding,
            ymin - padding,
            xmax + padding,
            ymax + padding,
        )

    def reset(self):
        self.screen.reset()

    def move(self, n):
        tkTurtle = self.tkTurtle
        assert isinstance(tkTurtle, RawTurtle)
        tkTurtle.speed(self.curSpeed)
        tkTurtle.forward(n)

    def turn(self, d):
        tkTurtle = self.tkTurtle
        assert isinstance(tkTurtle, RawTurtle)
        tkTurtle.speed(self.curSpeed)
        tkTurtle.right(d)

    # --- Turtle state includes these fields:
    #     xpos, ypos, heading, isvisible, isdown

    def saveState(self):

        tkTurtle = self.tkTurtle
        assert isinstance(tkTurtle, RawTurtle)
        self.lSaveStack.append([
            tkTurtle.xcor(),
            tkTurtle.ycor(),
            tkTurtle.heading(),
            tkTurtle.isvisible(),
            tkTurtle.isdown(),
        ])

    def restoreState(self):

        tkTurtle = self.tkTurtle
        assert isinstance(tkTurtle, RawTurtle)
        if len(self.lSaveStack) == 0:
            raise Exception("restoreState(): No saved state to restore")
        lState = self.lSaveStack.pop()
        saved_x = lState[0]
        saved_y = lState[1]

        cur_x = tkTurtle.xcor()
        cur_y = tkTurtle.ycor()

        # --- determine whether we need to hide the turtle
        if tkTurtle.isvisible():
            dist = hypot(saved_x - cur_x, saved_y - cur_y)
            mustHide = (dist > 1)
        else:
            mustHide = False

        if mustHide:
            tkTurtle.hideturtle()

        tkTurtle.penup()
        tkTurtle.setposition(saved_x, saved_y)
        tkTurtle.setheading(lState[2])

        if lState[3] and mustHide:
            tkTurtle.showturtle()
        if lState[4]:
            tkTurtle.pendown()

    def moveTo(self, x, y):
        tkTurtle = self.tkTurtle
        tkTurtle.penup()
        tkTurtle.hideturtle()
        tkTurtle.setposition(x, y)
        tkTurtle.setheading(90)
        tkTurtle.pendown()
        tkTurtle.showturtle()

    def drawAt(self, x, y, func):

        # --- Must not draw or show movement
        tkTurtle = self.tkTurtle

        self.saveState()
        self.moveTo(x, y)
        func(self)
        self.restoreState()