home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pytho152.zip / emx / lib / python1.5 / turtle.py < prev    next >
Text File  |  2000-08-10  |  11KB  |  344 lines

  1. # LogoMation-like turtle graphics
  2.  
  3. from math import * # Also for export
  4. import Tkinter
  5. Tk = Tkinter
  6. Error = Exception
  7.  
  8. class RawPen:
  9.  
  10.     def __init__(self, canvas):
  11.         self._canvas = canvas
  12.         self._items = []
  13.         self._tracing = 1
  14.         self.degrees()
  15.         self.reset()
  16.  
  17.     def degrees(self, fullcircle=360.0):
  18.         self._fullcircle = fullcircle
  19.         self._invradian = pi / (fullcircle * 0.5)
  20.  
  21.     def radians(self):
  22.         self.degrees(2.0*pi)
  23.  
  24.     def reset(self):
  25.         canvas = self._canvas
  26.         width = canvas.winfo_width()
  27.         height = canvas.winfo_height()
  28.         if width <= 1:
  29.             width = canvas['width']
  30.         if height <= 1:
  31.             height = canvas['height']
  32.         self._origin = float(width)/2.0, float(height)/2.0
  33.         self._position = self._origin
  34.         self._angle = 0.0
  35.         self._drawing = 1
  36.         self._width = 1
  37.         self._color = "black"
  38.         self._filling = 0
  39.         self._path = []
  40.         self._tofill = []
  41.         self.clear()
  42.         canvas._root().tkraise()
  43.  
  44.     def clear(self):
  45.         self.fill(0)
  46.         canvas = self._canvas
  47.         items = self._items
  48.         self._items = []
  49.         for item in items:
  50.             canvas.delete(item)
  51.  
  52.     def tracer(self, flag):
  53.         self._tracing = flag
  54.  
  55.     def forward(self, distance):
  56.         x0, y0 = start = self._position
  57.         x1 = x0 + distance * cos(self._angle*self._invradian)
  58.         y1 = y0 - distance * sin(self._angle*self._invradian)
  59.         self._goto(x1, y1)
  60.  
  61.     def backward(self, distance):
  62.         self.forward(-distance)
  63.  
  64.     def left(self, angle):
  65.         self._angle = (self._angle + angle) % self._fullcircle
  66.  
  67.     def right(self, angle):
  68.         self.left(-angle)
  69.  
  70.     def up(self):
  71.         self._drawing = 0
  72.  
  73.     def down(self):
  74.         self._drawing = 1
  75.  
  76.     def width(self, width):
  77.         self._width = float(width)
  78.  
  79.     def color(self, *args):
  80.         if not args:
  81.             raise Error, "no color arguments"
  82.         if len(args) == 1:
  83.             color = args[0]
  84.             if type(color) == type(""):
  85.                 # Test the color first
  86.                 try:
  87.                     id = self._canvas.create_line(0, 0, 0, 0, fill=color)
  88.                 except Tk.TclError:
  89.                     raise Error, "bad color string: %s" % `color`
  90.                 self._color = color
  91.                 return
  92.             try:
  93.                 r, g, b = color
  94.             except:
  95.                 raise Error, "bad color sequence: %s" % `color`
  96.         else:
  97.             try:
  98.                 r, g, b = args
  99.             except:
  100.                 raise Error, "bad color arguments: %s" % `args`
  101.         assert 0 <= r <= 1
  102.         assert 0 <= g <= 1
  103.         assert 0 <= b <= 1
  104.         x = 255.0
  105.         y = 0.5
  106.         self._color = "#%02x%02x%02x" % (int(r*x+y), int(g*x+y), int(b*x+y))
  107.  
  108.     def write(self, arg, move=0):
  109.         x, y = start = self._position
  110.         x = x-1 # correction -- calibrated for Windows
  111.         item = self._canvas.create_text(x, y, 
  112.                                         text=str(arg), anchor="sw",
  113.                                         fill=self._color)
  114.         self._items.append(item)
  115.         if move:
  116.             x0, y0, x1, y1 = self._canvas.bbox(item)
  117.             self._goto(x1, y1)
  118.  
  119.     def fill(self, flag):
  120.         if self._filling:
  121.             path = tuple(self._path)
  122.             smooth = self._filling < 0
  123.             if len(path) > 2:
  124.                 item = self._canvas._create('polygon', path,
  125.                                             {'fill': self._color,
  126.                                              'smooth': smooth})
  127.                 self._items.append(item)
  128.                 self._canvas.lower(item)
  129.                 if self._tofill:
  130.                     for item in self._tofill:
  131.                         self._canvas.itemconfigure(item, fill=self._color)
  132.                         self._items.append(item)
  133.         self._path = []
  134.         self._tofill = []
  135.         self._filling = flag
  136.         if flag:
  137.             self._path.append(self._position)
  138.  
  139.     def circle(self, radius, extent=None):
  140.         if extent is None:
  141.             extent = self._fullcircle
  142.         x0, y0 = self._position
  143.         xc = x0 - radius * sin(self._angle * self._invradian)
  144.         yc = y0 - radius * cos(self._angle * self._invradian)
  145.         if radius >= 0.0:
  146.             start = self._angle - 90.0
  147.         else:
  148.             start = self._angle + 90.0
  149.             extent = -extent
  150.         if self._filling:
  151.             if abs(extent) >= self._fullcircle:
  152.                 item = self._canvas.create_oval(xc-radius, yc-radius,
  153.                                                 xc+radius, yc+radius,
  154.                                                 width=self._width,
  155.                                                 outline="")
  156.                 self._tofill.append(item)
  157.             item = self._canvas.create_arc(xc-radius, yc-radius,
  158.                                            xc+radius, yc+radius,
  159.                                            style="chord",
  160.                                            start=start,
  161.                                            extent=extent,
  162.                                            width=self._width,
  163.                                            outline="")
  164.             self._tofill.append(item)
  165.         if self._drawing:
  166.             if abs(extent) >= self._fullcircle:
  167.                 item = self._canvas.create_oval(xc-radius, yc-radius,
  168.                                                 xc+radius, yc+radius,
  169.                                                 width=self._width,
  170.                                                 outline=self._color)
  171.                 self._items.append(item)
  172.             item = self._canvas.create_arc(xc-radius, yc-radius,
  173.                                            xc+radius, yc+radius,
  174.                                            style="arc",
  175.                                            start=start,
  176.                                            extent=extent,
  177.                                            width=self._width,
  178.                                            outline=self._color)
  179.             self._items.append(item)
  180.         angle = start + extent
  181.         x1 = xc + abs(radius) * cos(angle * self._invradian)
  182.         y1 = yc - abs(radius) * sin(angle * self._invradian)
  183.         self._angle = (self._angle + extent) % self._fullcircle
  184.         self._position = x1, y1
  185.         if self._filling:
  186.             self._path.append(self._position)
  187.  
  188.     def goto(self, *args):
  189.         if len(args) == 1:
  190.             try:
  191.                 x, y = args[0]
  192.             except:
  193.                 raise Error, "bad point argument: %s" % `args[0]`
  194.         else:
  195.             try:
  196.                 x, y = args
  197.             except:
  198.                 raise Error, "bad coordinates: %s" % `args[0]`
  199.         x0, y0 = self._origin
  200.         self._goto(x0+x, y0-y)
  201.  
  202.     def _goto(self, x1, y1):
  203.         x0, y0 = start = self._position
  204.         self._position = map(float, (x1, y1))
  205.         if self._filling:
  206.             self._path.append(self._position)
  207.         if self._drawing:
  208.             if self._tracing:
  209.                 dx = float(x1 - x0)
  210.                 dy = float(y1 - y0)
  211.                 distance = hypot(dx, dy)
  212.                 nhops = int(distance)
  213.                 item = self._canvas.create_line(x0, y0, x0, y0,
  214.                                                 width=self._width,
  215.                                                 arrow="last",
  216.                                                 capstyle="round",
  217.                                                 fill=self._color)
  218.                 try:
  219.                     for i in range(1, 1+nhops):
  220.                         x, y = x0 + dx*i/nhops, y0 + dy*i/nhops
  221.                         self._canvas.coords(item, x0, y0, x, y)
  222.                         self._canvas.update()
  223.                         self._canvas.after(10)
  224.                     self._canvas.itemconfigure(item, arrow="none")
  225.                 except Tk.TclError:
  226.                     # Probably the window was closed!
  227.                     return
  228.             else:
  229.                 item = self._canvas.create_line(x0, y0, x1, y1,
  230.                                                 width=self._width,
  231.                                                 capstyle="round",
  232.                                                 fill=self._color)
  233.             self._items.append(item)
  234.  
  235.  
  236. _root = None
  237. _canvas = None
  238. _pen = None
  239.  
  240. class Pen(RawPen):
  241.  
  242.     def __init__(self):
  243.         global _root, _canvas
  244.         if _root is None:
  245.             _root = Tk.Tk()
  246.             _root.wm_protocol("WM_DELETE_WINDOW", self._destroy)
  247.         if _canvas is None:
  248.             # XXX Should have scroll bars
  249.             _canvas = Tk.Canvas(_root, background="white")
  250.             _canvas.pack(expand=1, fill="both")
  251.         RawPen.__init__(self, _canvas)
  252.  
  253.     def _destroy(self):
  254.         global _root, _canvas, _pen
  255.         root = self._canvas._root()
  256.         if root is _root:
  257.             _pen = None
  258.             _root = None
  259.             _canvas = None
  260.         root.destroy()
  261.         
  262.  
  263. def _getpen():
  264.     global _pen
  265.     pen = _pen
  266.     if not pen:
  267.         _pen = pen = Pen()
  268.     return pen
  269.  
  270. def degrees(): _getpen().degrees()
  271. def radians(): _getpen().radians()
  272. def reset(): _getpen().reset()
  273. def clear(): _getpen().clear()
  274. def tracer(flag): _getpen().tracer(flag)
  275. def forward(distance): _getpen().forward(distance)
  276. def backward(distance): _getpen().backward(distance)
  277. def left(angle): _getpen().left(angle)
  278. def right(angle): _getpen().right(angle)
  279. def up(): _getpen().up()
  280. def down(): _getpen().down()
  281. def width(width): _getpen().width(width)
  282. def color(*args): apply(_getpen().color, args)
  283. def write(arg, move=0): _getpen().write(arg, move)
  284. def fill(flag): _getpen().fill(flag)
  285. def circle(radius, extent=None): _getpen().circle(radius, extent)
  286. def goto(*args): apply(_getpen().goto, args)
  287.  
  288. def demo():
  289.     reset()
  290.     tracer(1)
  291.     up()
  292.     backward(100)
  293.     down()
  294.     # draw 3 squares; the last filled
  295.     width(3)
  296.     for i in range(3):
  297.         if i == 2:
  298.             fill(1)
  299.         for j in range(4):
  300.             forward(20)
  301.             left(90)
  302.         if i == 2:
  303.             color("maroon")
  304.             fill(0)
  305.         up()
  306.         forward(30)
  307.         down()
  308.     width(1)
  309.     color("black")
  310.     # move out of the way
  311.     tracer(0)
  312.     up()
  313.     right(90)
  314.     forward(100)
  315.     right(90)
  316.     forward(100)
  317.     right(180)
  318.     down()
  319.     # some text
  320.     write("startstart", 1)
  321.     write("start", 1)
  322.     color("red")
  323.     # staircase
  324.     for i in range(5):
  325.         forward(20)
  326.         left(90)
  327.         forward(20)
  328.         right(90)
  329.     # filled staircase
  330.     fill(1)
  331.     for i in range(5):
  332.         forward(20)
  333.         left(90)
  334.         forward(20)
  335.         right(90)
  336.     fill(0)
  337.     # more text
  338.     write("end")
  339.     if __name__ == '__main__':
  340.         _root.mainloop()
  341.  
  342. if __name__ == '__main__':
  343.     demo()
  344.