xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/turtle.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker#
2*cda5da8dSAndroid Build Coastguard Worker# turtle.py: a Tkinter based turtle graphics module for Python
3*cda5da8dSAndroid Build Coastguard Worker# Version 1.1b - 4. 5. 2009
4*cda5da8dSAndroid Build Coastguard Worker#
5*cda5da8dSAndroid Build Coastguard Worker# Copyright (C) 2006 - 2010  Gregor Lingl
6*cda5da8dSAndroid Build Coastguard Worker# email: [email protected]
7*cda5da8dSAndroid Build Coastguard Worker#
8*cda5da8dSAndroid Build Coastguard Worker# This software is provided 'as-is', without any express or implied
9*cda5da8dSAndroid Build Coastguard Worker# warranty.  In no event will the authors be held liable for any damages
10*cda5da8dSAndroid Build Coastguard Worker# arising from the use of this software.
11*cda5da8dSAndroid Build Coastguard Worker#
12*cda5da8dSAndroid Build Coastguard Worker# Permission is granted to anyone to use this software for any purpose,
13*cda5da8dSAndroid Build Coastguard Worker# including commercial applications, and to alter it and redistribute it
14*cda5da8dSAndroid Build Coastguard Worker# freely, subject to the following restrictions:
15*cda5da8dSAndroid Build Coastguard Worker#
16*cda5da8dSAndroid Build Coastguard Worker# 1. The origin of this software must not be misrepresented; you must not
17*cda5da8dSAndroid Build Coastguard Worker#    claim that you wrote the original software. If you use this software
18*cda5da8dSAndroid Build Coastguard Worker#    in a product, an acknowledgment in the product documentation would be
19*cda5da8dSAndroid Build Coastguard Worker#    appreciated but is not required.
20*cda5da8dSAndroid Build Coastguard Worker# 2. Altered source versions must be plainly marked as such, and must not be
21*cda5da8dSAndroid Build Coastguard Worker#    misrepresented as being the original software.
22*cda5da8dSAndroid Build Coastguard Worker# 3. This notice may not be removed or altered from any source distribution.
23*cda5da8dSAndroid Build Coastguard Worker
24*cda5da8dSAndroid Build Coastguard Worker
25*cda5da8dSAndroid Build Coastguard Worker"""
26*cda5da8dSAndroid Build Coastguard WorkerTurtle graphics is a popular way for introducing programming to
27*cda5da8dSAndroid Build Coastguard Workerkids. It was part of the original Logo programming language developed
28*cda5da8dSAndroid Build Coastguard Workerby Wally Feurzig and Seymour Papert in 1966.
29*cda5da8dSAndroid Build Coastguard Worker
30*cda5da8dSAndroid Build Coastguard WorkerImagine a robotic turtle starting at (0, 0) in the x-y plane. After an ``import turtle``, give it
31*cda5da8dSAndroid Build Coastguard Workerthe command turtle.forward(15), and it moves (on-screen!) 15 pixels in
32*cda5da8dSAndroid Build Coastguard Workerthe direction it is facing, drawing a line as it moves. Give it the
33*cda5da8dSAndroid Build Coastguard Workercommand turtle.right(25), and it rotates in-place 25 degrees clockwise.
34*cda5da8dSAndroid Build Coastguard Worker
35*cda5da8dSAndroid Build Coastguard WorkerBy combining together these and similar commands, intricate shapes and
36*cda5da8dSAndroid Build Coastguard Workerpictures can easily be drawn.
37*cda5da8dSAndroid Build Coastguard Worker
38*cda5da8dSAndroid Build Coastguard Worker----- turtle.py
39*cda5da8dSAndroid Build Coastguard Worker
40*cda5da8dSAndroid Build Coastguard WorkerThis module is an extended reimplementation of turtle.py from the
41*cda5da8dSAndroid Build Coastguard WorkerPython standard distribution up to Python 2.5. (See: https://www.python.org)
42*cda5da8dSAndroid Build Coastguard Worker
43*cda5da8dSAndroid Build Coastguard WorkerIt tries to keep the merits of turtle.py and to be (nearly) 100%
44*cda5da8dSAndroid Build Coastguard Workercompatible with it. This means in the first place to enable the
45*cda5da8dSAndroid Build Coastguard Workerlearning programmer to use all the commands, classes and methods
46*cda5da8dSAndroid Build Coastguard Workerinteractively when using the module from within IDLE run with
47*cda5da8dSAndroid Build Coastguard Workerthe -n switch.
48*cda5da8dSAndroid Build Coastguard Worker
49*cda5da8dSAndroid Build Coastguard WorkerRoughly it has the following features added:
50*cda5da8dSAndroid Build Coastguard Worker
51*cda5da8dSAndroid Build Coastguard Worker- Better animation of the turtle movements, especially of turning the
52*cda5da8dSAndroid Build Coastguard Worker  turtle. So the turtles can more easily be used as a visual feedback
53*cda5da8dSAndroid Build Coastguard Worker  instrument by the (beginning) programmer.
54*cda5da8dSAndroid Build Coastguard Worker
55*cda5da8dSAndroid Build Coastguard Worker- Different turtle shapes, gif-images as turtle shapes, user defined
56*cda5da8dSAndroid Build Coastguard Worker  and user controllable turtle shapes, among them compound
57*cda5da8dSAndroid Build Coastguard Worker  (multicolored) shapes. Turtle shapes can be stretched and tilted, which
58*cda5da8dSAndroid Build Coastguard Worker  makes turtles very versatile geometrical objects.
59*cda5da8dSAndroid Build Coastguard Worker
60*cda5da8dSAndroid Build Coastguard Worker- Fine control over turtle movement and screen updates via delay(),
61*cda5da8dSAndroid Build Coastguard Worker  and enhanced tracer() and speed() methods.
62*cda5da8dSAndroid Build Coastguard Worker
63*cda5da8dSAndroid Build Coastguard Worker- Aliases for the most commonly used commands, like fd for forward etc.,
64*cda5da8dSAndroid Build Coastguard Worker  following the early Logo traditions. This reduces the boring work of
65*cda5da8dSAndroid Build Coastguard Worker  typing long sequences of commands, which often occur in a natural way
66*cda5da8dSAndroid Build Coastguard Worker  when kids try to program fancy pictures on their first encounter with
67*cda5da8dSAndroid Build Coastguard Worker  turtle graphics.
68*cda5da8dSAndroid Build Coastguard Worker
69*cda5da8dSAndroid Build Coastguard Worker- Turtles now have an undo()-method with configurable undo-buffer.
70*cda5da8dSAndroid Build Coastguard Worker
71*cda5da8dSAndroid Build Coastguard Worker- Some simple commands/methods for creating event driven programs
72*cda5da8dSAndroid Build Coastguard Worker  (mouse-, key-, timer-events). Especially useful for programming games.
73*cda5da8dSAndroid Build Coastguard Worker
74*cda5da8dSAndroid Build Coastguard Worker- A scrollable Canvas class. The default scrollable Canvas can be
75*cda5da8dSAndroid Build Coastguard Worker  extended interactively as needed while playing around with the turtle(s).
76*cda5da8dSAndroid Build Coastguard Worker
77*cda5da8dSAndroid Build Coastguard Worker- A TurtleScreen class with methods controlling background color or
78*cda5da8dSAndroid Build Coastguard Worker  background image, window and canvas size and other properties of the
79*cda5da8dSAndroid Build Coastguard Worker  TurtleScreen.
80*cda5da8dSAndroid Build Coastguard Worker
81*cda5da8dSAndroid Build Coastguard Worker- There is a method, setworldcoordinates(), to install a user defined
82*cda5da8dSAndroid Build Coastguard Worker  coordinate-system for the TurtleScreen.
83*cda5da8dSAndroid Build Coastguard Worker
84*cda5da8dSAndroid Build Coastguard Worker- The implementation uses a 2-vector class named Vec2D, derived from tuple.
85*cda5da8dSAndroid Build Coastguard Worker  This class is public, so it can be imported by the application programmer,
86*cda5da8dSAndroid Build Coastguard Worker  which makes certain types of computations very natural and compact.
87*cda5da8dSAndroid Build Coastguard Worker
88*cda5da8dSAndroid Build Coastguard Worker- Appearance of the TurtleScreen and the Turtles at startup/import can be
89*cda5da8dSAndroid Build Coastguard Worker  configured by means of a turtle.cfg configuration file.
90*cda5da8dSAndroid Build Coastguard Worker  The default configuration mimics the appearance of the old turtle module.
91*cda5da8dSAndroid Build Coastguard Worker
92*cda5da8dSAndroid Build Coastguard Worker- If configured appropriately the module reads in docstrings from a docstring
93*cda5da8dSAndroid Build Coastguard Worker  dictionary in some different language, supplied separately  and replaces
94*cda5da8dSAndroid Build Coastguard Worker  the English ones by those read in. There is a utility function
95*cda5da8dSAndroid Build Coastguard Worker  write_docstringdict() to write a dictionary with the original (English)
96*cda5da8dSAndroid Build Coastguard Worker  docstrings to disc, so it can serve as a template for translations.
97*cda5da8dSAndroid Build Coastguard Worker
98*cda5da8dSAndroid Build Coastguard WorkerBehind the scenes there are some features included with possible
99*cda5da8dSAndroid Build Coastguard Workerextensions in mind. These will be commented and documented elsewhere.
100*cda5da8dSAndroid Build Coastguard Worker
101*cda5da8dSAndroid Build Coastguard Worker"""
102*cda5da8dSAndroid Build Coastguard Worker
103*cda5da8dSAndroid Build Coastguard Worker_ver = "turtle 1.1b- - for Python 3.1   -  4. 5. 2009"
104*cda5da8dSAndroid Build Coastguard Worker
105*cda5da8dSAndroid Build Coastguard Worker# print(_ver)
106*cda5da8dSAndroid Build Coastguard Worker
107*cda5da8dSAndroid Build Coastguard Workerimport tkinter as TK
108*cda5da8dSAndroid Build Coastguard Workerimport types
109*cda5da8dSAndroid Build Coastguard Workerimport math
110*cda5da8dSAndroid Build Coastguard Workerimport time
111*cda5da8dSAndroid Build Coastguard Workerimport inspect
112*cda5da8dSAndroid Build Coastguard Workerimport sys
113*cda5da8dSAndroid Build Coastguard Workerimport warnings
114*cda5da8dSAndroid Build Coastguard Worker
115*cda5da8dSAndroid Build Coastguard Workerfrom os.path import isfile, split, join
116*cda5da8dSAndroid Build Coastguard Workerfrom copy import deepcopy
117*cda5da8dSAndroid Build Coastguard Workerfrom tkinter import simpledialog
118*cda5da8dSAndroid Build Coastguard Worker
119*cda5da8dSAndroid Build Coastguard Worker_tg_classes = ['ScrolledCanvas', 'TurtleScreen', 'Screen',
120*cda5da8dSAndroid Build Coastguard Worker               'RawTurtle', 'Turtle', 'RawPen', 'Pen', 'Shape', 'Vec2D']
121*cda5da8dSAndroid Build Coastguard Worker_tg_screen_functions = ['addshape', 'bgcolor', 'bgpic', 'bye',
122*cda5da8dSAndroid Build Coastguard Worker        'clearscreen', 'colormode', 'delay', 'exitonclick', 'getcanvas',
123*cda5da8dSAndroid Build Coastguard Worker        'getshapes', 'listen', 'mainloop', 'mode', 'numinput',
124*cda5da8dSAndroid Build Coastguard Worker        'onkey', 'onkeypress', 'onkeyrelease', 'onscreenclick', 'ontimer',
125*cda5da8dSAndroid Build Coastguard Worker        'register_shape', 'resetscreen', 'screensize', 'setup',
126*cda5da8dSAndroid Build Coastguard Worker        'setworldcoordinates', 'textinput', 'title', 'tracer', 'turtles', 'update',
127*cda5da8dSAndroid Build Coastguard Worker        'window_height', 'window_width']
128*cda5da8dSAndroid Build Coastguard Worker_tg_turtle_functions = ['back', 'backward', 'begin_fill', 'begin_poly', 'bk',
129*cda5da8dSAndroid Build Coastguard Worker        'circle', 'clear', 'clearstamp', 'clearstamps', 'clone', 'color',
130*cda5da8dSAndroid Build Coastguard Worker        'degrees', 'distance', 'dot', 'down', 'end_fill', 'end_poly', 'fd',
131*cda5da8dSAndroid Build Coastguard Worker        'fillcolor', 'filling', 'forward', 'get_poly', 'getpen', 'getscreen', 'get_shapepoly',
132*cda5da8dSAndroid Build Coastguard Worker        'getturtle', 'goto', 'heading', 'hideturtle', 'home', 'ht', 'isdown',
133*cda5da8dSAndroid Build Coastguard Worker        'isvisible', 'left', 'lt', 'onclick', 'ondrag', 'onrelease', 'pd',
134*cda5da8dSAndroid Build Coastguard Worker        'pen', 'pencolor', 'pendown', 'pensize', 'penup', 'pos', 'position',
135*cda5da8dSAndroid Build Coastguard Worker        'pu', 'radians', 'right', 'reset', 'resizemode', 'rt',
136*cda5da8dSAndroid Build Coastguard Worker        'seth', 'setheading', 'setpos', 'setposition', 'settiltangle',
137*cda5da8dSAndroid Build Coastguard Worker        'setundobuffer', 'setx', 'sety', 'shape', 'shapesize', 'shapetransform', 'shearfactor', 'showturtle',
138*cda5da8dSAndroid Build Coastguard Worker        'speed', 'st', 'stamp', 'tilt', 'tiltangle', 'towards',
139*cda5da8dSAndroid Build Coastguard Worker        'turtlesize', 'undo', 'undobufferentries', 'up', 'width',
140*cda5da8dSAndroid Build Coastguard Worker        'write', 'xcor', 'ycor']
141*cda5da8dSAndroid Build Coastguard Worker_tg_utilities = ['write_docstringdict', 'done']
142*cda5da8dSAndroid Build Coastguard Worker
143*cda5da8dSAndroid Build Coastguard Worker__all__ = (_tg_classes + _tg_screen_functions + _tg_turtle_functions +
144*cda5da8dSAndroid Build Coastguard Worker           _tg_utilities + ['Terminator']) # + _math_functions)
145*cda5da8dSAndroid Build Coastguard Worker
146*cda5da8dSAndroid Build Coastguard Worker_alias_list = ['addshape', 'backward', 'bk', 'fd', 'ht', 'lt', 'pd', 'pos',
147*cda5da8dSAndroid Build Coastguard Worker               'pu', 'rt', 'seth', 'setpos', 'setposition', 'st',
148*cda5da8dSAndroid Build Coastguard Worker               'turtlesize', 'up', 'width']
149*cda5da8dSAndroid Build Coastguard Worker
150*cda5da8dSAndroid Build Coastguard Worker_CFG = {"width" : 0.5,               # Screen
151*cda5da8dSAndroid Build Coastguard Worker        "height" : 0.75,
152*cda5da8dSAndroid Build Coastguard Worker        "canvwidth" : 400,
153*cda5da8dSAndroid Build Coastguard Worker        "canvheight": 300,
154*cda5da8dSAndroid Build Coastguard Worker        "leftright": None,
155*cda5da8dSAndroid Build Coastguard Worker        "topbottom": None,
156*cda5da8dSAndroid Build Coastguard Worker        "mode": "standard",          # TurtleScreen
157*cda5da8dSAndroid Build Coastguard Worker        "colormode": 1.0,
158*cda5da8dSAndroid Build Coastguard Worker        "delay": 10,
159*cda5da8dSAndroid Build Coastguard Worker        "undobuffersize": 1000,      # RawTurtle
160*cda5da8dSAndroid Build Coastguard Worker        "shape": "classic",
161*cda5da8dSAndroid Build Coastguard Worker        "pencolor" : "black",
162*cda5da8dSAndroid Build Coastguard Worker        "fillcolor" : "black",
163*cda5da8dSAndroid Build Coastguard Worker        "resizemode" : "noresize",
164*cda5da8dSAndroid Build Coastguard Worker        "visible" : True,
165*cda5da8dSAndroid Build Coastguard Worker        "language": "english",        # docstrings
166*cda5da8dSAndroid Build Coastguard Worker        "exampleturtle": "turtle",
167*cda5da8dSAndroid Build Coastguard Worker        "examplescreen": "screen",
168*cda5da8dSAndroid Build Coastguard Worker        "title": "Python Turtle Graphics",
169*cda5da8dSAndroid Build Coastguard Worker        "using_IDLE": False
170*cda5da8dSAndroid Build Coastguard Worker       }
171*cda5da8dSAndroid Build Coastguard Worker
172*cda5da8dSAndroid Build Coastguard Workerdef config_dict(filename):
173*cda5da8dSAndroid Build Coastguard Worker    """Convert content of config-file into dictionary."""
174*cda5da8dSAndroid Build Coastguard Worker    with open(filename, "r") as f:
175*cda5da8dSAndroid Build Coastguard Worker        cfglines = f.readlines()
176*cda5da8dSAndroid Build Coastguard Worker    cfgdict = {}
177*cda5da8dSAndroid Build Coastguard Worker    for line in cfglines:
178*cda5da8dSAndroid Build Coastguard Worker        line = line.strip()
179*cda5da8dSAndroid Build Coastguard Worker        if not line or line.startswith("#"):
180*cda5da8dSAndroid Build Coastguard Worker            continue
181*cda5da8dSAndroid Build Coastguard Worker        try:
182*cda5da8dSAndroid Build Coastguard Worker            key, value = line.split("=")
183*cda5da8dSAndroid Build Coastguard Worker        except ValueError:
184*cda5da8dSAndroid Build Coastguard Worker            print("Bad line in config-file %s:\n%s" % (filename,line))
185*cda5da8dSAndroid Build Coastguard Worker            continue
186*cda5da8dSAndroid Build Coastguard Worker        key = key.strip()
187*cda5da8dSAndroid Build Coastguard Worker        value = value.strip()
188*cda5da8dSAndroid Build Coastguard Worker        if value in ["True", "False", "None", "''", '""']:
189*cda5da8dSAndroid Build Coastguard Worker            value = eval(value)
190*cda5da8dSAndroid Build Coastguard Worker        else:
191*cda5da8dSAndroid Build Coastguard Worker            try:
192*cda5da8dSAndroid Build Coastguard Worker                if "." in value:
193*cda5da8dSAndroid Build Coastguard Worker                    value = float(value)
194*cda5da8dSAndroid Build Coastguard Worker                else:
195*cda5da8dSAndroid Build Coastguard Worker                    value = int(value)
196*cda5da8dSAndroid Build Coastguard Worker            except ValueError:
197*cda5da8dSAndroid Build Coastguard Worker                pass # value need not be converted
198*cda5da8dSAndroid Build Coastguard Worker        cfgdict[key] = value
199*cda5da8dSAndroid Build Coastguard Worker    return cfgdict
200*cda5da8dSAndroid Build Coastguard Worker
201*cda5da8dSAndroid Build Coastguard Workerdef readconfig(cfgdict):
202*cda5da8dSAndroid Build Coastguard Worker    """Read config-files, change configuration-dict accordingly.
203*cda5da8dSAndroid Build Coastguard Worker
204*cda5da8dSAndroid Build Coastguard Worker    If there is a turtle.cfg file in the current working directory,
205*cda5da8dSAndroid Build Coastguard Worker    read it from there. If this contains an importconfig-value,
206*cda5da8dSAndroid Build Coastguard Worker    say 'myway', construct filename turtle_mayway.cfg else use
207*cda5da8dSAndroid Build Coastguard Worker    turtle.cfg and read it from the import-directory, where
208*cda5da8dSAndroid Build Coastguard Worker    turtle.py is located.
209*cda5da8dSAndroid Build Coastguard Worker    Update configuration dictionary first according to config-file,
210*cda5da8dSAndroid Build Coastguard Worker    in the import directory, then according to config-file in the
211*cda5da8dSAndroid Build Coastguard Worker    current working directory.
212*cda5da8dSAndroid Build Coastguard Worker    If no config-file is found, the default configuration is used.
213*cda5da8dSAndroid Build Coastguard Worker    """
214*cda5da8dSAndroid Build Coastguard Worker    default_cfg = "turtle.cfg"
215*cda5da8dSAndroid Build Coastguard Worker    cfgdict1 = {}
216*cda5da8dSAndroid Build Coastguard Worker    cfgdict2 = {}
217*cda5da8dSAndroid Build Coastguard Worker    if isfile(default_cfg):
218*cda5da8dSAndroid Build Coastguard Worker        cfgdict1 = config_dict(default_cfg)
219*cda5da8dSAndroid Build Coastguard Worker    if "importconfig" in cfgdict1:
220*cda5da8dSAndroid Build Coastguard Worker        default_cfg = "turtle_%s.cfg" % cfgdict1["importconfig"]
221*cda5da8dSAndroid Build Coastguard Worker    try:
222*cda5da8dSAndroid Build Coastguard Worker        head, tail = split(__file__)
223*cda5da8dSAndroid Build Coastguard Worker        cfg_file2 = join(head, default_cfg)
224*cda5da8dSAndroid Build Coastguard Worker    except Exception:
225*cda5da8dSAndroid Build Coastguard Worker        cfg_file2 = ""
226*cda5da8dSAndroid Build Coastguard Worker    if isfile(cfg_file2):
227*cda5da8dSAndroid Build Coastguard Worker        cfgdict2 = config_dict(cfg_file2)
228*cda5da8dSAndroid Build Coastguard Worker    _CFG.update(cfgdict2)
229*cda5da8dSAndroid Build Coastguard Worker    _CFG.update(cfgdict1)
230*cda5da8dSAndroid Build Coastguard Worker
231*cda5da8dSAndroid Build Coastguard Workertry:
232*cda5da8dSAndroid Build Coastguard Worker    readconfig(_CFG)
233*cda5da8dSAndroid Build Coastguard Workerexcept Exception:
234*cda5da8dSAndroid Build Coastguard Worker    print ("No configfile read, reason unknown")
235*cda5da8dSAndroid Build Coastguard Worker
236*cda5da8dSAndroid Build Coastguard Worker
237*cda5da8dSAndroid Build Coastguard Workerclass Vec2D(tuple):
238*cda5da8dSAndroid Build Coastguard Worker    """A 2 dimensional vector class, used as a helper class
239*cda5da8dSAndroid Build Coastguard Worker    for implementing turtle graphics.
240*cda5da8dSAndroid Build Coastguard Worker    May be useful for turtle graphics programs also.
241*cda5da8dSAndroid Build Coastguard Worker    Derived from tuple, so a vector is a tuple!
242*cda5da8dSAndroid Build Coastguard Worker
243*cda5da8dSAndroid Build Coastguard Worker    Provides (for a, b vectors, k number):
244*cda5da8dSAndroid Build Coastguard Worker       a+b vector addition
245*cda5da8dSAndroid Build Coastguard Worker       a-b vector subtraction
246*cda5da8dSAndroid Build Coastguard Worker       a*b inner product
247*cda5da8dSAndroid Build Coastguard Worker       k*a and a*k multiplication with scalar
248*cda5da8dSAndroid Build Coastguard Worker       |a| absolute value of a
249*cda5da8dSAndroid Build Coastguard Worker       a.rotate(angle) rotation
250*cda5da8dSAndroid Build Coastguard Worker    """
251*cda5da8dSAndroid Build Coastguard Worker    def __new__(cls, x, y):
252*cda5da8dSAndroid Build Coastguard Worker        return tuple.__new__(cls, (x, y))
253*cda5da8dSAndroid Build Coastguard Worker    def __add__(self, other):
254*cda5da8dSAndroid Build Coastguard Worker        return Vec2D(self[0]+other[0], self[1]+other[1])
255*cda5da8dSAndroid Build Coastguard Worker    def __mul__(self, other):
256*cda5da8dSAndroid Build Coastguard Worker        if isinstance(other, Vec2D):
257*cda5da8dSAndroid Build Coastguard Worker            return self[0]*other[0]+self[1]*other[1]
258*cda5da8dSAndroid Build Coastguard Worker        return Vec2D(self[0]*other, self[1]*other)
259*cda5da8dSAndroid Build Coastguard Worker    def __rmul__(self, other):
260*cda5da8dSAndroid Build Coastguard Worker        if isinstance(other, int) or isinstance(other, float):
261*cda5da8dSAndroid Build Coastguard Worker            return Vec2D(self[0]*other, self[1]*other)
262*cda5da8dSAndroid Build Coastguard Worker        return NotImplemented
263*cda5da8dSAndroid Build Coastguard Worker    def __sub__(self, other):
264*cda5da8dSAndroid Build Coastguard Worker        return Vec2D(self[0]-other[0], self[1]-other[1])
265*cda5da8dSAndroid Build Coastguard Worker    def __neg__(self):
266*cda5da8dSAndroid Build Coastguard Worker        return Vec2D(-self[0], -self[1])
267*cda5da8dSAndroid Build Coastguard Worker    def __abs__(self):
268*cda5da8dSAndroid Build Coastguard Worker        return math.hypot(*self)
269*cda5da8dSAndroid Build Coastguard Worker    def rotate(self, angle):
270*cda5da8dSAndroid Build Coastguard Worker        """rotate self counterclockwise by angle
271*cda5da8dSAndroid Build Coastguard Worker        """
272*cda5da8dSAndroid Build Coastguard Worker        perp = Vec2D(-self[1], self[0])
273*cda5da8dSAndroid Build Coastguard Worker        angle = math.radians(angle)
274*cda5da8dSAndroid Build Coastguard Worker        c, s = math.cos(angle), math.sin(angle)
275*cda5da8dSAndroid Build Coastguard Worker        return Vec2D(self[0]*c+perp[0]*s, self[1]*c+perp[1]*s)
276*cda5da8dSAndroid Build Coastguard Worker    def __getnewargs__(self):
277*cda5da8dSAndroid Build Coastguard Worker        return (self[0], self[1])
278*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
279*cda5da8dSAndroid Build Coastguard Worker        return "(%.2f,%.2f)" % self
280*cda5da8dSAndroid Build Coastguard Worker
281*cda5da8dSAndroid Build Coastguard Worker
282*cda5da8dSAndroid Build Coastguard Worker##############################################################################
283*cda5da8dSAndroid Build Coastguard Worker### From here up to line    : Tkinter - Interface for turtle.py            ###
284*cda5da8dSAndroid Build Coastguard Worker### May be replaced by an interface to some different graphics toolkit     ###
285*cda5da8dSAndroid Build Coastguard Worker##############################################################################
286*cda5da8dSAndroid Build Coastguard Worker
287*cda5da8dSAndroid Build Coastguard Worker## helper functions for Scrolled Canvas, to forward Canvas-methods
288*cda5da8dSAndroid Build Coastguard Worker## to ScrolledCanvas class
289*cda5da8dSAndroid Build Coastguard Worker
290*cda5da8dSAndroid Build Coastguard Workerdef __methodDict(cls, _dict):
291*cda5da8dSAndroid Build Coastguard Worker    """helper function for Scrolled Canvas"""
292*cda5da8dSAndroid Build Coastguard Worker    baseList = list(cls.__bases__)
293*cda5da8dSAndroid Build Coastguard Worker    baseList.reverse()
294*cda5da8dSAndroid Build Coastguard Worker    for _super in baseList:
295*cda5da8dSAndroid Build Coastguard Worker        __methodDict(_super, _dict)
296*cda5da8dSAndroid Build Coastguard Worker    for key, value in cls.__dict__.items():
297*cda5da8dSAndroid Build Coastguard Worker        if type(value) == types.FunctionType:
298*cda5da8dSAndroid Build Coastguard Worker            _dict[key] = value
299*cda5da8dSAndroid Build Coastguard Worker
300*cda5da8dSAndroid Build Coastguard Workerdef __methods(cls):
301*cda5da8dSAndroid Build Coastguard Worker    """helper function for Scrolled Canvas"""
302*cda5da8dSAndroid Build Coastguard Worker    _dict = {}
303*cda5da8dSAndroid Build Coastguard Worker    __methodDict(cls, _dict)
304*cda5da8dSAndroid Build Coastguard Worker    return _dict.keys()
305*cda5da8dSAndroid Build Coastguard Worker
306*cda5da8dSAndroid Build Coastguard Worker__stringBody = (
307*cda5da8dSAndroid Build Coastguard Worker    'def %(method)s(self, *args, **kw): return ' +
308*cda5da8dSAndroid Build Coastguard Worker    'self.%(attribute)s.%(method)s(*args, **kw)')
309*cda5da8dSAndroid Build Coastguard Worker
310*cda5da8dSAndroid Build Coastguard Workerdef __forwardmethods(fromClass, toClass, toPart, exclude = ()):
311*cda5da8dSAndroid Build Coastguard Worker    ### MANY CHANGES ###
312*cda5da8dSAndroid Build Coastguard Worker    _dict_1 = {}
313*cda5da8dSAndroid Build Coastguard Worker    __methodDict(toClass, _dict_1)
314*cda5da8dSAndroid Build Coastguard Worker    _dict = {}
315*cda5da8dSAndroid Build Coastguard Worker    mfc = __methods(fromClass)
316*cda5da8dSAndroid Build Coastguard Worker    for ex in _dict_1.keys():
317*cda5da8dSAndroid Build Coastguard Worker        if ex[:1] == '_' or ex[-1:] == '_' or ex in exclude or ex in mfc:
318*cda5da8dSAndroid Build Coastguard Worker            pass
319*cda5da8dSAndroid Build Coastguard Worker        else:
320*cda5da8dSAndroid Build Coastguard Worker            _dict[ex] = _dict_1[ex]
321*cda5da8dSAndroid Build Coastguard Worker
322*cda5da8dSAndroid Build Coastguard Worker    for method, func in _dict.items():
323*cda5da8dSAndroid Build Coastguard Worker        d = {'method': method, 'func': func}
324*cda5da8dSAndroid Build Coastguard Worker        if isinstance(toPart, str):
325*cda5da8dSAndroid Build Coastguard Worker            execString = \
326*cda5da8dSAndroid Build Coastguard Worker                __stringBody % {'method' : method, 'attribute' : toPart}
327*cda5da8dSAndroid Build Coastguard Worker        exec(execString, d)
328*cda5da8dSAndroid Build Coastguard Worker        setattr(fromClass, method, d[method])   ### NEWU!
329*cda5da8dSAndroid Build Coastguard Worker
330*cda5da8dSAndroid Build Coastguard Worker
331*cda5da8dSAndroid Build Coastguard Workerclass ScrolledCanvas(TK.Frame):
332*cda5da8dSAndroid Build Coastguard Worker    """Modeled after the scrolled canvas class from Grayons's Tkinter book.
333*cda5da8dSAndroid Build Coastguard Worker
334*cda5da8dSAndroid Build Coastguard Worker    Used as the default canvas, which pops up automatically when
335*cda5da8dSAndroid Build Coastguard Worker    using turtle graphics functions or the Turtle class.
336*cda5da8dSAndroid Build Coastguard Worker    """
337*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, master, width=500, height=350,
338*cda5da8dSAndroid Build Coastguard Worker                                          canvwidth=600, canvheight=500):
339*cda5da8dSAndroid Build Coastguard Worker        TK.Frame.__init__(self, master, width=width, height=height)
340*cda5da8dSAndroid Build Coastguard Worker        self._rootwindow = self.winfo_toplevel()
341*cda5da8dSAndroid Build Coastguard Worker        self.width, self.height = width, height
342*cda5da8dSAndroid Build Coastguard Worker        self.canvwidth, self.canvheight = canvwidth, canvheight
343*cda5da8dSAndroid Build Coastguard Worker        self.bg = "white"
344*cda5da8dSAndroid Build Coastguard Worker        self._canvas = TK.Canvas(master, width=width, height=height,
345*cda5da8dSAndroid Build Coastguard Worker                                 bg=self.bg, relief=TK.SUNKEN, borderwidth=2)
346*cda5da8dSAndroid Build Coastguard Worker        self.hscroll = TK.Scrollbar(master, command=self._canvas.xview,
347*cda5da8dSAndroid Build Coastguard Worker                                    orient=TK.HORIZONTAL)
348*cda5da8dSAndroid Build Coastguard Worker        self.vscroll = TK.Scrollbar(master, command=self._canvas.yview)
349*cda5da8dSAndroid Build Coastguard Worker        self._canvas.configure(xscrollcommand=self.hscroll.set,
350*cda5da8dSAndroid Build Coastguard Worker                               yscrollcommand=self.vscroll.set)
351*cda5da8dSAndroid Build Coastguard Worker        self.rowconfigure(0, weight=1, minsize=0)
352*cda5da8dSAndroid Build Coastguard Worker        self.columnconfigure(0, weight=1, minsize=0)
353*cda5da8dSAndroid Build Coastguard Worker        self._canvas.grid(padx=1, in_ = self, pady=1, row=0,
354*cda5da8dSAndroid Build Coastguard Worker                column=0, rowspan=1, columnspan=1, sticky='news')
355*cda5da8dSAndroid Build Coastguard Worker        self.vscroll.grid(padx=1, in_ = self, pady=1, row=0,
356*cda5da8dSAndroid Build Coastguard Worker                column=1, rowspan=1, columnspan=1, sticky='news')
357*cda5da8dSAndroid Build Coastguard Worker        self.hscroll.grid(padx=1, in_ = self, pady=1, row=1,
358*cda5da8dSAndroid Build Coastguard Worker                column=0, rowspan=1, columnspan=1, sticky='news')
359*cda5da8dSAndroid Build Coastguard Worker        self.reset()
360*cda5da8dSAndroid Build Coastguard Worker        self._rootwindow.bind('<Configure>', self.onResize)
361*cda5da8dSAndroid Build Coastguard Worker
362*cda5da8dSAndroid Build Coastguard Worker    def reset(self, canvwidth=None, canvheight=None, bg = None):
363*cda5da8dSAndroid Build Coastguard Worker        """Adjust canvas and scrollbars according to given canvas size."""
364*cda5da8dSAndroid Build Coastguard Worker        if canvwidth:
365*cda5da8dSAndroid Build Coastguard Worker            self.canvwidth = canvwidth
366*cda5da8dSAndroid Build Coastguard Worker        if canvheight:
367*cda5da8dSAndroid Build Coastguard Worker            self.canvheight = canvheight
368*cda5da8dSAndroid Build Coastguard Worker        if bg:
369*cda5da8dSAndroid Build Coastguard Worker            self.bg = bg
370*cda5da8dSAndroid Build Coastguard Worker        self._canvas.config(bg=bg,
371*cda5da8dSAndroid Build Coastguard Worker                        scrollregion=(-self.canvwidth//2, -self.canvheight//2,
372*cda5da8dSAndroid Build Coastguard Worker                                       self.canvwidth//2, self.canvheight//2))
373*cda5da8dSAndroid Build Coastguard Worker        self._canvas.xview_moveto(0.5*(self.canvwidth - self.width + 30) /
374*cda5da8dSAndroid Build Coastguard Worker                                                               self.canvwidth)
375*cda5da8dSAndroid Build Coastguard Worker        self._canvas.yview_moveto(0.5*(self.canvheight- self.height + 30) /
376*cda5da8dSAndroid Build Coastguard Worker                                                              self.canvheight)
377*cda5da8dSAndroid Build Coastguard Worker        self.adjustScrolls()
378*cda5da8dSAndroid Build Coastguard Worker
379*cda5da8dSAndroid Build Coastguard Worker
380*cda5da8dSAndroid Build Coastguard Worker    def adjustScrolls(self):
381*cda5da8dSAndroid Build Coastguard Worker        """ Adjust scrollbars according to window- and canvas-size.
382*cda5da8dSAndroid Build Coastguard Worker        """
383*cda5da8dSAndroid Build Coastguard Worker        cwidth = self._canvas.winfo_width()
384*cda5da8dSAndroid Build Coastguard Worker        cheight = self._canvas.winfo_height()
385*cda5da8dSAndroid Build Coastguard Worker        self._canvas.xview_moveto(0.5*(self.canvwidth-cwidth)/self.canvwidth)
386*cda5da8dSAndroid Build Coastguard Worker        self._canvas.yview_moveto(0.5*(self.canvheight-cheight)/self.canvheight)
387*cda5da8dSAndroid Build Coastguard Worker        if cwidth < self.canvwidth or cheight < self.canvheight:
388*cda5da8dSAndroid Build Coastguard Worker            self.hscroll.grid(padx=1, in_ = self, pady=1, row=1,
389*cda5da8dSAndroid Build Coastguard Worker                              column=0, rowspan=1, columnspan=1, sticky='news')
390*cda5da8dSAndroid Build Coastguard Worker            self.vscroll.grid(padx=1, in_ = self, pady=1, row=0,
391*cda5da8dSAndroid Build Coastguard Worker                              column=1, rowspan=1, columnspan=1, sticky='news')
392*cda5da8dSAndroid Build Coastguard Worker        else:
393*cda5da8dSAndroid Build Coastguard Worker            self.hscroll.grid_forget()
394*cda5da8dSAndroid Build Coastguard Worker            self.vscroll.grid_forget()
395*cda5da8dSAndroid Build Coastguard Worker
396*cda5da8dSAndroid Build Coastguard Worker    def onResize(self, event):
397*cda5da8dSAndroid Build Coastguard Worker        """self-explanatory"""
398*cda5da8dSAndroid Build Coastguard Worker        self.adjustScrolls()
399*cda5da8dSAndroid Build Coastguard Worker
400*cda5da8dSAndroid Build Coastguard Worker    def bbox(self, *args):
401*cda5da8dSAndroid Build Coastguard Worker        """ 'forward' method, which canvas itself has inherited...
402*cda5da8dSAndroid Build Coastguard Worker        """
403*cda5da8dSAndroid Build Coastguard Worker        return self._canvas.bbox(*args)
404*cda5da8dSAndroid Build Coastguard Worker
405*cda5da8dSAndroid Build Coastguard Worker    def cget(self, *args, **kwargs):
406*cda5da8dSAndroid Build Coastguard Worker        """ 'forward' method, which canvas itself has inherited...
407*cda5da8dSAndroid Build Coastguard Worker        """
408*cda5da8dSAndroid Build Coastguard Worker        return self._canvas.cget(*args, **kwargs)
409*cda5da8dSAndroid Build Coastguard Worker
410*cda5da8dSAndroid Build Coastguard Worker    def config(self, *args, **kwargs):
411*cda5da8dSAndroid Build Coastguard Worker        """ 'forward' method, which canvas itself has inherited...
412*cda5da8dSAndroid Build Coastguard Worker        """
413*cda5da8dSAndroid Build Coastguard Worker        self._canvas.config(*args, **kwargs)
414*cda5da8dSAndroid Build Coastguard Worker
415*cda5da8dSAndroid Build Coastguard Worker    def bind(self, *args, **kwargs):
416*cda5da8dSAndroid Build Coastguard Worker        """ 'forward' method, which canvas itself has inherited...
417*cda5da8dSAndroid Build Coastguard Worker        """
418*cda5da8dSAndroid Build Coastguard Worker        self._canvas.bind(*args, **kwargs)
419*cda5da8dSAndroid Build Coastguard Worker
420*cda5da8dSAndroid Build Coastguard Worker    def unbind(self, *args, **kwargs):
421*cda5da8dSAndroid Build Coastguard Worker        """ 'forward' method, which canvas itself has inherited...
422*cda5da8dSAndroid Build Coastguard Worker        """
423*cda5da8dSAndroid Build Coastguard Worker        self._canvas.unbind(*args, **kwargs)
424*cda5da8dSAndroid Build Coastguard Worker
425*cda5da8dSAndroid Build Coastguard Worker    def focus_force(self):
426*cda5da8dSAndroid Build Coastguard Worker        """ 'forward' method, which canvas itself has inherited...
427*cda5da8dSAndroid Build Coastguard Worker        """
428*cda5da8dSAndroid Build Coastguard Worker        self._canvas.focus_force()
429*cda5da8dSAndroid Build Coastguard Worker
430*cda5da8dSAndroid Build Coastguard Worker__forwardmethods(ScrolledCanvas, TK.Canvas, '_canvas')
431*cda5da8dSAndroid Build Coastguard Worker
432*cda5da8dSAndroid Build Coastguard Worker
433*cda5da8dSAndroid Build Coastguard Workerclass _Root(TK.Tk):
434*cda5da8dSAndroid Build Coastguard Worker    """Root class for Screen based on Tkinter."""
435*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
436*cda5da8dSAndroid Build Coastguard Worker        TK.Tk.__init__(self)
437*cda5da8dSAndroid Build Coastguard Worker
438*cda5da8dSAndroid Build Coastguard Worker    def setupcanvas(self, width, height, cwidth, cheight):
439*cda5da8dSAndroid Build Coastguard Worker        self._canvas = ScrolledCanvas(self, width, height, cwidth, cheight)
440*cda5da8dSAndroid Build Coastguard Worker        self._canvas.pack(expand=1, fill="both")
441*cda5da8dSAndroid Build Coastguard Worker
442*cda5da8dSAndroid Build Coastguard Worker    def _getcanvas(self):
443*cda5da8dSAndroid Build Coastguard Worker        return self._canvas
444*cda5da8dSAndroid Build Coastguard Worker
445*cda5da8dSAndroid Build Coastguard Worker    def set_geometry(self, width, height, startx, starty):
446*cda5da8dSAndroid Build Coastguard Worker        self.geometry("%dx%d%+d%+d"%(width, height, startx, starty))
447*cda5da8dSAndroid Build Coastguard Worker
448*cda5da8dSAndroid Build Coastguard Worker    def ondestroy(self, destroy):
449*cda5da8dSAndroid Build Coastguard Worker        self.wm_protocol("WM_DELETE_WINDOW", destroy)
450*cda5da8dSAndroid Build Coastguard Worker
451*cda5da8dSAndroid Build Coastguard Worker    def win_width(self):
452*cda5da8dSAndroid Build Coastguard Worker        return self.winfo_screenwidth()
453*cda5da8dSAndroid Build Coastguard Worker
454*cda5da8dSAndroid Build Coastguard Worker    def win_height(self):
455*cda5da8dSAndroid Build Coastguard Worker        return self.winfo_screenheight()
456*cda5da8dSAndroid Build Coastguard Worker
457*cda5da8dSAndroid Build Coastguard WorkerCanvas = TK.Canvas
458*cda5da8dSAndroid Build Coastguard Worker
459*cda5da8dSAndroid Build Coastguard Worker
460*cda5da8dSAndroid Build Coastguard Workerclass TurtleScreenBase(object):
461*cda5da8dSAndroid Build Coastguard Worker    """Provide the basic graphics functionality.
462*cda5da8dSAndroid Build Coastguard Worker       Interface between Tkinter and turtle.py.
463*cda5da8dSAndroid Build Coastguard Worker
464*cda5da8dSAndroid Build Coastguard Worker       To port turtle.py to some different graphics toolkit
465*cda5da8dSAndroid Build Coastguard Worker       a corresponding TurtleScreenBase class has to be implemented.
466*cda5da8dSAndroid Build Coastguard Worker    """
467*cda5da8dSAndroid Build Coastguard Worker
468*cda5da8dSAndroid Build Coastguard Worker    def _blankimage(self):
469*cda5da8dSAndroid Build Coastguard Worker        """return a blank image object
470*cda5da8dSAndroid Build Coastguard Worker        """
471*cda5da8dSAndroid Build Coastguard Worker        img = TK.PhotoImage(width=1, height=1, master=self.cv)
472*cda5da8dSAndroid Build Coastguard Worker        img.blank()
473*cda5da8dSAndroid Build Coastguard Worker        return img
474*cda5da8dSAndroid Build Coastguard Worker
475*cda5da8dSAndroid Build Coastguard Worker    def _image(self, filename):
476*cda5da8dSAndroid Build Coastguard Worker        """return an image object containing the
477*cda5da8dSAndroid Build Coastguard Worker        imagedata from a gif-file named filename.
478*cda5da8dSAndroid Build Coastguard Worker        """
479*cda5da8dSAndroid Build Coastguard Worker        return TK.PhotoImage(file=filename, master=self.cv)
480*cda5da8dSAndroid Build Coastguard Worker
481*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, cv):
482*cda5da8dSAndroid Build Coastguard Worker        self.cv = cv
483*cda5da8dSAndroid Build Coastguard Worker        if isinstance(cv, ScrolledCanvas):
484*cda5da8dSAndroid Build Coastguard Worker            w = self.cv.canvwidth
485*cda5da8dSAndroid Build Coastguard Worker            h = self.cv.canvheight
486*cda5da8dSAndroid Build Coastguard Worker        else:  # expected: ordinary TK.Canvas
487*cda5da8dSAndroid Build Coastguard Worker            w = int(self.cv.cget("width"))
488*cda5da8dSAndroid Build Coastguard Worker            h = int(self.cv.cget("height"))
489*cda5da8dSAndroid Build Coastguard Worker            self.cv.config(scrollregion = (-w//2, -h//2, w//2, h//2 ))
490*cda5da8dSAndroid Build Coastguard Worker        self.canvwidth = w
491*cda5da8dSAndroid Build Coastguard Worker        self.canvheight = h
492*cda5da8dSAndroid Build Coastguard Worker        self.xscale = self.yscale = 1.0
493*cda5da8dSAndroid Build Coastguard Worker
494*cda5da8dSAndroid Build Coastguard Worker    def _createpoly(self):
495*cda5da8dSAndroid Build Coastguard Worker        """Create an invisible polygon item on canvas self.cv)
496*cda5da8dSAndroid Build Coastguard Worker        """
497*cda5da8dSAndroid Build Coastguard Worker        return self.cv.create_polygon((0, 0, 0, 0, 0, 0), fill="", outline="")
498*cda5da8dSAndroid Build Coastguard Worker
499*cda5da8dSAndroid Build Coastguard Worker    def _drawpoly(self, polyitem, coordlist, fill=None,
500*cda5da8dSAndroid Build Coastguard Worker                  outline=None, width=None, top=False):
501*cda5da8dSAndroid Build Coastguard Worker        """Configure polygonitem polyitem according to provided
502*cda5da8dSAndroid Build Coastguard Worker        arguments:
503*cda5da8dSAndroid Build Coastguard Worker        coordlist is sequence of coordinates
504*cda5da8dSAndroid Build Coastguard Worker        fill is filling color
505*cda5da8dSAndroid Build Coastguard Worker        outline is outline color
506*cda5da8dSAndroid Build Coastguard Worker        top is a boolean value, which specifies if polyitem
507*cda5da8dSAndroid Build Coastguard Worker        will be put on top of the canvas' displaylist so it
508*cda5da8dSAndroid Build Coastguard Worker        will not be covered by other items.
509*cda5da8dSAndroid Build Coastguard Worker        """
510*cda5da8dSAndroid Build Coastguard Worker        cl = []
511*cda5da8dSAndroid Build Coastguard Worker        for x, y in coordlist:
512*cda5da8dSAndroid Build Coastguard Worker            cl.append(x * self.xscale)
513*cda5da8dSAndroid Build Coastguard Worker            cl.append(-y * self.yscale)
514*cda5da8dSAndroid Build Coastguard Worker        self.cv.coords(polyitem, *cl)
515*cda5da8dSAndroid Build Coastguard Worker        if fill is not None:
516*cda5da8dSAndroid Build Coastguard Worker            self.cv.itemconfigure(polyitem, fill=fill)
517*cda5da8dSAndroid Build Coastguard Worker        if outline is not None:
518*cda5da8dSAndroid Build Coastguard Worker            self.cv.itemconfigure(polyitem, outline=outline)
519*cda5da8dSAndroid Build Coastguard Worker        if width is not None:
520*cda5da8dSAndroid Build Coastguard Worker            self.cv.itemconfigure(polyitem, width=width)
521*cda5da8dSAndroid Build Coastguard Worker        if top:
522*cda5da8dSAndroid Build Coastguard Worker            self.cv.tag_raise(polyitem)
523*cda5da8dSAndroid Build Coastguard Worker
524*cda5da8dSAndroid Build Coastguard Worker    def _createline(self):
525*cda5da8dSAndroid Build Coastguard Worker        """Create an invisible line item on canvas self.cv)
526*cda5da8dSAndroid Build Coastguard Worker        """
527*cda5da8dSAndroid Build Coastguard Worker        return self.cv.create_line(0, 0, 0, 0, fill="", width=2,
528*cda5da8dSAndroid Build Coastguard Worker                                   capstyle = TK.ROUND)
529*cda5da8dSAndroid Build Coastguard Worker
530*cda5da8dSAndroid Build Coastguard Worker    def _drawline(self, lineitem, coordlist=None,
531*cda5da8dSAndroid Build Coastguard Worker                  fill=None, width=None, top=False):
532*cda5da8dSAndroid Build Coastguard Worker        """Configure lineitem according to provided arguments:
533*cda5da8dSAndroid Build Coastguard Worker        coordlist is sequence of coordinates
534*cda5da8dSAndroid Build Coastguard Worker        fill is drawing color
535*cda5da8dSAndroid Build Coastguard Worker        width is width of drawn line.
536*cda5da8dSAndroid Build Coastguard Worker        top is a boolean value, which specifies if polyitem
537*cda5da8dSAndroid Build Coastguard Worker        will be put on top of the canvas' displaylist so it
538*cda5da8dSAndroid Build Coastguard Worker        will not be covered by other items.
539*cda5da8dSAndroid Build Coastguard Worker        """
540*cda5da8dSAndroid Build Coastguard Worker        if coordlist is not None:
541*cda5da8dSAndroid Build Coastguard Worker            cl = []
542*cda5da8dSAndroid Build Coastguard Worker            for x, y in coordlist:
543*cda5da8dSAndroid Build Coastguard Worker                cl.append(x * self.xscale)
544*cda5da8dSAndroid Build Coastguard Worker                cl.append(-y * self.yscale)
545*cda5da8dSAndroid Build Coastguard Worker            self.cv.coords(lineitem, *cl)
546*cda5da8dSAndroid Build Coastguard Worker        if fill is not None:
547*cda5da8dSAndroid Build Coastguard Worker            self.cv.itemconfigure(lineitem, fill=fill)
548*cda5da8dSAndroid Build Coastguard Worker        if width is not None:
549*cda5da8dSAndroid Build Coastguard Worker            self.cv.itemconfigure(lineitem, width=width)
550*cda5da8dSAndroid Build Coastguard Worker        if top:
551*cda5da8dSAndroid Build Coastguard Worker            self.cv.tag_raise(lineitem)
552*cda5da8dSAndroid Build Coastguard Worker
553*cda5da8dSAndroid Build Coastguard Worker    def _delete(self, item):
554*cda5da8dSAndroid Build Coastguard Worker        """Delete graphics item from canvas.
555*cda5da8dSAndroid Build Coastguard Worker        If item is"all" delete all graphics items.
556*cda5da8dSAndroid Build Coastguard Worker        """
557*cda5da8dSAndroid Build Coastguard Worker        self.cv.delete(item)
558*cda5da8dSAndroid Build Coastguard Worker
559*cda5da8dSAndroid Build Coastguard Worker    def _update(self):
560*cda5da8dSAndroid Build Coastguard Worker        """Redraw graphics items on canvas
561*cda5da8dSAndroid Build Coastguard Worker        """
562*cda5da8dSAndroid Build Coastguard Worker        self.cv.update()
563*cda5da8dSAndroid Build Coastguard Worker
564*cda5da8dSAndroid Build Coastguard Worker    def _delay(self, delay):
565*cda5da8dSAndroid Build Coastguard Worker        """Delay subsequent canvas actions for delay ms."""
566*cda5da8dSAndroid Build Coastguard Worker        self.cv.after(delay)
567*cda5da8dSAndroid Build Coastguard Worker
568*cda5da8dSAndroid Build Coastguard Worker    def _iscolorstring(self, color):
569*cda5da8dSAndroid Build Coastguard Worker        """Check if the string color is a legal Tkinter color string.
570*cda5da8dSAndroid Build Coastguard Worker        """
571*cda5da8dSAndroid Build Coastguard Worker        try:
572*cda5da8dSAndroid Build Coastguard Worker            rgb = self.cv.winfo_rgb(color)
573*cda5da8dSAndroid Build Coastguard Worker            ok = True
574*cda5da8dSAndroid Build Coastguard Worker        except TK.TclError:
575*cda5da8dSAndroid Build Coastguard Worker            ok = False
576*cda5da8dSAndroid Build Coastguard Worker        return ok
577*cda5da8dSAndroid Build Coastguard Worker
578*cda5da8dSAndroid Build Coastguard Worker    def _bgcolor(self, color=None):
579*cda5da8dSAndroid Build Coastguard Worker        """Set canvas' backgroundcolor if color is not None,
580*cda5da8dSAndroid Build Coastguard Worker        else return backgroundcolor."""
581*cda5da8dSAndroid Build Coastguard Worker        if color is not None:
582*cda5da8dSAndroid Build Coastguard Worker            self.cv.config(bg = color)
583*cda5da8dSAndroid Build Coastguard Worker            self._update()
584*cda5da8dSAndroid Build Coastguard Worker        else:
585*cda5da8dSAndroid Build Coastguard Worker            return self.cv.cget("bg")
586*cda5da8dSAndroid Build Coastguard Worker
587*cda5da8dSAndroid Build Coastguard Worker    def _write(self, pos, txt, align, font, pencolor):
588*cda5da8dSAndroid Build Coastguard Worker        """Write txt at pos in canvas with specified font
589*cda5da8dSAndroid Build Coastguard Worker        and color.
590*cda5da8dSAndroid Build Coastguard Worker        Return text item and x-coord of right bottom corner
591*cda5da8dSAndroid Build Coastguard Worker        of text's bounding box."""
592*cda5da8dSAndroid Build Coastguard Worker        x, y = pos
593*cda5da8dSAndroid Build Coastguard Worker        x = x * self.xscale
594*cda5da8dSAndroid Build Coastguard Worker        y = y * self.yscale
595*cda5da8dSAndroid Build Coastguard Worker        anchor = {"left":"sw", "center":"s", "right":"se" }
596*cda5da8dSAndroid Build Coastguard Worker        item = self.cv.create_text(x-1, -y, text = txt, anchor = anchor[align],
597*cda5da8dSAndroid Build Coastguard Worker                                        fill = pencolor, font = font)
598*cda5da8dSAndroid Build Coastguard Worker        x0, y0, x1, y1 = self.cv.bbox(item)
599*cda5da8dSAndroid Build Coastguard Worker        return item, x1-1
600*cda5da8dSAndroid Build Coastguard Worker
601*cda5da8dSAndroid Build Coastguard Worker##    def _dot(self, pos, size, color):
602*cda5da8dSAndroid Build Coastguard Worker##        """may be implemented for some other graphics toolkit"""
603*cda5da8dSAndroid Build Coastguard Worker
604*cda5da8dSAndroid Build Coastguard Worker    def _onclick(self, item, fun, num=1, add=None):
605*cda5da8dSAndroid Build Coastguard Worker        """Bind fun to mouse-click event on turtle.
606*cda5da8dSAndroid Build Coastguard Worker        fun must be a function with two arguments, the coordinates
607*cda5da8dSAndroid Build Coastguard Worker        of the clicked point on the canvas.
608*cda5da8dSAndroid Build Coastguard Worker        num, the number of the mouse-button defaults to 1
609*cda5da8dSAndroid Build Coastguard Worker        """
610*cda5da8dSAndroid Build Coastguard Worker        if fun is None:
611*cda5da8dSAndroid Build Coastguard Worker            self.cv.tag_unbind(item, "<Button-%s>" % num)
612*cda5da8dSAndroid Build Coastguard Worker        else:
613*cda5da8dSAndroid Build Coastguard Worker            def eventfun(event):
614*cda5da8dSAndroid Build Coastguard Worker                x, y = (self.cv.canvasx(event.x)/self.xscale,
615*cda5da8dSAndroid Build Coastguard Worker                        -self.cv.canvasy(event.y)/self.yscale)
616*cda5da8dSAndroid Build Coastguard Worker                fun(x, y)
617*cda5da8dSAndroid Build Coastguard Worker            self.cv.tag_bind(item, "<Button-%s>" % num, eventfun, add)
618*cda5da8dSAndroid Build Coastguard Worker
619*cda5da8dSAndroid Build Coastguard Worker    def _onrelease(self, item, fun, num=1, add=None):
620*cda5da8dSAndroid Build Coastguard Worker        """Bind fun to mouse-button-release event on turtle.
621*cda5da8dSAndroid Build Coastguard Worker        fun must be a function with two arguments, the coordinates
622*cda5da8dSAndroid Build Coastguard Worker        of the point on the canvas where mouse button is released.
623*cda5da8dSAndroid Build Coastguard Worker        num, the number of the mouse-button defaults to 1
624*cda5da8dSAndroid Build Coastguard Worker
625*cda5da8dSAndroid Build Coastguard Worker        If a turtle is clicked, first _onclick-event will be performed,
626*cda5da8dSAndroid Build Coastguard Worker        then _onscreensclick-event.
627*cda5da8dSAndroid Build Coastguard Worker        """
628*cda5da8dSAndroid Build Coastguard Worker        if fun is None:
629*cda5da8dSAndroid Build Coastguard Worker            self.cv.tag_unbind(item, "<Button%s-ButtonRelease>" % num)
630*cda5da8dSAndroid Build Coastguard Worker        else:
631*cda5da8dSAndroid Build Coastguard Worker            def eventfun(event):
632*cda5da8dSAndroid Build Coastguard Worker                x, y = (self.cv.canvasx(event.x)/self.xscale,
633*cda5da8dSAndroid Build Coastguard Worker                        -self.cv.canvasy(event.y)/self.yscale)
634*cda5da8dSAndroid Build Coastguard Worker                fun(x, y)
635*cda5da8dSAndroid Build Coastguard Worker            self.cv.tag_bind(item, "<Button%s-ButtonRelease>" % num,
636*cda5da8dSAndroid Build Coastguard Worker                             eventfun, add)
637*cda5da8dSAndroid Build Coastguard Worker
638*cda5da8dSAndroid Build Coastguard Worker    def _ondrag(self, item, fun, num=1, add=None):
639*cda5da8dSAndroid Build Coastguard Worker        """Bind fun to mouse-move-event (with pressed mouse button) on turtle.
640*cda5da8dSAndroid Build Coastguard Worker        fun must be a function with two arguments, the coordinates of the
641*cda5da8dSAndroid Build Coastguard Worker        actual mouse position on the canvas.
642*cda5da8dSAndroid Build Coastguard Worker        num, the number of the mouse-button defaults to 1
643*cda5da8dSAndroid Build Coastguard Worker
644*cda5da8dSAndroid Build Coastguard Worker        Every sequence of mouse-move-events on a turtle is preceded by a
645*cda5da8dSAndroid Build Coastguard Worker        mouse-click event on that turtle.
646*cda5da8dSAndroid Build Coastguard Worker        """
647*cda5da8dSAndroid Build Coastguard Worker        if fun is None:
648*cda5da8dSAndroid Build Coastguard Worker            self.cv.tag_unbind(item, "<Button%s-Motion>" % num)
649*cda5da8dSAndroid Build Coastguard Worker        else:
650*cda5da8dSAndroid Build Coastguard Worker            def eventfun(event):
651*cda5da8dSAndroid Build Coastguard Worker                try:
652*cda5da8dSAndroid Build Coastguard Worker                    x, y = (self.cv.canvasx(event.x)/self.xscale,
653*cda5da8dSAndroid Build Coastguard Worker                           -self.cv.canvasy(event.y)/self.yscale)
654*cda5da8dSAndroid Build Coastguard Worker                    fun(x, y)
655*cda5da8dSAndroid Build Coastguard Worker                except Exception:
656*cda5da8dSAndroid Build Coastguard Worker                    pass
657*cda5da8dSAndroid Build Coastguard Worker            self.cv.tag_bind(item, "<Button%s-Motion>" % num, eventfun, add)
658*cda5da8dSAndroid Build Coastguard Worker
659*cda5da8dSAndroid Build Coastguard Worker    def _onscreenclick(self, fun, num=1, add=None):
660*cda5da8dSAndroid Build Coastguard Worker        """Bind fun to mouse-click event on canvas.
661*cda5da8dSAndroid Build Coastguard Worker        fun must be a function with two arguments, the coordinates
662*cda5da8dSAndroid Build Coastguard Worker        of the clicked point on the canvas.
663*cda5da8dSAndroid Build Coastguard Worker        num, the number of the mouse-button defaults to 1
664*cda5da8dSAndroid Build Coastguard Worker
665*cda5da8dSAndroid Build Coastguard Worker        If a turtle is clicked, first _onclick-event will be performed,
666*cda5da8dSAndroid Build Coastguard Worker        then _onscreensclick-event.
667*cda5da8dSAndroid Build Coastguard Worker        """
668*cda5da8dSAndroid Build Coastguard Worker        if fun is None:
669*cda5da8dSAndroid Build Coastguard Worker            self.cv.unbind("<Button-%s>" % num)
670*cda5da8dSAndroid Build Coastguard Worker        else:
671*cda5da8dSAndroid Build Coastguard Worker            def eventfun(event):
672*cda5da8dSAndroid Build Coastguard Worker                x, y = (self.cv.canvasx(event.x)/self.xscale,
673*cda5da8dSAndroid Build Coastguard Worker                        -self.cv.canvasy(event.y)/self.yscale)
674*cda5da8dSAndroid Build Coastguard Worker                fun(x, y)
675*cda5da8dSAndroid Build Coastguard Worker            self.cv.bind("<Button-%s>" % num, eventfun, add)
676*cda5da8dSAndroid Build Coastguard Worker
677*cda5da8dSAndroid Build Coastguard Worker    def _onkeyrelease(self, fun, key):
678*cda5da8dSAndroid Build Coastguard Worker        """Bind fun to key-release event of key.
679*cda5da8dSAndroid Build Coastguard Worker        Canvas must have focus. See method listen
680*cda5da8dSAndroid Build Coastguard Worker        """
681*cda5da8dSAndroid Build Coastguard Worker        if fun is None:
682*cda5da8dSAndroid Build Coastguard Worker            self.cv.unbind("<KeyRelease-%s>" % key, None)
683*cda5da8dSAndroid Build Coastguard Worker        else:
684*cda5da8dSAndroid Build Coastguard Worker            def eventfun(event):
685*cda5da8dSAndroid Build Coastguard Worker                fun()
686*cda5da8dSAndroid Build Coastguard Worker            self.cv.bind("<KeyRelease-%s>" % key, eventfun)
687*cda5da8dSAndroid Build Coastguard Worker
688*cda5da8dSAndroid Build Coastguard Worker    def _onkeypress(self, fun, key=None):
689*cda5da8dSAndroid Build Coastguard Worker        """If key is given, bind fun to key-press event of key.
690*cda5da8dSAndroid Build Coastguard Worker        Otherwise bind fun to any key-press.
691*cda5da8dSAndroid Build Coastguard Worker        Canvas must have focus. See method listen.
692*cda5da8dSAndroid Build Coastguard Worker        """
693*cda5da8dSAndroid Build Coastguard Worker        if fun is None:
694*cda5da8dSAndroid Build Coastguard Worker            if key is None:
695*cda5da8dSAndroid Build Coastguard Worker                self.cv.unbind("<KeyPress>", None)
696*cda5da8dSAndroid Build Coastguard Worker            else:
697*cda5da8dSAndroid Build Coastguard Worker                self.cv.unbind("<KeyPress-%s>" % key, None)
698*cda5da8dSAndroid Build Coastguard Worker        else:
699*cda5da8dSAndroid Build Coastguard Worker            def eventfun(event):
700*cda5da8dSAndroid Build Coastguard Worker                fun()
701*cda5da8dSAndroid Build Coastguard Worker            if key is None:
702*cda5da8dSAndroid Build Coastguard Worker                self.cv.bind("<KeyPress>", eventfun)
703*cda5da8dSAndroid Build Coastguard Worker            else:
704*cda5da8dSAndroid Build Coastguard Worker                self.cv.bind("<KeyPress-%s>" % key, eventfun)
705*cda5da8dSAndroid Build Coastguard Worker
706*cda5da8dSAndroid Build Coastguard Worker    def _listen(self):
707*cda5da8dSAndroid Build Coastguard Worker        """Set focus on canvas (in order to collect key-events)
708*cda5da8dSAndroid Build Coastguard Worker        """
709*cda5da8dSAndroid Build Coastguard Worker        self.cv.focus_force()
710*cda5da8dSAndroid Build Coastguard Worker
711*cda5da8dSAndroid Build Coastguard Worker    def _ontimer(self, fun, t):
712*cda5da8dSAndroid Build Coastguard Worker        """Install a timer, which calls fun after t milliseconds.
713*cda5da8dSAndroid Build Coastguard Worker        """
714*cda5da8dSAndroid Build Coastguard Worker        if t == 0:
715*cda5da8dSAndroid Build Coastguard Worker            self.cv.after_idle(fun)
716*cda5da8dSAndroid Build Coastguard Worker        else:
717*cda5da8dSAndroid Build Coastguard Worker            self.cv.after(t, fun)
718*cda5da8dSAndroid Build Coastguard Worker
719*cda5da8dSAndroid Build Coastguard Worker    def _createimage(self, image):
720*cda5da8dSAndroid Build Coastguard Worker        """Create and return image item on canvas.
721*cda5da8dSAndroid Build Coastguard Worker        """
722*cda5da8dSAndroid Build Coastguard Worker        return self.cv.create_image(0, 0, image=image)
723*cda5da8dSAndroid Build Coastguard Worker
724*cda5da8dSAndroid Build Coastguard Worker    def _drawimage(self, item, pos, image):
725*cda5da8dSAndroid Build Coastguard Worker        """Configure image item as to draw image object
726*cda5da8dSAndroid Build Coastguard Worker        at position (x,y) on canvas)
727*cda5da8dSAndroid Build Coastguard Worker        """
728*cda5da8dSAndroid Build Coastguard Worker        x, y = pos
729*cda5da8dSAndroid Build Coastguard Worker        self.cv.coords(item, (x * self.xscale, -y * self.yscale))
730*cda5da8dSAndroid Build Coastguard Worker        self.cv.itemconfig(item, image=image)
731*cda5da8dSAndroid Build Coastguard Worker
732*cda5da8dSAndroid Build Coastguard Worker    def _setbgpic(self, item, image):
733*cda5da8dSAndroid Build Coastguard Worker        """Configure image item as to draw image object
734*cda5da8dSAndroid Build Coastguard Worker        at center of canvas. Set item to the first item
735*cda5da8dSAndroid Build Coastguard Worker        in the displaylist, so it will be drawn below
736*cda5da8dSAndroid Build Coastguard Worker        any other item ."""
737*cda5da8dSAndroid Build Coastguard Worker        self.cv.itemconfig(item, image=image)
738*cda5da8dSAndroid Build Coastguard Worker        self.cv.tag_lower(item)
739*cda5da8dSAndroid Build Coastguard Worker
740*cda5da8dSAndroid Build Coastguard Worker    def _type(self, item):
741*cda5da8dSAndroid Build Coastguard Worker        """Return 'line' or 'polygon' or 'image' depending on
742*cda5da8dSAndroid Build Coastguard Worker        type of item.
743*cda5da8dSAndroid Build Coastguard Worker        """
744*cda5da8dSAndroid Build Coastguard Worker        return self.cv.type(item)
745*cda5da8dSAndroid Build Coastguard Worker
746*cda5da8dSAndroid Build Coastguard Worker    def _pointlist(self, item):
747*cda5da8dSAndroid Build Coastguard Worker        """returns list of coordinate-pairs of points of item
748*cda5da8dSAndroid Build Coastguard Worker        Example (for insiders):
749*cda5da8dSAndroid Build Coastguard Worker        >>> from turtle import *
750*cda5da8dSAndroid Build Coastguard Worker        >>> getscreen()._pointlist(getturtle().turtle._item)
751*cda5da8dSAndroid Build Coastguard Worker        [(0.0, 9.9999999999999982), (0.0, -9.9999999999999982),
752*cda5da8dSAndroid Build Coastguard Worker        (9.9999999999999982, 0.0)]
753*cda5da8dSAndroid Build Coastguard Worker        >>> """
754*cda5da8dSAndroid Build Coastguard Worker        cl = self.cv.coords(item)
755*cda5da8dSAndroid Build Coastguard Worker        pl = [(cl[i], -cl[i+1]) for i in range(0, len(cl), 2)]
756*cda5da8dSAndroid Build Coastguard Worker        return  pl
757*cda5da8dSAndroid Build Coastguard Worker
758*cda5da8dSAndroid Build Coastguard Worker    def _setscrollregion(self, srx1, sry1, srx2, sry2):
759*cda5da8dSAndroid Build Coastguard Worker        self.cv.config(scrollregion=(srx1, sry1, srx2, sry2))
760*cda5da8dSAndroid Build Coastguard Worker
761*cda5da8dSAndroid Build Coastguard Worker    def _rescale(self, xscalefactor, yscalefactor):
762*cda5da8dSAndroid Build Coastguard Worker        items = self.cv.find_all()
763*cda5da8dSAndroid Build Coastguard Worker        for item in items:
764*cda5da8dSAndroid Build Coastguard Worker            coordinates = list(self.cv.coords(item))
765*cda5da8dSAndroid Build Coastguard Worker            newcoordlist = []
766*cda5da8dSAndroid Build Coastguard Worker            while coordinates:
767*cda5da8dSAndroid Build Coastguard Worker                x, y = coordinates[:2]
768*cda5da8dSAndroid Build Coastguard Worker                newcoordlist.append(x * xscalefactor)
769*cda5da8dSAndroid Build Coastguard Worker                newcoordlist.append(y * yscalefactor)
770*cda5da8dSAndroid Build Coastguard Worker                coordinates = coordinates[2:]
771*cda5da8dSAndroid Build Coastguard Worker            self.cv.coords(item, *newcoordlist)
772*cda5da8dSAndroid Build Coastguard Worker
773*cda5da8dSAndroid Build Coastguard Worker    def _resize(self, canvwidth=None, canvheight=None, bg=None):
774*cda5da8dSAndroid Build Coastguard Worker        """Resize the canvas the turtles are drawing on. Does
775*cda5da8dSAndroid Build Coastguard Worker        not alter the drawing window.
776*cda5da8dSAndroid Build Coastguard Worker        """
777*cda5da8dSAndroid Build Coastguard Worker        # needs amendment
778*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(self.cv, ScrolledCanvas):
779*cda5da8dSAndroid Build Coastguard Worker            return self.canvwidth, self.canvheight
780*cda5da8dSAndroid Build Coastguard Worker        if canvwidth is canvheight is bg is None:
781*cda5da8dSAndroid Build Coastguard Worker            return self.cv.canvwidth, self.cv.canvheight
782*cda5da8dSAndroid Build Coastguard Worker        if canvwidth is not None:
783*cda5da8dSAndroid Build Coastguard Worker            self.canvwidth = canvwidth
784*cda5da8dSAndroid Build Coastguard Worker        if canvheight is not None:
785*cda5da8dSAndroid Build Coastguard Worker            self.canvheight = canvheight
786*cda5da8dSAndroid Build Coastguard Worker        self.cv.reset(canvwidth, canvheight, bg)
787*cda5da8dSAndroid Build Coastguard Worker
788*cda5da8dSAndroid Build Coastguard Worker    def _window_size(self):
789*cda5da8dSAndroid Build Coastguard Worker        """ Return the width and height of the turtle window.
790*cda5da8dSAndroid Build Coastguard Worker        """
791*cda5da8dSAndroid Build Coastguard Worker        width = self.cv.winfo_width()
792*cda5da8dSAndroid Build Coastguard Worker        if width <= 1:  # the window isn't managed by a geometry manager
793*cda5da8dSAndroid Build Coastguard Worker            width = self.cv['width']
794*cda5da8dSAndroid Build Coastguard Worker        height = self.cv.winfo_height()
795*cda5da8dSAndroid Build Coastguard Worker        if height <= 1: # the window isn't managed by a geometry manager
796*cda5da8dSAndroid Build Coastguard Worker            height = self.cv['height']
797*cda5da8dSAndroid Build Coastguard Worker        return width, height
798*cda5da8dSAndroid Build Coastguard Worker
799*cda5da8dSAndroid Build Coastguard Worker    def mainloop(self):
800*cda5da8dSAndroid Build Coastguard Worker        """Starts event loop - calling Tkinter's mainloop function.
801*cda5da8dSAndroid Build Coastguard Worker
802*cda5da8dSAndroid Build Coastguard Worker        No argument.
803*cda5da8dSAndroid Build Coastguard Worker
804*cda5da8dSAndroid Build Coastguard Worker        Must be last statement in a turtle graphics program.
805*cda5da8dSAndroid Build Coastguard Worker        Must NOT be used if a script is run from within IDLE in -n mode
806*cda5da8dSAndroid Build Coastguard Worker        (No subprocess) - for interactive use of turtle graphics.
807*cda5da8dSAndroid Build Coastguard Worker
808*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
809*cda5da8dSAndroid Build Coastguard Worker        >>> screen.mainloop()
810*cda5da8dSAndroid Build Coastguard Worker
811*cda5da8dSAndroid Build Coastguard Worker        """
812*cda5da8dSAndroid Build Coastguard Worker        self.cv.tk.mainloop()
813*cda5da8dSAndroid Build Coastguard Worker
814*cda5da8dSAndroid Build Coastguard Worker    def textinput(self, title, prompt):
815*cda5da8dSAndroid Build Coastguard Worker        """Pop up a dialog window for input of a string.
816*cda5da8dSAndroid Build Coastguard Worker
817*cda5da8dSAndroid Build Coastguard Worker        Arguments: title is the title of the dialog window,
818*cda5da8dSAndroid Build Coastguard Worker        prompt is a text mostly describing what information to input.
819*cda5da8dSAndroid Build Coastguard Worker
820*cda5da8dSAndroid Build Coastguard Worker        Return the string input
821*cda5da8dSAndroid Build Coastguard Worker        If the dialog is canceled, return None.
822*cda5da8dSAndroid Build Coastguard Worker
823*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
824*cda5da8dSAndroid Build Coastguard Worker        >>> screen.textinput("NIM", "Name of first player:")
825*cda5da8dSAndroid Build Coastguard Worker
826*cda5da8dSAndroid Build Coastguard Worker        """
827*cda5da8dSAndroid Build Coastguard Worker        return simpledialog.askstring(title, prompt, parent=self.cv)
828*cda5da8dSAndroid Build Coastguard Worker
829*cda5da8dSAndroid Build Coastguard Worker    def numinput(self, title, prompt, default=None, minval=None, maxval=None):
830*cda5da8dSAndroid Build Coastguard Worker        """Pop up a dialog window for input of a number.
831*cda5da8dSAndroid Build Coastguard Worker
832*cda5da8dSAndroid Build Coastguard Worker        Arguments: title is the title of the dialog window,
833*cda5da8dSAndroid Build Coastguard Worker        prompt is a text mostly describing what numerical information to input.
834*cda5da8dSAndroid Build Coastguard Worker        default: default value
835*cda5da8dSAndroid Build Coastguard Worker        minval: minimum value for input
836*cda5da8dSAndroid Build Coastguard Worker        maxval: maximum value for input
837*cda5da8dSAndroid Build Coastguard Worker
838*cda5da8dSAndroid Build Coastguard Worker        The number input must be in the range minval .. maxval if these are
839*cda5da8dSAndroid Build Coastguard Worker        given. If not, a hint is issued and the dialog remains open for
840*cda5da8dSAndroid Build Coastguard Worker        correction. Return the number input.
841*cda5da8dSAndroid Build Coastguard Worker        If the dialog is canceled,  return None.
842*cda5da8dSAndroid Build Coastguard Worker
843*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
844*cda5da8dSAndroid Build Coastguard Worker        >>> screen.numinput("Poker", "Your stakes:", 1000, minval=10, maxval=10000)
845*cda5da8dSAndroid Build Coastguard Worker
846*cda5da8dSAndroid Build Coastguard Worker        """
847*cda5da8dSAndroid Build Coastguard Worker        return simpledialog.askfloat(title, prompt, initialvalue=default,
848*cda5da8dSAndroid Build Coastguard Worker                                     minvalue=minval, maxvalue=maxval,
849*cda5da8dSAndroid Build Coastguard Worker                                     parent=self.cv)
850*cda5da8dSAndroid Build Coastguard Worker
851*cda5da8dSAndroid Build Coastguard Worker
852*cda5da8dSAndroid Build Coastguard Worker##############################################################################
853*cda5da8dSAndroid Build Coastguard Worker###                  End of Tkinter - interface                            ###
854*cda5da8dSAndroid Build Coastguard Worker##############################################################################
855*cda5da8dSAndroid Build Coastguard Worker
856*cda5da8dSAndroid Build Coastguard Worker
857*cda5da8dSAndroid Build Coastguard Workerclass Terminator (Exception):
858*cda5da8dSAndroid Build Coastguard Worker    """Will be raised in TurtleScreen.update, if _RUNNING becomes False.
859*cda5da8dSAndroid Build Coastguard Worker
860*cda5da8dSAndroid Build Coastguard Worker    This stops execution of a turtle graphics script.
861*cda5da8dSAndroid Build Coastguard Worker    Main purpose: use in the Demo-Viewer turtle.Demo.py.
862*cda5da8dSAndroid Build Coastguard Worker    """
863*cda5da8dSAndroid Build Coastguard Worker    pass
864*cda5da8dSAndroid Build Coastguard Worker
865*cda5da8dSAndroid Build Coastguard Worker
866*cda5da8dSAndroid Build Coastguard Workerclass TurtleGraphicsError(Exception):
867*cda5da8dSAndroid Build Coastguard Worker    """Some TurtleGraphics Error
868*cda5da8dSAndroid Build Coastguard Worker    """
869*cda5da8dSAndroid Build Coastguard Worker
870*cda5da8dSAndroid Build Coastguard Worker
871*cda5da8dSAndroid Build Coastguard Workerclass Shape(object):
872*cda5da8dSAndroid Build Coastguard Worker    """Data structure modeling shapes.
873*cda5da8dSAndroid Build Coastguard Worker
874*cda5da8dSAndroid Build Coastguard Worker    attribute _type is one of "polygon", "image", "compound"
875*cda5da8dSAndroid Build Coastguard Worker    attribute _data is - depending on _type a poygon-tuple,
876*cda5da8dSAndroid Build Coastguard Worker    an image or a list constructed using the addcomponent method.
877*cda5da8dSAndroid Build Coastguard Worker    """
878*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, type_, data=None):
879*cda5da8dSAndroid Build Coastguard Worker        self._type = type_
880*cda5da8dSAndroid Build Coastguard Worker        if type_ == "polygon":
881*cda5da8dSAndroid Build Coastguard Worker            if isinstance(data, list):
882*cda5da8dSAndroid Build Coastguard Worker                data = tuple(data)
883*cda5da8dSAndroid Build Coastguard Worker        elif type_ == "image":
884*cda5da8dSAndroid Build Coastguard Worker            if isinstance(data, str):
885*cda5da8dSAndroid Build Coastguard Worker                if data.lower().endswith(".gif") and isfile(data):
886*cda5da8dSAndroid Build Coastguard Worker                    data = TurtleScreen._image(data)
887*cda5da8dSAndroid Build Coastguard Worker                # else data assumed to be Photoimage
888*cda5da8dSAndroid Build Coastguard Worker        elif type_ == "compound":
889*cda5da8dSAndroid Build Coastguard Worker            data = []
890*cda5da8dSAndroid Build Coastguard Worker        else:
891*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("There is no shape type %s" % type_)
892*cda5da8dSAndroid Build Coastguard Worker        self._data = data
893*cda5da8dSAndroid Build Coastguard Worker
894*cda5da8dSAndroid Build Coastguard Worker    def addcomponent(self, poly, fill, outline=None):
895*cda5da8dSAndroid Build Coastguard Worker        """Add component to a shape of type compound.
896*cda5da8dSAndroid Build Coastguard Worker
897*cda5da8dSAndroid Build Coastguard Worker        Arguments: poly is a polygon, i. e. a tuple of number pairs.
898*cda5da8dSAndroid Build Coastguard Worker        fill is the fillcolor of the component,
899*cda5da8dSAndroid Build Coastguard Worker        outline is the outline color of the component.
900*cda5da8dSAndroid Build Coastguard Worker
901*cda5da8dSAndroid Build Coastguard Worker        call (for a Shapeobject namend s):
902*cda5da8dSAndroid Build Coastguard Worker        --   s.addcomponent(((0,0), (10,10), (-10,10)), "red", "blue")
903*cda5da8dSAndroid Build Coastguard Worker
904*cda5da8dSAndroid Build Coastguard Worker        Example:
905*cda5da8dSAndroid Build Coastguard Worker        >>> poly = ((0,0),(10,-5),(0,10),(-10,-5))
906*cda5da8dSAndroid Build Coastguard Worker        >>> s = Shape("compound")
907*cda5da8dSAndroid Build Coastguard Worker        >>> s.addcomponent(poly, "red", "blue")
908*cda5da8dSAndroid Build Coastguard Worker        >>> # .. add more components and then use register_shape()
909*cda5da8dSAndroid Build Coastguard Worker        """
910*cda5da8dSAndroid Build Coastguard Worker        if self._type != "compound":
911*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("Cannot add component to %s Shape"
912*cda5da8dSAndroid Build Coastguard Worker                                                                % self._type)
913*cda5da8dSAndroid Build Coastguard Worker        if outline is None:
914*cda5da8dSAndroid Build Coastguard Worker            outline = fill
915*cda5da8dSAndroid Build Coastguard Worker        self._data.append([poly, fill, outline])
916*cda5da8dSAndroid Build Coastguard Worker
917*cda5da8dSAndroid Build Coastguard Worker
918*cda5da8dSAndroid Build Coastguard Workerclass Tbuffer(object):
919*cda5da8dSAndroid Build Coastguard Worker    """Ring buffer used as undobuffer for RawTurtle objects."""
920*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, bufsize=10):
921*cda5da8dSAndroid Build Coastguard Worker        self.bufsize = bufsize
922*cda5da8dSAndroid Build Coastguard Worker        self.buffer = [[None]] * bufsize
923*cda5da8dSAndroid Build Coastguard Worker        self.ptr = -1
924*cda5da8dSAndroid Build Coastguard Worker        self.cumulate = False
925*cda5da8dSAndroid Build Coastguard Worker    def reset(self, bufsize=None):
926*cda5da8dSAndroid Build Coastguard Worker        if bufsize is None:
927*cda5da8dSAndroid Build Coastguard Worker            for i in range(self.bufsize):
928*cda5da8dSAndroid Build Coastguard Worker                self.buffer[i] = [None]
929*cda5da8dSAndroid Build Coastguard Worker        else:
930*cda5da8dSAndroid Build Coastguard Worker            self.bufsize = bufsize
931*cda5da8dSAndroid Build Coastguard Worker            self.buffer = [[None]] * bufsize
932*cda5da8dSAndroid Build Coastguard Worker        self.ptr = -1
933*cda5da8dSAndroid Build Coastguard Worker    def push(self, item):
934*cda5da8dSAndroid Build Coastguard Worker        if self.bufsize > 0:
935*cda5da8dSAndroid Build Coastguard Worker            if not self.cumulate:
936*cda5da8dSAndroid Build Coastguard Worker                self.ptr = (self.ptr + 1) % self.bufsize
937*cda5da8dSAndroid Build Coastguard Worker                self.buffer[self.ptr] = item
938*cda5da8dSAndroid Build Coastguard Worker            else:
939*cda5da8dSAndroid Build Coastguard Worker                self.buffer[self.ptr].append(item)
940*cda5da8dSAndroid Build Coastguard Worker    def pop(self):
941*cda5da8dSAndroid Build Coastguard Worker        if self.bufsize > 0:
942*cda5da8dSAndroid Build Coastguard Worker            item = self.buffer[self.ptr]
943*cda5da8dSAndroid Build Coastguard Worker            if item is None:
944*cda5da8dSAndroid Build Coastguard Worker                return None
945*cda5da8dSAndroid Build Coastguard Worker            else:
946*cda5da8dSAndroid Build Coastguard Worker                self.buffer[self.ptr] = [None]
947*cda5da8dSAndroid Build Coastguard Worker                self.ptr = (self.ptr - 1) % self.bufsize
948*cda5da8dSAndroid Build Coastguard Worker                return (item)
949*cda5da8dSAndroid Build Coastguard Worker    def nr_of_items(self):
950*cda5da8dSAndroid Build Coastguard Worker        return self.bufsize - self.buffer.count([None])
951*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
952*cda5da8dSAndroid Build Coastguard Worker        return str(self.buffer) + " " + str(self.ptr)
953*cda5da8dSAndroid Build Coastguard Worker
954*cda5da8dSAndroid Build Coastguard Worker
955*cda5da8dSAndroid Build Coastguard Worker
956*cda5da8dSAndroid Build Coastguard Workerclass TurtleScreen(TurtleScreenBase):
957*cda5da8dSAndroid Build Coastguard Worker    """Provides screen oriented methods like bgcolor etc.
958*cda5da8dSAndroid Build Coastguard Worker
959*cda5da8dSAndroid Build Coastguard Worker    Only relies upon the methods of TurtleScreenBase and NOT
960*cda5da8dSAndroid Build Coastguard Worker    upon components of the underlying graphics toolkit -
961*cda5da8dSAndroid Build Coastguard Worker    which is Tkinter in this case.
962*cda5da8dSAndroid Build Coastguard Worker    """
963*cda5da8dSAndroid Build Coastguard Worker    _RUNNING = True
964*cda5da8dSAndroid Build Coastguard Worker
965*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, cv, mode=_CFG["mode"],
966*cda5da8dSAndroid Build Coastguard Worker                 colormode=_CFG["colormode"], delay=_CFG["delay"]):
967*cda5da8dSAndroid Build Coastguard Worker        TurtleScreenBase.__init__(self, cv)
968*cda5da8dSAndroid Build Coastguard Worker
969*cda5da8dSAndroid Build Coastguard Worker        self._shapes = {
970*cda5da8dSAndroid Build Coastguard Worker                   "arrow" : Shape("polygon", ((-10,0), (10,0), (0,10))),
971*cda5da8dSAndroid Build Coastguard Worker                  "turtle" : Shape("polygon", ((0,16), (-2,14), (-1,10), (-4,7),
972*cda5da8dSAndroid Build Coastguard Worker                              (-7,9), (-9,8), (-6,5), (-7,1), (-5,-3), (-8,-6),
973*cda5da8dSAndroid Build Coastguard Worker                              (-6,-8), (-4,-5), (0,-7), (4,-5), (6,-8), (8,-6),
974*cda5da8dSAndroid Build Coastguard Worker                              (5,-3), (7,1), (6,5), (9,8), (7,9), (4,7), (1,10),
975*cda5da8dSAndroid Build Coastguard Worker                              (2,14))),
976*cda5da8dSAndroid Build Coastguard Worker                  "circle" : Shape("polygon", ((10,0), (9.51,3.09), (8.09,5.88),
977*cda5da8dSAndroid Build Coastguard Worker                              (5.88,8.09), (3.09,9.51), (0,10), (-3.09,9.51),
978*cda5da8dSAndroid Build Coastguard Worker                              (-5.88,8.09), (-8.09,5.88), (-9.51,3.09), (-10,0),
979*cda5da8dSAndroid Build Coastguard Worker                              (-9.51,-3.09), (-8.09,-5.88), (-5.88,-8.09),
980*cda5da8dSAndroid Build Coastguard Worker                              (-3.09,-9.51), (-0.00,-10.00), (3.09,-9.51),
981*cda5da8dSAndroid Build Coastguard Worker                              (5.88,-8.09), (8.09,-5.88), (9.51,-3.09))),
982*cda5da8dSAndroid Build Coastguard Worker                  "square" : Shape("polygon", ((10,-10), (10,10), (-10,10),
983*cda5da8dSAndroid Build Coastguard Worker                              (-10,-10))),
984*cda5da8dSAndroid Build Coastguard Worker                "triangle" : Shape("polygon", ((10,-5.77), (0,11.55),
985*cda5da8dSAndroid Build Coastguard Worker                              (-10,-5.77))),
986*cda5da8dSAndroid Build Coastguard Worker                  "classic": Shape("polygon", ((0,0),(-5,-9),(0,-7),(5,-9))),
987*cda5da8dSAndroid Build Coastguard Worker                   "blank" : Shape("image", self._blankimage())
988*cda5da8dSAndroid Build Coastguard Worker                  }
989*cda5da8dSAndroid Build Coastguard Worker
990*cda5da8dSAndroid Build Coastguard Worker        self._bgpics = {"nopic" : ""}
991*cda5da8dSAndroid Build Coastguard Worker
992*cda5da8dSAndroid Build Coastguard Worker        self._mode = mode
993*cda5da8dSAndroid Build Coastguard Worker        self._delayvalue = delay
994*cda5da8dSAndroid Build Coastguard Worker        self._colormode = _CFG["colormode"]
995*cda5da8dSAndroid Build Coastguard Worker        self._keys = []
996*cda5da8dSAndroid Build Coastguard Worker        self.clear()
997*cda5da8dSAndroid Build Coastguard Worker        if sys.platform == 'darwin':
998*cda5da8dSAndroid Build Coastguard Worker            # Force Turtle window to the front on OS X. This is needed because
999*cda5da8dSAndroid Build Coastguard Worker            # the Turtle window will show behind the Terminal window when you
1000*cda5da8dSAndroid Build Coastguard Worker            # start the demo from the command line.
1001*cda5da8dSAndroid Build Coastguard Worker            rootwindow = cv.winfo_toplevel()
1002*cda5da8dSAndroid Build Coastguard Worker            rootwindow.call('wm', 'attributes', '.', '-topmost', '1')
1003*cda5da8dSAndroid Build Coastguard Worker            rootwindow.call('wm', 'attributes', '.', '-topmost', '0')
1004*cda5da8dSAndroid Build Coastguard Worker
1005*cda5da8dSAndroid Build Coastguard Worker    def clear(self):
1006*cda5da8dSAndroid Build Coastguard Worker        """Delete all drawings and all turtles from the TurtleScreen.
1007*cda5da8dSAndroid Build Coastguard Worker
1008*cda5da8dSAndroid Build Coastguard Worker        No argument.
1009*cda5da8dSAndroid Build Coastguard Worker
1010*cda5da8dSAndroid Build Coastguard Worker        Reset empty TurtleScreen to its initial state: white background,
1011*cda5da8dSAndroid Build Coastguard Worker        no backgroundimage, no eventbindings and tracing on.
1012*cda5da8dSAndroid Build Coastguard Worker
1013*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1014*cda5da8dSAndroid Build Coastguard Worker        >>> screen.clear()
1015*cda5da8dSAndroid Build Coastguard Worker
1016*cda5da8dSAndroid Build Coastguard Worker        Note: this method is not available as function.
1017*cda5da8dSAndroid Build Coastguard Worker        """
1018*cda5da8dSAndroid Build Coastguard Worker        self._delayvalue = _CFG["delay"]
1019*cda5da8dSAndroid Build Coastguard Worker        self._colormode = _CFG["colormode"]
1020*cda5da8dSAndroid Build Coastguard Worker        self._delete("all")
1021*cda5da8dSAndroid Build Coastguard Worker        self._bgpic = self._createimage("")
1022*cda5da8dSAndroid Build Coastguard Worker        self._bgpicname = "nopic"
1023*cda5da8dSAndroid Build Coastguard Worker        self._tracing = 1
1024*cda5da8dSAndroid Build Coastguard Worker        self._updatecounter = 0
1025*cda5da8dSAndroid Build Coastguard Worker        self._turtles = []
1026*cda5da8dSAndroid Build Coastguard Worker        self.bgcolor("white")
1027*cda5da8dSAndroid Build Coastguard Worker        for btn in 1, 2, 3:
1028*cda5da8dSAndroid Build Coastguard Worker            self.onclick(None, btn)
1029*cda5da8dSAndroid Build Coastguard Worker        self.onkeypress(None)
1030*cda5da8dSAndroid Build Coastguard Worker        for key in self._keys[:]:
1031*cda5da8dSAndroid Build Coastguard Worker            self.onkey(None, key)
1032*cda5da8dSAndroid Build Coastguard Worker            self.onkeypress(None, key)
1033*cda5da8dSAndroid Build Coastguard Worker        Turtle._pen = None
1034*cda5da8dSAndroid Build Coastguard Worker
1035*cda5da8dSAndroid Build Coastguard Worker    def mode(self, mode=None):
1036*cda5da8dSAndroid Build Coastguard Worker        """Set turtle-mode ('standard', 'logo' or 'world') and perform reset.
1037*cda5da8dSAndroid Build Coastguard Worker
1038*cda5da8dSAndroid Build Coastguard Worker        Optional argument:
1039*cda5da8dSAndroid Build Coastguard Worker        mode -- one of the strings 'standard', 'logo' or 'world'
1040*cda5da8dSAndroid Build Coastguard Worker
1041*cda5da8dSAndroid Build Coastguard Worker        Mode 'standard' is compatible with turtle.py.
1042*cda5da8dSAndroid Build Coastguard Worker        Mode 'logo' is compatible with most Logo-Turtle-Graphics.
1043*cda5da8dSAndroid Build Coastguard Worker        Mode 'world' uses userdefined 'worldcoordinates'. *Attention*: in
1044*cda5da8dSAndroid Build Coastguard Worker        this mode angles appear distorted if x/y unit-ratio doesn't equal 1.
1045*cda5da8dSAndroid Build Coastguard Worker        If mode is not given, return the current mode.
1046*cda5da8dSAndroid Build Coastguard Worker
1047*cda5da8dSAndroid Build Coastguard Worker             Mode      Initial turtle heading     positive angles
1048*cda5da8dSAndroid Build Coastguard Worker         ------------|-------------------------|-------------------
1049*cda5da8dSAndroid Build Coastguard Worker          'standard'    to the right (east)       counterclockwise
1050*cda5da8dSAndroid Build Coastguard Worker            'logo'        upward    (north)         clockwise
1051*cda5da8dSAndroid Build Coastguard Worker
1052*cda5da8dSAndroid Build Coastguard Worker        Examples:
1053*cda5da8dSAndroid Build Coastguard Worker        >>> mode('logo')   # resets turtle heading to north
1054*cda5da8dSAndroid Build Coastguard Worker        >>> mode()
1055*cda5da8dSAndroid Build Coastguard Worker        'logo'
1056*cda5da8dSAndroid Build Coastguard Worker        """
1057*cda5da8dSAndroid Build Coastguard Worker        if mode is None:
1058*cda5da8dSAndroid Build Coastguard Worker            return self._mode
1059*cda5da8dSAndroid Build Coastguard Worker        mode = mode.lower()
1060*cda5da8dSAndroid Build Coastguard Worker        if mode not in ["standard", "logo", "world"]:
1061*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("No turtle-graphics-mode %s" % mode)
1062*cda5da8dSAndroid Build Coastguard Worker        self._mode = mode
1063*cda5da8dSAndroid Build Coastguard Worker        if mode in ["standard", "logo"]:
1064*cda5da8dSAndroid Build Coastguard Worker            self._setscrollregion(-self.canvwidth//2, -self.canvheight//2,
1065*cda5da8dSAndroid Build Coastguard Worker                                       self.canvwidth//2, self.canvheight//2)
1066*cda5da8dSAndroid Build Coastguard Worker            self.xscale = self.yscale = 1.0
1067*cda5da8dSAndroid Build Coastguard Worker        self.reset()
1068*cda5da8dSAndroid Build Coastguard Worker
1069*cda5da8dSAndroid Build Coastguard Worker    def setworldcoordinates(self, llx, lly, urx, ury):
1070*cda5da8dSAndroid Build Coastguard Worker        """Set up a user defined coordinate-system.
1071*cda5da8dSAndroid Build Coastguard Worker
1072*cda5da8dSAndroid Build Coastguard Worker        Arguments:
1073*cda5da8dSAndroid Build Coastguard Worker        llx -- a number, x-coordinate of lower left corner of canvas
1074*cda5da8dSAndroid Build Coastguard Worker        lly -- a number, y-coordinate of lower left corner of canvas
1075*cda5da8dSAndroid Build Coastguard Worker        urx -- a number, x-coordinate of upper right corner of canvas
1076*cda5da8dSAndroid Build Coastguard Worker        ury -- a number, y-coordinate of upper right corner of canvas
1077*cda5da8dSAndroid Build Coastguard Worker
1078*cda5da8dSAndroid Build Coastguard Worker        Set up user coodinat-system and switch to mode 'world' if necessary.
1079*cda5da8dSAndroid Build Coastguard Worker        This performs a screen.reset. If mode 'world' is already active,
1080*cda5da8dSAndroid Build Coastguard Worker        all drawings are redrawn according to the new coordinates.
1081*cda5da8dSAndroid Build Coastguard Worker
1082*cda5da8dSAndroid Build Coastguard Worker        But ATTENTION: in user-defined coordinatesystems angles may appear
1083*cda5da8dSAndroid Build Coastguard Worker        distorted. (see Screen.mode())
1084*cda5da8dSAndroid Build Coastguard Worker
1085*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1086*cda5da8dSAndroid Build Coastguard Worker        >>> screen.setworldcoordinates(-10,-0.5,50,1.5)
1087*cda5da8dSAndroid Build Coastguard Worker        >>> for _ in range(36):
1088*cda5da8dSAndroid Build Coastguard Worker        ...     left(10)
1089*cda5da8dSAndroid Build Coastguard Worker        ...     forward(0.5)
1090*cda5da8dSAndroid Build Coastguard Worker        """
1091*cda5da8dSAndroid Build Coastguard Worker        if self.mode() != "world":
1092*cda5da8dSAndroid Build Coastguard Worker            self.mode("world")
1093*cda5da8dSAndroid Build Coastguard Worker        xspan = float(urx - llx)
1094*cda5da8dSAndroid Build Coastguard Worker        yspan = float(ury - lly)
1095*cda5da8dSAndroid Build Coastguard Worker        wx, wy = self._window_size()
1096*cda5da8dSAndroid Build Coastguard Worker        self.screensize(wx-20, wy-20)
1097*cda5da8dSAndroid Build Coastguard Worker        oldxscale, oldyscale = self.xscale, self.yscale
1098*cda5da8dSAndroid Build Coastguard Worker        self.xscale = self.canvwidth / xspan
1099*cda5da8dSAndroid Build Coastguard Worker        self.yscale = self.canvheight / yspan
1100*cda5da8dSAndroid Build Coastguard Worker        srx1 = llx * self.xscale
1101*cda5da8dSAndroid Build Coastguard Worker        sry1 = -ury * self.yscale
1102*cda5da8dSAndroid Build Coastguard Worker        srx2 = self.canvwidth + srx1
1103*cda5da8dSAndroid Build Coastguard Worker        sry2 = self.canvheight + sry1
1104*cda5da8dSAndroid Build Coastguard Worker        self._setscrollregion(srx1, sry1, srx2, sry2)
1105*cda5da8dSAndroid Build Coastguard Worker        self._rescale(self.xscale/oldxscale, self.yscale/oldyscale)
1106*cda5da8dSAndroid Build Coastguard Worker        self.update()
1107*cda5da8dSAndroid Build Coastguard Worker
1108*cda5da8dSAndroid Build Coastguard Worker    def register_shape(self, name, shape=None):
1109*cda5da8dSAndroid Build Coastguard Worker        """Adds a turtle shape to TurtleScreen's shapelist.
1110*cda5da8dSAndroid Build Coastguard Worker
1111*cda5da8dSAndroid Build Coastguard Worker        Arguments:
1112*cda5da8dSAndroid Build Coastguard Worker        (1) name is the name of a gif-file and shape is None.
1113*cda5da8dSAndroid Build Coastguard Worker            Installs the corresponding image shape.
1114*cda5da8dSAndroid Build Coastguard Worker            !! Image-shapes DO NOT rotate when turning the turtle,
1115*cda5da8dSAndroid Build Coastguard Worker            !! so they do not display the heading of the turtle!
1116*cda5da8dSAndroid Build Coastguard Worker        (2) name is an arbitrary string and shape is a tuple
1117*cda5da8dSAndroid Build Coastguard Worker            of pairs of coordinates. Installs the corresponding
1118*cda5da8dSAndroid Build Coastguard Worker            polygon shape
1119*cda5da8dSAndroid Build Coastguard Worker        (3) name is an arbitrary string and shape is a
1120*cda5da8dSAndroid Build Coastguard Worker            (compound) Shape object. Installs the corresponding
1121*cda5da8dSAndroid Build Coastguard Worker            compound shape.
1122*cda5da8dSAndroid Build Coastguard Worker        To use a shape, you have to issue the command shape(shapename).
1123*cda5da8dSAndroid Build Coastguard Worker
1124*cda5da8dSAndroid Build Coastguard Worker        call: register_shape("turtle.gif")
1125*cda5da8dSAndroid Build Coastguard Worker        --or: register_shape("tri", ((0,0), (10,10), (-10,10)))
1126*cda5da8dSAndroid Build Coastguard Worker
1127*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1128*cda5da8dSAndroid Build Coastguard Worker        >>> screen.register_shape("triangle", ((5,-3),(0,5),(-5,-3)))
1129*cda5da8dSAndroid Build Coastguard Worker
1130*cda5da8dSAndroid Build Coastguard Worker        """
1131*cda5da8dSAndroid Build Coastguard Worker        if shape is None:
1132*cda5da8dSAndroid Build Coastguard Worker            # image
1133*cda5da8dSAndroid Build Coastguard Worker            if name.lower().endswith(".gif"):
1134*cda5da8dSAndroid Build Coastguard Worker                shape = Shape("image", self._image(name))
1135*cda5da8dSAndroid Build Coastguard Worker            else:
1136*cda5da8dSAndroid Build Coastguard Worker                raise TurtleGraphicsError("Bad arguments for register_shape.\n"
1137*cda5da8dSAndroid Build Coastguard Worker                                          + "Use  help(register_shape)" )
1138*cda5da8dSAndroid Build Coastguard Worker        elif isinstance(shape, tuple):
1139*cda5da8dSAndroid Build Coastguard Worker            shape = Shape("polygon", shape)
1140*cda5da8dSAndroid Build Coastguard Worker        ## else shape assumed to be Shape-instance
1141*cda5da8dSAndroid Build Coastguard Worker        self._shapes[name] = shape
1142*cda5da8dSAndroid Build Coastguard Worker
1143*cda5da8dSAndroid Build Coastguard Worker    def _colorstr(self, color):
1144*cda5da8dSAndroid Build Coastguard Worker        """Return color string corresponding to args.
1145*cda5da8dSAndroid Build Coastguard Worker
1146*cda5da8dSAndroid Build Coastguard Worker        Argument may be a string or a tuple of three
1147*cda5da8dSAndroid Build Coastguard Worker        numbers corresponding to actual colormode,
1148*cda5da8dSAndroid Build Coastguard Worker        i.e. in the range 0<=n<=colormode.
1149*cda5da8dSAndroid Build Coastguard Worker
1150*cda5da8dSAndroid Build Coastguard Worker        If the argument doesn't represent a color,
1151*cda5da8dSAndroid Build Coastguard Worker        an error is raised.
1152*cda5da8dSAndroid Build Coastguard Worker        """
1153*cda5da8dSAndroid Build Coastguard Worker        if len(color) == 1:
1154*cda5da8dSAndroid Build Coastguard Worker            color = color[0]
1155*cda5da8dSAndroid Build Coastguard Worker        if isinstance(color, str):
1156*cda5da8dSAndroid Build Coastguard Worker            if self._iscolorstring(color) or color == "":
1157*cda5da8dSAndroid Build Coastguard Worker                return color
1158*cda5da8dSAndroid Build Coastguard Worker            else:
1159*cda5da8dSAndroid Build Coastguard Worker                raise TurtleGraphicsError("bad color string: %s" % str(color))
1160*cda5da8dSAndroid Build Coastguard Worker        try:
1161*cda5da8dSAndroid Build Coastguard Worker            r, g, b = color
1162*cda5da8dSAndroid Build Coastguard Worker        except (TypeError, ValueError):
1163*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("bad color arguments: %s" % str(color))
1164*cda5da8dSAndroid Build Coastguard Worker        if self._colormode == 1.0:
1165*cda5da8dSAndroid Build Coastguard Worker            r, g, b = [round(255.0*x) for x in (r, g, b)]
1166*cda5da8dSAndroid Build Coastguard Worker        if not ((0 <= r <= 255) and (0 <= g <= 255) and (0 <= b <= 255)):
1167*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("bad color sequence: %s" % str(color))
1168*cda5da8dSAndroid Build Coastguard Worker        return "#%02x%02x%02x" % (r, g, b)
1169*cda5da8dSAndroid Build Coastguard Worker
1170*cda5da8dSAndroid Build Coastguard Worker    def _color(self, cstr):
1171*cda5da8dSAndroid Build Coastguard Worker        if not cstr.startswith("#"):
1172*cda5da8dSAndroid Build Coastguard Worker            return cstr
1173*cda5da8dSAndroid Build Coastguard Worker        if len(cstr) == 7:
1174*cda5da8dSAndroid Build Coastguard Worker            cl = [int(cstr[i:i+2], 16) for i in (1, 3, 5)]
1175*cda5da8dSAndroid Build Coastguard Worker        elif len(cstr) == 4:
1176*cda5da8dSAndroid Build Coastguard Worker            cl = [16*int(cstr[h], 16) for h in cstr[1:]]
1177*cda5da8dSAndroid Build Coastguard Worker        else:
1178*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("bad colorstring: %s" % cstr)
1179*cda5da8dSAndroid Build Coastguard Worker        return tuple(c * self._colormode/255 for c in cl)
1180*cda5da8dSAndroid Build Coastguard Worker
1181*cda5da8dSAndroid Build Coastguard Worker    def colormode(self, cmode=None):
1182*cda5da8dSAndroid Build Coastguard Worker        """Return the colormode or set it to 1.0 or 255.
1183*cda5da8dSAndroid Build Coastguard Worker
1184*cda5da8dSAndroid Build Coastguard Worker        Optional argument:
1185*cda5da8dSAndroid Build Coastguard Worker        cmode -- one of the values 1.0 or 255
1186*cda5da8dSAndroid Build Coastguard Worker
1187*cda5da8dSAndroid Build Coastguard Worker        r, g, b values of colortriples have to be in range 0..cmode.
1188*cda5da8dSAndroid Build Coastguard Worker
1189*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1190*cda5da8dSAndroid Build Coastguard Worker        >>> screen.colormode()
1191*cda5da8dSAndroid Build Coastguard Worker        1.0
1192*cda5da8dSAndroid Build Coastguard Worker        >>> screen.colormode(255)
1193*cda5da8dSAndroid Build Coastguard Worker        >>> pencolor(240,160,80)
1194*cda5da8dSAndroid Build Coastguard Worker        """
1195*cda5da8dSAndroid Build Coastguard Worker        if cmode is None:
1196*cda5da8dSAndroid Build Coastguard Worker            return self._colormode
1197*cda5da8dSAndroid Build Coastguard Worker        if cmode == 1.0:
1198*cda5da8dSAndroid Build Coastguard Worker            self._colormode = float(cmode)
1199*cda5da8dSAndroid Build Coastguard Worker        elif cmode == 255:
1200*cda5da8dSAndroid Build Coastguard Worker            self._colormode = int(cmode)
1201*cda5da8dSAndroid Build Coastguard Worker
1202*cda5da8dSAndroid Build Coastguard Worker    def reset(self):
1203*cda5da8dSAndroid Build Coastguard Worker        """Reset all Turtles on the Screen to their initial state.
1204*cda5da8dSAndroid Build Coastguard Worker
1205*cda5da8dSAndroid Build Coastguard Worker        No argument.
1206*cda5da8dSAndroid Build Coastguard Worker
1207*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1208*cda5da8dSAndroid Build Coastguard Worker        >>> screen.reset()
1209*cda5da8dSAndroid Build Coastguard Worker        """
1210*cda5da8dSAndroid Build Coastguard Worker        for turtle in self._turtles:
1211*cda5da8dSAndroid Build Coastguard Worker            turtle._setmode(self._mode)
1212*cda5da8dSAndroid Build Coastguard Worker            turtle.reset()
1213*cda5da8dSAndroid Build Coastguard Worker
1214*cda5da8dSAndroid Build Coastguard Worker    def turtles(self):
1215*cda5da8dSAndroid Build Coastguard Worker        """Return the list of turtles on the screen.
1216*cda5da8dSAndroid Build Coastguard Worker
1217*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1218*cda5da8dSAndroid Build Coastguard Worker        >>> screen.turtles()
1219*cda5da8dSAndroid Build Coastguard Worker        [<turtle.Turtle object at 0x00E11FB0>]
1220*cda5da8dSAndroid Build Coastguard Worker        """
1221*cda5da8dSAndroid Build Coastguard Worker        return self._turtles
1222*cda5da8dSAndroid Build Coastguard Worker
1223*cda5da8dSAndroid Build Coastguard Worker    def bgcolor(self, *args):
1224*cda5da8dSAndroid Build Coastguard Worker        """Set or return backgroundcolor of the TurtleScreen.
1225*cda5da8dSAndroid Build Coastguard Worker
1226*cda5da8dSAndroid Build Coastguard Worker        Arguments (if given): a color string or three numbers
1227*cda5da8dSAndroid Build Coastguard Worker        in the range 0..colormode or a 3-tuple of such numbers.
1228*cda5da8dSAndroid Build Coastguard Worker
1229*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1230*cda5da8dSAndroid Build Coastguard Worker        >>> screen.bgcolor("orange")
1231*cda5da8dSAndroid Build Coastguard Worker        >>> screen.bgcolor()
1232*cda5da8dSAndroid Build Coastguard Worker        'orange'
1233*cda5da8dSAndroid Build Coastguard Worker        >>> screen.bgcolor(0.5,0,0.5)
1234*cda5da8dSAndroid Build Coastguard Worker        >>> screen.bgcolor()
1235*cda5da8dSAndroid Build Coastguard Worker        '#800080'
1236*cda5da8dSAndroid Build Coastguard Worker        """
1237*cda5da8dSAndroid Build Coastguard Worker        if args:
1238*cda5da8dSAndroid Build Coastguard Worker            color = self._colorstr(args)
1239*cda5da8dSAndroid Build Coastguard Worker        else:
1240*cda5da8dSAndroid Build Coastguard Worker            color = None
1241*cda5da8dSAndroid Build Coastguard Worker        color = self._bgcolor(color)
1242*cda5da8dSAndroid Build Coastguard Worker        if color is not None:
1243*cda5da8dSAndroid Build Coastguard Worker            color = self._color(color)
1244*cda5da8dSAndroid Build Coastguard Worker        return color
1245*cda5da8dSAndroid Build Coastguard Worker
1246*cda5da8dSAndroid Build Coastguard Worker    def tracer(self, n=None, delay=None):
1247*cda5da8dSAndroid Build Coastguard Worker        """Turns turtle animation on/off and set delay for update drawings.
1248*cda5da8dSAndroid Build Coastguard Worker
1249*cda5da8dSAndroid Build Coastguard Worker        Optional arguments:
1250*cda5da8dSAndroid Build Coastguard Worker        n -- nonnegative  integer
1251*cda5da8dSAndroid Build Coastguard Worker        delay -- nonnegative  integer
1252*cda5da8dSAndroid Build Coastguard Worker
1253*cda5da8dSAndroid Build Coastguard Worker        If n is given, only each n-th regular screen update is really performed.
1254*cda5da8dSAndroid Build Coastguard Worker        (Can be used to accelerate the drawing of complex graphics.)
1255*cda5da8dSAndroid Build Coastguard Worker        Second arguments sets delay value (see RawTurtle.delay())
1256*cda5da8dSAndroid Build Coastguard Worker
1257*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1258*cda5da8dSAndroid Build Coastguard Worker        >>> screen.tracer(8, 25)
1259*cda5da8dSAndroid Build Coastguard Worker        >>> dist = 2
1260*cda5da8dSAndroid Build Coastguard Worker        >>> for i in range(200):
1261*cda5da8dSAndroid Build Coastguard Worker        ...     fd(dist)
1262*cda5da8dSAndroid Build Coastguard Worker        ...     rt(90)
1263*cda5da8dSAndroid Build Coastguard Worker        ...     dist += 2
1264*cda5da8dSAndroid Build Coastguard Worker        """
1265*cda5da8dSAndroid Build Coastguard Worker        if n is None:
1266*cda5da8dSAndroid Build Coastguard Worker            return self._tracing
1267*cda5da8dSAndroid Build Coastguard Worker        self._tracing = int(n)
1268*cda5da8dSAndroid Build Coastguard Worker        self._updatecounter = 0
1269*cda5da8dSAndroid Build Coastguard Worker        if delay is not None:
1270*cda5da8dSAndroid Build Coastguard Worker            self._delayvalue = int(delay)
1271*cda5da8dSAndroid Build Coastguard Worker        if self._tracing:
1272*cda5da8dSAndroid Build Coastguard Worker            self.update()
1273*cda5da8dSAndroid Build Coastguard Worker
1274*cda5da8dSAndroid Build Coastguard Worker    def delay(self, delay=None):
1275*cda5da8dSAndroid Build Coastguard Worker        """ Return or set the drawing delay in milliseconds.
1276*cda5da8dSAndroid Build Coastguard Worker
1277*cda5da8dSAndroid Build Coastguard Worker        Optional argument:
1278*cda5da8dSAndroid Build Coastguard Worker        delay -- positive integer
1279*cda5da8dSAndroid Build Coastguard Worker
1280*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1281*cda5da8dSAndroid Build Coastguard Worker        >>> screen.delay(15)
1282*cda5da8dSAndroid Build Coastguard Worker        >>> screen.delay()
1283*cda5da8dSAndroid Build Coastguard Worker        15
1284*cda5da8dSAndroid Build Coastguard Worker        """
1285*cda5da8dSAndroid Build Coastguard Worker        if delay is None:
1286*cda5da8dSAndroid Build Coastguard Worker            return self._delayvalue
1287*cda5da8dSAndroid Build Coastguard Worker        self._delayvalue = int(delay)
1288*cda5da8dSAndroid Build Coastguard Worker
1289*cda5da8dSAndroid Build Coastguard Worker    def _incrementudc(self):
1290*cda5da8dSAndroid Build Coastguard Worker        """Increment update counter."""
1291*cda5da8dSAndroid Build Coastguard Worker        if not TurtleScreen._RUNNING:
1292*cda5da8dSAndroid Build Coastguard Worker            TurtleScreen._RUNNING = True
1293*cda5da8dSAndroid Build Coastguard Worker            raise Terminator
1294*cda5da8dSAndroid Build Coastguard Worker        if self._tracing > 0:
1295*cda5da8dSAndroid Build Coastguard Worker            self._updatecounter += 1
1296*cda5da8dSAndroid Build Coastguard Worker            self._updatecounter %= self._tracing
1297*cda5da8dSAndroid Build Coastguard Worker
1298*cda5da8dSAndroid Build Coastguard Worker    def update(self):
1299*cda5da8dSAndroid Build Coastguard Worker        """Perform a TurtleScreen update.
1300*cda5da8dSAndroid Build Coastguard Worker        """
1301*cda5da8dSAndroid Build Coastguard Worker        tracing = self._tracing
1302*cda5da8dSAndroid Build Coastguard Worker        self._tracing = True
1303*cda5da8dSAndroid Build Coastguard Worker        for t in self.turtles():
1304*cda5da8dSAndroid Build Coastguard Worker            t._update_data()
1305*cda5da8dSAndroid Build Coastguard Worker            t._drawturtle()
1306*cda5da8dSAndroid Build Coastguard Worker        self._tracing = tracing
1307*cda5da8dSAndroid Build Coastguard Worker        self._update()
1308*cda5da8dSAndroid Build Coastguard Worker
1309*cda5da8dSAndroid Build Coastguard Worker    def window_width(self):
1310*cda5da8dSAndroid Build Coastguard Worker        """ Return the width of the turtle window.
1311*cda5da8dSAndroid Build Coastguard Worker
1312*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1313*cda5da8dSAndroid Build Coastguard Worker        >>> screen.window_width()
1314*cda5da8dSAndroid Build Coastguard Worker        640
1315*cda5da8dSAndroid Build Coastguard Worker        """
1316*cda5da8dSAndroid Build Coastguard Worker        return self._window_size()[0]
1317*cda5da8dSAndroid Build Coastguard Worker
1318*cda5da8dSAndroid Build Coastguard Worker    def window_height(self):
1319*cda5da8dSAndroid Build Coastguard Worker        """ Return the height of the turtle window.
1320*cda5da8dSAndroid Build Coastguard Worker
1321*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1322*cda5da8dSAndroid Build Coastguard Worker        >>> screen.window_height()
1323*cda5da8dSAndroid Build Coastguard Worker        480
1324*cda5da8dSAndroid Build Coastguard Worker        """
1325*cda5da8dSAndroid Build Coastguard Worker        return self._window_size()[1]
1326*cda5da8dSAndroid Build Coastguard Worker
1327*cda5da8dSAndroid Build Coastguard Worker    def getcanvas(self):
1328*cda5da8dSAndroid Build Coastguard Worker        """Return the Canvas of this TurtleScreen.
1329*cda5da8dSAndroid Build Coastguard Worker
1330*cda5da8dSAndroid Build Coastguard Worker        No argument.
1331*cda5da8dSAndroid Build Coastguard Worker
1332*cda5da8dSAndroid Build Coastguard Worker        Example (for a Screen instance named screen):
1333*cda5da8dSAndroid Build Coastguard Worker        >>> cv = screen.getcanvas()
1334*cda5da8dSAndroid Build Coastguard Worker        >>> cv
1335*cda5da8dSAndroid Build Coastguard Worker        <turtle.ScrolledCanvas instance at 0x010742D8>
1336*cda5da8dSAndroid Build Coastguard Worker        """
1337*cda5da8dSAndroid Build Coastguard Worker        return self.cv
1338*cda5da8dSAndroid Build Coastguard Worker
1339*cda5da8dSAndroid Build Coastguard Worker    def getshapes(self):
1340*cda5da8dSAndroid Build Coastguard Worker        """Return a list of names of all currently available turtle shapes.
1341*cda5da8dSAndroid Build Coastguard Worker
1342*cda5da8dSAndroid Build Coastguard Worker        No argument.
1343*cda5da8dSAndroid Build Coastguard Worker
1344*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1345*cda5da8dSAndroid Build Coastguard Worker        >>> screen.getshapes()
1346*cda5da8dSAndroid Build Coastguard Worker        ['arrow', 'blank', 'circle', ... , 'turtle']
1347*cda5da8dSAndroid Build Coastguard Worker        """
1348*cda5da8dSAndroid Build Coastguard Worker        return sorted(self._shapes.keys())
1349*cda5da8dSAndroid Build Coastguard Worker
1350*cda5da8dSAndroid Build Coastguard Worker    def onclick(self, fun, btn=1, add=None):
1351*cda5da8dSAndroid Build Coastguard Worker        """Bind fun to mouse-click event on canvas.
1352*cda5da8dSAndroid Build Coastguard Worker
1353*cda5da8dSAndroid Build Coastguard Worker        Arguments:
1354*cda5da8dSAndroid Build Coastguard Worker        fun -- a function with two arguments, the coordinates of the
1355*cda5da8dSAndroid Build Coastguard Worker               clicked point on the canvas.
1356*cda5da8dSAndroid Build Coastguard Worker        btn -- the number of the mouse-button, defaults to 1
1357*cda5da8dSAndroid Build Coastguard Worker
1358*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen)
1359*cda5da8dSAndroid Build Coastguard Worker
1360*cda5da8dSAndroid Build Coastguard Worker        >>> screen.onclick(goto)
1361*cda5da8dSAndroid Build Coastguard Worker        >>> # Subsequently clicking into the TurtleScreen will
1362*cda5da8dSAndroid Build Coastguard Worker        >>> # make the turtle move to the clicked point.
1363*cda5da8dSAndroid Build Coastguard Worker        >>> screen.onclick(None)
1364*cda5da8dSAndroid Build Coastguard Worker        """
1365*cda5da8dSAndroid Build Coastguard Worker        self._onscreenclick(fun, btn, add)
1366*cda5da8dSAndroid Build Coastguard Worker
1367*cda5da8dSAndroid Build Coastguard Worker    def onkey(self, fun, key):
1368*cda5da8dSAndroid Build Coastguard Worker        """Bind fun to key-release event of key.
1369*cda5da8dSAndroid Build Coastguard Worker
1370*cda5da8dSAndroid Build Coastguard Worker        Arguments:
1371*cda5da8dSAndroid Build Coastguard Worker        fun -- a function with no arguments
1372*cda5da8dSAndroid Build Coastguard Worker        key -- a string: key (e.g. "a") or key-symbol (e.g. "space")
1373*cda5da8dSAndroid Build Coastguard Worker
1374*cda5da8dSAndroid Build Coastguard Worker        In order to be able to register key-events, TurtleScreen
1375*cda5da8dSAndroid Build Coastguard Worker        must have focus. (See method listen.)
1376*cda5da8dSAndroid Build Coastguard Worker
1377*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1378*cda5da8dSAndroid Build Coastguard Worker
1379*cda5da8dSAndroid Build Coastguard Worker        >>> def f():
1380*cda5da8dSAndroid Build Coastguard Worker        ...     fd(50)
1381*cda5da8dSAndroid Build Coastguard Worker        ...     lt(60)
1382*cda5da8dSAndroid Build Coastguard Worker        ...
1383*cda5da8dSAndroid Build Coastguard Worker        >>> screen.onkey(f, "Up")
1384*cda5da8dSAndroid Build Coastguard Worker        >>> screen.listen()
1385*cda5da8dSAndroid Build Coastguard Worker
1386*cda5da8dSAndroid Build Coastguard Worker        Subsequently the turtle can be moved by repeatedly pressing
1387*cda5da8dSAndroid Build Coastguard Worker        the up-arrow key, consequently drawing a hexagon
1388*cda5da8dSAndroid Build Coastguard Worker
1389*cda5da8dSAndroid Build Coastguard Worker        """
1390*cda5da8dSAndroid Build Coastguard Worker        if fun is None:
1391*cda5da8dSAndroid Build Coastguard Worker            if key in self._keys:
1392*cda5da8dSAndroid Build Coastguard Worker                self._keys.remove(key)
1393*cda5da8dSAndroid Build Coastguard Worker        elif key not in self._keys:
1394*cda5da8dSAndroid Build Coastguard Worker            self._keys.append(key)
1395*cda5da8dSAndroid Build Coastguard Worker        self._onkeyrelease(fun, key)
1396*cda5da8dSAndroid Build Coastguard Worker
1397*cda5da8dSAndroid Build Coastguard Worker    def onkeypress(self, fun, key=None):
1398*cda5da8dSAndroid Build Coastguard Worker        """Bind fun to key-press event of key if key is given,
1399*cda5da8dSAndroid Build Coastguard Worker        or to any key-press-event if no key is given.
1400*cda5da8dSAndroid Build Coastguard Worker
1401*cda5da8dSAndroid Build Coastguard Worker        Arguments:
1402*cda5da8dSAndroid Build Coastguard Worker        fun -- a function with no arguments
1403*cda5da8dSAndroid Build Coastguard Worker        key -- a string: key (e.g. "a") or key-symbol (e.g. "space")
1404*cda5da8dSAndroid Build Coastguard Worker
1405*cda5da8dSAndroid Build Coastguard Worker        In order to be able to register key-events, TurtleScreen
1406*cda5da8dSAndroid Build Coastguard Worker        must have focus. (See method listen.)
1407*cda5da8dSAndroid Build Coastguard Worker
1408*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen
1409*cda5da8dSAndroid Build Coastguard Worker        and a Turtle instance named turtle):
1410*cda5da8dSAndroid Build Coastguard Worker
1411*cda5da8dSAndroid Build Coastguard Worker        >>> def f():
1412*cda5da8dSAndroid Build Coastguard Worker        ...     fd(50)
1413*cda5da8dSAndroid Build Coastguard Worker        ...     lt(60)
1414*cda5da8dSAndroid Build Coastguard Worker        ...
1415*cda5da8dSAndroid Build Coastguard Worker        >>> screen.onkeypress(f, "Up")
1416*cda5da8dSAndroid Build Coastguard Worker        >>> screen.listen()
1417*cda5da8dSAndroid Build Coastguard Worker
1418*cda5da8dSAndroid Build Coastguard Worker        Subsequently the turtle can be moved by repeatedly pressing
1419*cda5da8dSAndroid Build Coastguard Worker        the up-arrow key, or by keeping pressed the up-arrow key.
1420*cda5da8dSAndroid Build Coastguard Worker        consequently drawing a hexagon.
1421*cda5da8dSAndroid Build Coastguard Worker        """
1422*cda5da8dSAndroid Build Coastguard Worker        if fun is None:
1423*cda5da8dSAndroid Build Coastguard Worker            if key in self._keys:
1424*cda5da8dSAndroid Build Coastguard Worker                self._keys.remove(key)
1425*cda5da8dSAndroid Build Coastguard Worker        elif key is not None and key not in self._keys:
1426*cda5da8dSAndroid Build Coastguard Worker            self._keys.append(key)
1427*cda5da8dSAndroid Build Coastguard Worker        self._onkeypress(fun, key)
1428*cda5da8dSAndroid Build Coastguard Worker
1429*cda5da8dSAndroid Build Coastguard Worker    def listen(self, xdummy=None, ydummy=None):
1430*cda5da8dSAndroid Build Coastguard Worker        """Set focus on TurtleScreen (in order to collect key-events)
1431*cda5da8dSAndroid Build Coastguard Worker
1432*cda5da8dSAndroid Build Coastguard Worker        No arguments.
1433*cda5da8dSAndroid Build Coastguard Worker        Dummy arguments are provided in order
1434*cda5da8dSAndroid Build Coastguard Worker        to be able to pass listen to the onclick method.
1435*cda5da8dSAndroid Build Coastguard Worker
1436*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1437*cda5da8dSAndroid Build Coastguard Worker        >>> screen.listen()
1438*cda5da8dSAndroid Build Coastguard Worker        """
1439*cda5da8dSAndroid Build Coastguard Worker        self._listen()
1440*cda5da8dSAndroid Build Coastguard Worker
1441*cda5da8dSAndroid Build Coastguard Worker    def ontimer(self, fun, t=0):
1442*cda5da8dSAndroid Build Coastguard Worker        """Install a timer, which calls fun after t milliseconds.
1443*cda5da8dSAndroid Build Coastguard Worker
1444*cda5da8dSAndroid Build Coastguard Worker        Arguments:
1445*cda5da8dSAndroid Build Coastguard Worker        fun -- a function with no arguments.
1446*cda5da8dSAndroid Build Coastguard Worker        t -- a number >= 0
1447*cda5da8dSAndroid Build Coastguard Worker
1448*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1449*cda5da8dSAndroid Build Coastguard Worker
1450*cda5da8dSAndroid Build Coastguard Worker        >>> running = True
1451*cda5da8dSAndroid Build Coastguard Worker        >>> def f():
1452*cda5da8dSAndroid Build Coastguard Worker        ...     if running:
1453*cda5da8dSAndroid Build Coastguard Worker        ...             fd(50)
1454*cda5da8dSAndroid Build Coastguard Worker        ...             lt(60)
1455*cda5da8dSAndroid Build Coastguard Worker        ...             screen.ontimer(f, 250)
1456*cda5da8dSAndroid Build Coastguard Worker        ...
1457*cda5da8dSAndroid Build Coastguard Worker        >>> f()   # makes the turtle marching around
1458*cda5da8dSAndroid Build Coastguard Worker        >>> running = False
1459*cda5da8dSAndroid Build Coastguard Worker        """
1460*cda5da8dSAndroid Build Coastguard Worker        self._ontimer(fun, t)
1461*cda5da8dSAndroid Build Coastguard Worker
1462*cda5da8dSAndroid Build Coastguard Worker    def bgpic(self, picname=None):
1463*cda5da8dSAndroid Build Coastguard Worker        """Set background image or return name of current backgroundimage.
1464*cda5da8dSAndroid Build Coastguard Worker
1465*cda5da8dSAndroid Build Coastguard Worker        Optional argument:
1466*cda5da8dSAndroid Build Coastguard Worker        picname -- a string, name of a gif-file or "nopic".
1467*cda5da8dSAndroid Build Coastguard Worker
1468*cda5da8dSAndroid Build Coastguard Worker        If picname is a filename, set the corresponding image as background.
1469*cda5da8dSAndroid Build Coastguard Worker        If picname is "nopic", delete backgroundimage, if present.
1470*cda5da8dSAndroid Build Coastguard Worker        If picname is None, return the filename of the current backgroundimage.
1471*cda5da8dSAndroid Build Coastguard Worker
1472*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
1473*cda5da8dSAndroid Build Coastguard Worker        >>> screen.bgpic()
1474*cda5da8dSAndroid Build Coastguard Worker        'nopic'
1475*cda5da8dSAndroid Build Coastguard Worker        >>> screen.bgpic("landscape.gif")
1476*cda5da8dSAndroid Build Coastguard Worker        >>> screen.bgpic()
1477*cda5da8dSAndroid Build Coastguard Worker        'landscape.gif'
1478*cda5da8dSAndroid Build Coastguard Worker        """
1479*cda5da8dSAndroid Build Coastguard Worker        if picname is None:
1480*cda5da8dSAndroid Build Coastguard Worker            return self._bgpicname
1481*cda5da8dSAndroid Build Coastguard Worker        if picname not in self._bgpics:
1482*cda5da8dSAndroid Build Coastguard Worker            self._bgpics[picname] = self._image(picname)
1483*cda5da8dSAndroid Build Coastguard Worker        self._setbgpic(self._bgpic, self._bgpics[picname])
1484*cda5da8dSAndroid Build Coastguard Worker        self._bgpicname = picname
1485*cda5da8dSAndroid Build Coastguard Worker
1486*cda5da8dSAndroid Build Coastguard Worker    def screensize(self, canvwidth=None, canvheight=None, bg=None):
1487*cda5da8dSAndroid Build Coastguard Worker        """Resize the canvas the turtles are drawing on.
1488*cda5da8dSAndroid Build Coastguard Worker
1489*cda5da8dSAndroid Build Coastguard Worker        Optional arguments:
1490*cda5da8dSAndroid Build Coastguard Worker        canvwidth -- positive integer, new width of canvas in pixels
1491*cda5da8dSAndroid Build Coastguard Worker        canvheight --  positive integer, new height of canvas in pixels
1492*cda5da8dSAndroid Build Coastguard Worker        bg -- colorstring or color-tuple, new backgroundcolor
1493*cda5da8dSAndroid Build Coastguard Worker        If no arguments are given, return current (canvaswidth, canvasheight)
1494*cda5da8dSAndroid Build Coastguard Worker
1495*cda5da8dSAndroid Build Coastguard Worker        Do not alter the drawing window. To observe hidden parts of
1496*cda5da8dSAndroid Build Coastguard Worker        the canvas use the scrollbars. (Can make visible those parts
1497*cda5da8dSAndroid Build Coastguard Worker        of a drawing, which were outside the canvas before!)
1498*cda5da8dSAndroid Build Coastguard Worker
1499*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1500*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.screensize(2000,1500)
1501*cda5da8dSAndroid Build Coastguard Worker        >>> # e.g. to search for an erroneously escaped turtle ;-)
1502*cda5da8dSAndroid Build Coastguard Worker        """
1503*cda5da8dSAndroid Build Coastguard Worker        return self._resize(canvwidth, canvheight, bg)
1504*cda5da8dSAndroid Build Coastguard Worker
1505*cda5da8dSAndroid Build Coastguard Worker    onscreenclick = onclick
1506*cda5da8dSAndroid Build Coastguard Worker    resetscreen = reset
1507*cda5da8dSAndroid Build Coastguard Worker    clearscreen = clear
1508*cda5da8dSAndroid Build Coastguard Worker    addshape = register_shape
1509*cda5da8dSAndroid Build Coastguard Worker    onkeyrelease = onkey
1510*cda5da8dSAndroid Build Coastguard Worker
1511*cda5da8dSAndroid Build Coastguard Workerclass TNavigator(object):
1512*cda5da8dSAndroid Build Coastguard Worker    """Navigation part of the RawTurtle.
1513*cda5da8dSAndroid Build Coastguard Worker    Implements methods for turtle movement.
1514*cda5da8dSAndroid Build Coastguard Worker    """
1515*cda5da8dSAndroid Build Coastguard Worker    START_ORIENTATION = {
1516*cda5da8dSAndroid Build Coastguard Worker        "standard": Vec2D(1.0, 0.0),
1517*cda5da8dSAndroid Build Coastguard Worker        "world"   : Vec2D(1.0, 0.0),
1518*cda5da8dSAndroid Build Coastguard Worker        "logo"    : Vec2D(0.0, 1.0)  }
1519*cda5da8dSAndroid Build Coastguard Worker    DEFAULT_MODE = "standard"
1520*cda5da8dSAndroid Build Coastguard Worker    DEFAULT_ANGLEOFFSET = 0
1521*cda5da8dSAndroid Build Coastguard Worker    DEFAULT_ANGLEORIENT = 1
1522*cda5da8dSAndroid Build Coastguard Worker
1523*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, mode=DEFAULT_MODE):
1524*cda5da8dSAndroid Build Coastguard Worker        self._angleOffset = self.DEFAULT_ANGLEOFFSET
1525*cda5da8dSAndroid Build Coastguard Worker        self._angleOrient = self.DEFAULT_ANGLEORIENT
1526*cda5da8dSAndroid Build Coastguard Worker        self._mode = mode
1527*cda5da8dSAndroid Build Coastguard Worker        self.undobuffer = None
1528*cda5da8dSAndroid Build Coastguard Worker        self.degrees()
1529*cda5da8dSAndroid Build Coastguard Worker        self._mode = None
1530*cda5da8dSAndroid Build Coastguard Worker        self._setmode(mode)
1531*cda5da8dSAndroid Build Coastguard Worker        TNavigator.reset(self)
1532*cda5da8dSAndroid Build Coastguard Worker
1533*cda5da8dSAndroid Build Coastguard Worker    def reset(self):
1534*cda5da8dSAndroid Build Coastguard Worker        """reset turtle to its initial values
1535*cda5da8dSAndroid Build Coastguard Worker
1536*cda5da8dSAndroid Build Coastguard Worker        Will be overwritten by parent class
1537*cda5da8dSAndroid Build Coastguard Worker        """
1538*cda5da8dSAndroid Build Coastguard Worker        self._position = Vec2D(0.0, 0.0)
1539*cda5da8dSAndroid Build Coastguard Worker        self._orient =  TNavigator.START_ORIENTATION[self._mode]
1540*cda5da8dSAndroid Build Coastguard Worker
1541*cda5da8dSAndroid Build Coastguard Worker    def _setmode(self, mode=None):
1542*cda5da8dSAndroid Build Coastguard Worker        """Set turtle-mode to 'standard', 'world' or 'logo'.
1543*cda5da8dSAndroid Build Coastguard Worker        """
1544*cda5da8dSAndroid Build Coastguard Worker        if mode is None:
1545*cda5da8dSAndroid Build Coastguard Worker            return self._mode
1546*cda5da8dSAndroid Build Coastguard Worker        if mode not in ["standard", "logo", "world"]:
1547*cda5da8dSAndroid Build Coastguard Worker            return
1548*cda5da8dSAndroid Build Coastguard Worker        self._mode = mode
1549*cda5da8dSAndroid Build Coastguard Worker        if mode in ["standard", "world"]:
1550*cda5da8dSAndroid Build Coastguard Worker            self._angleOffset = 0
1551*cda5da8dSAndroid Build Coastguard Worker            self._angleOrient = 1
1552*cda5da8dSAndroid Build Coastguard Worker        else: # mode == "logo":
1553*cda5da8dSAndroid Build Coastguard Worker            self._angleOffset = self._fullcircle/4.
1554*cda5da8dSAndroid Build Coastguard Worker            self._angleOrient = -1
1555*cda5da8dSAndroid Build Coastguard Worker
1556*cda5da8dSAndroid Build Coastguard Worker    def _setDegreesPerAU(self, fullcircle):
1557*cda5da8dSAndroid Build Coastguard Worker        """Helper function for degrees() and radians()"""
1558*cda5da8dSAndroid Build Coastguard Worker        self._fullcircle = fullcircle
1559*cda5da8dSAndroid Build Coastguard Worker        self._degreesPerAU = 360/fullcircle
1560*cda5da8dSAndroid Build Coastguard Worker        if self._mode == "standard":
1561*cda5da8dSAndroid Build Coastguard Worker            self._angleOffset = 0
1562*cda5da8dSAndroid Build Coastguard Worker        else:
1563*cda5da8dSAndroid Build Coastguard Worker            self._angleOffset = fullcircle/4.
1564*cda5da8dSAndroid Build Coastguard Worker
1565*cda5da8dSAndroid Build Coastguard Worker    def degrees(self, fullcircle=360.0):
1566*cda5da8dSAndroid Build Coastguard Worker        """ Set angle measurement units to degrees.
1567*cda5da8dSAndroid Build Coastguard Worker
1568*cda5da8dSAndroid Build Coastguard Worker        Optional argument:
1569*cda5da8dSAndroid Build Coastguard Worker        fullcircle -  a number
1570*cda5da8dSAndroid Build Coastguard Worker
1571*cda5da8dSAndroid Build Coastguard Worker        Set angle measurement units, i. e. set number
1572*cda5da8dSAndroid Build Coastguard Worker        of 'degrees' for a full circle. Default value is
1573*cda5da8dSAndroid Build Coastguard Worker        360 degrees.
1574*cda5da8dSAndroid Build Coastguard Worker
1575*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1576*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.left(90)
1577*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
1578*cda5da8dSAndroid Build Coastguard Worker        90
1579*cda5da8dSAndroid Build Coastguard Worker
1580*cda5da8dSAndroid Build Coastguard Worker        Change angle measurement unit to grad (also known as gon,
1581*cda5da8dSAndroid Build Coastguard Worker        grade, or gradian and equals 1/100-th of the right angle.)
1582*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.degrees(400.0)
1583*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
1584*cda5da8dSAndroid Build Coastguard Worker        100
1585*cda5da8dSAndroid Build Coastguard Worker
1586*cda5da8dSAndroid Build Coastguard Worker        """
1587*cda5da8dSAndroid Build Coastguard Worker        self._setDegreesPerAU(fullcircle)
1588*cda5da8dSAndroid Build Coastguard Worker
1589*cda5da8dSAndroid Build Coastguard Worker    def radians(self):
1590*cda5da8dSAndroid Build Coastguard Worker        """ Set the angle measurement units to radians.
1591*cda5da8dSAndroid Build Coastguard Worker
1592*cda5da8dSAndroid Build Coastguard Worker        No arguments.
1593*cda5da8dSAndroid Build Coastguard Worker
1594*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1595*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
1596*cda5da8dSAndroid Build Coastguard Worker        90
1597*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.radians()
1598*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
1599*cda5da8dSAndroid Build Coastguard Worker        1.5707963267948966
1600*cda5da8dSAndroid Build Coastguard Worker        """
1601*cda5da8dSAndroid Build Coastguard Worker        self._setDegreesPerAU(math.tau)
1602*cda5da8dSAndroid Build Coastguard Worker
1603*cda5da8dSAndroid Build Coastguard Worker    def _go(self, distance):
1604*cda5da8dSAndroid Build Coastguard Worker        """move turtle forward by specified distance"""
1605*cda5da8dSAndroid Build Coastguard Worker        ende = self._position + self._orient * distance
1606*cda5da8dSAndroid Build Coastguard Worker        self._goto(ende)
1607*cda5da8dSAndroid Build Coastguard Worker
1608*cda5da8dSAndroid Build Coastguard Worker    def _rotate(self, angle):
1609*cda5da8dSAndroid Build Coastguard Worker        """Turn turtle counterclockwise by specified angle if angle > 0."""
1610*cda5da8dSAndroid Build Coastguard Worker        angle *= self._degreesPerAU
1611*cda5da8dSAndroid Build Coastguard Worker        self._orient = self._orient.rotate(angle)
1612*cda5da8dSAndroid Build Coastguard Worker
1613*cda5da8dSAndroid Build Coastguard Worker    def _goto(self, end):
1614*cda5da8dSAndroid Build Coastguard Worker        """move turtle to position end."""
1615*cda5da8dSAndroid Build Coastguard Worker        self._position = end
1616*cda5da8dSAndroid Build Coastguard Worker
1617*cda5da8dSAndroid Build Coastguard Worker    def forward(self, distance):
1618*cda5da8dSAndroid Build Coastguard Worker        """Move the turtle forward by the specified distance.
1619*cda5da8dSAndroid Build Coastguard Worker
1620*cda5da8dSAndroid Build Coastguard Worker        Aliases: forward | fd
1621*cda5da8dSAndroid Build Coastguard Worker
1622*cda5da8dSAndroid Build Coastguard Worker        Argument:
1623*cda5da8dSAndroid Build Coastguard Worker        distance -- a number (integer or float)
1624*cda5da8dSAndroid Build Coastguard Worker
1625*cda5da8dSAndroid Build Coastguard Worker        Move the turtle forward by the specified distance, in the direction
1626*cda5da8dSAndroid Build Coastguard Worker        the turtle is headed.
1627*cda5da8dSAndroid Build Coastguard Worker
1628*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1629*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.position()
1630*cda5da8dSAndroid Build Coastguard Worker        (0.00, 0.00)
1631*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.forward(25)
1632*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.position()
1633*cda5da8dSAndroid Build Coastguard Worker        (25.00,0.00)
1634*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.forward(-75)
1635*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.position()
1636*cda5da8dSAndroid Build Coastguard Worker        (-50.00,0.00)
1637*cda5da8dSAndroid Build Coastguard Worker        """
1638*cda5da8dSAndroid Build Coastguard Worker        self._go(distance)
1639*cda5da8dSAndroid Build Coastguard Worker
1640*cda5da8dSAndroid Build Coastguard Worker    def back(self, distance):
1641*cda5da8dSAndroid Build Coastguard Worker        """Move the turtle backward by distance.
1642*cda5da8dSAndroid Build Coastguard Worker
1643*cda5da8dSAndroid Build Coastguard Worker        Aliases: back | backward | bk
1644*cda5da8dSAndroid Build Coastguard Worker
1645*cda5da8dSAndroid Build Coastguard Worker        Argument:
1646*cda5da8dSAndroid Build Coastguard Worker        distance -- a number
1647*cda5da8dSAndroid Build Coastguard Worker
1648*cda5da8dSAndroid Build Coastguard Worker        Move the turtle backward by distance, opposite to the direction the
1649*cda5da8dSAndroid Build Coastguard Worker        turtle is headed. Do not change the turtle's heading.
1650*cda5da8dSAndroid Build Coastguard Worker
1651*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1652*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.position()
1653*cda5da8dSAndroid Build Coastguard Worker        (0.00, 0.00)
1654*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.backward(30)
1655*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.position()
1656*cda5da8dSAndroid Build Coastguard Worker        (-30.00, 0.00)
1657*cda5da8dSAndroid Build Coastguard Worker        """
1658*cda5da8dSAndroid Build Coastguard Worker        self._go(-distance)
1659*cda5da8dSAndroid Build Coastguard Worker
1660*cda5da8dSAndroid Build Coastguard Worker    def right(self, angle):
1661*cda5da8dSAndroid Build Coastguard Worker        """Turn turtle right by angle units.
1662*cda5da8dSAndroid Build Coastguard Worker
1663*cda5da8dSAndroid Build Coastguard Worker        Aliases: right | rt
1664*cda5da8dSAndroid Build Coastguard Worker
1665*cda5da8dSAndroid Build Coastguard Worker        Argument:
1666*cda5da8dSAndroid Build Coastguard Worker        angle -- a number (integer or float)
1667*cda5da8dSAndroid Build Coastguard Worker
1668*cda5da8dSAndroid Build Coastguard Worker        Turn turtle right by angle units. (Units are by default degrees,
1669*cda5da8dSAndroid Build Coastguard Worker        but can be set via the degrees() and radians() functions.)
1670*cda5da8dSAndroid Build Coastguard Worker        Angle orientation depends on mode. (See this.)
1671*cda5da8dSAndroid Build Coastguard Worker
1672*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1673*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
1674*cda5da8dSAndroid Build Coastguard Worker        22.0
1675*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.right(45)
1676*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
1677*cda5da8dSAndroid Build Coastguard Worker        337.0
1678*cda5da8dSAndroid Build Coastguard Worker        """
1679*cda5da8dSAndroid Build Coastguard Worker        self._rotate(-angle)
1680*cda5da8dSAndroid Build Coastguard Worker
1681*cda5da8dSAndroid Build Coastguard Worker    def left(self, angle):
1682*cda5da8dSAndroid Build Coastguard Worker        """Turn turtle left by angle units.
1683*cda5da8dSAndroid Build Coastguard Worker
1684*cda5da8dSAndroid Build Coastguard Worker        Aliases: left | lt
1685*cda5da8dSAndroid Build Coastguard Worker
1686*cda5da8dSAndroid Build Coastguard Worker        Argument:
1687*cda5da8dSAndroid Build Coastguard Worker        angle -- a number (integer or float)
1688*cda5da8dSAndroid Build Coastguard Worker
1689*cda5da8dSAndroid Build Coastguard Worker        Turn turtle left by angle units. (Units are by default degrees,
1690*cda5da8dSAndroid Build Coastguard Worker        but can be set via the degrees() and radians() functions.)
1691*cda5da8dSAndroid Build Coastguard Worker        Angle orientation depends on mode. (See this.)
1692*cda5da8dSAndroid Build Coastguard Worker
1693*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1694*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
1695*cda5da8dSAndroid Build Coastguard Worker        22.0
1696*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.left(45)
1697*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
1698*cda5da8dSAndroid Build Coastguard Worker        67.0
1699*cda5da8dSAndroid Build Coastguard Worker        """
1700*cda5da8dSAndroid Build Coastguard Worker        self._rotate(angle)
1701*cda5da8dSAndroid Build Coastguard Worker
1702*cda5da8dSAndroid Build Coastguard Worker    def pos(self):
1703*cda5da8dSAndroid Build Coastguard Worker        """Return the turtle's current location (x,y), as a Vec2D-vector.
1704*cda5da8dSAndroid Build Coastguard Worker
1705*cda5da8dSAndroid Build Coastguard Worker        Aliases: pos | position
1706*cda5da8dSAndroid Build Coastguard Worker
1707*cda5da8dSAndroid Build Coastguard Worker        No arguments.
1708*cda5da8dSAndroid Build Coastguard Worker
1709*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1710*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pos()
1711*cda5da8dSAndroid Build Coastguard Worker        (0.00, 240.00)
1712*cda5da8dSAndroid Build Coastguard Worker        """
1713*cda5da8dSAndroid Build Coastguard Worker        return self._position
1714*cda5da8dSAndroid Build Coastguard Worker
1715*cda5da8dSAndroid Build Coastguard Worker    def xcor(self):
1716*cda5da8dSAndroid Build Coastguard Worker        """ Return the turtle's x coordinate.
1717*cda5da8dSAndroid Build Coastguard Worker
1718*cda5da8dSAndroid Build Coastguard Worker        No arguments.
1719*cda5da8dSAndroid Build Coastguard Worker
1720*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1721*cda5da8dSAndroid Build Coastguard Worker        >>> reset()
1722*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.left(60)
1723*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.forward(100)
1724*cda5da8dSAndroid Build Coastguard Worker        >>> print turtle.xcor()
1725*cda5da8dSAndroid Build Coastguard Worker        50.0
1726*cda5da8dSAndroid Build Coastguard Worker        """
1727*cda5da8dSAndroid Build Coastguard Worker        return self._position[0]
1728*cda5da8dSAndroid Build Coastguard Worker
1729*cda5da8dSAndroid Build Coastguard Worker    def ycor(self):
1730*cda5da8dSAndroid Build Coastguard Worker        """ Return the turtle's y coordinate
1731*cda5da8dSAndroid Build Coastguard Worker        ---
1732*cda5da8dSAndroid Build Coastguard Worker        No arguments.
1733*cda5da8dSAndroid Build Coastguard Worker
1734*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1735*cda5da8dSAndroid Build Coastguard Worker        >>> reset()
1736*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.left(60)
1737*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.forward(100)
1738*cda5da8dSAndroid Build Coastguard Worker        >>> print turtle.ycor()
1739*cda5da8dSAndroid Build Coastguard Worker        86.6025403784
1740*cda5da8dSAndroid Build Coastguard Worker        """
1741*cda5da8dSAndroid Build Coastguard Worker        return self._position[1]
1742*cda5da8dSAndroid Build Coastguard Worker
1743*cda5da8dSAndroid Build Coastguard Worker
1744*cda5da8dSAndroid Build Coastguard Worker    def goto(self, x, y=None):
1745*cda5da8dSAndroid Build Coastguard Worker        """Move turtle to an absolute position.
1746*cda5da8dSAndroid Build Coastguard Worker
1747*cda5da8dSAndroid Build Coastguard Worker        Aliases: setpos | setposition | goto:
1748*cda5da8dSAndroid Build Coastguard Worker
1749*cda5da8dSAndroid Build Coastguard Worker        Arguments:
1750*cda5da8dSAndroid Build Coastguard Worker        x -- a number      or     a pair/vector of numbers
1751*cda5da8dSAndroid Build Coastguard Worker        y -- a number             None
1752*cda5da8dSAndroid Build Coastguard Worker
1753*cda5da8dSAndroid Build Coastguard Worker        call: goto(x, y)         # two coordinates
1754*cda5da8dSAndroid Build Coastguard Worker        --or: goto((x, y))       # a pair (tuple) of coordinates
1755*cda5da8dSAndroid Build Coastguard Worker        --or: goto(vec)          # e.g. as returned by pos()
1756*cda5da8dSAndroid Build Coastguard Worker
1757*cda5da8dSAndroid Build Coastguard Worker        Move turtle to an absolute position. If the pen is down,
1758*cda5da8dSAndroid Build Coastguard Worker        a line will be drawn. The turtle's orientation does not change.
1759*cda5da8dSAndroid Build Coastguard Worker
1760*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1761*cda5da8dSAndroid Build Coastguard Worker        >>> tp = turtle.pos()
1762*cda5da8dSAndroid Build Coastguard Worker        >>> tp
1763*cda5da8dSAndroid Build Coastguard Worker        (0.00, 0.00)
1764*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.setpos(60,30)
1765*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pos()
1766*cda5da8dSAndroid Build Coastguard Worker        (60.00,30.00)
1767*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.setpos((20,80))
1768*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pos()
1769*cda5da8dSAndroid Build Coastguard Worker        (20.00,80.00)
1770*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.setpos(tp)
1771*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pos()
1772*cda5da8dSAndroid Build Coastguard Worker        (0.00,0.00)
1773*cda5da8dSAndroid Build Coastguard Worker        """
1774*cda5da8dSAndroid Build Coastguard Worker        if y is None:
1775*cda5da8dSAndroid Build Coastguard Worker            self._goto(Vec2D(*x))
1776*cda5da8dSAndroid Build Coastguard Worker        else:
1777*cda5da8dSAndroid Build Coastguard Worker            self._goto(Vec2D(x, y))
1778*cda5da8dSAndroid Build Coastguard Worker
1779*cda5da8dSAndroid Build Coastguard Worker    def home(self):
1780*cda5da8dSAndroid Build Coastguard Worker        """Move turtle to the origin - coordinates (0,0).
1781*cda5da8dSAndroid Build Coastguard Worker
1782*cda5da8dSAndroid Build Coastguard Worker        No arguments.
1783*cda5da8dSAndroid Build Coastguard Worker
1784*cda5da8dSAndroid Build Coastguard Worker        Move turtle to the origin - coordinates (0,0) and set its
1785*cda5da8dSAndroid Build Coastguard Worker        heading to its start-orientation (which depends on mode).
1786*cda5da8dSAndroid Build Coastguard Worker
1787*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1788*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.home()
1789*cda5da8dSAndroid Build Coastguard Worker        """
1790*cda5da8dSAndroid Build Coastguard Worker        self.goto(0, 0)
1791*cda5da8dSAndroid Build Coastguard Worker        self.setheading(0)
1792*cda5da8dSAndroid Build Coastguard Worker
1793*cda5da8dSAndroid Build Coastguard Worker    def setx(self, x):
1794*cda5da8dSAndroid Build Coastguard Worker        """Set the turtle's first coordinate to x
1795*cda5da8dSAndroid Build Coastguard Worker
1796*cda5da8dSAndroid Build Coastguard Worker        Argument:
1797*cda5da8dSAndroid Build Coastguard Worker        x -- a number (integer or float)
1798*cda5da8dSAndroid Build Coastguard Worker
1799*cda5da8dSAndroid Build Coastguard Worker        Set the turtle's first coordinate to x, leave second coordinate
1800*cda5da8dSAndroid Build Coastguard Worker        unchanged.
1801*cda5da8dSAndroid Build Coastguard Worker
1802*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1803*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.position()
1804*cda5da8dSAndroid Build Coastguard Worker        (0.00, 240.00)
1805*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.setx(10)
1806*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.position()
1807*cda5da8dSAndroid Build Coastguard Worker        (10.00, 240.00)
1808*cda5da8dSAndroid Build Coastguard Worker        """
1809*cda5da8dSAndroid Build Coastguard Worker        self._goto(Vec2D(x, self._position[1]))
1810*cda5da8dSAndroid Build Coastguard Worker
1811*cda5da8dSAndroid Build Coastguard Worker    def sety(self, y):
1812*cda5da8dSAndroid Build Coastguard Worker        """Set the turtle's second coordinate to y
1813*cda5da8dSAndroid Build Coastguard Worker
1814*cda5da8dSAndroid Build Coastguard Worker        Argument:
1815*cda5da8dSAndroid Build Coastguard Worker        y -- a number (integer or float)
1816*cda5da8dSAndroid Build Coastguard Worker
1817*cda5da8dSAndroid Build Coastguard Worker        Set the turtle's first coordinate to x, second coordinate remains
1818*cda5da8dSAndroid Build Coastguard Worker        unchanged.
1819*cda5da8dSAndroid Build Coastguard Worker
1820*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1821*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.position()
1822*cda5da8dSAndroid Build Coastguard Worker        (0.00, 40.00)
1823*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.sety(-10)
1824*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.position()
1825*cda5da8dSAndroid Build Coastguard Worker        (0.00, -10.00)
1826*cda5da8dSAndroid Build Coastguard Worker        """
1827*cda5da8dSAndroid Build Coastguard Worker        self._goto(Vec2D(self._position[0], y))
1828*cda5da8dSAndroid Build Coastguard Worker
1829*cda5da8dSAndroid Build Coastguard Worker    def distance(self, x, y=None):
1830*cda5da8dSAndroid Build Coastguard Worker        """Return the distance from the turtle to (x,y) in turtle step units.
1831*cda5da8dSAndroid Build Coastguard Worker
1832*cda5da8dSAndroid Build Coastguard Worker        Arguments:
1833*cda5da8dSAndroid Build Coastguard Worker        x -- a number   or  a pair/vector of numbers   or   a turtle instance
1834*cda5da8dSAndroid Build Coastguard Worker        y -- a number       None                            None
1835*cda5da8dSAndroid Build Coastguard Worker
1836*cda5da8dSAndroid Build Coastguard Worker        call: distance(x, y)         # two coordinates
1837*cda5da8dSAndroid Build Coastguard Worker        --or: distance((x, y))       # a pair (tuple) of coordinates
1838*cda5da8dSAndroid Build Coastguard Worker        --or: distance(vec)          # e.g. as returned by pos()
1839*cda5da8dSAndroid Build Coastguard Worker        --or: distance(mypen)        # where mypen is another turtle
1840*cda5da8dSAndroid Build Coastguard Worker
1841*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1842*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pos()
1843*cda5da8dSAndroid Build Coastguard Worker        (0.00, 0.00)
1844*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.distance(30,40)
1845*cda5da8dSAndroid Build Coastguard Worker        50.0
1846*cda5da8dSAndroid Build Coastguard Worker        >>> pen = Turtle()
1847*cda5da8dSAndroid Build Coastguard Worker        >>> pen.forward(77)
1848*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.distance(pen)
1849*cda5da8dSAndroid Build Coastguard Worker        77.0
1850*cda5da8dSAndroid Build Coastguard Worker        """
1851*cda5da8dSAndroid Build Coastguard Worker        if y is not None:
1852*cda5da8dSAndroid Build Coastguard Worker            pos = Vec2D(x, y)
1853*cda5da8dSAndroid Build Coastguard Worker        if isinstance(x, Vec2D):
1854*cda5da8dSAndroid Build Coastguard Worker            pos = x
1855*cda5da8dSAndroid Build Coastguard Worker        elif isinstance(x, tuple):
1856*cda5da8dSAndroid Build Coastguard Worker            pos = Vec2D(*x)
1857*cda5da8dSAndroid Build Coastguard Worker        elif isinstance(x, TNavigator):
1858*cda5da8dSAndroid Build Coastguard Worker            pos = x._position
1859*cda5da8dSAndroid Build Coastguard Worker        return abs(pos - self._position)
1860*cda5da8dSAndroid Build Coastguard Worker
1861*cda5da8dSAndroid Build Coastguard Worker    def towards(self, x, y=None):
1862*cda5da8dSAndroid Build Coastguard Worker        """Return the angle of the line from the turtle's position to (x, y).
1863*cda5da8dSAndroid Build Coastguard Worker
1864*cda5da8dSAndroid Build Coastguard Worker        Arguments:
1865*cda5da8dSAndroid Build Coastguard Worker        x -- a number   or  a pair/vector of numbers   or   a turtle instance
1866*cda5da8dSAndroid Build Coastguard Worker        y -- a number       None                            None
1867*cda5da8dSAndroid Build Coastguard Worker
1868*cda5da8dSAndroid Build Coastguard Worker        call: distance(x, y)         # two coordinates
1869*cda5da8dSAndroid Build Coastguard Worker        --or: distance((x, y))       # a pair (tuple) of coordinates
1870*cda5da8dSAndroid Build Coastguard Worker        --or: distance(vec)          # e.g. as returned by pos()
1871*cda5da8dSAndroid Build Coastguard Worker        --or: distance(mypen)        # where mypen is another turtle
1872*cda5da8dSAndroid Build Coastguard Worker
1873*cda5da8dSAndroid Build Coastguard Worker        Return the angle, between the line from turtle-position to position
1874*cda5da8dSAndroid Build Coastguard Worker        specified by x, y and the turtle's start orientation. (Depends on
1875*cda5da8dSAndroid Build Coastguard Worker        modes - "standard" or "logo")
1876*cda5da8dSAndroid Build Coastguard Worker
1877*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1878*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pos()
1879*cda5da8dSAndroid Build Coastguard Worker        (10.00, 10.00)
1880*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.towards(0,0)
1881*cda5da8dSAndroid Build Coastguard Worker        225.0
1882*cda5da8dSAndroid Build Coastguard Worker        """
1883*cda5da8dSAndroid Build Coastguard Worker        if y is not None:
1884*cda5da8dSAndroid Build Coastguard Worker            pos = Vec2D(x, y)
1885*cda5da8dSAndroid Build Coastguard Worker        if isinstance(x, Vec2D):
1886*cda5da8dSAndroid Build Coastguard Worker            pos = x
1887*cda5da8dSAndroid Build Coastguard Worker        elif isinstance(x, tuple):
1888*cda5da8dSAndroid Build Coastguard Worker            pos = Vec2D(*x)
1889*cda5da8dSAndroid Build Coastguard Worker        elif isinstance(x, TNavigator):
1890*cda5da8dSAndroid Build Coastguard Worker            pos = x._position
1891*cda5da8dSAndroid Build Coastguard Worker        x, y = pos - self._position
1892*cda5da8dSAndroid Build Coastguard Worker        result = round(math.degrees(math.atan2(y, x)), 10) % 360.0
1893*cda5da8dSAndroid Build Coastguard Worker        result /= self._degreesPerAU
1894*cda5da8dSAndroid Build Coastguard Worker        return (self._angleOffset + self._angleOrient*result) % self._fullcircle
1895*cda5da8dSAndroid Build Coastguard Worker
1896*cda5da8dSAndroid Build Coastguard Worker    def heading(self):
1897*cda5da8dSAndroid Build Coastguard Worker        """ Return the turtle's current heading.
1898*cda5da8dSAndroid Build Coastguard Worker
1899*cda5da8dSAndroid Build Coastguard Worker        No arguments.
1900*cda5da8dSAndroid Build Coastguard Worker
1901*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1902*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.left(67)
1903*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
1904*cda5da8dSAndroid Build Coastguard Worker        67.0
1905*cda5da8dSAndroid Build Coastguard Worker        """
1906*cda5da8dSAndroid Build Coastguard Worker        x, y = self._orient
1907*cda5da8dSAndroid Build Coastguard Worker        result = round(math.degrees(math.atan2(y, x)), 10) % 360.0
1908*cda5da8dSAndroid Build Coastguard Worker        result /= self._degreesPerAU
1909*cda5da8dSAndroid Build Coastguard Worker        return (self._angleOffset + self._angleOrient*result) % self._fullcircle
1910*cda5da8dSAndroid Build Coastguard Worker
1911*cda5da8dSAndroid Build Coastguard Worker    def setheading(self, to_angle):
1912*cda5da8dSAndroid Build Coastguard Worker        """Set the orientation of the turtle to to_angle.
1913*cda5da8dSAndroid Build Coastguard Worker
1914*cda5da8dSAndroid Build Coastguard Worker        Aliases:  setheading | seth
1915*cda5da8dSAndroid Build Coastguard Worker
1916*cda5da8dSAndroid Build Coastguard Worker        Argument:
1917*cda5da8dSAndroid Build Coastguard Worker        to_angle -- a number (integer or float)
1918*cda5da8dSAndroid Build Coastguard Worker
1919*cda5da8dSAndroid Build Coastguard Worker        Set the orientation of the turtle to to_angle.
1920*cda5da8dSAndroid Build Coastguard Worker        Here are some common directions in degrees:
1921*cda5da8dSAndroid Build Coastguard Worker
1922*cda5da8dSAndroid Build Coastguard Worker         standard - mode:          logo-mode:
1923*cda5da8dSAndroid Build Coastguard Worker        -------------------|--------------------
1924*cda5da8dSAndroid Build Coastguard Worker           0 - east                0 - north
1925*cda5da8dSAndroid Build Coastguard Worker          90 - north              90 - east
1926*cda5da8dSAndroid Build Coastguard Worker         180 - west              180 - south
1927*cda5da8dSAndroid Build Coastguard Worker         270 - south             270 - west
1928*cda5da8dSAndroid Build Coastguard Worker
1929*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1930*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.setheading(90)
1931*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
1932*cda5da8dSAndroid Build Coastguard Worker        90
1933*cda5da8dSAndroid Build Coastguard Worker        """
1934*cda5da8dSAndroid Build Coastguard Worker        angle = (to_angle - self.heading())*self._angleOrient
1935*cda5da8dSAndroid Build Coastguard Worker        full = self._fullcircle
1936*cda5da8dSAndroid Build Coastguard Worker        angle = (angle+full/2.)%full - full/2.
1937*cda5da8dSAndroid Build Coastguard Worker        self._rotate(angle)
1938*cda5da8dSAndroid Build Coastguard Worker
1939*cda5da8dSAndroid Build Coastguard Worker    def circle(self, radius, extent = None, steps = None):
1940*cda5da8dSAndroid Build Coastguard Worker        """ Draw a circle with given radius.
1941*cda5da8dSAndroid Build Coastguard Worker
1942*cda5da8dSAndroid Build Coastguard Worker        Arguments:
1943*cda5da8dSAndroid Build Coastguard Worker        radius -- a number
1944*cda5da8dSAndroid Build Coastguard Worker        extent (optional) -- a number
1945*cda5da8dSAndroid Build Coastguard Worker        steps (optional) -- an integer
1946*cda5da8dSAndroid Build Coastguard Worker
1947*cda5da8dSAndroid Build Coastguard Worker        Draw a circle with given radius. The center is radius units left
1948*cda5da8dSAndroid Build Coastguard Worker        of the turtle; extent - an angle - determines which part of the
1949*cda5da8dSAndroid Build Coastguard Worker        circle is drawn. If extent is not given, draw the entire circle.
1950*cda5da8dSAndroid Build Coastguard Worker        If extent is not a full circle, one endpoint of the arc is the
1951*cda5da8dSAndroid Build Coastguard Worker        current pen position. Draw the arc in counterclockwise direction
1952*cda5da8dSAndroid Build Coastguard Worker        if radius is positive, otherwise in clockwise direction. Finally
1953*cda5da8dSAndroid Build Coastguard Worker        the direction of the turtle is changed by the amount of extent.
1954*cda5da8dSAndroid Build Coastguard Worker
1955*cda5da8dSAndroid Build Coastguard Worker        As the circle is approximated by an inscribed regular polygon,
1956*cda5da8dSAndroid Build Coastguard Worker        steps determines the number of steps to use. If not given,
1957*cda5da8dSAndroid Build Coastguard Worker        it will be calculated automatically. Maybe used to draw regular
1958*cda5da8dSAndroid Build Coastguard Worker        polygons.
1959*cda5da8dSAndroid Build Coastguard Worker
1960*cda5da8dSAndroid Build Coastguard Worker        call: circle(radius)                  # full circle
1961*cda5da8dSAndroid Build Coastguard Worker        --or: circle(radius, extent)          # arc
1962*cda5da8dSAndroid Build Coastguard Worker        --or: circle(radius, extent, steps)
1963*cda5da8dSAndroid Build Coastguard Worker        --or: circle(radius, steps=6)         # 6-sided polygon
1964*cda5da8dSAndroid Build Coastguard Worker
1965*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
1966*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.circle(50)
1967*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.circle(120, 180)  # semicircle
1968*cda5da8dSAndroid Build Coastguard Worker        """
1969*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer:
1970*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.push(["seq"])
1971*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.cumulate = True
1972*cda5da8dSAndroid Build Coastguard Worker        speed = self.speed()
1973*cda5da8dSAndroid Build Coastguard Worker        if extent is None:
1974*cda5da8dSAndroid Build Coastguard Worker            extent = self._fullcircle
1975*cda5da8dSAndroid Build Coastguard Worker        if steps is None:
1976*cda5da8dSAndroid Build Coastguard Worker            frac = abs(extent)/self._fullcircle
1977*cda5da8dSAndroid Build Coastguard Worker            steps = 1+int(min(11+abs(radius)/6.0, 59.0)*frac)
1978*cda5da8dSAndroid Build Coastguard Worker        w = 1.0 * extent / steps
1979*cda5da8dSAndroid Build Coastguard Worker        w2 = 0.5 * w
1980*cda5da8dSAndroid Build Coastguard Worker        l = 2.0 * radius * math.sin(math.radians(w2)*self._degreesPerAU)
1981*cda5da8dSAndroid Build Coastguard Worker        if radius < 0:
1982*cda5da8dSAndroid Build Coastguard Worker            l, w, w2 = -l, -w, -w2
1983*cda5da8dSAndroid Build Coastguard Worker        tr = self._tracer()
1984*cda5da8dSAndroid Build Coastguard Worker        dl = self._delay()
1985*cda5da8dSAndroid Build Coastguard Worker        if speed == 0:
1986*cda5da8dSAndroid Build Coastguard Worker            self._tracer(0, 0)
1987*cda5da8dSAndroid Build Coastguard Worker        else:
1988*cda5da8dSAndroid Build Coastguard Worker            self.speed(0)
1989*cda5da8dSAndroid Build Coastguard Worker        self._rotate(w2)
1990*cda5da8dSAndroid Build Coastguard Worker        for i in range(steps):
1991*cda5da8dSAndroid Build Coastguard Worker            self.speed(speed)
1992*cda5da8dSAndroid Build Coastguard Worker            self._go(l)
1993*cda5da8dSAndroid Build Coastguard Worker            self.speed(0)
1994*cda5da8dSAndroid Build Coastguard Worker            self._rotate(w)
1995*cda5da8dSAndroid Build Coastguard Worker        self._rotate(-w2)
1996*cda5da8dSAndroid Build Coastguard Worker        if speed == 0:
1997*cda5da8dSAndroid Build Coastguard Worker            self._tracer(tr, dl)
1998*cda5da8dSAndroid Build Coastguard Worker        self.speed(speed)
1999*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer:
2000*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.cumulate = False
2001*cda5da8dSAndroid Build Coastguard Worker
2002*cda5da8dSAndroid Build Coastguard Worker## three dummy methods to be implemented by child class:
2003*cda5da8dSAndroid Build Coastguard Worker
2004*cda5da8dSAndroid Build Coastguard Worker    def speed(self, s=0):
2005*cda5da8dSAndroid Build Coastguard Worker        """dummy method - to be overwritten by child class"""
2006*cda5da8dSAndroid Build Coastguard Worker    def _tracer(self, a=None, b=None):
2007*cda5da8dSAndroid Build Coastguard Worker        """dummy method - to be overwritten by child class"""
2008*cda5da8dSAndroid Build Coastguard Worker    def _delay(self, n=None):
2009*cda5da8dSAndroid Build Coastguard Worker        """dummy method - to be overwritten by child class"""
2010*cda5da8dSAndroid Build Coastguard Worker
2011*cda5da8dSAndroid Build Coastguard Worker    fd = forward
2012*cda5da8dSAndroid Build Coastguard Worker    bk = back
2013*cda5da8dSAndroid Build Coastguard Worker    backward = back
2014*cda5da8dSAndroid Build Coastguard Worker    rt = right
2015*cda5da8dSAndroid Build Coastguard Worker    lt = left
2016*cda5da8dSAndroid Build Coastguard Worker    position = pos
2017*cda5da8dSAndroid Build Coastguard Worker    setpos = goto
2018*cda5da8dSAndroid Build Coastguard Worker    setposition = goto
2019*cda5da8dSAndroid Build Coastguard Worker    seth = setheading
2020*cda5da8dSAndroid Build Coastguard Worker
2021*cda5da8dSAndroid Build Coastguard Worker
2022*cda5da8dSAndroid Build Coastguard Workerclass TPen(object):
2023*cda5da8dSAndroid Build Coastguard Worker    """Drawing part of the RawTurtle.
2024*cda5da8dSAndroid Build Coastguard Worker    Implements drawing properties.
2025*cda5da8dSAndroid Build Coastguard Worker    """
2026*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, resizemode=_CFG["resizemode"]):
2027*cda5da8dSAndroid Build Coastguard Worker        self._resizemode = resizemode # or "user" or "noresize"
2028*cda5da8dSAndroid Build Coastguard Worker        self.undobuffer = None
2029*cda5da8dSAndroid Build Coastguard Worker        TPen._reset(self)
2030*cda5da8dSAndroid Build Coastguard Worker
2031*cda5da8dSAndroid Build Coastguard Worker    def _reset(self, pencolor=_CFG["pencolor"],
2032*cda5da8dSAndroid Build Coastguard Worker                     fillcolor=_CFG["fillcolor"]):
2033*cda5da8dSAndroid Build Coastguard Worker        self._pensize = 1
2034*cda5da8dSAndroid Build Coastguard Worker        self._shown = True
2035*cda5da8dSAndroid Build Coastguard Worker        self._pencolor = pencolor
2036*cda5da8dSAndroid Build Coastguard Worker        self._fillcolor = fillcolor
2037*cda5da8dSAndroid Build Coastguard Worker        self._drawing = True
2038*cda5da8dSAndroid Build Coastguard Worker        self._speed = 3
2039*cda5da8dSAndroid Build Coastguard Worker        self._stretchfactor = (1., 1.)
2040*cda5da8dSAndroid Build Coastguard Worker        self._shearfactor = 0.
2041*cda5da8dSAndroid Build Coastguard Worker        self._tilt = 0.
2042*cda5da8dSAndroid Build Coastguard Worker        self._shapetrafo = (1., 0., 0., 1.)
2043*cda5da8dSAndroid Build Coastguard Worker        self._outlinewidth = 1
2044*cda5da8dSAndroid Build Coastguard Worker
2045*cda5da8dSAndroid Build Coastguard Worker    def resizemode(self, rmode=None):
2046*cda5da8dSAndroid Build Coastguard Worker        """Set resizemode to one of the values: "auto", "user", "noresize".
2047*cda5da8dSAndroid Build Coastguard Worker
2048*cda5da8dSAndroid Build Coastguard Worker        (Optional) Argument:
2049*cda5da8dSAndroid Build Coastguard Worker        rmode -- one of the strings "auto", "user", "noresize"
2050*cda5da8dSAndroid Build Coastguard Worker
2051*cda5da8dSAndroid Build Coastguard Worker        Different resizemodes have the following effects:
2052*cda5da8dSAndroid Build Coastguard Worker          - "auto" adapts the appearance of the turtle
2053*cda5da8dSAndroid Build Coastguard Worker                   corresponding to the value of pensize.
2054*cda5da8dSAndroid Build Coastguard Worker          - "user" adapts the appearance of the turtle according to the
2055*cda5da8dSAndroid Build Coastguard Worker                   values of stretchfactor and outlinewidth (outline),
2056*cda5da8dSAndroid Build Coastguard Worker                   which are set by shapesize()
2057*cda5da8dSAndroid Build Coastguard Worker          - "noresize" no adaption of the turtle's appearance takes place.
2058*cda5da8dSAndroid Build Coastguard Worker        If no argument is given, return current resizemode.
2059*cda5da8dSAndroid Build Coastguard Worker        resizemode("user") is called by a call of shapesize with arguments.
2060*cda5da8dSAndroid Build Coastguard Worker
2061*cda5da8dSAndroid Build Coastguard Worker
2062*cda5da8dSAndroid Build Coastguard Worker        Examples (for a Turtle instance named turtle):
2063*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.resizemode("noresize")
2064*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.resizemode()
2065*cda5da8dSAndroid Build Coastguard Worker        'noresize'
2066*cda5da8dSAndroid Build Coastguard Worker        """
2067*cda5da8dSAndroid Build Coastguard Worker        if rmode is None:
2068*cda5da8dSAndroid Build Coastguard Worker            return self._resizemode
2069*cda5da8dSAndroid Build Coastguard Worker        rmode = rmode.lower()
2070*cda5da8dSAndroid Build Coastguard Worker        if rmode in ["auto", "user", "noresize"]:
2071*cda5da8dSAndroid Build Coastguard Worker            self.pen(resizemode=rmode)
2072*cda5da8dSAndroid Build Coastguard Worker
2073*cda5da8dSAndroid Build Coastguard Worker    def pensize(self, width=None):
2074*cda5da8dSAndroid Build Coastguard Worker        """Set or return the line thickness.
2075*cda5da8dSAndroid Build Coastguard Worker
2076*cda5da8dSAndroid Build Coastguard Worker        Aliases:  pensize | width
2077*cda5da8dSAndroid Build Coastguard Worker
2078*cda5da8dSAndroid Build Coastguard Worker        Argument:
2079*cda5da8dSAndroid Build Coastguard Worker        width -- positive number
2080*cda5da8dSAndroid Build Coastguard Worker
2081*cda5da8dSAndroid Build Coastguard Worker        Set the line thickness to width or return it. If resizemode is set
2082*cda5da8dSAndroid Build Coastguard Worker        to "auto" and turtleshape is a polygon, that polygon is drawn with
2083*cda5da8dSAndroid Build Coastguard Worker        the same line thickness. If no argument is given, current pensize
2084*cda5da8dSAndroid Build Coastguard Worker        is returned.
2085*cda5da8dSAndroid Build Coastguard Worker
2086*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2087*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pensize()
2088*cda5da8dSAndroid Build Coastguard Worker        1
2089*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pensize(10)   # from here on lines of width 10 are drawn
2090*cda5da8dSAndroid Build Coastguard Worker        """
2091*cda5da8dSAndroid Build Coastguard Worker        if width is None:
2092*cda5da8dSAndroid Build Coastguard Worker            return self._pensize
2093*cda5da8dSAndroid Build Coastguard Worker        self.pen(pensize=width)
2094*cda5da8dSAndroid Build Coastguard Worker
2095*cda5da8dSAndroid Build Coastguard Worker
2096*cda5da8dSAndroid Build Coastguard Worker    def penup(self):
2097*cda5da8dSAndroid Build Coastguard Worker        """Pull the pen up -- no drawing when moving.
2098*cda5da8dSAndroid Build Coastguard Worker
2099*cda5da8dSAndroid Build Coastguard Worker        Aliases: penup | pu | up
2100*cda5da8dSAndroid Build Coastguard Worker
2101*cda5da8dSAndroid Build Coastguard Worker        No argument
2102*cda5da8dSAndroid Build Coastguard Worker
2103*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2104*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.penup()
2105*cda5da8dSAndroid Build Coastguard Worker        """
2106*cda5da8dSAndroid Build Coastguard Worker        if not self._drawing:
2107*cda5da8dSAndroid Build Coastguard Worker            return
2108*cda5da8dSAndroid Build Coastguard Worker        self.pen(pendown=False)
2109*cda5da8dSAndroid Build Coastguard Worker
2110*cda5da8dSAndroid Build Coastguard Worker    def pendown(self):
2111*cda5da8dSAndroid Build Coastguard Worker        """Pull the pen down -- drawing when moving.
2112*cda5da8dSAndroid Build Coastguard Worker
2113*cda5da8dSAndroid Build Coastguard Worker        Aliases: pendown | pd | down
2114*cda5da8dSAndroid Build Coastguard Worker
2115*cda5da8dSAndroid Build Coastguard Worker        No argument.
2116*cda5da8dSAndroid Build Coastguard Worker
2117*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2118*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pendown()
2119*cda5da8dSAndroid Build Coastguard Worker        """
2120*cda5da8dSAndroid Build Coastguard Worker        if self._drawing:
2121*cda5da8dSAndroid Build Coastguard Worker            return
2122*cda5da8dSAndroid Build Coastguard Worker        self.pen(pendown=True)
2123*cda5da8dSAndroid Build Coastguard Worker
2124*cda5da8dSAndroid Build Coastguard Worker    def isdown(self):
2125*cda5da8dSAndroid Build Coastguard Worker        """Return True if pen is down, False if it's up.
2126*cda5da8dSAndroid Build Coastguard Worker
2127*cda5da8dSAndroid Build Coastguard Worker        No argument.
2128*cda5da8dSAndroid Build Coastguard Worker
2129*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2130*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.penup()
2131*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.isdown()
2132*cda5da8dSAndroid Build Coastguard Worker        False
2133*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pendown()
2134*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.isdown()
2135*cda5da8dSAndroid Build Coastguard Worker        True
2136*cda5da8dSAndroid Build Coastguard Worker        """
2137*cda5da8dSAndroid Build Coastguard Worker        return self._drawing
2138*cda5da8dSAndroid Build Coastguard Worker
2139*cda5da8dSAndroid Build Coastguard Worker    def speed(self, speed=None):
2140*cda5da8dSAndroid Build Coastguard Worker        """ Return or set the turtle's speed.
2141*cda5da8dSAndroid Build Coastguard Worker
2142*cda5da8dSAndroid Build Coastguard Worker        Optional argument:
2143*cda5da8dSAndroid Build Coastguard Worker        speed -- an integer in the range 0..10 or a speedstring (see below)
2144*cda5da8dSAndroid Build Coastguard Worker
2145*cda5da8dSAndroid Build Coastguard Worker        Set the turtle's speed to an integer value in the range 0 .. 10.
2146*cda5da8dSAndroid Build Coastguard Worker        If no argument is given: return current speed.
2147*cda5da8dSAndroid Build Coastguard Worker
2148*cda5da8dSAndroid Build Coastguard Worker        If input is a number greater than 10 or smaller than 0.5,
2149*cda5da8dSAndroid Build Coastguard Worker        speed is set to 0.
2150*cda5da8dSAndroid Build Coastguard Worker        Speedstrings  are mapped to speedvalues in the following way:
2151*cda5da8dSAndroid Build Coastguard Worker            'fastest' :  0
2152*cda5da8dSAndroid Build Coastguard Worker            'fast'    :  10
2153*cda5da8dSAndroid Build Coastguard Worker            'normal'  :  6
2154*cda5da8dSAndroid Build Coastguard Worker            'slow'    :  3
2155*cda5da8dSAndroid Build Coastguard Worker            'slowest' :  1
2156*cda5da8dSAndroid Build Coastguard Worker        speeds from 1 to 10 enforce increasingly faster animation of
2157*cda5da8dSAndroid Build Coastguard Worker        line drawing and turtle turning.
2158*cda5da8dSAndroid Build Coastguard Worker
2159*cda5da8dSAndroid Build Coastguard Worker        Attention:
2160*cda5da8dSAndroid Build Coastguard Worker        speed = 0 : *no* animation takes place. forward/back makes turtle jump
2161*cda5da8dSAndroid Build Coastguard Worker        and likewise left/right make the turtle turn instantly.
2162*cda5da8dSAndroid Build Coastguard Worker
2163*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2164*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.speed(3)
2165*cda5da8dSAndroid Build Coastguard Worker        """
2166*cda5da8dSAndroid Build Coastguard Worker        speeds = {'fastest':0, 'fast':10, 'normal':6, 'slow':3, 'slowest':1 }
2167*cda5da8dSAndroid Build Coastguard Worker        if speed is None:
2168*cda5da8dSAndroid Build Coastguard Worker            return self._speed
2169*cda5da8dSAndroid Build Coastguard Worker        if speed in speeds:
2170*cda5da8dSAndroid Build Coastguard Worker            speed = speeds[speed]
2171*cda5da8dSAndroid Build Coastguard Worker        elif 0.5 < speed < 10.5:
2172*cda5da8dSAndroid Build Coastguard Worker            speed = int(round(speed))
2173*cda5da8dSAndroid Build Coastguard Worker        else:
2174*cda5da8dSAndroid Build Coastguard Worker            speed = 0
2175*cda5da8dSAndroid Build Coastguard Worker        self.pen(speed=speed)
2176*cda5da8dSAndroid Build Coastguard Worker
2177*cda5da8dSAndroid Build Coastguard Worker    def color(self, *args):
2178*cda5da8dSAndroid Build Coastguard Worker        """Return or set the pencolor and fillcolor.
2179*cda5da8dSAndroid Build Coastguard Worker
2180*cda5da8dSAndroid Build Coastguard Worker        Arguments:
2181*cda5da8dSAndroid Build Coastguard Worker        Several input formats are allowed.
2182*cda5da8dSAndroid Build Coastguard Worker        They use 0, 1, 2, or 3 arguments as follows:
2183*cda5da8dSAndroid Build Coastguard Worker
2184*cda5da8dSAndroid Build Coastguard Worker        color()
2185*cda5da8dSAndroid Build Coastguard Worker            Return the current pencolor and the current fillcolor
2186*cda5da8dSAndroid Build Coastguard Worker            as a pair of color specification strings as are returned
2187*cda5da8dSAndroid Build Coastguard Worker            by pencolor and fillcolor.
2188*cda5da8dSAndroid Build Coastguard Worker        color(colorstring), color((r,g,b)), color(r,g,b)
2189*cda5da8dSAndroid Build Coastguard Worker            inputs as in pencolor, set both, fillcolor and pencolor,
2190*cda5da8dSAndroid Build Coastguard Worker            to the given value.
2191*cda5da8dSAndroid Build Coastguard Worker        color(colorstring1, colorstring2),
2192*cda5da8dSAndroid Build Coastguard Worker        color((r1,g1,b1), (r2,g2,b2))
2193*cda5da8dSAndroid Build Coastguard Worker            equivalent to pencolor(colorstring1) and fillcolor(colorstring2)
2194*cda5da8dSAndroid Build Coastguard Worker            and analogously, if the other input format is used.
2195*cda5da8dSAndroid Build Coastguard Worker
2196*cda5da8dSAndroid Build Coastguard Worker        If turtleshape is a polygon, outline and interior of that polygon
2197*cda5da8dSAndroid Build Coastguard Worker        is drawn with the newly set colors.
2198*cda5da8dSAndroid Build Coastguard Worker        For more info see: pencolor, fillcolor
2199*cda5da8dSAndroid Build Coastguard Worker
2200*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2201*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.color('red', 'green')
2202*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.color()
2203*cda5da8dSAndroid Build Coastguard Worker        ('red', 'green')
2204*cda5da8dSAndroid Build Coastguard Worker        >>> colormode(255)
2205*cda5da8dSAndroid Build Coastguard Worker        >>> color((40, 80, 120), (160, 200, 240))
2206*cda5da8dSAndroid Build Coastguard Worker        >>> color()
2207*cda5da8dSAndroid Build Coastguard Worker        ('#285078', '#a0c8f0')
2208*cda5da8dSAndroid Build Coastguard Worker        """
2209*cda5da8dSAndroid Build Coastguard Worker        if args:
2210*cda5da8dSAndroid Build Coastguard Worker            l = len(args)
2211*cda5da8dSAndroid Build Coastguard Worker            if l == 1:
2212*cda5da8dSAndroid Build Coastguard Worker                pcolor = fcolor = args[0]
2213*cda5da8dSAndroid Build Coastguard Worker            elif l == 2:
2214*cda5da8dSAndroid Build Coastguard Worker                pcolor, fcolor = args
2215*cda5da8dSAndroid Build Coastguard Worker            elif l == 3:
2216*cda5da8dSAndroid Build Coastguard Worker                pcolor = fcolor = args
2217*cda5da8dSAndroid Build Coastguard Worker            pcolor = self._colorstr(pcolor)
2218*cda5da8dSAndroid Build Coastguard Worker            fcolor = self._colorstr(fcolor)
2219*cda5da8dSAndroid Build Coastguard Worker            self.pen(pencolor=pcolor, fillcolor=fcolor)
2220*cda5da8dSAndroid Build Coastguard Worker        else:
2221*cda5da8dSAndroid Build Coastguard Worker            return self._color(self._pencolor), self._color(self._fillcolor)
2222*cda5da8dSAndroid Build Coastguard Worker
2223*cda5da8dSAndroid Build Coastguard Worker    def pencolor(self, *args):
2224*cda5da8dSAndroid Build Coastguard Worker        """ Return or set the pencolor.
2225*cda5da8dSAndroid Build Coastguard Worker
2226*cda5da8dSAndroid Build Coastguard Worker        Arguments:
2227*cda5da8dSAndroid Build Coastguard Worker        Four input formats are allowed:
2228*cda5da8dSAndroid Build Coastguard Worker          - pencolor()
2229*cda5da8dSAndroid Build Coastguard Worker            Return the current pencolor as color specification string,
2230*cda5da8dSAndroid Build Coastguard Worker            possibly in hex-number format (see example).
2231*cda5da8dSAndroid Build Coastguard Worker            May be used as input to another color/pencolor/fillcolor call.
2232*cda5da8dSAndroid Build Coastguard Worker          - pencolor(colorstring)
2233*cda5da8dSAndroid Build Coastguard Worker            s is a Tk color specification string, such as "red" or "yellow"
2234*cda5da8dSAndroid Build Coastguard Worker          - pencolor((r, g, b))
2235*cda5da8dSAndroid Build Coastguard Worker            *a tuple* of r, g, and b, which represent, an RGB color,
2236*cda5da8dSAndroid Build Coastguard Worker            and each of r, g, and b are in the range 0..colormode,
2237*cda5da8dSAndroid Build Coastguard Worker            where colormode is either 1.0 or 255
2238*cda5da8dSAndroid Build Coastguard Worker          - pencolor(r, g, b)
2239*cda5da8dSAndroid Build Coastguard Worker            r, g, and b represent an RGB color, and each of r, g, and b
2240*cda5da8dSAndroid Build Coastguard Worker            are in the range 0..colormode
2241*cda5da8dSAndroid Build Coastguard Worker
2242*cda5da8dSAndroid Build Coastguard Worker        If turtleshape is a polygon, the outline of that polygon is drawn
2243*cda5da8dSAndroid Build Coastguard Worker        with the newly set pencolor.
2244*cda5da8dSAndroid Build Coastguard Worker
2245*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2246*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pencolor('brown')
2247*cda5da8dSAndroid Build Coastguard Worker        >>> tup = (0.2, 0.8, 0.55)
2248*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pencolor(tup)
2249*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pencolor()
2250*cda5da8dSAndroid Build Coastguard Worker        '#33cc8c'
2251*cda5da8dSAndroid Build Coastguard Worker        """
2252*cda5da8dSAndroid Build Coastguard Worker        if args:
2253*cda5da8dSAndroid Build Coastguard Worker            color = self._colorstr(args)
2254*cda5da8dSAndroid Build Coastguard Worker            if color == self._pencolor:
2255*cda5da8dSAndroid Build Coastguard Worker                return
2256*cda5da8dSAndroid Build Coastguard Worker            self.pen(pencolor=color)
2257*cda5da8dSAndroid Build Coastguard Worker        else:
2258*cda5da8dSAndroid Build Coastguard Worker            return self._color(self._pencolor)
2259*cda5da8dSAndroid Build Coastguard Worker
2260*cda5da8dSAndroid Build Coastguard Worker    def fillcolor(self, *args):
2261*cda5da8dSAndroid Build Coastguard Worker        """ Return or set the fillcolor.
2262*cda5da8dSAndroid Build Coastguard Worker
2263*cda5da8dSAndroid Build Coastguard Worker        Arguments:
2264*cda5da8dSAndroid Build Coastguard Worker        Four input formats are allowed:
2265*cda5da8dSAndroid Build Coastguard Worker          - fillcolor()
2266*cda5da8dSAndroid Build Coastguard Worker            Return the current fillcolor as color specification string,
2267*cda5da8dSAndroid Build Coastguard Worker            possibly in hex-number format (see example).
2268*cda5da8dSAndroid Build Coastguard Worker            May be used as input to another color/pencolor/fillcolor call.
2269*cda5da8dSAndroid Build Coastguard Worker          - fillcolor(colorstring)
2270*cda5da8dSAndroid Build Coastguard Worker            s is a Tk color specification string, such as "red" or "yellow"
2271*cda5da8dSAndroid Build Coastguard Worker          - fillcolor((r, g, b))
2272*cda5da8dSAndroid Build Coastguard Worker            *a tuple* of r, g, and b, which represent, an RGB color,
2273*cda5da8dSAndroid Build Coastguard Worker            and each of r, g, and b are in the range 0..colormode,
2274*cda5da8dSAndroid Build Coastguard Worker            where colormode is either 1.0 or 255
2275*cda5da8dSAndroid Build Coastguard Worker          - fillcolor(r, g, b)
2276*cda5da8dSAndroid Build Coastguard Worker            r, g, and b represent an RGB color, and each of r, g, and b
2277*cda5da8dSAndroid Build Coastguard Worker            are in the range 0..colormode
2278*cda5da8dSAndroid Build Coastguard Worker
2279*cda5da8dSAndroid Build Coastguard Worker        If turtleshape is a polygon, the interior of that polygon is drawn
2280*cda5da8dSAndroid Build Coastguard Worker        with the newly set fillcolor.
2281*cda5da8dSAndroid Build Coastguard Worker
2282*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2283*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fillcolor('violet')
2284*cda5da8dSAndroid Build Coastguard Worker        >>> col = turtle.pencolor()
2285*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fillcolor(col)
2286*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fillcolor(0, .5, 0)
2287*cda5da8dSAndroid Build Coastguard Worker        """
2288*cda5da8dSAndroid Build Coastguard Worker        if args:
2289*cda5da8dSAndroid Build Coastguard Worker            color = self._colorstr(args)
2290*cda5da8dSAndroid Build Coastguard Worker            if color == self._fillcolor:
2291*cda5da8dSAndroid Build Coastguard Worker                return
2292*cda5da8dSAndroid Build Coastguard Worker            self.pen(fillcolor=color)
2293*cda5da8dSAndroid Build Coastguard Worker        else:
2294*cda5da8dSAndroid Build Coastguard Worker            return self._color(self._fillcolor)
2295*cda5da8dSAndroid Build Coastguard Worker
2296*cda5da8dSAndroid Build Coastguard Worker    def showturtle(self):
2297*cda5da8dSAndroid Build Coastguard Worker        """Makes the turtle visible.
2298*cda5da8dSAndroid Build Coastguard Worker
2299*cda5da8dSAndroid Build Coastguard Worker        Aliases: showturtle | st
2300*cda5da8dSAndroid Build Coastguard Worker
2301*cda5da8dSAndroid Build Coastguard Worker        No argument.
2302*cda5da8dSAndroid Build Coastguard Worker
2303*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2304*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.hideturtle()
2305*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.showturtle()
2306*cda5da8dSAndroid Build Coastguard Worker        """
2307*cda5da8dSAndroid Build Coastguard Worker        self.pen(shown=True)
2308*cda5da8dSAndroid Build Coastguard Worker
2309*cda5da8dSAndroid Build Coastguard Worker    def hideturtle(self):
2310*cda5da8dSAndroid Build Coastguard Worker        """Makes the turtle invisible.
2311*cda5da8dSAndroid Build Coastguard Worker
2312*cda5da8dSAndroid Build Coastguard Worker        Aliases: hideturtle | ht
2313*cda5da8dSAndroid Build Coastguard Worker
2314*cda5da8dSAndroid Build Coastguard Worker        No argument.
2315*cda5da8dSAndroid Build Coastguard Worker
2316*cda5da8dSAndroid Build Coastguard Worker        It's a good idea to do this while you're in the
2317*cda5da8dSAndroid Build Coastguard Worker        middle of a complicated drawing, because hiding
2318*cda5da8dSAndroid Build Coastguard Worker        the turtle speeds up the drawing observably.
2319*cda5da8dSAndroid Build Coastguard Worker
2320*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2321*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.hideturtle()
2322*cda5da8dSAndroid Build Coastguard Worker        """
2323*cda5da8dSAndroid Build Coastguard Worker        self.pen(shown=False)
2324*cda5da8dSAndroid Build Coastguard Worker
2325*cda5da8dSAndroid Build Coastguard Worker    def isvisible(self):
2326*cda5da8dSAndroid Build Coastguard Worker        """Return True if the Turtle is shown, False if it's hidden.
2327*cda5da8dSAndroid Build Coastguard Worker
2328*cda5da8dSAndroid Build Coastguard Worker        No argument.
2329*cda5da8dSAndroid Build Coastguard Worker
2330*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2331*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.hideturtle()
2332*cda5da8dSAndroid Build Coastguard Worker        >>> print turtle.isvisible():
2333*cda5da8dSAndroid Build Coastguard Worker        False
2334*cda5da8dSAndroid Build Coastguard Worker        """
2335*cda5da8dSAndroid Build Coastguard Worker        return self._shown
2336*cda5da8dSAndroid Build Coastguard Worker
2337*cda5da8dSAndroid Build Coastguard Worker    def pen(self, pen=None, **pendict):
2338*cda5da8dSAndroid Build Coastguard Worker        """Return or set the pen's attributes.
2339*cda5da8dSAndroid Build Coastguard Worker
2340*cda5da8dSAndroid Build Coastguard Worker        Arguments:
2341*cda5da8dSAndroid Build Coastguard Worker            pen -- a dictionary with some or all of the below listed keys.
2342*cda5da8dSAndroid Build Coastguard Worker            **pendict -- one or more keyword-arguments with the below
2343*cda5da8dSAndroid Build Coastguard Worker                         listed keys as keywords.
2344*cda5da8dSAndroid Build Coastguard Worker
2345*cda5da8dSAndroid Build Coastguard Worker        Return or set the pen's attributes in a 'pen-dictionary'
2346*cda5da8dSAndroid Build Coastguard Worker        with the following key/value pairs:
2347*cda5da8dSAndroid Build Coastguard Worker           "shown"      :   True/False
2348*cda5da8dSAndroid Build Coastguard Worker           "pendown"    :   True/False
2349*cda5da8dSAndroid Build Coastguard Worker           "pencolor"   :   color-string or color-tuple
2350*cda5da8dSAndroid Build Coastguard Worker           "fillcolor"  :   color-string or color-tuple
2351*cda5da8dSAndroid Build Coastguard Worker           "pensize"    :   positive number
2352*cda5da8dSAndroid Build Coastguard Worker           "speed"      :   number in range 0..10
2353*cda5da8dSAndroid Build Coastguard Worker           "resizemode" :   "auto" or "user" or "noresize"
2354*cda5da8dSAndroid Build Coastguard Worker           "stretchfactor": (positive number, positive number)
2355*cda5da8dSAndroid Build Coastguard Worker           "shearfactor":   number
2356*cda5da8dSAndroid Build Coastguard Worker           "outline"    :   positive number
2357*cda5da8dSAndroid Build Coastguard Worker           "tilt"       :   number
2358*cda5da8dSAndroid Build Coastguard Worker
2359*cda5da8dSAndroid Build Coastguard Worker        This dictionary can be used as argument for a subsequent
2360*cda5da8dSAndroid Build Coastguard Worker        pen()-call to restore the former pen-state. Moreover one
2361*cda5da8dSAndroid Build Coastguard Worker        or more of these attributes can be provided as keyword-arguments.
2362*cda5da8dSAndroid Build Coastguard Worker        This can be used to set several pen attributes in one statement.
2363*cda5da8dSAndroid Build Coastguard Worker
2364*cda5da8dSAndroid Build Coastguard Worker
2365*cda5da8dSAndroid Build Coastguard Worker        Examples (for a Turtle instance named turtle):
2366*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pen(fillcolor="black", pencolor="red", pensize=10)
2367*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pen()
2368*cda5da8dSAndroid Build Coastguard Worker        {'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1,
2369*cda5da8dSAndroid Build Coastguard Worker        'pencolor': 'red', 'pendown': True, 'fillcolor': 'black',
2370*cda5da8dSAndroid Build Coastguard Worker        'stretchfactor': (1,1), 'speed': 3, 'shearfactor': 0.0}
2371*cda5da8dSAndroid Build Coastguard Worker        >>> penstate=turtle.pen()
2372*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.color("yellow","")
2373*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.penup()
2374*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.pen()
2375*cda5da8dSAndroid Build Coastguard Worker        {'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1,
2376*cda5da8dSAndroid Build Coastguard Worker        'pencolor': 'yellow', 'pendown': False, 'fillcolor': '',
2377*cda5da8dSAndroid Build Coastguard Worker        'stretchfactor': (1,1), 'speed': 3, 'shearfactor': 0.0}
2378*cda5da8dSAndroid Build Coastguard Worker        >>> p.pen(penstate, fillcolor="green")
2379*cda5da8dSAndroid Build Coastguard Worker        >>> p.pen()
2380*cda5da8dSAndroid Build Coastguard Worker        {'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1,
2381*cda5da8dSAndroid Build Coastguard Worker        'pencolor': 'red', 'pendown': True, 'fillcolor': 'green',
2382*cda5da8dSAndroid Build Coastguard Worker        'stretchfactor': (1,1), 'speed': 3, 'shearfactor': 0.0}
2383*cda5da8dSAndroid Build Coastguard Worker        """
2384*cda5da8dSAndroid Build Coastguard Worker        _pd =  {"shown"         : self._shown,
2385*cda5da8dSAndroid Build Coastguard Worker                "pendown"       : self._drawing,
2386*cda5da8dSAndroid Build Coastguard Worker                "pencolor"      : self._pencolor,
2387*cda5da8dSAndroid Build Coastguard Worker                "fillcolor"     : self._fillcolor,
2388*cda5da8dSAndroid Build Coastguard Worker                "pensize"       : self._pensize,
2389*cda5da8dSAndroid Build Coastguard Worker                "speed"         : self._speed,
2390*cda5da8dSAndroid Build Coastguard Worker                "resizemode"    : self._resizemode,
2391*cda5da8dSAndroid Build Coastguard Worker                "stretchfactor" : self._stretchfactor,
2392*cda5da8dSAndroid Build Coastguard Worker                "shearfactor"   : self._shearfactor,
2393*cda5da8dSAndroid Build Coastguard Worker                "outline"       : self._outlinewidth,
2394*cda5da8dSAndroid Build Coastguard Worker                "tilt"          : self._tilt
2395*cda5da8dSAndroid Build Coastguard Worker               }
2396*cda5da8dSAndroid Build Coastguard Worker
2397*cda5da8dSAndroid Build Coastguard Worker        if not (pen or pendict):
2398*cda5da8dSAndroid Build Coastguard Worker            return _pd
2399*cda5da8dSAndroid Build Coastguard Worker
2400*cda5da8dSAndroid Build Coastguard Worker        if isinstance(pen, dict):
2401*cda5da8dSAndroid Build Coastguard Worker            p = pen
2402*cda5da8dSAndroid Build Coastguard Worker        else:
2403*cda5da8dSAndroid Build Coastguard Worker            p = {}
2404*cda5da8dSAndroid Build Coastguard Worker        p.update(pendict)
2405*cda5da8dSAndroid Build Coastguard Worker
2406*cda5da8dSAndroid Build Coastguard Worker        _p_buf = {}
2407*cda5da8dSAndroid Build Coastguard Worker        for key in p:
2408*cda5da8dSAndroid Build Coastguard Worker            _p_buf[key] = _pd[key]
2409*cda5da8dSAndroid Build Coastguard Worker
2410*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer:
2411*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.push(("pen", _p_buf))
2412*cda5da8dSAndroid Build Coastguard Worker
2413*cda5da8dSAndroid Build Coastguard Worker        newLine = False
2414*cda5da8dSAndroid Build Coastguard Worker        if "pendown" in p:
2415*cda5da8dSAndroid Build Coastguard Worker            if self._drawing != p["pendown"]:
2416*cda5da8dSAndroid Build Coastguard Worker                newLine = True
2417*cda5da8dSAndroid Build Coastguard Worker        if "pencolor" in p:
2418*cda5da8dSAndroid Build Coastguard Worker            if isinstance(p["pencolor"], tuple):
2419*cda5da8dSAndroid Build Coastguard Worker                p["pencolor"] = self._colorstr((p["pencolor"],))
2420*cda5da8dSAndroid Build Coastguard Worker            if self._pencolor != p["pencolor"]:
2421*cda5da8dSAndroid Build Coastguard Worker                newLine = True
2422*cda5da8dSAndroid Build Coastguard Worker        if "pensize" in p:
2423*cda5da8dSAndroid Build Coastguard Worker            if self._pensize != p["pensize"]:
2424*cda5da8dSAndroid Build Coastguard Worker                newLine = True
2425*cda5da8dSAndroid Build Coastguard Worker        if newLine:
2426*cda5da8dSAndroid Build Coastguard Worker            self._newLine()
2427*cda5da8dSAndroid Build Coastguard Worker        if "pendown" in p:
2428*cda5da8dSAndroid Build Coastguard Worker            self._drawing = p["pendown"]
2429*cda5da8dSAndroid Build Coastguard Worker        if "pencolor" in p:
2430*cda5da8dSAndroid Build Coastguard Worker            self._pencolor = p["pencolor"]
2431*cda5da8dSAndroid Build Coastguard Worker        if "pensize" in p:
2432*cda5da8dSAndroid Build Coastguard Worker            self._pensize = p["pensize"]
2433*cda5da8dSAndroid Build Coastguard Worker        if "fillcolor" in p:
2434*cda5da8dSAndroid Build Coastguard Worker            if isinstance(p["fillcolor"], tuple):
2435*cda5da8dSAndroid Build Coastguard Worker                p["fillcolor"] = self._colorstr((p["fillcolor"],))
2436*cda5da8dSAndroid Build Coastguard Worker            self._fillcolor = p["fillcolor"]
2437*cda5da8dSAndroid Build Coastguard Worker        if "speed" in p:
2438*cda5da8dSAndroid Build Coastguard Worker            self._speed = p["speed"]
2439*cda5da8dSAndroid Build Coastguard Worker        if "resizemode" in p:
2440*cda5da8dSAndroid Build Coastguard Worker            self._resizemode = p["resizemode"]
2441*cda5da8dSAndroid Build Coastguard Worker        if "stretchfactor" in p:
2442*cda5da8dSAndroid Build Coastguard Worker            sf = p["stretchfactor"]
2443*cda5da8dSAndroid Build Coastguard Worker            if isinstance(sf, (int, float)):
2444*cda5da8dSAndroid Build Coastguard Worker                sf = (sf, sf)
2445*cda5da8dSAndroid Build Coastguard Worker            self._stretchfactor = sf
2446*cda5da8dSAndroid Build Coastguard Worker        if "shearfactor" in p:
2447*cda5da8dSAndroid Build Coastguard Worker            self._shearfactor = p["shearfactor"]
2448*cda5da8dSAndroid Build Coastguard Worker        if "outline" in p:
2449*cda5da8dSAndroid Build Coastguard Worker            self._outlinewidth = p["outline"]
2450*cda5da8dSAndroid Build Coastguard Worker        if "shown" in p:
2451*cda5da8dSAndroid Build Coastguard Worker            self._shown = p["shown"]
2452*cda5da8dSAndroid Build Coastguard Worker        if "tilt" in p:
2453*cda5da8dSAndroid Build Coastguard Worker            self._tilt = p["tilt"]
2454*cda5da8dSAndroid Build Coastguard Worker        if "stretchfactor" in p or "tilt" in p or "shearfactor" in p:
2455*cda5da8dSAndroid Build Coastguard Worker            scx, scy = self._stretchfactor
2456*cda5da8dSAndroid Build Coastguard Worker            shf = self._shearfactor
2457*cda5da8dSAndroid Build Coastguard Worker            sa, ca = math.sin(self._tilt), math.cos(self._tilt)
2458*cda5da8dSAndroid Build Coastguard Worker            self._shapetrafo = ( scx*ca, scy*(shf*ca + sa),
2459*cda5da8dSAndroid Build Coastguard Worker                                -scx*sa, scy*(ca - shf*sa))
2460*cda5da8dSAndroid Build Coastguard Worker        self._update()
2461*cda5da8dSAndroid Build Coastguard Worker
2462*cda5da8dSAndroid Build Coastguard Worker## three dummy methods to be implemented by child class:
2463*cda5da8dSAndroid Build Coastguard Worker
2464*cda5da8dSAndroid Build Coastguard Worker    def _newLine(self, usePos = True):
2465*cda5da8dSAndroid Build Coastguard Worker        """dummy method - to be overwritten by child class"""
2466*cda5da8dSAndroid Build Coastguard Worker    def _update(self, count=True, forced=False):
2467*cda5da8dSAndroid Build Coastguard Worker        """dummy method - to be overwritten by child class"""
2468*cda5da8dSAndroid Build Coastguard Worker    def _color(self, args):
2469*cda5da8dSAndroid Build Coastguard Worker        """dummy method - to be overwritten by child class"""
2470*cda5da8dSAndroid Build Coastguard Worker    def _colorstr(self, args):
2471*cda5da8dSAndroid Build Coastguard Worker        """dummy method - to be overwritten by child class"""
2472*cda5da8dSAndroid Build Coastguard Worker
2473*cda5da8dSAndroid Build Coastguard Worker    width = pensize
2474*cda5da8dSAndroid Build Coastguard Worker    up = penup
2475*cda5da8dSAndroid Build Coastguard Worker    pu = penup
2476*cda5da8dSAndroid Build Coastguard Worker    pd = pendown
2477*cda5da8dSAndroid Build Coastguard Worker    down = pendown
2478*cda5da8dSAndroid Build Coastguard Worker    st = showturtle
2479*cda5da8dSAndroid Build Coastguard Worker    ht = hideturtle
2480*cda5da8dSAndroid Build Coastguard Worker
2481*cda5da8dSAndroid Build Coastguard Worker
2482*cda5da8dSAndroid Build Coastguard Workerclass _TurtleImage(object):
2483*cda5da8dSAndroid Build Coastguard Worker    """Helper class: Datatype to store Turtle attributes
2484*cda5da8dSAndroid Build Coastguard Worker    """
2485*cda5da8dSAndroid Build Coastguard Worker
2486*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, screen, shapeIndex):
2487*cda5da8dSAndroid Build Coastguard Worker        self.screen = screen
2488*cda5da8dSAndroid Build Coastguard Worker        self._type = None
2489*cda5da8dSAndroid Build Coastguard Worker        self._setshape(shapeIndex)
2490*cda5da8dSAndroid Build Coastguard Worker
2491*cda5da8dSAndroid Build Coastguard Worker    def _setshape(self, shapeIndex):
2492*cda5da8dSAndroid Build Coastguard Worker        screen = self.screen
2493*cda5da8dSAndroid Build Coastguard Worker        self.shapeIndex = shapeIndex
2494*cda5da8dSAndroid Build Coastguard Worker        if self._type == "polygon" == screen._shapes[shapeIndex]._type:
2495*cda5da8dSAndroid Build Coastguard Worker            return
2496*cda5da8dSAndroid Build Coastguard Worker        if self._type == "image" == screen._shapes[shapeIndex]._type:
2497*cda5da8dSAndroid Build Coastguard Worker            return
2498*cda5da8dSAndroid Build Coastguard Worker        if self._type in ["image", "polygon"]:
2499*cda5da8dSAndroid Build Coastguard Worker            screen._delete(self._item)
2500*cda5da8dSAndroid Build Coastguard Worker        elif self._type == "compound":
2501*cda5da8dSAndroid Build Coastguard Worker            for item in self._item:
2502*cda5da8dSAndroid Build Coastguard Worker                screen._delete(item)
2503*cda5da8dSAndroid Build Coastguard Worker        self._type = screen._shapes[shapeIndex]._type
2504*cda5da8dSAndroid Build Coastguard Worker        if self._type == "polygon":
2505*cda5da8dSAndroid Build Coastguard Worker            self._item = screen._createpoly()
2506*cda5da8dSAndroid Build Coastguard Worker        elif self._type == "image":
2507*cda5da8dSAndroid Build Coastguard Worker            self._item = screen._createimage(screen._shapes["blank"]._data)
2508*cda5da8dSAndroid Build Coastguard Worker        elif self._type == "compound":
2509*cda5da8dSAndroid Build Coastguard Worker            self._item = [screen._createpoly() for item in
2510*cda5da8dSAndroid Build Coastguard Worker                                          screen._shapes[shapeIndex]._data]
2511*cda5da8dSAndroid Build Coastguard Worker
2512*cda5da8dSAndroid Build Coastguard Worker
2513*cda5da8dSAndroid Build Coastguard Workerclass RawTurtle(TPen, TNavigator):
2514*cda5da8dSAndroid Build Coastguard Worker    """Animation part of the RawTurtle.
2515*cda5da8dSAndroid Build Coastguard Worker    Puts RawTurtle upon a TurtleScreen and provides tools for
2516*cda5da8dSAndroid Build Coastguard Worker    its animation.
2517*cda5da8dSAndroid Build Coastguard Worker    """
2518*cda5da8dSAndroid Build Coastguard Worker    screens = []
2519*cda5da8dSAndroid Build Coastguard Worker
2520*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, canvas=None,
2521*cda5da8dSAndroid Build Coastguard Worker                 shape=_CFG["shape"],
2522*cda5da8dSAndroid Build Coastguard Worker                 undobuffersize=_CFG["undobuffersize"],
2523*cda5da8dSAndroid Build Coastguard Worker                 visible=_CFG["visible"]):
2524*cda5da8dSAndroid Build Coastguard Worker        if isinstance(canvas, _Screen):
2525*cda5da8dSAndroid Build Coastguard Worker            self.screen = canvas
2526*cda5da8dSAndroid Build Coastguard Worker        elif isinstance(canvas, TurtleScreen):
2527*cda5da8dSAndroid Build Coastguard Worker            if canvas not in RawTurtle.screens:
2528*cda5da8dSAndroid Build Coastguard Worker                RawTurtle.screens.append(canvas)
2529*cda5da8dSAndroid Build Coastguard Worker            self.screen = canvas
2530*cda5da8dSAndroid Build Coastguard Worker        elif isinstance(canvas, (ScrolledCanvas, Canvas)):
2531*cda5da8dSAndroid Build Coastguard Worker            for screen in RawTurtle.screens:
2532*cda5da8dSAndroid Build Coastguard Worker                if screen.cv == canvas:
2533*cda5da8dSAndroid Build Coastguard Worker                    self.screen = screen
2534*cda5da8dSAndroid Build Coastguard Worker                    break
2535*cda5da8dSAndroid Build Coastguard Worker            else:
2536*cda5da8dSAndroid Build Coastguard Worker                self.screen = TurtleScreen(canvas)
2537*cda5da8dSAndroid Build Coastguard Worker                RawTurtle.screens.append(self.screen)
2538*cda5da8dSAndroid Build Coastguard Worker        else:
2539*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("bad canvas argument %s" % canvas)
2540*cda5da8dSAndroid Build Coastguard Worker
2541*cda5da8dSAndroid Build Coastguard Worker        screen = self.screen
2542*cda5da8dSAndroid Build Coastguard Worker        TNavigator.__init__(self, screen.mode())
2543*cda5da8dSAndroid Build Coastguard Worker        TPen.__init__(self)
2544*cda5da8dSAndroid Build Coastguard Worker        screen._turtles.append(self)
2545*cda5da8dSAndroid Build Coastguard Worker        self.drawingLineItem = screen._createline()
2546*cda5da8dSAndroid Build Coastguard Worker        self.turtle = _TurtleImage(screen, shape)
2547*cda5da8dSAndroid Build Coastguard Worker        self._poly = None
2548*cda5da8dSAndroid Build Coastguard Worker        self._creatingPoly = False
2549*cda5da8dSAndroid Build Coastguard Worker        self._fillitem = self._fillpath = None
2550*cda5da8dSAndroid Build Coastguard Worker        self._shown = visible
2551*cda5da8dSAndroid Build Coastguard Worker        self._hidden_from_screen = False
2552*cda5da8dSAndroid Build Coastguard Worker        self.currentLineItem = screen._createline()
2553*cda5da8dSAndroid Build Coastguard Worker        self.currentLine = [self._position]
2554*cda5da8dSAndroid Build Coastguard Worker        self.items = [self.currentLineItem]
2555*cda5da8dSAndroid Build Coastguard Worker        self.stampItems = []
2556*cda5da8dSAndroid Build Coastguard Worker        self._undobuffersize = undobuffersize
2557*cda5da8dSAndroid Build Coastguard Worker        self.undobuffer = Tbuffer(undobuffersize)
2558*cda5da8dSAndroid Build Coastguard Worker        self._update()
2559*cda5da8dSAndroid Build Coastguard Worker
2560*cda5da8dSAndroid Build Coastguard Worker    def reset(self):
2561*cda5da8dSAndroid Build Coastguard Worker        """Delete the turtle's drawings and restore its default values.
2562*cda5da8dSAndroid Build Coastguard Worker
2563*cda5da8dSAndroid Build Coastguard Worker        No argument.
2564*cda5da8dSAndroid Build Coastguard Worker
2565*cda5da8dSAndroid Build Coastguard Worker        Delete the turtle's drawings from the screen, re-center the turtle
2566*cda5da8dSAndroid Build Coastguard Worker        and set variables to the default values.
2567*cda5da8dSAndroid Build Coastguard Worker
2568*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2569*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.position()
2570*cda5da8dSAndroid Build Coastguard Worker        (0.00,-22.00)
2571*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
2572*cda5da8dSAndroid Build Coastguard Worker        100.0
2573*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.reset()
2574*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.position()
2575*cda5da8dSAndroid Build Coastguard Worker        (0.00,0.00)
2576*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.heading()
2577*cda5da8dSAndroid Build Coastguard Worker        0.0
2578*cda5da8dSAndroid Build Coastguard Worker        """
2579*cda5da8dSAndroid Build Coastguard Worker        TNavigator.reset(self)
2580*cda5da8dSAndroid Build Coastguard Worker        TPen._reset(self)
2581*cda5da8dSAndroid Build Coastguard Worker        self._clear()
2582*cda5da8dSAndroid Build Coastguard Worker        self._drawturtle()
2583*cda5da8dSAndroid Build Coastguard Worker        self._update()
2584*cda5da8dSAndroid Build Coastguard Worker
2585*cda5da8dSAndroid Build Coastguard Worker    def setundobuffer(self, size):
2586*cda5da8dSAndroid Build Coastguard Worker        """Set or disable undobuffer.
2587*cda5da8dSAndroid Build Coastguard Worker
2588*cda5da8dSAndroid Build Coastguard Worker        Argument:
2589*cda5da8dSAndroid Build Coastguard Worker        size -- an integer or None
2590*cda5da8dSAndroid Build Coastguard Worker
2591*cda5da8dSAndroid Build Coastguard Worker        If size is an integer an empty undobuffer of given size is installed.
2592*cda5da8dSAndroid Build Coastguard Worker        Size gives the maximum number of turtle-actions that can be undone
2593*cda5da8dSAndroid Build Coastguard Worker        by the undo() function.
2594*cda5da8dSAndroid Build Coastguard Worker        If size is None, no undobuffer is present.
2595*cda5da8dSAndroid Build Coastguard Worker
2596*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2597*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.setundobuffer(42)
2598*cda5da8dSAndroid Build Coastguard Worker        """
2599*cda5da8dSAndroid Build Coastguard Worker        if size is None or size <= 0:
2600*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer = None
2601*cda5da8dSAndroid Build Coastguard Worker        else:
2602*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer = Tbuffer(size)
2603*cda5da8dSAndroid Build Coastguard Worker
2604*cda5da8dSAndroid Build Coastguard Worker    def undobufferentries(self):
2605*cda5da8dSAndroid Build Coastguard Worker        """Return count of entries in the undobuffer.
2606*cda5da8dSAndroid Build Coastguard Worker
2607*cda5da8dSAndroid Build Coastguard Worker        No argument.
2608*cda5da8dSAndroid Build Coastguard Worker
2609*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2610*cda5da8dSAndroid Build Coastguard Worker        >>> while undobufferentries():
2611*cda5da8dSAndroid Build Coastguard Worker        ...     undo()
2612*cda5da8dSAndroid Build Coastguard Worker        """
2613*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer is None:
2614*cda5da8dSAndroid Build Coastguard Worker            return 0
2615*cda5da8dSAndroid Build Coastguard Worker        return self.undobuffer.nr_of_items()
2616*cda5da8dSAndroid Build Coastguard Worker
2617*cda5da8dSAndroid Build Coastguard Worker    def _clear(self):
2618*cda5da8dSAndroid Build Coastguard Worker        """Delete all of pen's drawings"""
2619*cda5da8dSAndroid Build Coastguard Worker        self._fillitem = self._fillpath = None
2620*cda5da8dSAndroid Build Coastguard Worker        for item in self.items:
2621*cda5da8dSAndroid Build Coastguard Worker            self.screen._delete(item)
2622*cda5da8dSAndroid Build Coastguard Worker        self.currentLineItem = self.screen._createline()
2623*cda5da8dSAndroid Build Coastguard Worker        self.currentLine = []
2624*cda5da8dSAndroid Build Coastguard Worker        if self._drawing:
2625*cda5da8dSAndroid Build Coastguard Worker            self.currentLine.append(self._position)
2626*cda5da8dSAndroid Build Coastguard Worker        self.items = [self.currentLineItem]
2627*cda5da8dSAndroid Build Coastguard Worker        self.clearstamps()
2628*cda5da8dSAndroid Build Coastguard Worker        self.setundobuffer(self._undobuffersize)
2629*cda5da8dSAndroid Build Coastguard Worker
2630*cda5da8dSAndroid Build Coastguard Worker
2631*cda5da8dSAndroid Build Coastguard Worker    def clear(self):
2632*cda5da8dSAndroid Build Coastguard Worker        """Delete the turtle's drawings from the screen. Do not move turtle.
2633*cda5da8dSAndroid Build Coastguard Worker
2634*cda5da8dSAndroid Build Coastguard Worker        No arguments.
2635*cda5da8dSAndroid Build Coastguard Worker
2636*cda5da8dSAndroid Build Coastguard Worker        Delete the turtle's drawings from the screen. Do not move turtle.
2637*cda5da8dSAndroid Build Coastguard Worker        State and position of the turtle as well as drawings of other
2638*cda5da8dSAndroid Build Coastguard Worker        turtles are not affected.
2639*cda5da8dSAndroid Build Coastguard Worker
2640*cda5da8dSAndroid Build Coastguard Worker        Examples (for a Turtle instance named turtle):
2641*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.clear()
2642*cda5da8dSAndroid Build Coastguard Worker        """
2643*cda5da8dSAndroid Build Coastguard Worker        self._clear()
2644*cda5da8dSAndroid Build Coastguard Worker        self._update()
2645*cda5da8dSAndroid Build Coastguard Worker
2646*cda5da8dSAndroid Build Coastguard Worker    def _update_data(self):
2647*cda5da8dSAndroid Build Coastguard Worker        self.screen._incrementudc()
2648*cda5da8dSAndroid Build Coastguard Worker        if self.screen._updatecounter != 0:
2649*cda5da8dSAndroid Build Coastguard Worker            return
2650*cda5da8dSAndroid Build Coastguard Worker        if len(self.currentLine)>1:
2651*cda5da8dSAndroid Build Coastguard Worker            self.screen._drawline(self.currentLineItem, self.currentLine,
2652*cda5da8dSAndroid Build Coastguard Worker                                  self._pencolor, self._pensize)
2653*cda5da8dSAndroid Build Coastguard Worker
2654*cda5da8dSAndroid Build Coastguard Worker    def _update(self):
2655*cda5da8dSAndroid Build Coastguard Worker        """Perform a Turtle-data update.
2656*cda5da8dSAndroid Build Coastguard Worker        """
2657*cda5da8dSAndroid Build Coastguard Worker        screen = self.screen
2658*cda5da8dSAndroid Build Coastguard Worker        if screen._tracing == 0:
2659*cda5da8dSAndroid Build Coastguard Worker            return
2660*cda5da8dSAndroid Build Coastguard Worker        elif screen._tracing == 1:
2661*cda5da8dSAndroid Build Coastguard Worker            self._update_data()
2662*cda5da8dSAndroid Build Coastguard Worker            self._drawturtle()
2663*cda5da8dSAndroid Build Coastguard Worker            screen._update()                  # TurtleScreenBase
2664*cda5da8dSAndroid Build Coastguard Worker            screen._delay(screen._delayvalue) # TurtleScreenBase
2665*cda5da8dSAndroid Build Coastguard Worker        else:
2666*cda5da8dSAndroid Build Coastguard Worker            self._update_data()
2667*cda5da8dSAndroid Build Coastguard Worker            if screen._updatecounter == 0:
2668*cda5da8dSAndroid Build Coastguard Worker                for t in screen.turtles():
2669*cda5da8dSAndroid Build Coastguard Worker                    t._drawturtle()
2670*cda5da8dSAndroid Build Coastguard Worker                screen._update()
2671*cda5da8dSAndroid Build Coastguard Worker
2672*cda5da8dSAndroid Build Coastguard Worker    def _tracer(self, flag=None, delay=None):
2673*cda5da8dSAndroid Build Coastguard Worker        """Turns turtle animation on/off and set delay for update drawings.
2674*cda5da8dSAndroid Build Coastguard Worker
2675*cda5da8dSAndroid Build Coastguard Worker        Optional arguments:
2676*cda5da8dSAndroid Build Coastguard Worker        n -- nonnegative  integer
2677*cda5da8dSAndroid Build Coastguard Worker        delay -- nonnegative  integer
2678*cda5da8dSAndroid Build Coastguard Worker
2679*cda5da8dSAndroid Build Coastguard Worker        If n is given, only each n-th regular screen update is really performed.
2680*cda5da8dSAndroid Build Coastguard Worker        (Can be used to accelerate the drawing of complex graphics.)
2681*cda5da8dSAndroid Build Coastguard Worker        Second arguments sets delay value (see RawTurtle.delay())
2682*cda5da8dSAndroid Build Coastguard Worker
2683*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2684*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.tracer(8, 25)
2685*cda5da8dSAndroid Build Coastguard Worker        >>> dist = 2
2686*cda5da8dSAndroid Build Coastguard Worker        >>> for i in range(200):
2687*cda5da8dSAndroid Build Coastguard Worker        ...     turtle.fd(dist)
2688*cda5da8dSAndroid Build Coastguard Worker        ...     turtle.rt(90)
2689*cda5da8dSAndroid Build Coastguard Worker        ...     dist += 2
2690*cda5da8dSAndroid Build Coastguard Worker        """
2691*cda5da8dSAndroid Build Coastguard Worker        return self.screen.tracer(flag, delay)
2692*cda5da8dSAndroid Build Coastguard Worker
2693*cda5da8dSAndroid Build Coastguard Worker    def _color(self, args):
2694*cda5da8dSAndroid Build Coastguard Worker        return self.screen._color(args)
2695*cda5da8dSAndroid Build Coastguard Worker
2696*cda5da8dSAndroid Build Coastguard Worker    def _colorstr(self, args):
2697*cda5da8dSAndroid Build Coastguard Worker        return self.screen._colorstr(args)
2698*cda5da8dSAndroid Build Coastguard Worker
2699*cda5da8dSAndroid Build Coastguard Worker    def _cc(self, args):
2700*cda5da8dSAndroid Build Coastguard Worker        """Convert colortriples to hexstrings.
2701*cda5da8dSAndroid Build Coastguard Worker        """
2702*cda5da8dSAndroid Build Coastguard Worker        if isinstance(args, str):
2703*cda5da8dSAndroid Build Coastguard Worker            return args
2704*cda5da8dSAndroid Build Coastguard Worker        try:
2705*cda5da8dSAndroid Build Coastguard Worker            r, g, b = args
2706*cda5da8dSAndroid Build Coastguard Worker        except (TypeError, ValueError):
2707*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("bad color arguments: %s" % str(args))
2708*cda5da8dSAndroid Build Coastguard Worker        if self.screen._colormode == 1.0:
2709*cda5da8dSAndroid Build Coastguard Worker            r, g, b = [round(255.0*x) for x in (r, g, b)]
2710*cda5da8dSAndroid Build Coastguard Worker        if not ((0 <= r <= 255) and (0 <= g <= 255) and (0 <= b <= 255)):
2711*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("bad color sequence: %s" % str(args))
2712*cda5da8dSAndroid Build Coastguard Worker        return "#%02x%02x%02x" % (r, g, b)
2713*cda5da8dSAndroid Build Coastguard Worker
2714*cda5da8dSAndroid Build Coastguard Worker    def clone(self):
2715*cda5da8dSAndroid Build Coastguard Worker        """Create and return a clone of the turtle.
2716*cda5da8dSAndroid Build Coastguard Worker
2717*cda5da8dSAndroid Build Coastguard Worker        No argument.
2718*cda5da8dSAndroid Build Coastguard Worker
2719*cda5da8dSAndroid Build Coastguard Worker        Create and return a clone of the turtle with same position, heading
2720*cda5da8dSAndroid Build Coastguard Worker        and turtle properties.
2721*cda5da8dSAndroid Build Coastguard Worker
2722*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named mick):
2723*cda5da8dSAndroid Build Coastguard Worker        mick = Turtle()
2724*cda5da8dSAndroid Build Coastguard Worker        joe = mick.clone()
2725*cda5da8dSAndroid Build Coastguard Worker        """
2726*cda5da8dSAndroid Build Coastguard Worker        screen = self.screen
2727*cda5da8dSAndroid Build Coastguard Worker        self._newLine(self._drawing)
2728*cda5da8dSAndroid Build Coastguard Worker
2729*cda5da8dSAndroid Build Coastguard Worker        turtle = self.turtle
2730*cda5da8dSAndroid Build Coastguard Worker        self.screen = None
2731*cda5da8dSAndroid Build Coastguard Worker        self.turtle = None  # too make self deepcopy-able
2732*cda5da8dSAndroid Build Coastguard Worker
2733*cda5da8dSAndroid Build Coastguard Worker        q = deepcopy(self)
2734*cda5da8dSAndroid Build Coastguard Worker
2735*cda5da8dSAndroid Build Coastguard Worker        self.screen = screen
2736*cda5da8dSAndroid Build Coastguard Worker        self.turtle = turtle
2737*cda5da8dSAndroid Build Coastguard Worker
2738*cda5da8dSAndroid Build Coastguard Worker        q.screen = screen
2739*cda5da8dSAndroid Build Coastguard Worker        q.turtle = _TurtleImage(screen, self.turtle.shapeIndex)
2740*cda5da8dSAndroid Build Coastguard Worker
2741*cda5da8dSAndroid Build Coastguard Worker        screen._turtles.append(q)
2742*cda5da8dSAndroid Build Coastguard Worker        ttype = screen._shapes[self.turtle.shapeIndex]._type
2743*cda5da8dSAndroid Build Coastguard Worker        if ttype == "polygon":
2744*cda5da8dSAndroid Build Coastguard Worker            q.turtle._item = screen._createpoly()
2745*cda5da8dSAndroid Build Coastguard Worker        elif ttype == "image":
2746*cda5da8dSAndroid Build Coastguard Worker            q.turtle._item = screen._createimage(screen._shapes["blank"]._data)
2747*cda5da8dSAndroid Build Coastguard Worker        elif ttype == "compound":
2748*cda5da8dSAndroid Build Coastguard Worker            q.turtle._item = [screen._createpoly() for item in
2749*cda5da8dSAndroid Build Coastguard Worker                              screen._shapes[self.turtle.shapeIndex]._data]
2750*cda5da8dSAndroid Build Coastguard Worker        q.currentLineItem = screen._createline()
2751*cda5da8dSAndroid Build Coastguard Worker        q._update()
2752*cda5da8dSAndroid Build Coastguard Worker        return q
2753*cda5da8dSAndroid Build Coastguard Worker
2754*cda5da8dSAndroid Build Coastguard Worker    def shape(self, name=None):
2755*cda5da8dSAndroid Build Coastguard Worker        """Set turtle shape to shape with given name / return current shapename.
2756*cda5da8dSAndroid Build Coastguard Worker
2757*cda5da8dSAndroid Build Coastguard Worker        Optional argument:
2758*cda5da8dSAndroid Build Coastguard Worker        name -- a string, which is a valid shapename
2759*cda5da8dSAndroid Build Coastguard Worker
2760*cda5da8dSAndroid Build Coastguard Worker        Set turtle shape to shape with given name or, if name is not given,
2761*cda5da8dSAndroid Build Coastguard Worker        return name of current shape.
2762*cda5da8dSAndroid Build Coastguard Worker        Shape with name must exist in the TurtleScreen's shape dictionary.
2763*cda5da8dSAndroid Build Coastguard Worker        Initially there are the following polygon shapes:
2764*cda5da8dSAndroid Build Coastguard Worker        'arrow', 'turtle', 'circle', 'square', 'triangle', 'classic'.
2765*cda5da8dSAndroid Build Coastguard Worker        To learn about how to deal with shapes see Screen-method register_shape.
2766*cda5da8dSAndroid Build Coastguard Worker
2767*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
2768*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shape()
2769*cda5da8dSAndroid Build Coastguard Worker        'arrow'
2770*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shape("turtle")
2771*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shape()
2772*cda5da8dSAndroid Build Coastguard Worker        'turtle'
2773*cda5da8dSAndroid Build Coastguard Worker        """
2774*cda5da8dSAndroid Build Coastguard Worker        if name is None:
2775*cda5da8dSAndroid Build Coastguard Worker            return self.turtle.shapeIndex
2776*cda5da8dSAndroid Build Coastguard Worker        if not name in self.screen.getshapes():
2777*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("There is no shape named %s" % name)
2778*cda5da8dSAndroid Build Coastguard Worker        self.turtle._setshape(name)
2779*cda5da8dSAndroid Build Coastguard Worker        self._update()
2780*cda5da8dSAndroid Build Coastguard Worker
2781*cda5da8dSAndroid Build Coastguard Worker    def shapesize(self, stretch_wid=None, stretch_len=None, outline=None):
2782*cda5da8dSAndroid Build Coastguard Worker        """Set/return turtle's stretchfactors/outline. Set resizemode to "user".
2783*cda5da8dSAndroid Build Coastguard Worker
2784*cda5da8dSAndroid Build Coastguard Worker        Optional arguments:
2785*cda5da8dSAndroid Build Coastguard Worker           stretch_wid : positive number
2786*cda5da8dSAndroid Build Coastguard Worker           stretch_len : positive number
2787*cda5da8dSAndroid Build Coastguard Worker           outline  : positive number
2788*cda5da8dSAndroid Build Coastguard Worker
2789*cda5da8dSAndroid Build Coastguard Worker        Return or set the pen's attributes x/y-stretchfactors and/or outline.
2790*cda5da8dSAndroid Build Coastguard Worker        Set resizemode to "user".
2791*cda5da8dSAndroid Build Coastguard Worker        If and only if resizemode is set to "user", the turtle will be displayed
2792*cda5da8dSAndroid Build Coastguard Worker        stretched according to its stretchfactors:
2793*cda5da8dSAndroid Build Coastguard Worker        stretch_wid is stretchfactor perpendicular to orientation
2794*cda5da8dSAndroid Build Coastguard Worker        stretch_len is stretchfactor in direction of turtles orientation.
2795*cda5da8dSAndroid Build Coastguard Worker        outline determines the width of the shapes's outline.
2796*cda5da8dSAndroid Build Coastguard Worker
2797*cda5da8dSAndroid Build Coastguard Worker        Examples (for a Turtle instance named turtle):
2798*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.resizemode("user")
2799*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shapesize(5, 5, 12)
2800*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shapesize(outline=8)
2801*cda5da8dSAndroid Build Coastguard Worker        """
2802*cda5da8dSAndroid Build Coastguard Worker        if stretch_wid is stretch_len is outline is None:
2803*cda5da8dSAndroid Build Coastguard Worker            stretch_wid, stretch_len = self._stretchfactor
2804*cda5da8dSAndroid Build Coastguard Worker            return stretch_wid, stretch_len, self._outlinewidth
2805*cda5da8dSAndroid Build Coastguard Worker        if stretch_wid == 0 or stretch_len == 0:
2806*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("stretch_wid/stretch_len must not be zero")
2807*cda5da8dSAndroid Build Coastguard Worker        if stretch_wid is not None:
2808*cda5da8dSAndroid Build Coastguard Worker            if stretch_len is None:
2809*cda5da8dSAndroid Build Coastguard Worker                stretchfactor = stretch_wid, stretch_wid
2810*cda5da8dSAndroid Build Coastguard Worker            else:
2811*cda5da8dSAndroid Build Coastguard Worker                stretchfactor = stretch_wid, stretch_len
2812*cda5da8dSAndroid Build Coastguard Worker        elif stretch_len is not None:
2813*cda5da8dSAndroid Build Coastguard Worker            stretchfactor = self._stretchfactor[0], stretch_len
2814*cda5da8dSAndroid Build Coastguard Worker        else:
2815*cda5da8dSAndroid Build Coastguard Worker            stretchfactor = self._stretchfactor
2816*cda5da8dSAndroid Build Coastguard Worker        if outline is None:
2817*cda5da8dSAndroid Build Coastguard Worker            outline = self._outlinewidth
2818*cda5da8dSAndroid Build Coastguard Worker        self.pen(resizemode="user",
2819*cda5da8dSAndroid Build Coastguard Worker                 stretchfactor=stretchfactor, outline=outline)
2820*cda5da8dSAndroid Build Coastguard Worker
2821*cda5da8dSAndroid Build Coastguard Worker    def shearfactor(self, shear=None):
2822*cda5da8dSAndroid Build Coastguard Worker        """Set or return the current shearfactor.
2823*cda5da8dSAndroid Build Coastguard Worker
2824*cda5da8dSAndroid Build Coastguard Worker        Optional argument: shear -- number, tangent of the shear angle
2825*cda5da8dSAndroid Build Coastguard Worker
2826*cda5da8dSAndroid Build Coastguard Worker        Shear the turtleshape according to the given shearfactor shear,
2827*cda5da8dSAndroid Build Coastguard Worker        which is the tangent of the shear angle. DO NOT change the
2828*cda5da8dSAndroid Build Coastguard Worker        turtle's heading (direction of movement).
2829*cda5da8dSAndroid Build Coastguard Worker        If shear is not given: return the current shearfactor, i. e. the
2830*cda5da8dSAndroid Build Coastguard Worker        tangent of the shear angle, by which lines parallel to the
2831*cda5da8dSAndroid Build Coastguard Worker        heading of the turtle are sheared.
2832*cda5da8dSAndroid Build Coastguard Worker
2833*cda5da8dSAndroid Build Coastguard Worker        Examples (for a Turtle instance named turtle):
2834*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shape("circle")
2835*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shapesize(5,2)
2836*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shearfactor(0.5)
2837*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shearfactor()
2838*cda5da8dSAndroid Build Coastguard Worker        >>> 0.5
2839*cda5da8dSAndroid Build Coastguard Worker        """
2840*cda5da8dSAndroid Build Coastguard Worker        if shear is None:
2841*cda5da8dSAndroid Build Coastguard Worker            return self._shearfactor
2842*cda5da8dSAndroid Build Coastguard Worker        self.pen(resizemode="user", shearfactor=shear)
2843*cda5da8dSAndroid Build Coastguard Worker
2844*cda5da8dSAndroid Build Coastguard Worker    def settiltangle(self, angle):
2845*cda5da8dSAndroid Build Coastguard Worker        """Rotate the turtleshape to point in the specified direction
2846*cda5da8dSAndroid Build Coastguard Worker
2847*cda5da8dSAndroid Build Coastguard Worker        Argument: angle -- number
2848*cda5da8dSAndroid Build Coastguard Worker
2849*cda5da8dSAndroid Build Coastguard Worker        Rotate the turtleshape to point in the direction specified by angle,
2850*cda5da8dSAndroid Build Coastguard Worker        regardless of its current tilt-angle. DO NOT change the turtle's
2851*cda5da8dSAndroid Build Coastguard Worker        heading (direction of movement).
2852*cda5da8dSAndroid Build Coastguard Worker
2853*cda5da8dSAndroid Build Coastguard Worker        Deprecated since Python 3.1
2854*cda5da8dSAndroid Build Coastguard Worker
2855*cda5da8dSAndroid Build Coastguard Worker        Examples (for a Turtle instance named turtle):
2856*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shape("circle")
2857*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shapesize(5,2)
2858*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.settiltangle(45)
2859*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.stamp()
2860*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fd(50)
2861*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.settiltangle(-45)
2862*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.stamp()
2863*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fd(50)
2864*cda5da8dSAndroid Build Coastguard Worker        """
2865*cda5da8dSAndroid Build Coastguard Worker        warnings._deprecated("turtle.RawTurtle.settiltangle()",
2866*cda5da8dSAndroid Build Coastguard Worker                             "{name!r} is deprecated since Python 3.1 and scheduled "
2867*cda5da8dSAndroid Build Coastguard Worker                             "for removal in Python {remove}. Use tiltangle() instead.",
2868*cda5da8dSAndroid Build Coastguard Worker                             remove=(3, 13))
2869*cda5da8dSAndroid Build Coastguard Worker        self.tiltangle(angle)
2870*cda5da8dSAndroid Build Coastguard Worker
2871*cda5da8dSAndroid Build Coastguard Worker    def tiltangle(self, angle=None):
2872*cda5da8dSAndroid Build Coastguard Worker        """Set or return the current tilt-angle.
2873*cda5da8dSAndroid Build Coastguard Worker
2874*cda5da8dSAndroid Build Coastguard Worker        Optional argument: angle -- number
2875*cda5da8dSAndroid Build Coastguard Worker
2876*cda5da8dSAndroid Build Coastguard Worker        Rotate the turtleshape to point in the direction specified by angle,
2877*cda5da8dSAndroid Build Coastguard Worker        regardless of its current tilt-angle. DO NOT change the turtle's
2878*cda5da8dSAndroid Build Coastguard Worker        heading (direction of movement).
2879*cda5da8dSAndroid Build Coastguard Worker        If angle is not given: return the current tilt-angle, i. e. the angle
2880*cda5da8dSAndroid Build Coastguard Worker        between the orientation of the turtleshape and the heading of the
2881*cda5da8dSAndroid Build Coastguard Worker        turtle (its direction of movement).
2882*cda5da8dSAndroid Build Coastguard Worker
2883*cda5da8dSAndroid Build Coastguard Worker        (Incorrectly marked as deprecated since Python 3.1, it is really
2884*cda5da8dSAndroid Build Coastguard Worker        settiltangle that is deprecated.)
2885*cda5da8dSAndroid Build Coastguard Worker
2886*cda5da8dSAndroid Build Coastguard Worker        Examples (for a Turtle instance named turtle):
2887*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shape("circle")
2888*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shapesize(5, 2)
2889*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.tiltangle()
2890*cda5da8dSAndroid Build Coastguard Worker        0.0
2891*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.tiltangle(45)
2892*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.tiltangle()
2893*cda5da8dSAndroid Build Coastguard Worker        45.0
2894*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.stamp()
2895*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fd(50)
2896*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.tiltangle(-45)
2897*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.tiltangle()
2898*cda5da8dSAndroid Build Coastguard Worker        315.0
2899*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.stamp()
2900*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fd(50)
2901*cda5da8dSAndroid Build Coastguard Worker        """
2902*cda5da8dSAndroid Build Coastguard Worker        if angle is None:
2903*cda5da8dSAndroid Build Coastguard Worker            tilt = -math.degrees(self._tilt) * self._angleOrient
2904*cda5da8dSAndroid Build Coastguard Worker            return (tilt / self._degreesPerAU) % self._fullcircle
2905*cda5da8dSAndroid Build Coastguard Worker        else:
2906*cda5da8dSAndroid Build Coastguard Worker            tilt = -angle * self._degreesPerAU * self._angleOrient
2907*cda5da8dSAndroid Build Coastguard Worker            tilt = math.radians(tilt) % math.tau
2908*cda5da8dSAndroid Build Coastguard Worker            self.pen(resizemode="user", tilt=tilt)
2909*cda5da8dSAndroid Build Coastguard Worker
2910*cda5da8dSAndroid Build Coastguard Worker    def tilt(self, angle):
2911*cda5da8dSAndroid Build Coastguard Worker        """Rotate the turtleshape by angle.
2912*cda5da8dSAndroid Build Coastguard Worker
2913*cda5da8dSAndroid Build Coastguard Worker        Argument:
2914*cda5da8dSAndroid Build Coastguard Worker        angle - a number
2915*cda5da8dSAndroid Build Coastguard Worker
2916*cda5da8dSAndroid Build Coastguard Worker        Rotate the turtleshape by angle from its current tilt-angle,
2917*cda5da8dSAndroid Build Coastguard Worker        but do NOT change the turtle's heading (direction of movement).
2918*cda5da8dSAndroid Build Coastguard Worker
2919*cda5da8dSAndroid Build Coastguard Worker        Examples (for a Turtle instance named turtle):
2920*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shape("circle")
2921*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shapesize(5,2)
2922*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.tilt(30)
2923*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fd(50)
2924*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.tilt(30)
2925*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fd(50)
2926*cda5da8dSAndroid Build Coastguard Worker        """
2927*cda5da8dSAndroid Build Coastguard Worker        self.tiltangle(angle + self.tiltangle())
2928*cda5da8dSAndroid Build Coastguard Worker
2929*cda5da8dSAndroid Build Coastguard Worker    def shapetransform(self, t11=None, t12=None, t21=None, t22=None):
2930*cda5da8dSAndroid Build Coastguard Worker        """Set or return the current transformation matrix of the turtle shape.
2931*cda5da8dSAndroid Build Coastguard Worker
2932*cda5da8dSAndroid Build Coastguard Worker        Optional arguments: t11, t12, t21, t22 -- numbers.
2933*cda5da8dSAndroid Build Coastguard Worker
2934*cda5da8dSAndroid Build Coastguard Worker        If none of the matrix elements are given, return the transformation
2935*cda5da8dSAndroid Build Coastguard Worker        matrix.
2936*cda5da8dSAndroid Build Coastguard Worker        Otherwise set the given elements and transform the turtleshape
2937*cda5da8dSAndroid Build Coastguard Worker        according to the matrix consisting of first row t11, t12 and
2938*cda5da8dSAndroid Build Coastguard Worker        second row t21, 22.
2939*cda5da8dSAndroid Build Coastguard Worker        Modify stretchfactor, shearfactor and tiltangle according to the
2940*cda5da8dSAndroid Build Coastguard Worker        given matrix.
2941*cda5da8dSAndroid Build Coastguard Worker
2942*cda5da8dSAndroid Build Coastguard Worker        Examples (for a Turtle instance named turtle):
2943*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shape("square")
2944*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shapesize(4,2)
2945*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shearfactor(-0.5)
2946*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shapetransform()
2947*cda5da8dSAndroid Build Coastguard Worker        (4.0, -1.0, -0.0, 2.0)
2948*cda5da8dSAndroid Build Coastguard Worker        """
2949*cda5da8dSAndroid Build Coastguard Worker        if t11 is t12 is t21 is t22 is None:
2950*cda5da8dSAndroid Build Coastguard Worker            return self._shapetrafo
2951*cda5da8dSAndroid Build Coastguard Worker        m11, m12, m21, m22 = self._shapetrafo
2952*cda5da8dSAndroid Build Coastguard Worker        if t11 is not None: m11 = t11
2953*cda5da8dSAndroid Build Coastguard Worker        if t12 is not None: m12 = t12
2954*cda5da8dSAndroid Build Coastguard Worker        if t21 is not None: m21 = t21
2955*cda5da8dSAndroid Build Coastguard Worker        if t22 is not None: m22 = t22
2956*cda5da8dSAndroid Build Coastguard Worker        if t11 * t22 - t12 * t21 == 0:
2957*cda5da8dSAndroid Build Coastguard Worker            raise TurtleGraphicsError("Bad shape transform matrix: must not be singular")
2958*cda5da8dSAndroid Build Coastguard Worker        self._shapetrafo = (m11, m12, m21, m22)
2959*cda5da8dSAndroid Build Coastguard Worker        alfa = math.atan2(-m21, m11) % math.tau
2960*cda5da8dSAndroid Build Coastguard Worker        sa, ca = math.sin(alfa), math.cos(alfa)
2961*cda5da8dSAndroid Build Coastguard Worker        a11, a12, a21, a22 = (ca*m11 - sa*m21, ca*m12 - sa*m22,
2962*cda5da8dSAndroid Build Coastguard Worker                              sa*m11 + ca*m21, sa*m12 + ca*m22)
2963*cda5da8dSAndroid Build Coastguard Worker        self._stretchfactor = a11, a22
2964*cda5da8dSAndroid Build Coastguard Worker        self._shearfactor = a12/a22
2965*cda5da8dSAndroid Build Coastguard Worker        self._tilt = alfa
2966*cda5da8dSAndroid Build Coastguard Worker        self.pen(resizemode="user")
2967*cda5da8dSAndroid Build Coastguard Worker
2968*cda5da8dSAndroid Build Coastguard Worker
2969*cda5da8dSAndroid Build Coastguard Worker    def _polytrafo(self, poly):
2970*cda5da8dSAndroid Build Coastguard Worker        """Computes transformed polygon shapes from a shape
2971*cda5da8dSAndroid Build Coastguard Worker        according to current position and heading.
2972*cda5da8dSAndroid Build Coastguard Worker        """
2973*cda5da8dSAndroid Build Coastguard Worker        screen = self.screen
2974*cda5da8dSAndroid Build Coastguard Worker        p0, p1 = self._position
2975*cda5da8dSAndroid Build Coastguard Worker        e0, e1 = self._orient
2976*cda5da8dSAndroid Build Coastguard Worker        e = Vec2D(e0, e1 * screen.yscale / screen.xscale)
2977*cda5da8dSAndroid Build Coastguard Worker        e0, e1 = (1.0 / abs(e)) * e
2978*cda5da8dSAndroid Build Coastguard Worker        return [(p0+(e1*x+e0*y)/screen.xscale, p1+(-e0*x+e1*y)/screen.yscale)
2979*cda5da8dSAndroid Build Coastguard Worker                                                           for (x, y) in poly]
2980*cda5da8dSAndroid Build Coastguard Worker
2981*cda5da8dSAndroid Build Coastguard Worker    def get_shapepoly(self):
2982*cda5da8dSAndroid Build Coastguard Worker        """Return the current shape polygon as tuple of coordinate pairs.
2983*cda5da8dSAndroid Build Coastguard Worker
2984*cda5da8dSAndroid Build Coastguard Worker        No argument.
2985*cda5da8dSAndroid Build Coastguard Worker
2986*cda5da8dSAndroid Build Coastguard Worker        Examples (for a Turtle instance named turtle):
2987*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shape("square")
2988*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.shapetransform(4, -1, 0, 2)
2989*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.get_shapepoly()
2990*cda5da8dSAndroid Build Coastguard Worker        ((50, -20), (30, 20), (-50, 20), (-30, -20))
2991*cda5da8dSAndroid Build Coastguard Worker
2992*cda5da8dSAndroid Build Coastguard Worker        """
2993*cda5da8dSAndroid Build Coastguard Worker        shape = self.screen._shapes[self.turtle.shapeIndex]
2994*cda5da8dSAndroid Build Coastguard Worker        if shape._type == "polygon":
2995*cda5da8dSAndroid Build Coastguard Worker            return self._getshapepoly(shape._data, shape._type == "compound")
2996*cda5da8dSAndroid Build Coastguard Worker        # else return None
2997*cda5da8dSAndroid Build Coastguard Worker
2998*cda5da8dSAndroid Build Coastguard Worker    def _getshapepoly(self, polygon, compound=False):
2999*cda5da8dSAndroid Build Coastguard Worker        """Calculate transformed shape polygon according to resizemode
3000*cda5da8dSAndroid Build Coastguard Worker        and shapetransform.
3001*cda5da8dSAndroid Build Coastguard Worker        """
3002*cda5da8dSAndroid Build Coastguard Worker        if self._resizemode == "user" or compound:
3003*cda5da8dSAndroid Build Coastguard Worker            t11, t12, t21, t22 = self._shapetrafo
3004*cda5da8dSAndroid Build Coastguard Worker        elif self._resizemode == "auto":
3005*cda5da8dSAndroid Build Coastguard Worker            l = max(1, self._pensize/5.0)
3006*cda5da8dSAndroid Build Coastguard Worker            t11, t12, t21, t22 = l, 0, 0, l
3007*cda5da8dSAndroid Build Coastguard Worker        elif self._resizemode == "noresize":
3008*cda5da8dSAndroid Build Coastguard Worker            return polygon
3009*cda5da8dSAndroid Build Coastguard Worker        return tuple((t11*x + t12*y, t21*x + t22*y) for (x, y) in polygon)
3010*cda5da8dSAndroid Build Coastguard Worker
3011*cda5da8dSAndroid Build Coastguard Worker    def _drawturtle(self):
3012*cda5da8dSAndroid Build Coastguard Worker        """Manages the correct rendering of the turtle with respect to
3013*cda5da8dSAndroid Build Coastguard Worker        its shape, resizemode, stretch and tilt etc."""
3014*cda5da8dSAndroid Build Coastguard Worker        screen = self.screen
3015*cda5da8dSAndroid Build Coastguard Worker        shape = screen._shapes[self.turtle.shapeIndex]
3016*cda5da8dSAndroid Build Coastguard Worker        ttype = shape._type
3017*cda5da8dSAndroid Build Coastguard Worker        titem = self.turtle._item
3018*cda5da8dSAndroid Build Coastguard Worker        if self._shown and screen._updatecounter == 0 and screen._tracing > 0:
3019*cda5da8dSAndroid Build Coastguard Worker            self._hidden_from_screen = False
3020*cda5da8dSAndroid Build Coastguard Worker            tshape = shape._data
3021*cda5da8dSAndroid Build Coastguard Worker            if ttype == "polygon":
3022*cda5da8dSAndroid Build Coastguard Worker                if self._resizemode == "noresize": w = 1
3023*cda5da8dSAndroid Build Coastguard Worker                elif self._resizemode == "auto": w = self._pensize
3024*cda5da8dSAndroid Build Coastguard Worker                else: w =self._outlinewidth
3025*cda5da8dSAndroid Build Coastguard Worker                shape = self._polytrafo(self._getshapepoly(tshape))
3026*cda5da8dSAndroid Build Coastguard Worker                fc, oc = self._fillcolor, self._pencolor
3027*cda5da8dSAndroid Build Coastguard Worker                screen._drawpoly(titem, shape, fill=fc, outline=oc,
3028*cda5da8dSAndroid Build Coastguard Worker                                                      width=w, top=True)
3029*cda5da8dSAndroid Build Coastguard Worker            elif ttype == "image":
3030*cda5da8dSAndroid Build Coastguard Worker                screen._drawimage(titem, self._position, tshape)
3031*cda5da8dSAndroid Build Coastguard Worker            elif ttype == "compound":
3032*cda5da8dSAndroid Build Coastguard Worker                for item, (poly, fc, oc) in zip(titem, tshape):
3033*cda5da8dSAndroid Build Coastguard Worker                    poly = self._polytrafo(self._getshapepoly(poly, True))
3034*cda5da8dSAndroid Build Coastguard Worker                    screen._drawpoly(item, poly, fill=self._cc(fc),
3035*cda5da8dSAndroid Build Coastguard Worker                                     outline=self._cc(oc), width=self._outlinewidth, top=True)
3036*cda5da8dSAndroid Build Coastguard Worker        else:
3037*cda5da8dSAndroid Build Coastguard Worker            if self._hidden_from_screen:
3038*cda5da8dSAndroid Build Coastguard Worker                return
3039*cda5da8dSAndroid Build Coastguard Worker            if ttype == "polygon":
3040*cda5da8dSAndroid Build Coastguard Worker                screen._drawpoly(titem, ((0, 0), (0, 0), (0, 0)), "", "")
3041*cda5da8dSAndroid Build Coastguard Worker            elif ttype == "image":
3042*cda5da8dSAndroid Build Coastguard Worker                screen._drawimage(titem, self._position,
3043*cda5da8dSAndroid Build Coastguard Worker                                          screen._shapes["blank"]._data)
3044*cda5da8dSAndroid Build Coastguard Worker            elif ttype == "compound":
3045*cda5da8dSAndroid Build Coastguard Worker                for item in titem:
3046*cda5da8dSAndroid Build Coastguard Worker                    screen._drawpoly(item, ((0, 0), (0, 0), (0, 0)), "", "")
3047*cda5da8dSAndroid Build Coastguard Worker            self._hidden_from_screen = True
3048*cda5da8dSAndroid Build Coastguard Worker
3049*cda5da8dSAndroid Build Coastguard Worker##############################  stamp stuff  ###############################
3050*cda5da8dSAndroid Build Coastguard Worker
3051*cda5da8dSAndroid Build Coastguard Worker    def stamp(self):
3052*cda5da8dSAndroid Build Coastguard Worker        """Stamp a copy of the turtleshape onto the canvas and return its id.
3053*cda5da8dSAndroid Build Coastguard Worker
3054*cda5da8dSAndroid Build Coastguard Worker        No argument.
3055*cda5da8dSAndroid Build Coastguard Worker
3056*cda5da8dSAndroid Build Coastguard Worker        Stamp a copy of the turtle shape onto the canvas at the current
3057*cda5da8dSAndroid Build Coastguard Worker        turtle position. Return a stamp_id for that stamp, which can be
3058*cda5da8dSAndroid Build Coastguard Worker        used to delete it by calling clearstamp(stamp_id).
3059*cda5da8dSAndroid Build Coastguard Worker
3060*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3061*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.color("blue")
3062*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.stamp()
3063*cda5da8dSAndroid Build Coastguard Worker        13
3064*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fd(50)
3065*cda5da8dSAndroid Build Coastguard Worker        """
3066*cda5da8dSAndroid Build Coastguard Worker        screen = self.screen
3067*cda5da8dSAndroid Build Coastguard Worker        shape = screen._shapes[self.turtle.shapeIndex]
3068*cda5da8dSAndroid Build Coastguard Worker        ttype = shape._type
3069*cda5da8dSAndroid Build Coastguard Worker        tshape = shape._data
3070*cda5da8dSAndroid Build Coastguard Worker        if ttype == "polygon":
3071*cda5da8dSAndroid Build Coastguard Worker            stitem = screen._createpoly()
3072*cda5da8dSAndroid Build Coastguard Worker            if self._resizemode == "noresize": w = 1
3073*cda5da8dSAndroid Build Coastguard Worker            elif self._resizemode == "auto": w = self._pensize
3074*cda5da8dSAndroid Build Coastguard Worker            else: w =self._outlinewidth
3075*cda5da8dSAndroid Build Coastguard Worker            shape = self._polytrafo(self._getshapepoly(tshape))
3076*cda5da8dSAndroid Build Coastguard Worker            fc, oc = self._fillcolor, self._pencolor
3077*cda5da8dSAndroid Build Coastguard Worker            screen._drawpoly(stitem, shape, fill=fc, outline=oc,
3078*cda5da8dSAndroid Build Coastguard Worker                                                  width=w, top=True)
3079*cda5da8dSAndroid Build Coastguard Worker        elif ttype == "image":
3080*cda5da8dSAndroid Build Coastguard Worker            stitem = screen._createimage("")
3081*cda5da8dSAndroid Build Coastguard Worker            screen._drawimage(stitem, self._position, tshape)
3082*cda5da8dSAndroid Build Coastguard Worker        elif ttype == "compound":
3083*cda5da8dSAndroid Build Coastguard Worker            stitem = []
3084*cda5da8dSAndroid Build Coastguard Worker            for element in tshape:
3085*cda5da8dSAndroid Build Coastguard Worker                item = screen._createpoly()
3086*cda5da8dSAndroid Build Coastguard Worker                stitem.append(item)
3087*cda5da8dSAndroid Build Coastguard Worker            stitem = tuple(stitem)
3088*cda5da8dSAndroid Build Coastguard Worker            for item, (poly, fc, oc) in zip(stitem, tshape):
3089*cda5da8dSAndroid Build Coastguard Worker                poly = self._polytrafo(self._getshapepoly(poly, True))
3090*cda5da8dSAndroid Build Coastguard Worker                screen._drawpoly(item, poly, fill=self._cc(fc),
3091*cda5da8dSAndroid Build Coastguard Worker                                 outline=self._cc(oc), width=self._outlinewidth, top=True)
3092*cda5da8dSAndroid Build Coastguard Worker        self.stampItems.append(stitem)
3093*cda5da8dSAndroid Build Coastguard Worker        self.undobuffer.push(("stamp", stitem))
3094*cda5da8dSAndroid Build Coastguard Worker        return stitem
3095*cda5da8dSAndroid Build Coastguard Worker
3096*cda5da8dSAndroid Build Coastguard Worker    def _clearstamp(self, stampid):
3097*cda5da8dSAndroid Build Coastguard Worker        """does the work for clearstamp() and clearstamps()
3098*cda5da8dSAndroid Build Coastguard Worker        """
3099*cda5da8dSAndroid Build Coastguard Worker        if stampid in self.stampItems:
3100*cda5da8dSAndroid Build Coastguard Worker            if isinstance(stampid, tuple):
3101*cda5da8dSAndroid Build Coastguard Worker                for subitem in stampid:
3102*cda5da8dSAndroid Build Coastguard Worker                    self.screen._delete(subitem)
3103*cda5da8dSAndroid Build Coastguard Worker            else:
3104*cda5da8dSAndroid Build Coastguard Worker                self.screen._delete(stampid)
3105*cda5da8dSAndroid Build Coastguard Worker            self.stampItems.remove(stampid)
3106*cda5da8dSAndroid Build Coastguard Worker        # Delete stampitem from undobuffer if necessary
3107*cda5da8dSAndroid Build Coastguard Worker        # if clearstamp is called directly.
3108*cda5da8dSAndroid Build Coastguard Worker        item = ("stamp", stampid)
3109*cda5da8dSAndroid Build Coastguard Worker        buf = self.undobuffer
3110*cda5da8dSAndroid Build Coastguard Worker        if item not in buf.buffer:
3111*cda5da8dSAndroid Build Coastguard Worker            return
3112*cda5da8dSAndroid Build Coastguard Worker        index = buf.buffer.index(item)
3113*cda5da8dSAndroid Build Coastguard Worker        buf.buffer.remove(item)
3114*cda5da8dSAndroid Build Coastguard Worker        if index <= buf.ptr:
3115*cda5da8dSAndroid Build Coastguard Worker            buf.ptr = (buf.ptr - 1) % buf.bufsize
3116*cda5da8dSAndroid Build Coastguard Worker        buf.buffer.insert((buf.ptr+1)%buf.bufsize, [None])
3117*cda5da8dSAndroid Build Coastguard Worker
3118*cda5da8dSAndroid Build Coastguard Worker    def clearstamp(self, stampid):
3119*cda5da8dSAndroid Build Coastguard Worker        """Delete stamp with given stampid
3120*cda5da8dSAndroid Build Coastguard Worker
3121*cda5da8dSAndroid Build Coastguard Worker        Argument:
3122*cda5da8dSAndroid Build Coastguard Worker        stampid - an integer, must be return value of previous stamp() call.
3123*cda5da8dSAndroid Build Coastguard Worker
3124*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3125*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.color("blue")
3126*cda5da8dSAndroid Build Coastguard Worker        >>> astamp = turtle.stamp()
3127*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fd(50)
3128*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.clearstamp(astamp)
3129*cda5da8dSAndroid Build Coastguard Worker        """
3130*cda5da8dSAndroid Build Coastguard Worker        self._clearstamp(stampid)
3131*cda5da8dSAndroid Build Coastguard Worker        self._update()
3132*cda5da8dSAndroid Build Coastguard Worker
3133*cda5da8dSAndroid Build Coastguard Worker    def clearstamps(self, n=None):
3134*cda5da8dSAndroid Build Coastguard Worker        """Delete all or first/last n of turtle's stamps.
3135*cda5da8dSAndroid Build Coastguard Worker
3136*cda5da8dSAndroid Build Coastguard Worker        Optional argument:
3137*cda5da8dSAndroid Build Coastguard Worker        n -- an integer
3138*cda5da8dSAndroid Build Coastguard Worker
3139*cda5da8dSAndroid Build Coastguard Worker        If n is None, delete all of pen's stamps,
3140*cda5da8dSAndroid Build Coastguard Worker        else if n > 0 delete first n stamps
3141*cda5da8dSAndroid Build Coastguard Worker        else if n < 0 delete last n stamps.
3142*cda5da8dSAndroid Build Coastguard Worker
3143*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3144*cda5da8dSAndroid Build Coastguard Worker        >>> for i in range(8):
3145*cda5da8dSAndroid Build Coastguard Worker        ...     turtle.stamp(); turtle.fd(30)
3146*cda5da8dSAndroid Build Coastguard Worker        ...
3147*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.clearstamps(2)
3148*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.clearstamps(-2)
3149*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.clearstamps()
3150*cda5da8dSAndroid Build Coastguard Worker        """
3151*cda5da8dSAndroid Build Coastguard Worker        if n is None:
3152*cda5da8dSAndroid Build Coastguard Worker            toDelete = self.stampItems[:]
3153*cda5da8dSAndroid Build Coastguard Worker        elif n >= 0:
3154*cda5da8dSAndroid Build Coastguard Worker            toDelete = self.stampItems[:n]
3155*cda5da8dSAndroid Build Coastguard Worker        else:
3156*cda5da8dSAndroid Build Coastguard Worker            toDelete = self.stampItems[n:]
3157*cda5da8dSAndroid Build Coastguard Worker        for item in toDelete:
3158*cda5da8dSAndroid Build Coastguard Worker            self._clearstamp(item)
3159*cda5da8dSAndroid Build Coastguard Worker        self._update()
3160*cda5da8dSAndroid Build Coastguard Worker
3161*cda5da8dSAndroid Build Coastguard Worker    def _goto(self, end):
3162*cda5da8dSAndroid Build Coastguard Worker        """Move the pen to the point end, thereby drawing a line
3163*cda5da8dSAndroid Build Coastguard Worker        if pen is down. All other methods for turtle movement depend
3164*cda5da8dSAndroid Build Coastguard Worker        on this one.
3165*cda5da8dSAndroid Build Coastguard Worker        """
3166*cda5da8dSAndroid Build Coastguard Worker        ## Version with undo-stuff
3167*cda5da8dSAndroid Build Coastguard Worker        go_modes = ( self._drawing,
3168*cda5da8dSAndroid Build Coastguard Worker                     self._pencolor,
3169*cda5da8dSAndroid Build Coastguard Worker                     self._pensize,
3170*cda5da8dSAndroid Build Coastguard Worker                     isinstance(self._fillpath, list))
3171*cda5da8dSAndroid Build Coastguard Worker        screen = self.screen
3172*cda5da8dSAndroid Build Coastguard Worker        undo_entry = ("go", self._position, end, go_modes,
3173*cda5da8dSAndroid Build Coastguard Worker                      (self.currentLineItem,
3174*cda5da8dSAndroid Build Coastguard Worker                      self.currentLine[:],
3175*cda5da8dSAndroid Build Coastguard Worker                      screen._pointlist(self.currentLineItem),
3176*cda5da8dSAndroid Build Coastguard Worker                      self.items[:])
3177*cda5da8dSAndroid Build Coastguard Worker                      )
3178*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer:
3179*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.push(undo_entry)
3180*cda5da8dSAndroid Build Coastguard Worker        start = self._position
3181*cda5da8dSAndroid Build Coastguard Worker        if self._speed and screen._tracing == 1:
3182*cda5da8dSAndroid Build Coastguard Worker            diff = (end-start)
3183*cda5da8dSAndroid Build Coastguard Worker            diffsq = (diff[0]*screen.xscale)**2 + (diff[1]*screen.yscale)**2
3184*cda5da8dSAndroid Build Coastguard Worker            nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed))
3185*cda5da8dSAndroid Build Coastguard Worker            delta = diff * (1.0/nhops)
3186*cda5da8dSAndroid Build Coastguard Worker            for n in range(1, nhops):
3187*cda5da8dSAndroid Build Coastguard Worker                if n == 1:
3188*cda5da8dSAndroid Build Coastguard Worker                    top = True
3189*cda5da8dSAndroid Build Coastguard Worker                else:
3190*cda5da8dSAndroid Build Coastguard Worker                    top = False
3191*cda5da8dSAndroid Build Coastguard Worker                self._position = start + delta * n
3192*cda5da8dSAndroid Build Coastguard Worker                if self._drawing:
3193*cda5da8dSAndroid Build Coastguard Worker                    screen._drawline(self.drawingLineItem,
3194*cda5da8dSAndroid Build Coastguard Worker                                     (start, self._position),
3195*cda5da8dSAndroid Build Coastguard Worker                                     self._pencolor, self._pensize, top)
3196*cda5da8dSAndroid Build Coastguard Worker                self._update()
3197*cda5da8dSAndroid Build Coastguard Worker            if self._drawing:
3198*cda5da8dSAndroid Build Coastguard Worker                screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)),
3199*cda5da8dSAndroid Build Coastguard Worker                                               fill="", width=self._pensize)
3200*cda5da8dSAndroid Build Coastguard Worker        # Turtle now at end,
3201*cda5da8dSAndroid Build Coastguard Worker        if self._drawing: # now update currentLine
3202*cda5da8dSAndroid Build Coastguard Worker            self.currentLine.append(end)
3203*cda5da8dSAndroid Build Coastguard Worker        if isinstance(self._fillpath, list):
3204*cda5da8dSAndroid Build Coastguard Worker            self._fillpath.append(end)
3205*cda5da8dSAndroid Build Coastguard Worker        ######    vererbung!!!!!!!!!!!!!!!!!!!!!!
3206*cda5da8dSAndroid Build Coastguard Worker        self._position = end
3207*cda5da8dSAndroid Build Coastguard Worker        if self._creatingPoly:
3208*cda5da8dSAndroid Build Coastguard Worker            self._poly.append(end)
3209*cda5da8dSAndroid Build Coastguard Worker        if len(self.currentLine) > 42: # 42! answer to the ultimate question
3210*cda5da8dSAndroid Build Coastguard Worker                                       # of life, the universe and everything
3211*cda5da8dSAndroid Build Coastguard Worker            self._newLine()
3212*cda5da8dSAndroid Build Coastguard Worker        self._update() #count=True)
3213*cda5da8dSAndroid Build Coastguard Worker
3214*cda5da8dSAndroid Build Coastguard Worker    def _undogoto(self, entry):
3215*cda5da8dSAndroid Build Coastguard Worker        """Reverse a _goto. Used for undo()
3216*cda5da8dSAndroid Build Coastguard Worker        """
3217*cda5da8dSAndroid Build Coastguard Worker        old, new, go_modes, coodata = entry
3218*cda5da8dSAndroid Build Coastguard Worker        drawing, pc, ps, filling = go_modes
3219*cda5da8dSAndroid Build Coastguard Worker        cLI, cL, pl, items = coodata
3220*cda5da8dSAndroid Build Coastguard Worker        screen = self.screen
3221*cda5da8dSAndroid Build Coastguard Worker        if abs(self._position - new) > 0.5:
3222*cda5da8dSAndroid Build Coastguard Worker            print ("undogoto: HALLO-DA-STIMMT-WAS-NICHT!")
3223*cda5da8dSAndroid Build Coastguard Worker        # restore former situation
3224*cda5da8dSAndroid Build Coastguard Worker        self.currentLineItem = cLI
3225*cda5da8dSAndroid Build Coastguard Worker        self.currentLine = cL
3226*cda5da8dSAndroid Build Coastguard Worker
3227*cda5da8dSAndroid Build Coastguard Worker        if pl == [(0, 0), (0, 0)]:
3228*cda5da8dSAndroid Build Coastguard Worker            usepc = ""
3229*cda5da8dSAndroid Build Coastguard Worker        else:
3230*cda5da8dSAndroid Build Coastguard Worker            usepc = pc
3231*cda5da8dSAndroid Build Coastguard Worker        screen._drawline(cLI, pl, fill=usepc, width=ps)
3232*cda5da8dSAndroid Build Coastguard Worker
3233*cda5da8dSAndroid Build Coastguard Worker        todelete = [i for i in self.items if (i not in items) and
3234*cda5da8dSAndroid Build Coastguard Worker                                       (screen._type(i) == "line")]
3235*cda5da8dSAndroid Build Coastguard Worker        for i in todelete:
3236*cda5da8dSAndroid Build Coastguard Worker            screen._delete(i)
3237*cda5da8dSAndroid Build Coastguard Worker            self.items.remove(i)
3238*cda5da8dSAndroid Build Coastguard Worker
3239*cda5da8dSAndroid Build Coastguard Worker        start = old
3240*cda5da8dSAndroid Build Coastguard Worker        if self._speed and screen._tracing == 1:
3241*cda5da8dSAndroid Build Coastguard Worker            diff = old - new
3242*cda5da8dSAndroid Build Coastguard Worker            diffsq = (diff[0]*screen.xscale)**2 + (diff[1]*screen.yscale)**2
3243*cda5da8dSAndroid Build Coastguard Worker            nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed))
3244*cda5da8dSAndroid Build Coastguard Worker            delta = diff * (1.0/nhops)
3245*cda5da8dSAndroid Build Coastguard Worker            for n in range(1, nhops):
3246*cda5da8dSAndroid Build Coastguard Worker                if n == 1:
3247*cda5da8dSAndroid Build Coastguard Worker                    top = True
3248*cda5da8dSAndroid Build Coastguard Worker                else:
3249*cda5da8dSAndroid Build Coastguard Worker                    top = False
3250*cda5da8dSAndroid Build Coastguard Worker                self._position = new + delta * n
3251*cda5da8dSAndroid Build Coastguard Worker                if drawing:
3252*cda5da8dSAndroid Build Coastguard Worker                    screen._drawline(self.drawingLineItem,
3253*cda5da8dSAndroid Build Coastguard Worker                                     (start, self._position),
3254*cda5da8dSAndroid Build Coastguard Worker                                     pc, ps, top)
3255*cda5da8dSAndroid Build Coastguard Worker                self._update()
3256*cda5da8dSAndroid Build Coastguard Worker            if drawing:
3257*cda5da8dSAndroid Build Coastguard Worker                screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)),
3258*cda5da8dSAndroid Build Coastguard Worker                                               fill="", width=ps)
3259*cda5da8dSAndroid Build Coastguard Worker        # Turtle now at position old,
3260*cda5da8dSAndroid Build Coastguard Worker        self._position = old
3261*cda5da8dSAndroid Build Coastguard Worker        ##  if undo is done during creating a polygon, the last vertex
3262*cda5da8dSAndroid Build Coastguard Worker        ##  will be deleted. if the polygon is entirely deleted,
3263*cda5da8dSAndroid Build Coastguard Worker        ##  creatingPoly will be set to False.
3264*cda5da8dSAndroid Build Coastguard Worker        ##  Polygons created before the last one will not be affected by undo()
3265*cda5da8dSAndroid Build Coastguard Worker        if self._creatingPoly:
3266*cda5da8dSAndroid Build Coastguard Worker            if len(self._poly) > 0:
3267*cda5da8dSAndroid Build Coastguard Worker                self._poly.pop()
3268*cda5da8dSAndroid Build Coastguard Worker            if self._poly == []:
3269*cda5da8dSAndroid Build Coastguard Worker                self._creatingPoly = False
3270*cda5da8dSAndroid Build Coastguard Worker                self._poly = None
3271*cda5da8dSAndroid Build Coastguard Worker        if filling:
3272*cda5da8dSAndroid Build Coastguard Worker            if self._fillpath == []:
3273*cda5da8dSAndroid Build Coastguard Worker                self._fillpath = None
3274*cda5da8dSAndroid Build Coastguard Worker                print("Unwahrscheinlich in _undogoto!")
3275*cda5da8dSAndroid Build Coastguard Worker            elif self._fillpath is not None:
3276*cda5da8dSAndroid Build Coastguard Worker                self._fillpath.pop()
3277*cda5da8dSAndroid Build Coastguard Worker        self._update() #count=True)
3278*cda5da8dSAndroid Build Coastguard Worker
3279*cda5da8dSAndroid Build Coastguard Worker    def _rotate(self, angle):
3280*cda5da8dSAndroid Build Coastguard Worker        """Turns pen clockwise by angle.
3281*cda5da8dSAndroid Build Coastguard Worker        """
3282*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer:
3283*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.push(("rot", angle, self._degreesPerAU))
3284*cda5da8dSAndroid Build Coastguard Worker        angle *= self._degreesPerAU
3285*cda5da8dSAndroid Build Coastguard Worker        neworient = self._orient.rotate(angle)
3286*cda5da8dSAndroid Build Coastguard Worker        tracing = self.screen._tracing
3287*cda5da8dSAndroid Build Coastguard Worker        if tracing == 1 and self._speed > 0:
3288*cda5da8dSAndroid Build Coastguard Worker            anglevel = 3.0 * self._speed
3289*cda5da8dSAndroid Build Coastguard Worker            steps = 1 + int(abs(angle)/anglevel)
3290*cda5da8dSAndroid Build Coastguard Worker            delta = 1.0*angle/steps
3291*cda5da8dSAndroid Build Coastguard Worker            for _ in range(steps):
3292*cda5da8dSAndroid Build Coastguard Worker                self._orient = self._orient.rotate(delta)
3293*cda5da8dSAndroid Build Coastguard Worker                self._update()
3294*cda5da8dSAndroid Build Coastguard Worker        self._orient = neworient
3295*cda5da8dSAndroid Build Coastguard Worker        self._update()
3296*cda5da8dSAndroid Build Coastguard Worker
3297*cda5da8dSAndroid Build Coastguard Worker    def _newLine(self, usePos=True):
3298*cda5da8dSAndroid Build Coastguard Worker        """Closes current line item and starts a new one.
3299*cda5da8dSAndroid Build Coastguard Worker           Remark: if current line became too long, animation
3300*cda5da8dSAndroid Build Coastguard Worker           performance (via _drawline) slowed down considerably.
3301*cda5da8dSAndroid Build Coastguard Worker        """
3302*cda5da8dSAndroid Build Coastguard Worker        if len(self.currentLine) > 1:
3303*cda5da8dSAndroid Build Coastguard Worker            self.screen._drawline(self.currentLineItem, self.currentLine,
3304*cda5da8dSAndroid Build Coastguard Worker                                      self._pencolor, self._pensize)
3305*cda5da8dSAndroid Build Coastguard Worker            self.currentLineItem = self.screen._createline()
3306*cda5da8dSAndroid Build Coastguard Worker            self.items.append(self.currentLineItem)
3307*cda5da8dSAndroid Build Coastguard Worker        else:
3308*cda5da8dSAndroid Build Coastguard Worker            self.screen._drawline(self.currentLineItem, top=True)
3309*cda5da8dSAndroid Build Coastguard Worker        self.currentLine = []
3310*cda5da8dSAndroid Build Coastguard Worker        if usePos:
3311*cda5da8dSAndroid Build Coastguard Worker            self.currentLine = [self._position]
3312*cda5da8dSAndroid Build Coastguard Worker
3313*cda5da8dSAndroid Build Coastguard Worker    def filling(self):
3314*cda5da8dSAndroid Build Coastguard Worker        """Return fillstate (True if filling, False else).
3315*cda5da8dSAndroid Build Coastguard Worker
3316*cda5da8dSAndroid Build Coastguard Worker        No argument.
3317*cda5da8dSAndroid Build Coastguard Worker
3318*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3319*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.begin_fill()
3320*cda5da8dSAndroid Build Coastguard Worker        >>> if turtle.filling():
3321*cda5da8dSAndroid Build Coastguard Worker        ...     turtle.pensize(5)
3322*cda5da8dSAndroid Build Coastguard Worker        ... else:
3323*cda5da8dSAndroid Build Coastguard Worker        ...     turtle.pensize(3)
3324*cda5da8dSAndroid Build Coastguard Worker        """
3325*cda5da8dSAndroid Build Coastguard Worker        return isinstance(self._fillpath, list)
3326*cda5da8dSAndroid Build Coastguard Worker
3327*cda5da8dSAndroid Build Coastguard Worker    def begin_fill(self):
3328*cda5da8dSAndroid Build Coastguard Worker        """Called just before drawing a shape to be filled.
3329*cda5da8dSAndroid Build Coastguard Worker
3330*cda5da8dSAndroid Build Coastguard Worker        No argument.
3331*cda5da8dSAndroid Build Coastguard Worker
3332*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3333*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.color("black", "red")
3334*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.begin_fill()
3335*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.circle(60)
3336*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.end_fill()
3337*cda5da8dSAndroid Build Coastguard Worker        """
3338*cda5da8dSAndroid Build Coastguard Worker        if not self.filling():
3339*cda5da8dSAndroid Build Coastguard Worker            self._fillitem = self.screen._createpoly()
3340*cda5da8dSAndroid Build Coastguard Worker            self.items.append(self._fillitem)
3341*cda5da8dSAndroid Build Coastguard Worker        self._fillpath = [self._position]
3342*cda5da8dSAndroid Build Coastguard Worker        self._newLine()
3343*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer:
3344*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.push(("beginfill", self._fillitem))
3345*cda5da8dSAndroid Build Coastguard Worker        self._update()
3346*cda5da8dSAndroid Build Coastguard Worker
3347*cda5da8dSAndroid Build Coastguard Worker
3348*cda5da8dSAndroid Build Coastguard Worker    def end_fill(self):
3349*cda5da8dSAndroid Build Coastguard Worker        """Fill the shape drawn after the call begin_fill().
3350*cda5da8dSAndroid Build Coastguard Worker
3351*cda5da8dSAndroid Build Coastguard Worker        No argument.
3352*cda5da8dSAndroid Build Coastguard Worker
3353*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3354*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.color("black", "red")
3355*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.begin_fill()
3356*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.circle(60)
3357*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.end_fill()
3358*cda5da8dSAndroid Build Coastguard Worker        """
3359*cda5da8dSAndroid Build Coastguard Worker        if self.filling():
3360*cda5da8dSAndroid Build Coastguard Worker            if len(self._fillpath) > 2:
3361*cda5da8dSAndroid Build Coastguard Worker                self.screen._drawpoly(self._fillitem, self._fillpath,
3362*cda5da8dSAndroid Build Coastguard Worker                                      fill=self._fillcolor)
3363*cda5da8dSAndroid Build Coastguard Worker                if self.undobuffer:
3364*cda5da8dSAndroid Build Coastguard Worker                    self.undobuffer.push(("dofill", self._fillitem))
3365*cda5da8dSAndroid Build Coastguard Worker            self._fillitem = self._fillpath = None
3366*cda5da8dSAndroid Build Coastguard Worker            self._update()
3367*cda5da8dSAndroid Build Coastguard Worker
3368*cda5da8dSAndroid Build Coastguard Worker    def dot(self, size=None, *color):
3369*cda5da8dSAndroid Build Coastguard Worker        """Draw a dot with diameter size, using color.
3370*cda5da8dSAndroid Build Coastguard Worker
3371*cda5da8dSAndroid Build Coastguard Worker        Optional arguments:
3372*cda5da8dSAndroid Build Coastguard Worker        size -- an integer >= 1 (if given)
3373*cda5da8dSAndroid Build Coastguard Worker        color -- a colorstring or a numeric color tuple
3374*cda5da8dSAndroid Build Coastguard Worker
3375*cda5da8dSAndroid Build Coastguard Worker        Draw a circular dot with diameter size, using color.
3376*cda5da8dSAndroid Build Coastguard Worker        If size is not given, the maximum of pensize+4 and 2*pensize is used.
3377*cda5da8dSAndroid Build Coastguard Worker
3378*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3379*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.dot()
3380*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.fd(50); turtle.dot(20, "blue"); turtle.fd(50)
3381*cda5da8dSAndroid Build Coastguard Worker        """
3382*cda5da8dSAndroid Build Coastguard Worker        if not color:
3383*cda5da8dSAndroid Build Coastguard Worker            if isinstance(size, (str, tuple)):
3384*cda5da8dSAndroid Build Coastguard Worker                color = self._colorstr(size)
3385*cda5da8dSAndroid Build Coastguard Worker                size = self._pensize + max(self._pensize, 4)
3386*cda5da8dSAndroid Build Coastguard Worker            else:
3387*cda5da8dSAndroid Build Coastguard Worker                color = self._pencolor
3388*cda5da8dSAndroid Build Coastguard Worker                if not size:
3389*cda5da8dSAndroid Build Coastguard Worker                    size = self._pensize + max(self._pensize, 4)
3390*cda5da8dSAndroid Build Coastguard Worker        else:
3391*cda5da8dSAndroid Build Coastguard Worker            if size is None:
3392*cda5da8dSAndroid Build Coastguard Worker                size = self._pensize + max(self._pensize, 4)
3393*cda5da8dSAndroid Build Coastguard Worker            color = self._colorstr(color)
3394*cda5da8dSAndroid Build Coastguard Worker        if hasattr(self.screen, "_dot"):
3395*cda5da8dSAndroid Build Coastguard Worker            item = self.screen._dot(self._position, size, color)
3396*cda5da8dSAndroid Build Coastguard Worker            self.items.append(item)
3397*cda5da8dSAndroid Build Coastguard Worker            if self.undobuffer:
3398*cda5da8dSAndroid Build Coastguard Worker                self.undobuffer.push(("dot", item))
3399*cda5da8dSAndroid Build Coastguard Worker        else:
3400*cda5da8dSAndroid Build Coastguard Worker            pen = self.pen()
3401*cda5da8dSAndroid Build Coastguard Worker            if self.undobuffer:
3402*cda5da8dSAndroid Build Coastguard Worker                self.undobuffer.push(["seq"])
3403*cda5da8dSAndroid Build Coastguard Worker                self.undobuffer.cumulate = True
3404*cda5da8dSAndroid Build Coastguard Worker            try:
3405*cda5da8dSAndroid Build Coastguard Worker                if self.resizemode() == 'auto':
3406*cda5da8dSAndroid Build Coastguard Worker                    self.ht()
3407*cda5da8dSAndroid Build Coastguard Worker                self.pendown()
3408*cda5da8dSAndroid Build Coastguard Worker                self.pensize(size)
3409*cda5da8dSAndroid Build Coastguard Worker                self.pencolor(color)
3410*cda5da8dSAndroid Build Coastguard Worker                self.forward(0)
3411*cda5da8dSAndroid Build Coastguard Worker            finally:
3412*cda5da8dSAndroid Build Coastguard Worker                self.pen(pen)
3413*cda5da8dSAndroid Build Coastguard Worker            if self.undobuffer:
3414*cda5da8dSAndroid Build Coastguard Worker                self.undobuffer.cumulate = False
3415*cda5da8dSAndroid Build Coastguard Worker
3416*cda5da8dSAndroid Build Coastguard Worker    def _write(self, txt, align, font):
3417*cda5da8dSAndroid Build Coastguard Worker        """Performs the writing for write()
3418*cda5da8dSAndroid Build Coastguard Worker        """
3419*cda5da8dSAndroid Build Coastguard Worker        item, end = self.screen._write(self._position, txt, align, font,
3420*cda5da8dSAndroid Build Coastguard Worker                                                          self._pencolor)
3421*cda5da8dSAndroid Build Coastguard Worker        self._update()
3422*cda5da8dSAndroid Build Coastguard Worker        self.items.append(item)
3423*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer:
3424*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.push(("wri", item))
3425*cda5da8dSAndroid Build Coastguard Worker        return end
3426*cda5da8dSAndroid Build Coastguard Worker
3427*cda5da8dSAndroid Build Coastguard Worker    def write(self, arg, move=False, align="left", font=("Arial", 8, "normal")):
3428*cda5da8dSAndroid Build Coastguard Worker        """Write text at the current turtle position.
3429*cda5da8dSAndroid Build Coastguard Worker
3430*cda5da8dSAndroid Build Coastguard Worker        Arguments:
3431*cda5da8dSAndroid Build Coastguard Worker        arg -- info, which is to be written to the TurtleScreen
3432*cda5da8dSAndroid Build Coastguard Worker        move (optional) -- True/False
3433*cda5da8dSAndroid Build Coastguard Worker        align (optional) -- one of the strings "left", "center" or right"
3434*cda5da8dSAndroid Build Coastguard Worker        font (optional) -- a triple (fontname, fontsize, fonttype)
3435*cda5da8dSAndroid Build Coastguard Worker
3436*cda5da8dSAndroid Build Coastguard Worker        Write text - the string representation of arg - at the current
3437*cda5da8dSAndroid Build Coastguard Worker        turtle position according to align ("left", "center" or right")
3438*cda5da8dSAndroid Build Coastguard Worker        and with the given font.
3439*cda5da8dSAndroid Build Coastguard Worker        If move is True, the pen is moved to the bottom-right corner
3440*cda5da8dSAndroid Build Coastguard Worker        of the text. By default, move is False.
3441*cda5da8dSAndroid Build Coastguard Worker
3442*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3443*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.write('Home = ', True, align="center")
3444*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.write((0,0), True)
3445*cda5da8dSAndroid Build Coastguard Worker        """
3446*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer:
3447*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.push(["seq"])
3448*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.cumulate = True
3449*cda5da8dSAndroid Build Coastguard Worker        end = self._write(str(arg), align.lower(), font)
3450*cda5da8dSAndroid Build Coastguard Worker        if move:
3451*cda5da8dSAndroid Build Coastguard Worker            x, y = self.pos()
3452*cda5da8dSAndroid Build Coastguard Worker            self.setpos(end, y)
3453*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer:
3454*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.cumulate = False
3455*cda5da8dSAndroid Build Coastguard Worker
3456*cda5da8dSAndroid Build Coastguard Worker    def begin_poly(self):
3457*cda5da8dSAndroid Build Coastguard Worker        """Start recording the vertices of a polygon.
3458*cda5da8dSAndroid Build Coastguard Worker
3459*cda5da8dSAndroid Build Coastguard Worker        No argument.
3460*cda5da8dSAndroid Build Coastguard Worker
3461*cda5da8dSAndroid Build Coastguard Worker        Start recording the vertices of a polygon. Current turtle position
3462*cda5da8dSAndroid Build Coastguard Worker        is first point of polygon.
3463*cda5da8dSAndroid Build Coastguard Worker
3464*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3465*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.begin_poly()
3466*cda5da8dSAndroid Build Coastguard Worker        """
3467*cda5da8dSAndroid Build Coastguard Worker        self._poly = [self._position]
3468*cda5da8dSAndroid Build Coastguard Worker        self._creatingPoly = True
3469*cda5da8dSAndroid Build Coastguard Worker
3470*cda5da8dSAndroid Build Coastguard Worker    def end_poly(self):
3471*cda5da8dSAndroid Build Coastguard Worker        """Stop recording the vertices of a polygon.
3472*cda5da8dSAndroid Build Coastguard Worker
3473*cda5da8dSAndroid Build Coastguard Worker        No argument.
3474*cda5da8dSAndroid Build Coastguard Worker
3475*cda5da8dSAndroid Build Coastguard Worker        Stop recording the vertices of a polygon. Current turtle position is
3476*cda5da8dSAndroid Build Coastguard Worker        last point of polygon. This will be connected with the first point.
3477*cda5da8dSAndroid Build Coastguard Worker
3478*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3479*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.end_poly()
3480*cda5da8dSAndroid Build Coastguard Worker        """
3481*cda5da8dSAndroid Build Coastguard Worker        self._creatingPoly = False
3482*cda5da8dSAndroid Build Coastguard Worker
3483*cda5da8dSAndroid Build Coastguard Worker    def get_poly(self):
3484*cda5da8dSAndroid Build Coastguard Worker        """Return the lastly recorded polygon.
3485*cda5da8dSAndroid Build Coastguard Worker
3486*cda5da8dSAndroid Build Coastguard Worker        No argument.
3487*cda5da8dSAndroid Build Coastguard Worker
3488*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3489*cda5da8dSAndroid Build Coastguard Worker        >>> p = turtle.get_poly()
3490*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.register_shape("myFavouriteShape", p)
3491*cda5da8dSAndroid Build Coastguard Worker        """
3492*cda5da8dSAndroid Build Coastguard Worker        ## check if there is any poly?
3493*cda5da8dSAndroid Build Coastguard Worker        if self._poly is not None:
3494*cda5da8dSAndroid Build Coastguard Worker            return tuple(self._poly)
3495*cda5da8dSAndroid Build Coastguard Worker
3496*cda5da8dSAndroid Build Coastguard Worker    def getscreen(self):
3497*cda5da8dSAndroid Build Coastguard Worker        """Return the TurtleScreen object, the turtle is drawing  on.
3498*cda5da8dSAndroid Build Coastguard Worker
3499*cda5da8dSAndroid Build Coastguard Worker        No argument.
3500*cda5da8dSAndroid Build Coastguard Worker
3501*cda5da8dSAndroid Build Coastguard Worker        Return the TurtleScreen object, the turtle is drawing  on.
3502*cda5da8dSAndroid Build Coastguard Worker        So TurtleScreen-methods can be called for that object.
3503*cda5da8dSAndroid Build Coastguard Worker
3504*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3505*cda5da8dSAndroid Build Coastguard Worker        >>> ts = turtle.getscreen()
3506*cda5da8dSAndroid Build Coastguard Worker        >>> ts
3507*cda5da8dSAndroid Build Coastguard Worker        <turtle.TurtleScreen object at 0x0106B770>
3508*cda5da8dSAndroid Build Coastguard Worker        >>> ts.bgcolor("pink")
3509*cda5da8dSAndroid Build Coastguard Worker        """
3510*cda5da8dSAndroid Build Coastguard Worker        return self.screen
3511*cda5da8dSAndroid Build Coastguard Worker
3512*cda5da8dSAndroid Build Coastguard Worker    def getturtle(self):
3513*cda5da8dSAndroid Build Coastguard Worker        """Return the Turtleobject itself.
3514*cda5da8dSAndroid Build Coastguard Worker
3515*cda5da8dSAndroid Build Coastguard Worker        No argument.
3516*cda5da8dSAndroid Build Coastguard Worker
3517*cda5da8dSAndroid Build Coastguard Worker        Only reasonable use: as a function to return the 'anonymous turtle':
3518*cda5da8dSAndroid Build Coastguard Worker
3519*cda5da8dSAndroid Build Coastguard Worker        Example:
3520*cda5da8dSAndroid Build Coastguard Worker        >>> pet = getturtle()
3521*cda5da8dSAndroid Build Coastguard Worker        >>> pet.fd(50)
3522*cda5da8dSAndroid Build Coastguard Worker        >>> pet
3523*cda5da8dSAndroid Build Coastguard Worker        <turtle.Turtle object at 0x0187D810>
3524*cda5da8dSAndroid Build Coastguard Worker        >>> turtles()
3525*cda5da8dSAndroid Build Coastguard Worker        [<turtle.Turtle object at 0x0187D810>]
3526*cda5da8dSAndroid Build Coastguard Worker        """
3527*cda5da8dSAndroid Build Coastguard Worker        return self
3528*cda5da8dSAndroid Build Coastguard Worker
3529*cda5da8dSAndroid Build Coastguard Worker    getpen = getturtle
3530*cda5da8dSAndroid Build Coastguard Worker
3531*cda5da8dSAndroid Build Coastguard Worker
3532*cda5da8dSAndroid Build Coastguard Worker    ################################################################
3533*cda5da8dSAndroid Build Coastguard Worker    ### screen oriented methods recurring to methods of TurtleScreen
3534*cda5da8dSAndroid Build Coastguard Worker    ################################################################
3535*cda5da8dSAndroid Build Coastguard Worker
3536*cda5da8dSAndroid Build Coastguard Worker    def _delay(self, delay=None):
3537*cda5da8dSAndroid Build Coastguard Worker        """Set delay value which determines speed of turtle animation.
3538*cda5da8dSAndroid Build Coastguard Worker        """
3539*cda5da8dSAndroid Build Coastguard Worker        return self.screen.delay(delay)
3540*cda5da8dSAndroid Build Coastguard Worker
3541*cda5da8dSAndroid Build Coastguard Worker    def onclick(self, fun, btn=1, add=None):
3542*cda5da8dSAndroid Build Coastguard Worker        """Bind fun to mouse-click event on this turtle on canvas.
3543*cda5da8dSAndroid Build Coastguard Worker
3544*cda5da8dSAndroid Build Coastguard Worker        Arguments:
3545*cda5da8dSAndroid Build Coastguard Worker        fun --  a function with two arguments, to which will be assigned
3546*cda5da8dSAndroid Build Coastguard Worker                the coordinates of the clicked point on the canvas.
3547*cda5da8dSAndroid Build Coastguard Worker        btn --  number of the mouse-button defaults to 1 (left mouse button).
3548*cda5da8dSAndroid Build Coastguard Worker        add --  True or False. If True, new binding will be added, otherwise
3549*cda5da8dSAndroid Build Coastguard Worker                it will replace a former binding.
3550*cda5da8dSAndroid Build Coastguard Worker
3551*cda5da8dSAndroid Build Coastguard Worker        Example for the anonymous turtle, i. e. the procedural way:
3552*cda5da8dSAndroid Build Coastguard Worker
3553*cda5da8dSAndroid Build Coastguard Worker        >>> def turn(x, y):
3554*cda5da8dSAndroid Build Coastguard Worker        ...     left(360)
3555*cda5da8dSAndroid Build Coastguard Worker        ...
3556*cda5da8dSAndroid Build Coastguard Worker        >>> onclick(turn)  # Now clicking into the turtle will turn it.
3557*cda5da8dSAndroid Build Coastguard Worker        >>> onclick(None)  # event-binding will be removed
3558*cda5da8dSAndroid Build Coastguard Worker        """
3559*cda5da8dSAndroid Build Coastguard Worker        self.screen._onclick(self.turtle._item, fun, btn, add)
3560*cda5da8dSAndroid Build Coastguard Worker        self._update()
3561*cda5da8dSAndroid Build Coastguard Worker
3562*cda5da8dSAndroid Build Coastguard Worker    def onrelease(self, fun, btn=1, add=None):
3563*cda5da8dSAndroid Build Coastguard Worker        """Bind fun to mouse-button-release event on this turtle on canvas.
3564*cda5da8dSAndroid Build Coastguard Worker
3565*cda5da8dSAndroid Build Coastguard Worker        Arguments:
3566*cda5da8dSAndroid Build Coastguard Worker        fun -- a function with two arguments, to which will be assigned
3567*cda5da8dSAndroid Build Coastguard Worker                the coordinates of the clicked point on the canvas.
3568*cda5da8dSAndroid Build Coastguard Worker        btn --  number of the mouse-button defaults to 1 (left mouse button).
3569*cda5da8dSAndroid Build Coastguard Worker
3570*cda5da8dSAndroid Build Coastguard Worker        Example (for a MyTurtle instance named joe):
3571*cda5da8dSAndroid Build Coastguard Worker        >>> class MyTurtle(Turtle):
3572*cda5da8dSAndroid Build Coastguard Worker        ...     def glow(self,x,y):
3573*cda5da8dSAndroid Build Coastguard Worker        ...             self.fillcolor("red")
3574*cda5da8dSAndroid Build Coastguard Worker        ...     def unglow(self,x,y):
3575*cda5da8dSAndroid Build Coastguard Worker        ...             self.fillcolor("")
3576*cda5da8dSAndroid Build Coastguard Worker        ...
3577*cda5da8dSAndroid Build Coastguard Worker        >>> joe = MyTurtle()
3578*cda5da8dSAndroid Build Coastguard Worker        >>> joe.onclick(joe.glow)
3579*cda5da8dSAndroid Build Coastguard Worker        >>> joe.onrelease(joe.unglow)
3580*cda5da8dSAndroid Build Coastguard Worker
3581*cda5da8dSAndroid Build Coastguard Worker        Clicking on joe turns fillcolor red, unclicking turns it to
3582*cda5da8dSAndroid Build Coastguard Worker        transparent.
3583*cda5da8dSAndroid Build Coastguard Worker        """
3584*cda5da8dSAndroid Build Coastguard Worker        self.screen._onrelease(self.turtle._item, fun, btn, add)
3585*cda5da8dSAndroid Build Coastguard Worker        self._update()
3586*cda5da8dSAndroid Build Coastguard Worker
3587*cda5da8dSAndroid Build Coastguard Worker    def ondrag(self, fun, btn=1, add=None):
3588*cda5da8dSAndroid Build Coastguard Worker        """Bind fun to mouse-move event on this turtle on canvas.
3589*cda5da8dSAndroid Build Coastguard Worker
3590*cda5da8dSAndroid Build Coastguard Worker        Arguments:
3591*cda5da8dSAndroid Build Coastguard Worker        fun -- a function with two arguments, to which will be assigned
3592*cda5da8dSAndroid Build Coastguard Worker               the coordinates of the clicked point on the canvas.
3593*cda5da8dSAndroid Build Coastguard Worker        btn -- number of the mouse-button defaults to 1 (left mouse button).
3594*cda5da8dSAndroid Build Coastguard Worker
3595*cda5da8dSAndroid Build Coastguard Worker        Every sequence of mouse-move-events on a turtle is preceded by a
3596*cda5da8dSAndroid Build Coastguard Worker        mouse-click event on that turtle.
3597*cda5da8dSAndroid Build Coastguard Worker
3598*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3599*cda5da8dSAndroid Build Coastguard Worker        >>> turtle.ondrag(turtle.goto)
3600*cda5da8dSAndroid Build Coastguard Worker
3601*cda5da8dSAndroid Build Coastguard Worker        Subsequently clicking and dragging a Turtle will move it
3602*cda5da8dSAndroid Build Coastguard Worker        across the screen thereby producing handdrawings (if pen is
3603*cda5da8dSAndroid Build Coastguard Worker        down).
3604*cda5da8dSAndroid Build Coastguard Worker        """
3605*cda5da8dSAndroid Build Coastguard Worker        self.screen._ondrag(self.turtle._item, fun, btn, add)
3606*cda5da8dSAndroid Build Coastguard Worker
3607*cda5da8dSAndroid Build Coastguard Worker
3608*cda5da8dSAndroid Build Coastguard Worker    def _undo(self, action, data):
3609*cda5da8dSAndroid Build Coastguard Worker        """Does the main part of the work for undo()
3610*cda5da8dSAndroid Build Coastguard Worker        """
3611*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer is None:
3612*cda5da8dSAndroid Build Coastguard Worker            return
3613*cda5da8dSAndroid Build Coastguard Worker        if action == "rot":
3614*cda5da8dSAndroid Build Coastguard Worker            angle, degPAU = data
3615*cda5da8dSAndroid Build Coastguard Worker            self._rotate(-angle*degPAU/self._degreesPerAU)
3616*cda5da8dSAndroid Build Coastguard Worker            dummy = self.undobuffer.pop()
3617*cda5da8dSAndroid Build Coastguard Worker        elif action == "stamp":
3618*cda5da8dSAndroid Build Coastguard Worker            stitem = data[0]
3619*cda5da8dSAndroid Build Coastguard Worker            self.clearstamp(stitem)
3620*cda5da8dSAndroid Build Coastguard Worker        elif action == "go":
3621*cda5da8dSAndroid Build Coastguard Worker            self._undogoto(data)
3622*cda5da8dSAndroid Build Coastguard Worker        elif action in ["wri", "dot"]:
3623*cda5da8dSAndroid Build Coastguard Worker            item = data[0]
3624*cda5da8dSAndroid Build Coastguard Worker            self.screen._delete(item)
3625*cda5da8dSAndroid Build Coastguard Worker            self.items.remove(item)
3626*cda5da8dSAndroid Build Coastguard Worker        elif action == "dofill":
3627*cda5da8dSAndroid Build Coastguard Worker            item = data[0]
3628*cda5da8dSAndroid Build Coastguard Worker            self.screen._drawpoly(item, ((0, 0),(0, 0),(0, 0)),
3629*cda5da8dSAndroid Build Coastguard Worker                                  fill="", outline="")
3630*cda5da8dSAndroid Build Coastguard Worker        elif action == "beginfill":
3631*cda5da8dSAndroid Build Coastguard Worker            item = data[0]
3632*cda5da8dSAndroid Build Coastguard Worker            self._fillitem = self._fillpath = None
3633*cda5da8dSAndroid Build Coastguard Worker            if item in self.items:
3634*cda5da8dSAndroid Build Coastguard Worker                self.screen._delete(item)
3635*cda5da8dSAndroid Build Coastguard Worker                self.items.remove(item)
3636*cda5da8dSAndroid Build Coastguard Worker        elif action == "pen":
3637*cda5da8dSAndroid Build Coastguard Worker            TPen.pen(self, data[0])
3638*cda5da8dSAndroid Build Coastguard Worker            self.undobuffer.pop()
3639*cda5da8dSAndroid Build Coastguard Worker
3640*cda5da8dSAndroid Build Coastguard Worker    def undo(self):
3641*cda5da8dSAndroid Build Coastguard Worker        """undo (repeatedly) the last turtle action.
3642*cda5da8dSAndroid Build Coastguard Worker
3643*cda5da8dSAndroid Build Coastguard Worker        No argument.
3644*cda5da8dSAndroid Build Coastguard Worker
3645*cda5da8dSAndroid Build Coastguard Worker        undo (repeatedly) the last turtle action.
3646*cda5da8dSAndroid Build Coastguard Worker        Number of available undo actions is determined by the size of
3647*cda5da8dSAndroid Build Coastguard Worker        the undobuffer.
3648*cda5da8dSAndroid Build Coastguard Worker
3649*cda5da8dSAndroid Build Coastguard Worker        Example (for a Turtle instance named turtle):
3650*cda5da8dSAndroid Build Coastguard Worker        >>> for i in range(4):
3651*cda5da8dSAndroid Build Coastguard Worker        ...     turtle.fd(50); turtle.lt(80)
3652*cda5da8dSAndroid Build Coastguard Worker        ...
3653*cda5da8dSAndroid Build Coastguard Worker        >>> for i in range(8):
3654*cda5da8dSAndroid Build Coastguard Worker        ...     turtle.undo()
3655*cda5da8dSAndroid Build Coastguard Worker        ...
3656*cda5da8dSAndroid Build Coastguard Worker        """
3657*cda5da8dSAndroid Build Coastguard Worker        if self.undobuffer is None:
3658*cda5da8dSAndroid Build Coastguard Worker            return
3659*cda5da8dSAndroid Build Coastguard Worker        item = self.undobuffer.pop()
3660*cda5da8dSAndroid Build Coastguard Worker        action = item[0]
3661*cda5da8dSAndroid Build Coastguard Worker        data = item[1:]
3662*cda5da8dSAndroid Build Coastguard Worker        if action == "seq":
3663*cda5da8dSAndroid Build Coastguard Worker            while data:
3664*cda5da8dSAndroid Build Coastguard Worker                item = data.pop()
3665*cda5da8dSAndroid Build Coastguard Worker                self._undo(item[0], item[1:])
3666*cda5da8dSAndroid Build Coastguard Worker        else:
3667*cda5da8dSAndroid Build Coastguard Worker            self._undo(action, data)
3668*cda5da8dSAndroid Build Coastguard Worker
3669*cda5da8dSAndroid Build Coastguard Worker    turtlesize = shapesize
3670*cda5da8dSAndroid Build Coastguard Worker
3671*cda5da8dSAndroid Build Coastguard WorkerRawPen = RawTurtle
3672*cda5da8dSAndroid Build Coastguard Worker
3673*cda5da8dSAndroid Build Coastguard Worker###  Screen - Singleton  ########################
3674*cda5da8dSAndroid Build Coastguard Worker
3675*cda5da8dSAndroid Build Coastguard Workerdef Screen():
3676*cda5da8dSAndroid Build Coastguard Worker    """Return the singleton screen object.
3677*cda5da8dSAndroid Build Coastguard Worker    If none exists at the moment, create a new one and return it,
3678*cda5da8dSAndroid Build Coastguard Worker    else return the existing one."""
3679*cda5da8dSAndroid Build Coastguard Worker    if Turtle._screen is None:
3680*cda5da8dSAndroid Build Coastguard Worker        Turtle._screen = _Screen()
3681*cda5da8dSAndroid Build Coastguard Worker    return Turtle._screen
3682*cda5da8dSAndroid Build Coastguard Worker
3683*cda5da8dSAndroid Build Coastguard Workerclass _Screen(TurtleScreen):
3684*cda5da8dSAndroid Build Coastguard Worker
3685*cda5da8dSAndroid Build Coastguard Worker    _root = None
3686*cda5da8dSAndroid Build Coastguard Worker    _canvas = None
3687*cda5da8dSAndroid Build Coastguard Worker    _title = _CFG["title"]
3688*cda5da8dSAndroid Build Coastguard Worker
3689*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
3690*cda5da8dSAndroid Build Coastguard Worker        # XXX there is no need for this code to be conditional,
3691*cda5da8dSAndroid Build Coastguard Worker        # as there will be only a single _Screen instance, anyway
3692*cda5da8dSAndroid Build Coastguard Worker        # XXX actually, the turtle demo is injecting root window,
3693*cda5da8dSAndroid Build Coastguard Worker        # so perhaps the conditional creation of a root should be
3694*cda5da8dSAndroid Build Coastguard Worker        # preserved (perhaps by passing it as an optional parameter)
3695*cda5da8dSAndroid Build Coastguard Worker        if _Screen._root is None:
3696*cda5da8dSAndroid Build Coastguard Worker            _Screen._root = self._root = _Root()
3697*cda5da8dSAndroid Build Coastguard Worker            self._root.title(_Screen._title)
3698*cda5da8dSAndroid Build Coastguard Worker            self._root.ondestroy(self._destroy)
3699*cda5da8dSAndroid Build Coastguard Worker        if _Screen._canvas is None:
3700*cda5da8dSAndroid Build Coastguard Worker            width = _CFG["width"]
3701*cda5da8dSAndroid Build Coastguard Worker            height = _CFG["height"]
3702*cda5da8dSAndroid Build Coastguard Worker            canvwidth = _CFG["canvwidth"]
3703*cda5da8dSAndroid Build Coastguard Worker            canvheight = _CFG["canvheight"]
3704*cda5da8dSAndroid Build Coastguard Worker            leftright = _CFG["leftright"]
3705*cda5da8dSAndroid Build Coastguard Worker            topbottom = _CFG["topbottom"]
3706*cda5da8dSAndroid Build Coastguard Worker            self._root.setupcanvas(width, height, canvwidth, canvheight)
3707*cda5da8dSAndroid Build Coastguard Worker            _Screen._canvas = self._root._getcanvas()
3708*cda5da8dSAndroid Build Coastguard Worker            TurtleScreen.__init__(self, _Screen._canvas)
3709*cda5da8dSAndroid Build Coastguard Worker            self.setup(width, height, leftright, topbottom)
3710*cda5da8dSAndroid Build Coastguard Worker
3711*cda5da8dSAndroid Build Coastguard Worker    def setup(self, width=_CFG["width"], height=_CFG["height"],
3712*cda5da8dSAndroid Build Coastguard Worker              startx=_CFG["leftright"], starty=_CFG["topbottom"]):
3713*cda5da8dSAndroid Build Coastguard Worker        """ Set the size and position of the main window.
3714*cda5da8dSAndroid Build Coastguard Worker
3715*cda5da8dSAndroid Build Coastguard Worker        Arguments:
3716*cda5da8dSAndroid Build Coastguard Worker        width: as integer a size in pixels, as float a fraction of the screen.
3717*cda5da8dSAndroid Build Coastguard Worker          Default is 50% of screen.
3718*cda5da8dSAndroid Build Coastguard Worker        height: as integer the height in pixels, as float a fraction of the
3719*cda5da8dSAndroid Build Coastguard Worker          screen. Default is 75% of screen.
3720*cda5da8dSAndroid Build Coastguard Worker        startx: if positive, starting position in pixels from the left
3721*cda5da8dSAndroid Build Coastguard Worker          edge of the screen, if negative from the right edge
3722*cda5da8dSAndroid Build Coastguard Worker          Default, startx=None is to center window horizontally.
3723*cda5da8dSAndroid Build Coastguard Worker        starty: if positive, starting position in pixels from the top
3724*cda5da8dSAndroid Build Coastguard Worker          edge of the screen, if negative from the bottom edge
3725*cda5da8dSAndroid Build Coastguard Worker          Default, starty=None is to center window vertically.
3726*cda5da8dSAndroid Build Coastguard Worker
3727*cda5da8dSAndroid Build Coastguard Worker        Examples (for a Screen instance named screen):
3728*cda5da8dSAndroid Build Coastguard Worker        >>> screen.setup (width=200, height=200, startx=0, starty=0)
3729*cda5da8dSAndroid Build Coastguard Worker
3730*cda5da8dSAndroid Build Coastguard Worker        sets window to 200x200 pixels, in upper left of screen
3731*cda5da8dSAndroid Build Coastguard Worker
3732*cda5da8dSAndroid Build Coastguard Worker        >>> screen.setup(width=.75, height=0.5, startx=None, starty=None)
3733*cda5da8dSAndroid Build Coastguard Worker
3734*cda5da8dSAndroid Build Coastguard Worker        sets window to 75% of screen by 50% of screen and centers
3735*cda5da8dSAndroid Build Coastguard Worker        """
3736*cda5da8dSAndroid Build Coastguard Worker        if not hasattr(self._root, "set_geometry"):
3737*cda5da8dSAndroid Build Coastguard Worker            return
3738*cda5da8dSAndroid Build Coastguard Worker        sw = self._root.win_width()
3739*cda5da8dSAndroid Build Coastguard Worker        sh = self._root.win_height()
3740*cda5da8dSAndroid Build Coastguard Worker        if isinstance(width, float) and 0 <= width <= 1:
3741*cda5da8dSAndroid Build Coastguard Worker            width = sw*width
3742*cda5da8dSAndroid Build Coastguard Worker        if startx is None:
3743*cda5da8dSAndroid Build Coastguard Worker            startx = (sw - width) / 2
3744*cda5da8dSAndroid Build Coastguard Worker        if isinstance(height, float) and 0 <= height <= 1:
3745*cda5da8dSAndroid Build Coastguard Worker            height = sh*height
3746*cda5da8dSAndroid Build Coastguard Worker        if starty is None:
3747*cda5da8dSAndroid Build Coastguard Worker            starty = (sh - height) / 2
3748*cda5da8dSAndroid Build Coastguard Worker        self._root.set_geometry(width, height, startx, starty)
3749*cda5da8dSAndroid Build Coastguard Worker        self.update()
3750*cda5da8dSAndroid Build Coastguard Worker
3751*cda5da8dSAndroid Build Coastguard Worker    def title(self, titlestring):
3752*cda5da8dSAndroid Build Coastguard Worker        """Set title of turtle-window
3753*cda5da8dSAndroid Build Coastguard Worker
3754*cda5da8dSAndroid Build Coastguard Worker        Argument:
3755*cda5da8dSAndroid Build Coastguard Worker        titlestring -- a string, to appear in the titlebar of the
3756*cda5da8dSAndroid Build Coastguard Worker                       turtle graphics window.
3757*cda5da8dSAndroid Build Coastguard Worker
3758*cda5da8dSAndroid Build Coastguard Worker        This is a method of Screen-class. Not available for TurtleScreen-
3759*cda5da8dSAndroid Build Coastguard Worker        objects.
3760*cda5da8dSAndroid Build Coastguard Worker
3761*cda5da8dSAndroid Build Coastguard Worker        Example (for a Screen instance named screen):
3762*cda5da8dSAndroid Build Coastguard Worker        >>> screen.title("Welcome to the turtle-zoo!")
3763*cda5da8dSAndroid Build Coastguard Worker        """
3764*cda5da8dSAndroid Build Coastguard Worker        if _Screen._root is not None:
3765*cda5da8dSAndroid Build Coastguard Worker            _Screen._root.title(titlestring)
3766*cda5da8dSAndroid Build Coastguard Worker        _Screen._title = titlestring
3767*cda5da8dSAndroid Build Coastguard Worker
3768*cda5da8dSAndroid Build Coastguard Worker    def _destroy(self):
3769*cda5da8dSAndroid Build Coastguard Worker        root = self._root
3770*cda5da8dSAndroid Build Coastguard Worker        if root is _Screen._root:
3771*cda5da8dSAndroid Build Coastguard Worker            Turtle._pen = None
3772*cda5da8dSAndroid Build Coastguard Worker            Turtle._screen = None
3773*cda5da8dSAndroid Build Coastguard Worker            _Screen._root = None
3774*cda5da8dSAndroid Build Coastguard Worker            _Screen._canvas = None
3775*cda5da8dSAndroid Build Coastguard Worker        TurtleScreen._RUNNING = False
3776*cda5da8dSAndroid Build Coastguard Worker        root.destroy()
3777*cda5da8dSAndroid Build Coastguard Worker
3778*cda5da8dSAndroid Build Coastguard Worker    def bye(self):
3779*cda5da8dSAndroid Build Coastguard Worker        """Shut the turtlegraphics window.
3780*cda5da8dSAndroid Build Coastguard Worker
3781*cda5da8dSAndroid Build Coastguard Worker        Example (for a TurtleScreen instance named screen):
3782*cda5da8dSAndroid Build Coastguard Worker        >>> screen.bye()
3783*cda5da8dSAndroid Build Coastguard Worker        """
3784*cda5da8dSAndroid Build Coastguard Worker        self._destroy()
3785*cda5da8dSAndroid Build Coastguard Worker
3786*cda5da8dSAndroid Build Coastguard Worker    def exitonclick(self):
3787*cda5da8dSAndroid Build Coastguard Worker        """Go into mainloop until the mouse is clicked.
3788*cda5da8dSAndroid Build Coastguard Worker
3789*cda5da8dSAndroid Build Coastguard Worker        No arguments.
3790*cda5da8dSAndroid Build Coastguard Worker
3791*cda5da8dSAndroid Build Coastguard Worker        Bind bye() method to mouseclick on TurtleScreen.
3792*cda5da8dSAndroid Build Coastguard Worker        If "using_IDLE" - value in configuration dictionary is False
3793*cda5da8dSAndroid Build Coastguard Worker        (default value), enter mainloop.
3794*cda5da8dSAndroid Build Coastguard Worker        If IDLE with -n switch (no subprocess) is used, this value should be
3795*cda5da8dSAndroid Build Coastguard Worker        set to True in turtle.cfg. In this case IDLE's mainloop
3796*cda5da8dSAndroid Build Coastguard Worker        is active also for the client script.
3797*cda5da8dSAndroid Build Coastguard Worker
3798*cda5da8dSAndroid Build Coastguard Worker        This is a method of the Screen-class and not available for
3799*cda5da8dSAndroid Build Coastguard Worker        TurtleScreen instances.
3800*cda5da8dSAndroid Build Coastguard Worker
3801*cda5da8dSAndroid Build Coastguard Worker        Example (for a Screen instance named screen):
3802*cda5da8dSAndroid Build Coastguard Worker        >>> screen.exitonclick()
3803*cda5da8dSAndroid Build Coastguard Worker
3804*cda5da8dSAndroid Build Coastguard Worker        """
3805*cda5da8dSAndroid Build Coastguard Worker        def exitGracefully(x, y):
3806*cda5da8dSAndroid Build Coastguard Worker            """Screen.bye() with two dummy-parameters"""
3807*cda5da8dSAndroid Build Coastguard Worker            self.bye()
3808*cda5da8dSAndroid Build Coastguard Worker        self.onclick(exitGracefully)
3809*cda5da8dSAndroid Build Coastguard Worker        if _CFG["using_IDLE"]:
3810*cda5da8dSAndroid Build Coastguard Worker            return
3811*cda5da8dSAndroid Build Coastguard Worker        try:
3812*cda5da8dSAndroid Build Coastguard Worker            mainloop()
3813*cda5da8dSAndroid Build Coastguard Worker        except AttributeError:
3814*cda5da8dSAndroid Build Coastguard Worker            exit(0)
3815*cda5da8dSAndroid Build Coastguard Worker
3816*cda5da8dSAndroid Build Coastguard Workerclass Turtle(RawTurtle):
3817*cda5da8dSAndroid Build Coastguard Worker    """RawTurtle auto-creating (scrolled) canvas.
3818*cda5da8dSAndroid Build Coastguard Worker
3819*cda5da8dSAndroid Build Coastguard Worker    When a Turtle object is created or a function derived from some
3820*cda5da8dSAndroid Build Coastguard Worker    Turtle method is called a TurtleScreen object is automatically created.
3821*cda5da8dSAndroid Build Coastguard Worker    """
3822*cda5da8dSAndroid Build Coastguard Worker    _pen = None
3823*cda5da8dSAndroid Build Coastguard Worker    _screen = None
3824*cda5da8dSAndroid Build Coastguard Worker
3825*cda5da8dSAndroid Build Coastguard Worker    def __init__(self,
3826*cda5da8dSAndroid Build Coastguard Worker                 shape=_CFG["shape"],
3827*cda5da8dSAndroid Build Coastguard Worker                 undobuffersize=_CFG["undobuffersize"],
3828*cda5da8dSAndroid Build Coastguard Worker                 visible=_CFG["visible"]):
3829*cda5da8dSAndroid Build Coastguard Worker        if Turtle._screen is None:
3830*cda5da8dSAndroid Build Coastguard Worker            Turtle._screen = Screen()
3831*cda5da8dSAndroid Build Coastguard Worker        RawTurtle.__init__(self, Turtle._screen,
3832*cda5da8dSAndroid Build Coastguard Worker                           shape=shape,
3833*cda5da8dSAndroid Build Coastguard Worker                           undobuffersize=undobuffersize,
3834*cda5da8dSAndroid Build Coastguard Worker                           visible=visible)
3835*cda5da8dSAndroid Build Coastguard Worker
3836*cda5da8dSAndroid Build Coastguard WorkerPen = Turtle
3837*cda5da8dSAndroid Build Coastguard Worker
3838*cda5da8dSAndroid Build Coastguard Workerdef write_docstringdict(filename="turtle_docstringdict"):
3839*cda5da8dSAndroid Build Coastguard Worker    """Create and write docstring-dictionary to file.
3840*cda5da8dSAndroid Build Coastguard Worker
3841*cda5da8dSAndroid Build Coastguard Worker    Optional argument:
3842*cda5da8dSAndroid Build Coastguard Worker    filename -- a string, used as filename
3843*cda5da8dSAndroid Build Coastguard Worker                default value is turtle_docstringdict
3844*cda5da8dSAndroid Build Coastguard Worker
3845*cda5da8dSAndroid Build Coastguard Worker    Has to be called explicitly, (not used by the turtle-graphics classes)
3846*cda5da8dSAndroid Build Coastguard Worker    The docstring dictionary will be written to the Python script <filename>.py
3847*cda5da8dSAndroid Build Coastguard Worker    It is intended to serve as a template for translation of the docstrings
3848*cda5da8dSAndroid Build Coastguard Worker    into different languages.
3849*cda5da8dSAndroid Build Coastguard Worker    """
3850*cda5da8dSAndroid Build Coastguard Worker    docsdict = {}
3851*cda5da8dSAndroid Build Coastguard Worker
3852*cda5da8dSAndroid Build Coastguard Worker    for methodname in _tg_screen_functions:
3853*cda5da8dSAndroid Build Coastguard Worker        key = "_Screen."+methodname
3854*cda5da8dSAndroid Build Coastguard Worker        docsdict[key] = eval(key).__doc__
3855*cda5da8dSAndroid Build Coastguard Worker    for methodname in _tg_turtle_functions:
3856*cda5da8dSAndroid Build Coastguard Worker        key = "Turtle."+methodname
3857*cda5da8dSAndroid Build Coastguard Worker        docsdict[key] = eval(key).__doc__
3858*cda5da8dSAndroid Build Coastguard Worker
3859*cda5da8dSAndroid Build Coastguard Worker    with open("%s.py" % filename,"w") as f:
3860*cda5da8dSAndroid Build Coastguard Worker        keys = sorted(x for x in docsdict
3861*cda5da8dSAndroid Build Coastguard Worker                      if x.split('.')[1] not in _alias_list)
3862*cda5da8dSAndroid Build Coastguard Worker        f.write('docsdict = {\n\n')
3863*cda5da8dSAndroid Build Coastguard Worker        for key in keys[:-1]:
3864*cda5da8dSAndroid Build Coastguard Worker            f.write('%s :\n' % repr(key))
3865*cda5da8dSAndroid Build Coastguard Worker            f.write('        """%s\n""",\n\n' % docsdict[key])
3866*cda5da8dSAndroid Build Coastguard Worker        key = keys[-1]
3867*cda5da8dSAndroid Build Coastguard Worker        f.write('%s :\n' % repr(key))
3868*cda5da8dSAndroid Build Coastguard Worker        f.write('        """%s\n"""\n\n' % docsdict[key])
3869*cda5da8dSAndroid Build Coastguard Worker        f.write("}\n")
3870*cda5da8dSAndroid Build Coastguard Worker        f.close()
3871*cda5da8dSAndroid Build Coastguard Worker
3872*cda5da8dSAndroid Build Coastguard Workerdef read_docstrings(lang):
3873*cda5da8dSAndroid Build Coastguard Worker    """Read in docstrings from lang-specific docstring dictionary.
3874*cda5da8dSAndroid Build Coastguard Worker
3875*cda5da8dSAndroid Build Coastguard Worker    Transfer docstrings, translated to lang, from a dictionary-file
3876*cda5da8dSAndroid Build Coastguard Worker    to the methods of classes Screen and Turtle and - in revised form -
3877*cda5da8dSAndroid Build Coastguard Worker    to the corresponding functions.
3878*cda5da8dSAndroid Build Coastguard Worker    """
3879*cda5da8dSAndroid Build Coastguard Worker    modname = "turtle_docstringdict_%(language)s" % {'language':lang.lower()}
3880*cda5da8dSAndroid Build Coastguard Worker    module = __import__(modname)
3881*cda5da8dSAndroid Build Coastguard Worker    docsdict = module.docsdict
3882*cda5da8dSAndroid Build Coastguard Worker    for key in docsdict:
3883*cda5da8dSAndroid Build Coastguard Worker        try:
3884*cda5da8dSAndroid Build Coastguard Worker#            eval(key).im_func.__doc__ = docsdict[key]
3885*cda5da8dSAndroid Build Coastguard Worker            eval(key).__doc__ = docsdict[key]
3886*cda5da8dSAndroid Build Coastguard Worker        except Exception:
3887*cda5da8dSAndroid Build Coastguard Worker            print("Bad docstring-entry: %s" % key)
3888*cda5da8dSAndroid Build Coastguard Worker
3889*cda5da8dSAndroid Build Coastguard Worker_LANGUAGE = _CFG["language"]
3890*cda5da8dSAndroid Build Coastguard Worker
3891*cda5da8dSAndroid Build Coastguard Workertry:
3892*cda5da8dSAndroid Build Coastguard Worker    if _LANGUAGE != "english":
3893*cda5da8dSAndroid Build Coastguard Worker        read_docstrings(_LANGUAGE)
3894*cda5da8dSAndroid Build Coastguard Workerexcept ImportError:
3895*cda5da8dSAndroid Build Coastguard Worker    print("Cannot find docsdict for", _LANGUAGE)
3896*cda5da8dSAndroid Build Coastguard Workerexcept Exception:
3897*cda5da8dSAndroid Build Coastguard Worker    print ("Unknown Error when trying to import %s-docstring-dictionary" %
3898*cda5da8dSAndroid Build Coastguard Worker                                                                  _LANGUAGE)
3899*cda5da8dSAndroid Build Coastguard Worker
3900*cda5da8dSAndroid Build Coastguard Worker
3901*cda5da8dSAndroid Build Coastguard Workerdef getmethparlist(ob):
3902*cda5da8dSAndroid Build Coastguard Worker    """Get strings describing the arguments for the given object
3903*cda5da8dSAndroid Build Coastguard Worker
3904*cda5da8dSAndroid Build Coastguard Worker    Returns a pair of strings representing function parameter lists
3905*cda5da8dSAndroid Build Coastguard Worker    including parenthesis.  The first string is suitable for use in
3906*cda5da8dSAndroid Build Coastguard Worker    function definition and the second is suitable for use in function
3907*cda5da8dSAndroid Build Coastguard Worker    call.  The "self" parameter is not included.
3908*cda5da8dSAndroid Build Coastguard Worker    """
3909*cda5da8dSAndroid Build Coastguard Worker    defText = callText = ""
3910*cda5da8dSAndroid Build Coastguard Worker    # bit of a hack for methods - turn it into a function
3911*cda5da8dSAndroid Build Coastguard Worker    # but we drop the "self" param.
3912*cda5da8dSAndroid Build Coastguard Worker    # Try and build one for Python defined functions
3913*cda5da8dSAndroid Build Coastguard Worker    args, varargs, varkw = inspect.getargs(ob.__code__)
3914*cda5da8dSAndroid Build Coastguard Worker    items2 = args[1:]
3915*cda5da8dSAndroid Build Coastguard Worker    realArgs = args[1:]
3916*cda5da8dSAndroid Build Coastguard Worker    defaults = ob.__defaults__ or []
3917*cda5da8dSAndroid Build Coastguard Worker    defaults = ["=%r" % (value,) for value in defaults]
3918*cda5da8dSAndroid Build Coastguard Worker    defaults = [""] * (len(realArgs)-len(defaults)) + defaults
3919*cda5da8dSAndroid Build Coastguard Worker    items1 = [arg + dflt for arg, dflt in zip(realArgs, defaults)]
3920*cda5da8dSAndroid Build Coastguard Worker    if varargs is not None:
3921*cda5da8dSAndroid Build Coastguard Worker        items1.append("*" + varargs)
3922*cda5da8dSAndroid Build Coastguard Worker        items2.append("*" + varargs)
3923*cda5da8dSAndroid Build Coastguard Worker    if varkw is not None:
3924*cda5da8dSAndroid Build Coastguard Worker        items1.append("**" + varkw)
3925*cda5da8dSAndroid Build Coastguard Worker        items2.append("**" + varkw)
3926*cda5da8dSAndroid Build Coastguard Worker    defText = ", ".join(items1)
3927*cda5da8dSAndroid Build Coastguard Worker    defText = "(%s)" % defText
3928*cda5da8dSAndroid Build Coastguard Worker    callText = ", ".join(items2)
3929*cda5da8dSAndroid Build Coastguard Worker    callText = "(%s)" % callText
3930*cda5da8dSAndroid Build Coastguard Worker    return defText, callText
3931*cda5da8dSAndroid Build Coastguard Worker
3932*cda5da8dSAndroid Build Coastguard Workerdef _turtle_docrevise(docstr):
3933*cda5da8dSAndroid Build Coastguard Worker    """To reduce docstrings from RawTurtle class for functions
3934*cda5da8dSAndroid Build Coastguard Worker    """
3935*cda5da8dSAndroid Build Coastguard Worker    import re
3936*cda5da8dSAndroid Build Coastguard Worker    if docstr is None:
3937*cda5da8dSAndroid Build Coastguard Worker        return None
3938*cda5da8dSAndroid Build Coastguard Worker    turtlename = _CFG["exampleturtle"]
3939*cda5da8dSAndroid Build Coastguard Worker    newdocstr = docstr.replace("%s." % turtlename,"")
3940*cda5da8dSAndroid Build Coastguard Worker    parexp = re.compile(r' \(.+ %s\):' % turtlename)
3941*cda5da8dSAndroid Build Coastguard Worker    newdocstr = parexp.sub(":", newdocstr)
3942*cda5da8dSAndroid Build Coastguard Worker    return newdocstr
3943*cda5da8dSAndroid Build Coastguard Worker
3944*cda5da8dSAndroid Build Coastguard Workerdef _screen_docrevise(docstr):
3945*cda5da8dSAndroid Build Coastguard Worker    """To reduce docstrings from TurtleScreen class for functions
3946*cda5da8dSAndroid Build Coastguard Worker    """
3947*cda5da8dSAndroid Build Coastguard Worker    import re
3948*cda5da8dSAndroid Build Coastguard Worker    if docstr is None:
3949*cda5da8dSAndroid Build Coastguard Worker        return None
3950*cda5da8dSAndroid Build Coastguard Worker    screenname = _CFG["examplescreen"]
3951*cda5da8dSAndroid Build Coastguard Worker    newdocstr = docstr.replace("%s." % screenname,"")
3952*cda5da8dSAndroid Build Coastguard Worker    parexp = re.compile(r' \(.+ %s\):' % screenname)
3953*cda5da8dSAndroid Build Coastguard Worker    newdocstr = parexp.sub(":", newdocstr)
3954*cda5da8dSAndroid Build Coastguard Worker    return newdocstr
3955*cda5da8dSAndroid Build Coastguard Worker
3956*cda5da8dSAndroid Build Coastguard Worker## The following mechanism makes all methods of RawTurtle and Turtle available
3957*cda5da8dSAndroid Build Coastguard Worker## as functions. So we can enhance, change, add, delete methods to these
3958*cda5da8dSAndroid Build Coastguard Worker## classes and do not need to change anything here.
3959*cda5da8dSAndroid Build Coastguard Worker
3960*cda5da8dSAndroid Build Coastguard Worker__func_body = """\
3961*cda5da8dSAndroid Build Coastguard Workerdef {name}{paramslist}:
3962*cda5da8dSAndroid Build Coastguard Worker    if {obj} is None:
3963*cda5da8dSAndroid Build Coastguard Worker        if not TurtleScreen._RUNNING:
3964*cda5da8dSAndroid Build Coastguard Worker            TurtleScreen._RUNNING = True
3965*cda5da8dSAndroid Build Coastguard Worker            raise Terminator
3966*cda5da8dSAndroid Build Coastguard Worker        {obj} = {init}
3967*cda5da8dSAndroid Build Coastguard Worker    try:
3968*cda5da8dSAndroid Build Coastguard Worker        return {obj}.{name}{argslist}
3969*cda5da8dSAndroid Build Coastguard Worker    except TK.TclError:
3970*cda5da8dSAndroid Build Coastguard Worker        if not TurtleScreen._RUNNING:
3971*cda5da8dSAndroid Build Coastguard Worker            TurtleScreen._RUNNING = True
3972*cda5da8dSAndroid Build Coastguard Worker            raise Terminator
3973*cda5da8dSAndroid Build Coastguard Worker        raise
3974*cda5da8dSAndroid Build Coastguard Worker"""
3975*cda5da8dSAndroid Build Coastguard Worker
3976*cda5da8dSAndroid Build Coastguard Workerdef _make_global_funcs(functions, cls, obj, init, docrevise):
3977*cda5da8dSAndroid Build Coastguard Worker    for methodname in functions:
3978*cda5da8dSAndroid Build Coastguard Worker        method = getattr(cls, methodname)
3979*cda5da8dSAndroid Build Coastguard Worker        pl1, pl2 = getmethparlist(method)
3980*cda5da8dSAndroid Build Coastguard Worker        if pl1 == "":
3981*cda5da8dSAndroid Build Coastguard Worker            print(">>>>>>", pl1, pl2)
3982*cda5da8dSAndroid Build Coastguard Worker            continue
3983*cda5da8dSAndroid Build Coastguard Worker        defstr = __func_body.format(obj=obj, init=init, name=methodname,
3984*cda5da8dSAndroid Build Coastguard Worker                                    paramslist=pl1, argslist=pl2)
3985*cda5da8dSAndroid Build Coastguard Worker        exec(defstr, globals())
3986*cda5da8dSAndroid Build Coastguard Worker        globals()[methodname].__doc__ = docrevise(method.__doc__)
3987*cda5da8dSAndroid Build Coastguard Worker
3988*cda5da8dSAndroid Build Coastguard Worker_make_global_funcs(_tg_screen_functions, _Screen,
3989*cda5da8dSAndroid Build Coastguard Worker                   'Turtle._screen', 'Screen()', _screen_docrevise)
3990*cda5da8dSAndroid Build Coastguard Worker_make_global_funcs(_tg_turtle_functions, Turtle,
3991*cda5da8dSAndroid Build Coastguard Worker                   'Turtle._pen', 'Turtle()', _turtle_docrevise)
3992*cda5da8dSAndroid Build Coastguard Worker
3993*cda5da8dSAndroid Build Coastguard Worker
3994*cda5da8dSAndroid Build Coastguard Workerdone = mainloop
3995*cda5da8dSAndroid Build Coastguard Worker
3996*cda5da8dSAndroid Build Coastguard Workerif __name__ == "__main__":
3997*cda5da8dSAndroid Build Coastguard Worker    def switchpen():
3998*cda5da8dSAndroid Build Coastguard Worker        if isdown():
3999*cda5da8dSAndroid Build Coastguard Worker            pu()
4000*cda5da8dSAndroid Build Coastguard Worker        else:
4001*cda5da8dSAndroid Build Coastguard Worker            pd()
4002*cda5da8dSAndroid Build Coastguard Worker
4003*cda5da8dSAndroid Build Coastguard Worker    def demo1():
4004*cda5da8dSAndroid Build Coastguard Worker        """Demo of old turtle.py - module"""
4005*cda5da8dSAndroid Build Coastguard Worker        reset()
4006*cda5da8dSAndroid Build Coastguard Worker        tracer(True)
4007*cda5da8dSAndroid Build Coastguard Worker        up()
4008*cda5da8dSAndroid Build Coastguard Worker        backward(100)
4009*cda5da8dSAndroid Build Coastguard Worker        down()
4010*cda5da8dSAndroid Build Coastguard Worker        # draw 3 squares; the last filled
4011*cda5da8dSAndroid Build Coastguard Worker        width(3)
4012*cda5da8dSAndroid Build Coastguard Worker        for i in range(3):
4013*cda5da8dSAndroid Build Coastguard Worker            if i == 2:
4014*cda5da8dSAndroid Build Coastguard Worker                begin_fill()
4015*cda5da8dSAndroid Build Coastguard Worker            for _ in range(4):
4016*cda5da8dSAndroid Build Coastguard Worker                forward(20)
4017*cda5da8dSAndroid Build Coastguard Worker                left(90)
4018*cda5da8dSAndroid Build Coastguard Worker            if i == 2:
4019*cda5da8dSAndroid Build Coastguard Worker                color("maroon")
4020*cda5da8dSAndroid Build Coastguard Worker                end_fill()
4021*cda5da8dSAndroid Build Coastguard Worker            up()
4022*cda5da8dSAndroid Build Coastguard Worker            forward(30)
4023*cda5da8dSAndroid Build Coastguard Worker            down()
4024*cda5da8dSAndroid Build Coastguard Worker        width(1)
4025*cda5da8dSAndroid Build Coastguard Worker        color("black")
4026*cda5da8dSAndroid Build Coastguard Worker        # move out of the way
4027*cda5da8dSAndroid Build Coastguard Worker        tracer(False)
4028*cda5da8dSAndroid Build Coastguard Worker        up()
4029*cda5da8dSAndroid Build Coastguard Worker        right(90)
4030*cda5da8dSAndroid Build Coastguard Worker        forward(100)
4031*cda5da8dSAndroid Build Coastguard Worker        right(90)
4032*cda5da8dSAndroid Build Coastguard Worker        forward(100)
4033*cda5da8dSAndroid Build Coastguard Worker        right(180)
4034*cda5da8dSAndroid Build Coastguard Worker        down()
4035*cda5da8dSAndroid Build Coastguard Worker        # some text
4036*cda5da8dSAndroid Build Coastguard Worker        write("startstart", 1)
4037*cda5da8dSAndroid Build Coastguard Worker        write("start", 1)
4038*cda5da8dSAndroid Build Coastguard Worker        color("red")
4039*cda5da8dSAndroid Build Coastguard Worker        # staircase
4040*cda5da8dSAndroid Build Coastguard Worker        for i in range(5):
4041*cda5da8dSAndroid Build Coastguard Worker            forward(20)
4042*cda5da8dSAndroid Build Coastguard Worker            left(90)
4043*cda5da8dSAndroid Build Coastguard Worker            forward(20)
4044*cda5da8dSAndroid Build Coastguard Worker            right(90)
4045*cda5da8dSAndroid Build Coastguard Worker        # filled staircase
4046*cda5da8dSAndroid Build Coastguard Worker        tracer(True)
4047*cda5da8dSAndroid Build Coastguard Worker        begin_fill()
4048*cda5da8dSAndroid Build Coastguard Worker        for i in range(5):
4049*cda5da8dSAndroid Build Coastguard Worker            forward(20)
4050*cda5da8dSAndroid Build Coastguard Worker            left(90)
4051*cda5da8dSAndroid Build Coastguard Worker            forward(20)
4052*cda5da8dSAndroid Build Coastguard Worker            right(90)
4053*cda5da8dSAndroid Build Coastguard Worker        end_fill()
4054*cda5da8dSAndroid Build Coastguard Worker        # more text
4055*cda5da8dSAndroid Build Coastguard Worker
4056*cda5da8dSAndroid Build Coastguard Worker    def demo2():
4057*cda5da8dSAndroid Build Coastguard Worker        """Demo of some new features."""
4058*cda5da8dSAndroid Build Coastguard Worker        speed(1)
4059*cda5da8dSAndroid Build Coastguard Worker        st()
4060*cda5da8dSAndroid Build Coastguard Worker        pensize(3)
4061*cda5da8dSAndroid Build Coastguard Worker        setheading(towards(0, 0))
4062*cda5da8dSAndroid Build Coastguard Worker        radius = distance(0, 0)/2.0
4063*cda5da8dSAndroid Build Coastguard Worker        rt(90)
4064*cda5da8dSAndroid Build Coastguard Worker        for _ in range(18):
4065*cda5da8dSAndroid Build Coastguard Worker            switchpen()
4066*cda5da8dSAndroid Build Coastguard Worker            circle(radius, 10)
4067*cda5da8dSAndroid Build Coastguard Worker        write("wait a moment...")
4068*cda5da8dSAndroid Build Coastguard Worker        while undobufferentries():
4069*cda5da8dSAndroid Build Coastguard Worker            undo()
4070*cda5da8dSAndroid Build Coastguard Worker        reset()
4071*cda5da8dSAndroid Build Coastguard Worker        lt(90)
4072*cda5da8dSAndroid Build Coastguard Worker        colormode(255)
4073*cda5da8dSAndroid Build Coastguard Worker        laenge = 10
4074*cda5da8dSAndroid Build Coastguard Worker        pencolor("green")
4075*cda5da8dSAndroid Build Coastguard Worker        pensize(3)
4076*cda5da8dSAndroid Build Coastguard Worker        lt(180)
4077*cda5da8dSAndroid Build Coastguard Worker        for i in range(-2, 16):
4078*cda5da8dSAndroid Build Coastguard Worker            if i > 0:
4079*cda5da8dSAndroid Build Coastguard Worker                begin_fill()
4080*cda5da8dSAndroid Build Coastguard Worker                fillcolor(255-15*i, 0, 15*i)
4081*cda5da8dSAndroid Build Coastguard Worker            for _ in range(3):
4082*cda5da8dSAndroid Build Coastguard Worker                fd(laenge)
4083*cda5da8dSAndroid Build Coastguard Worker                lt(120)
4084*cda5da8dSAndroid Build Coastguard Worker            end_fill()
4085*cda5da8dSAndroid Build Coastguard Worker            laenge += 10
4086*cda5da8dSAndroid Build Coastguard Worker            lt(15)
4087*cda5da8dSAndroid Build Coastguard Worker            speed((speed()+1)%12)
4088*cda5da8dSAndroid Build Coastguard Worker        #end_fill()
4089*cda5da8dSAndroid Build Coastguard Worker
4090*cda5da8dSAndroid Build Coastguard Worker        lt(120)
4091*cda5da8dSAndroid Build Coastguard Worker        pu()
4092*cda5da8dSAndroid Build Coastguard Worker        fd(70)
4093*cda5da8dSAndroid Build Coastguard Worker        rt(30)
4094*cda5da8dSAndroid Build Coastguard Worker        pd()
4095*cda5da8dSAndroid Build Coastguard Worker        color("red","yellow")
4096*cda5da8dSAndroid Build Coastguard Worker        speed(0)
4097*cda5da8dSAndroid Build Coastguard Worker        begin_fill()
4098*cda5da8dSAndroid Build Coastguard Worker        for _ in range(4):
4099*cda5da8dSAndroid Build Coastguard Worker            circle(50, 90)
4100*cda5da8dSAndroid Build Coastguard Worker            rt(90)
4101*cda5da8dSAndroid Build Coastguard Worker            fd(30)
4102*cda5da8dSAndroid Build Coastguard Worker            rt(90)
4103*cda5da8dSAndroid Build Coastguard Worker        end_fill()
4104*cda5da8dSAndroid Build Coastguard Worker        lt(90)
4105*cda5da8dSAndroid Build Coastguard Worker        pu()
4106*cda5da8dSAndroid Build Coastguard Worker        fd(30)
4107*cda5da8dSAndroid Build Coastguard Worker        pd()
4108*cda5da8dSAndroid Build Coastguard Worker        shape("turtle")
4109*cda5da8dSAndroid Build Coastguard Worker
4110*cda5da8dSAndroid Build Coastguard Worker        tri = getturtle()
4111*cda5da8dSAndroid Build Coastguard Worker        tri.resizemode("auto")
4112*cda5da8dSAndroid Build Coastguard Worker        turtle = Turtle()
4113*cda5da8dSAndroid Build Coastguard Worker        turtle.resizemode("auto")
4114*cda5da8dSAndroid Build Coastguard Worker        turtle.shape("turtle")
4115*cda5da8dSAndroid Build Coastguard Worker        turtle.reset()
4116*cda5da8dSAndroid Build Coastguard Worker        turtle.left(90)
4117*cda5da8dSAndroid Build Coastguard Worker        turtle.speed(0)
4118*cda5da8dSAndroid Build Coastguard Worker        turtle.up()
4119*cda5da8dSAndroid Build Coastguard Worker        turtle.goto(280, 40)
4120*cda5da8dSAndroid Build Coastguard Worker        turtle.lt(30)
4121*cda5da8dSAndroid Build Coastguard Worker        turtle.down()
4122*cda5da8dSAndroid Build Coastguard Worker        turtle.speed(6)
4123*cda5da8dSAndroid Build Coastguard Worker        turtle.color("blue","orange")
4124*cda5da8dSAndroid Build Coastguard Worker        turtle.pensize(2)
4125*cda5da8dSAndroid Build Coastguard Worker        tri.speed(6)
4126*cda5da8dSAndroid Build Coastguard Worker        setheading(towards(turtle))
4127*cda5da8dSAndroid Build Coastguard Worker        count = 1
4128*cda5da8dSAndroid Build Coastguard Worker        while tri.distance(turtle) > 4:
4129*cda5da8dSAndroid Build Coastguard Worker            turtle.fd(3.5)
4130*cda5da8dSAndroid Build Coastguard Worker            turtle.lt(0.6)
4131*cda5da8dSAndroid Build Coastguard Worker            tri.setheading(tri.towards(turtle))
4132*cda5da8dSAndroid Build Coastguard Worker            tri.fd(4)
4133*cda5da8dSAndroid Build Coastguard Worker            if count % 20 == 0:
4134*cda5da8dSAndroid Build Coastguard Worker                turtle.stamp()
4135*cda5da8dSAndroid Build Coastguard Worker                tri.stamp()
4136*cda5da8dSAndroid Build Coastguard Worker                switchpen()
4137*cda5da8dSAndroid Build Coastguard Worker            count += 1
4138*cda5da8dSAndroid Build Coastguard Worker        tri.write("CAUGHT! ", font=("Arial", 16, "bold"), align="right")
4139*cda5da8dSAndroid Build Coastguard Worker        tri.pencolor("black")
4140*cda5da8dSAndroid Build Coastguard Worker        tri.pencolor("red")
4141*cda5da8dSAndroid Build Coastguard Worker
4142*cda5da8dSAndroid Build Coastguard Worker        def baba(xdummy, ydummy):
4143*cda5da8dSAndroid Build Coastguard Worker            clearscreen()
4144*cda5da8dSAndroid Build Coastguard Worker            bye()
4145*cda5da8dSAndroid Build Coastguard Worker
4146*cda5da8dSAndroid Build Coastguard Worker        time.sleep(2)
4147*cda5da8dSAndroid Build Coastguard Worker
4148*cda5da8dSAndroid Build Coastguard Worker        while undobufferentries():
4149*cda5da8dSAndroid Build Coastguard Worker            tri.undo()
4150*cda5da8dSAndroid Build Coastguard Worker            turtle.undo()
4151*cda5da8dSAndroid Build Coastguard Worker        tri.fd(50)
4152*cda5da8dSAndroid Build Coastguard Worker        tri.write("  Click me!", font = ("Courier", 12, "bold") )
4153*cda5da8dSAndroid Build Coastguard Worker        tri.onclick(baba, 1)
4154*cda5da8dSAndroid Build Coastguard Worker
4155*cda5da8dSAndroid Build Coastguard Worker    demo1()
4156*cda5da8dSAndroid Build Coastguard Worker    demo2()
4157*cda5da8dSAndroid Build Coastguard Worker    exitonclick()
4158