ยปCore Development>Code coverage>Lib/lib-tk/turtle.py

Python code coverage for Lib/lib-tk/turtle.py

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