diff --git a/adafruit_turtle.py b/adafruit_turtle.py index 9f98534..298ff96 100644 --- a/adafruit_turtle.py +++ b/adafruit_turtle.py @@ -46,7 +46,8 @@ * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice """ -#pylint:disable=too-many-public-methods,invalid-name,too-many-instance-attributes,too-few-public-methods +#pylint:disable=too-many-public-methods,invalid-name,too-many-instance-attributes +#pylint:disable=too-few-public-methods,too-many-lines import gc import math @@ -196,7 +197,9 @@ def _drawturtle(self): self._turtle_sprite.y = int(self._y - 4) #self._logger.debug("pos (%d, %d)", self._x, self._y) - # Turtle motion + ############################################################################ + # Move and draw + def forward(self, distance): """Move the turtle forward by the specified distance, in the direction the turtle is headed. @@ -219,18 +222,6 @@ def backward(self, distance): bk = backward back = backward - def degrees(self, fullcircle=360): - """Set angle measurement units, i.e. set number of "degrees" for a full circle. - Default value is 360 degrees. - - :param fullcircle: the number of degrees in a full circle - """ - raise NotImplementedError - - def radians(self): - """Set the angle measurement units to radians. Equivalent to degrees(2*math.pi).""" - raise NotImplementedError - def right(self, angle): """Turn turtle right by angle units. (Units are by default degrees, but can be set via the degrees() and radians() functions.) @@ -367,7 +358,9 @@ def home(self): self.goto(0, 0) def circle(self, radius, extent=None, steps=None): - """Draw a circle with given radius. The center is radius units left of + """Not implemented + + Draw a circle with given radius. The center is radius units left of the turtle; extent - an angle - determines which part of the circle is drawn. If extent is not given, draw the entire circle. If extent is not a full circle, one endpoint of the arc is the current pen position. @@ -388,7 +381,9 @@ def circle(self, radius, extent=None, steps=None): #pylint:disable=keyword-arg-before-vararg def dot(self, size=None, *color): - """Draw a circular dot with diameter size, using color. + """Not implemented + + Draw a circular dot with diameter size, using color. If size is not given, the maximum of pensize+4 and 2*pensize is used. @@ -399,14 +394,18 @@ def dot(self, size=None, *color): raise NotImplementedError def stamp(self): - """Stamp a copy of the turtle shape onto the canvas at the current + """Not implemented + + Stamp a copy of the turtle shape onto the canvas at the current turtle position. Return a stamp_id for that stamp, which can be used to delete it by calling clearstamp(stamp_id). """ raise NotImplementedError def clearstamp(self, stampid): - """Delete stamp with given stampid. + """Not implemented + + Delete stamp with given stampid. :param stampid: the id of the stamp to be deleted @@ -414,7 +413,9 @@ def clearstamp(self, stampid): raise NotImplementedError def clearstamps(self, n=None): - """Delete all or first/last n of turtle's stamps. If n is None, delete + """Not implemented + + Delete all or first/last n of turtle's stamps. If n is None, delete all stamps, if n > 0 delete first n stamps, else if n < 0 delete last n stamps. @@ -424,13 +425,17 @@ def clearstamps(self, n=None): raise NotImplementedError def undo(self): - """Undo (repeatedly) the last turtle action(s). Number of available undo + """Not implemented + + Undo (repeatedly) the last turtle action(s). Number of available undo actions is determined by the size of the undobuffer. """ raise NotImplementedError def speed(self, speed=None): - """Set the turtle's speed to an integer value in the range 0..10. If no + """Not implemented + + Set the turtle's speed to an integer value in the range 0..10. If no argument is given, return current speed. If input is a number greater than 10 or smaller than 0.5, speed is set @@ -454,34 +459,80 @@ def speed(self, speed=None): raise NotImplementedError - #################### + ############################################################################ # Tell turtle's state + def pos(self): """Return the turtle's current location (x,y) (as a Vec2D vector).""" return Vec2D(self._x - self._w // 2, self._h // 2 - self._y) position = pos - def clear(self): - """Delete the turtle's drawings from the screen. Do not move turtle. - State and position of the turtle as well as drawings of other turtles - are not affected. + def towards(self, x1, y1=None): + """Not implemented + + Return the angle between the line from turtle position to position + specified by (x,y) or the vector. This depends on the turtle's start + orientation which depends on the mode - "standard" or "logo"). + + :param x: a number or a pair/vector of numbers + :param y: a number if x is a number, else None + """ - for w in range(self._w): - for h in range(self._h): - self._fg_bitmap[w, h] = 0 - for i, c in enumerate(Color.colors): - self._fg_palette[i + 1] = c ^ 0xFFFFFF - self._display.refresh_soon() - for i, c in enumerate(Color.colors): - self._fg_palette[i + 1] = c - self._display.refresh_soon() - time.sleep(0.1) + raise NotImplementedError + + def xcor(self): + """Not implemented + + Return the turtle's x coordinate.""" + raise NotImplementedError + + def ycor(self): + """Not implemented + + Return the turtle's y coordinate.""" + raise NotImplementedError def heading(self): - """Return the turtle's current heading (value depends on the turtle mode, see mode()).""" + """Return the turtle's current heading (value depends on the turtle + mode, see mode()). + """ return self._heading - # Pen control + def distance(self, x1, y1=None): + """Not implemented + + Return the distance from the turtle to (x,y) or the vector, in turtle + step units. + + :param x: a number or a pair/vector of numbers + :param y: a number if x is a number, else None + + """ + raise NotImplementedError + + ############################################################################ + # Setting and measurement + + def degrees(self, fullcircle=360): + """Not implemented + + Set angle measurement units, i.e. set number of "degrees" for a full circle. + Default value is 360 degrees. + + :param fullcircle: the number of degrees in a full circle + """ + raise NotImplementedError + + def radians(self): + """Not implemented + + Set the angle measurement units to radians. Equivalent to degrees(2*math.pi).""" + raise NotImplementedError + + + ############################################################################ + # Drawing state + def pendown(self): """Pull the pen down - drawing when moving.""" self._penstate = True @@ -494,16 +545,108 @@ def penup(self): pu = penup up = penup + def pensize(self, width=None): + """Not implemented + + Set the line thickness to width or return it. If resizemode is set to + "auto" and turtleshape is a polygon, that polygon is drawn with the same + line thickness. If no argument is given, the current pensize is returned. + + :param width: - a positive number + + """ + raise NotImplementedError + width = pensize + + def pen(self, pen=None, **pendict): + """Not implemented + + Not implemented + + Return or set the pen's attributes in a "pen-dictionary" with + the following key/value pairs: + + "shown": True/False + "pendown": True/False + "pencolor": color-string or color-tuple + "fillcolor": color-string or color-tuple + "pensize": positive number + "speed": number in range 0..10 + "resizemode": "auto" or "user" or "noresize" + "stretchfactor": (positive number, positive number) + "outline": positive number + "tilt": number + + This dictionary can be used as argument for a subsequent call to pen() + to restore the former pen-state. Moreover one or more of these + attributes can be provided as keyword-arguments. This can be used to + set several pen attributes in one statement. + + :param pen: a dictionary with some or all of the above listed keys + :param pendict: ne or more keyword-arguments with the above listed keys + as keywords + """ + + raise NotImplementedError + def isdown(self): """Return True if pen is down, False if it's up.""" return self._penstate + ############################################################################ + # Color control + + def color(self, *args): + """Not implemented + + Return or set pencolor and fillcolor. + + Several input formats are allowed. They use 0 to 3 arguments as follows: + + color() + Return the current pencolor and the current fillcolor as a pair of + color specification strings or tuples as returned by pencolor() and + fillcolor(). + + color(colorstring), color((r, g, b)), color(r, g, b) + Inputs as in pencolor(), set both, fillcolor and pencolor, to the + given value. + + color(colorstring1, colorstring2), color((r1, g1, b1), (r2, g2, b2)) + Equivalent to pencolor(colorstring1) and fillcolor(colorstring2) + and analogously if the other input format is used. + + If turtleshape is a polygon, outline and interior of that polygon is + drawn with the newly set colors. + """ + raise NotImplementedError + def pencolor(self, c=None): """ Return or set the pencolor. - :param c: the color to which to set the pen, - None will cause the color to be returned + Four input formats are allowed: + + pencolor() + Return the current pencolor as color specification string or as a + tuple (see example). May be used as input to another color/ + pencolor/fillcolor call. + + pencolor(colorstring) + Set pencolor to colorstring, which is a Tk color specification + string, such as "red", "yellow", or "#33cc8c". + + pencolor((r, g, b)) + Set pencolor to the RGB color represented by the tuple of r, g, and + b. Each of r, g, and b must be in the range 0..colormode, where + colormode is either 1.0 or 255 (see colormode()). + + pencolor(r, g, b) + Set pencolor to the RGB color represented by r, g, and b. Each of r, + g, and b must be in the range 0..colormode. + + If turtleshape is a polygon, the outline of that polygon is drawn with + the newly set pencolor. """ if c is None: return Color.colors[self._pencolor - 1] @@ -512,9 +655,399 @@ def pencolor(self, c=None): self._pencolor = 1 + Color.colors.index(c) return c + def fillcolor(self, c=None): + """Not implemented + + Return or set the fillcolor. + + Four input formats are allowed: + + fillcolor() + Return the current fillcolor as color specification string, possibly + in tuple format (see example). May be used as input to another + color/pencolor/fillcolor call. + + fillcolor(colorstring) + Set fillcolor to colorstring, which is a Tk color specification + string, such as "red", "yellow", or "#33cc8c". + + fillcolor((r, g, b)) + Set fillcolor to the RGB color represented by the tuple of r, g, and + b. Each of r, g, and b must be in the range 0..colormode, where + colormode is either 1.0 or 255 (see colormode()). + + fillcolor(r, g, b) + Set fillcolor to the RGB color represented by r, g, and b. Each of + r, g, and b must be in the range 0..colormode. + + If turtleshape is a polygon, the interior of that polygon is drawn with + the newly set fillcolor. + """ + raise NotImplementedError + + ############################################################################ + # Filling + + def filling(self): + """Not implemented + + Return fillstate (True if filling, False else).""" + raise NotImplementedError + + def begin_fill(self): + """Not implemented + + To be called just before drawing a shape to be filled.""" + raise NotImplementedError + + def end_fill(self): + """Not implemented + + Fill the shape drawn after the last call to begin_fill().""" + raise NotImplementedError + + ############################################################################ + # More drawing control + + def reset(self): + """Not implemented + + Delete the turtle's drawings from the screen, re-center the turtle + and set variables to the default values.""" + raise NotImplementedError + + def clear(self): + """Delete the turtle's drawings from the screen. Do not move turtle. + State and position of the turtle as well as drawings of other turtles + are not affected. + """ + for w in range(self._w): + for h in range(self._h): + self._fg_bitmap[w, h] = 0 + for i, c in enumerate(Color.colors): + self._fg_palette[i + 1] = c ^ 0xFFFFFF + self._display.refresh_soon() + for i, c in enumerate(Color.colors): + self._fg_palette[i + 1] = c + self._display.refresh_soon() + time.sleep(0.1) + + def write(self, arg, move=False, align="left", font=("Arial", 8, "normal")): + """Not implemented + + Write text - the string representation of arg - at the current turtle + position according to align ("left", "center" or "right") and with the + given font. If move is true, the pen is moved to the bottom-right corner + of the text. By default, move is False. + + :param arg: object to be written to the TurtleScreen + :param move": True/False + :param align: one of the strings "left", "center" or "right" + :param font: a triple (fontname, fontsize, fonttype) + + """ + raise NotImplementedError + + ############################################################################ + # Visibility + + def showturtle(self): + """Not implemented + + Make the turtle visible.""" + raise NotImplementedError + st = showturtle + + def hideturtle(self): + """Not implemented + + Make the turtle invisible.""" + raise NotImplementedError + ht = hideturtle + + def isvisible(self): + """Not implemented + + Return True if the Turtle is shown, False if it's hidden.""" + raise NotImplementedError + + ############################################################################ + # Appearance + + def shape(self, name=None): + """Not implemented + + Set turtle shape to shape with given name or, if name is not + given, return name of current shape. Shape with name must exist + in the TurtleScreen's shape dictionary. Initially there are the + following polygon shapes: "arrow", "turtle", "circle", "square", + "triangle", "classic". To learn about how to deal with shapes + see Screen method register_shape(). + + :param name: a string which is a valid shapename + + """ + raise NotImplementedError + + def resizemode(self, rmode=None): + """Not implemented + + Set resizemode to one of the values: "auto", "user", + + "noresize". If rmode is not given, return current + resizemode. Different resizemodes have the following effects: + + "auto": adapts the appearance of the turtle corresponding to the value + of pensize. + + "user": adapts the appearance of the turtle according to the values of + stretchfactor and outlinewidth (outline), which are set by shapesize(). + + "noresize": no adaption of the turtle's appearance takes place. + + resizemode("user") is called by shapesize() when used with arguments. + + :param rmode: one of the strings "auto", "user", or "noresize" + + """ + raise NotImplementedError + + def shapesize(self, stretch_wid=None, stretch_len=None, outline=None): + """Not implemented + + Return or set the pen's attributes x/y-stretchfactors and/or + outline. Set resizemode to "user". If and only if resizemode is + set to "user", the turtle will be displayed stretched according + to its stretchfactors: stretch_wid is stretchfactor + perpendicular to its orientation, stretch_len is stretchfactor + in direction of its orientation, outline determines the width of + the shapes's outline. + + :param stretch_wid: positive number + :param stretch_len: positive number + :param outline: positive number + + """ + raise NotImplementedError + turtlesize = shapesize + + def sheerfactor(self, shear=None): + """Not implemented + + Set or return the current shearfactor. Shear the turtleshape + according to the given shearfactor shear, which is the tangent + of the shear angle. Do not change the turtle's heading + (direction of movement). If shear is not given: return the + current shearfactor, i. e. the tangent of the shear angle, by + which lines parallel to the heading of the turtle are sheared. + + :param shear: number (optional) + + """ + raise NotImplementedError + + def settiltangle(self, angle): + """Not implemented + + Rotate the turtleshape to point in the direction specified by + angle, regardless of its current tilt-angle. Do not change the + turtle's heading (direction of movement). + + :param angle: a number + + """ + raise NotImplementedError + + def tiltangle(self, angle=None): + """Not implemented + + Set or return the current tilt-angle. If angle is given, + rotate the turtleshape to point in the direction specified by + angle, regardless of its current tilt-angle. Do not change the + turtle's heading (direction of movement). If angle is not given: + return the current tilt-angle, i. e. the angle between the + orientation of the turtleshape and the heading of the turtle + (its direction of movement). + + :param angle: a number (optional) + + """ + raise NotImplementedError + + def tilt(self, angle): + """Not implemented + + Rotate the turtleshape by angle from its current tilt-angle, + but do not change the turtle's heading (direction of movement). + + :param angle: a number + """ + raise NotImplementedError + + def shapetransform(self, t11=None, t12=None, t21=None, t22=None): + """Not implemented + + Set or return the current transformation matrix of the turtle shape. + + If none of the matrix elements are given, return the transformation + matrix as a tuple of 4 elements. Otherwise set the given elements and + transform the turtleshape according to the matrix consisting of first + row t11, t12 and second row t21, 22. The determinant t11 * t22 - t12 * + t21 must not be zero, otherwise an error is raised. Modify + stretchfactor, shearfactor and tiltangle according to the given matrix. + + :param t11: a number (optional) + :param t12: a number (optional) + :param t21: a number (optional) + :param t12: a number (optional) + + """ + raise NotImplementedError + + def get_shapepoly(self): + """Not implemented + + Return the current shape polygon as tuple of coordinate + pairs. This can be used to define a new shape or components of a + compound shape. + """ + raise NotImplementedError + + ############################################################################ + # Using events + + def onclick(self, fun, btn=1, add=None): + """Not implemented + + Bind fun to mouse-click events on this turtle. If fun is + + None, existing bindings are removed. + + :param fun: a function with two arguments which will be called with the + coordinates of the clicked point on the canvas + + :param btn: number of the mouse-button, defaults to 1 (left mouse button) + + :param add: True or False - if True, a new binding will be added, + otherwise it will replace a former binding + + """ + raise NotImplementedError + + def onrelease(self, fun, btn=1, add=None): + """Not implemented + + Bind fun to mouse-button-release events on this turtle. If + fun is None, existing bindings are removed. + + :param fun: a function with two arguments which will be called with the + coordinates of the clicked point on the canvas + + :param btn: number of the mouse-button, defaults to 1 (left mouse button) + + :param add: True or False - if True, a new binding will be added, + otherwise it will replace a former binding + + """ + raise NotImplementedError + + def ondrag(self, fun, btn=1, add=None): + """Not implemented + + Bind fun to mouse-move events on this turtle. If fun is None, + existing bindings are removed. + + Remark: Every sequence of mouse-move-events on a turtle is + preceded by a mouse-click event on that turtle. + + :param fun: a function with two arguments which will be called with the + coordinates of the clicked point on the canvas + + :param btn: number of the mouse-button, defaults to 1 (left mouse button) + + :param add: True or False - if True, a new binding will be added, + otherwise it will replace a former binding + + """ + raise NotImplementedError + + ############################################################################ + # Special turtle methods + + def begin_poly(self): + """Not implemented + + Start recording the vertices of a polygon. Current turtle + position is first vertex of polygon. + """ + raise NotImplementedError + + def end_poly(self): + """Not implemented + + Stop recording the vertices of a polygon. Current turtle + position is last vertex of polygon. This will be connected with + the first vertex. + """ + raise NotImplementedError + + + def get_poly(self): + """Not implemented + + Return the last recorded polygon.""" + raise NotImplementedError + + def clone(self): + """Not implemented + + Create and return a clone of the turtle with same position, + heading and turtle properties. + """ + raise NotImplementedError + + def getturtle(self): + """Not implemented + + Return the Turtle object itself. Only reasonable use: as a + function to return the "anonymous turtle": + """ + raise NotImplementedError + getpen = getturtle + + def getscreen(self): + """Not implemented + + Return the TurtleScreen object the turtle is drawing + on. TurtleScreen methods can then be called for that object. + """ + raise NotImplementedError + + def setundobuffer(self, size): + """Not implemented + + Set or disable undobuffer. If size is an integer an empty + undobuffer of given size is installed. size gives the maximum + number of turtle actions that can be undone by the undo() + method/function. If size is None, the undobuffer is disabled. + + :param size: an integer or None + + """ + raise NotImplementedError + + def undobufferentries(self): + """Not implemented + + Return number of entries in the undobuffer.""" + raise NotImplementedError + + ############################################################################ + # Settings and special methods + def mode(self, mode=None): """ - Set turtle mode ("standard", "logo" or "world") and perform reset. + Set turtle mode ("standard" or "logo") and perform reset. If mode is not given, current mode is returned. Mode "standard" is compatible with old turtle. @@ -534,6 +1067,80 @@ def mode(self, mode=None): raise RuntimeError("Mode must be 'logo' or 'standard!'") return None + def colormode(self, cmode=None): + """Not implemented + + Return the colormode or set it to 1.0 or 255. Subsequently r, + g, b values of color triples have to be in the range 0..cmode. + + :param cmode: one of the valkues 1.0 or 255 + """ + raise NotImplementedError + + def getcanvas(self): + """Not implemented + + Return the Canvas of this TurtleScreen. Useful for insiders + who know what to do with a Tkinter Canvas. + """ + raise NotImplementedError + + def getshapes(self): + """Not implemented + + Return a list of names of all currently available turtle + shapes. + """ + raise NotImplementedError + + def register_shape(self, name, shape=None): + """Not implemented + + There are three different ways to call this function: + + 1. name is the name of a gif-file and shape is None: Install the + corresponding image shape. + + >>> screen.register_shape("turtle.gif") + + Note: Image shapes do not rotate when turning the turtle, so + they do not display the heading of the turtle! + + 2. name is an arbitrary string and shape is a tuple of pairs of + coordinates: Install the corresponding polygon shape. + + >>> screen.register_shape("triangle", ((5,-3), (0,5), (-5,-3))) + + 3. name is an arbitrary string and shape is a (compound) Shape + object: Install the corresponding compound shape. + + Add a turtle shape to TurtleScreen's shapelist. Only thusly registered + shapes can be used by issuing the command shape(shapename). + """ + raise NotImplementedError + addshape = register_shape + + def turtles(self): + """Not implemented + + Return the list of turtles on the screen.""" + raise NotImplementedError + + def window_height(self): + """Not implemented + + Return the height of the turtle window.""" + raise NotImplementedError + + def window_width(self): + """Not implemented + + Return the width of the turtle window.""" + raise NotImplementedError + + ############################################################################ + # Other + def _turn(self, angle): if self._logomode: self._heading -= angle