/Demo/turtle/turtleDemo.py

http://unladen-swallow.googlecode.com/ · Python · 280 lines · 226 code · 40 blank · 14 comment · 32 complexity · 50feff0782dd865dc04dd69d3cd14455 MD5 · raw file

  1. #!/usr/bin/python
  2. import sys
  3. import os
  4. from Tkinter import *
  5. from idlelib.Percolator import Percolator
  6. from idlelib.ColorDelegator import ColorDelegator
  7. from idlelib.textView import TextViewer
  8. import turtle
  9. import time
  10. STARTUP = 1
  11. READY = 2
  12. RUNNING = 3
  13. DONE = 4
  14. EVENTDRIVEN = 5
  15. menufont = ("Arial", 12, NORMAL)
  16. btnfont = ("Arial", 12, 'bold')
  17. txtfont = ('Lucida Console', 8, 'normal')
  18. def getExampleEntries():
  19. cwd = os.getcwd()
  20. if "turtleDemo.py" not in os.listdir(cwd):
  21. print "Directory of turtleDemo must be current working directory!"
  22. print "But in your case this is", cwd
  23. sys.exit()
  24. entries1 = [entry for entry in os.listdir(cwd) if
  25. entry.startswith("tdemo_") and
  26. not entry.endswith(".pyc")]
  27. entries2 = []
  28. for entry in entries1:
  29. if entry.endswith(".py"):
  30. entries2.append(entry)
  31. else:
  32. path = os.path.join(cwd,entry)
  33. sys.path.append(path)
  34. subdir = [entry]
  35. scripts = [script for script in os.listdir(path) if
  36. script.startswith("tdemo_") and
  37. script.endswith(".py")]
  38. entries2.append(subdir+scripts)
  39. return entries2
  40. def showDemoHelp():
  41. TextViewer(demo.root, "Help on turtleDemo", "demohelp.txt")
  42. def showAboutDemo():
  43. TextViewer(demo.root, "About turtleDemo", "about_turtledemo.txt")
  44. def showAboutTurtle():
  45. TextViewer(demo.root, "About the new turtle module", "about_turtle.txt")
  46. class DemoWindow(object):
  47. def __init__(self, filename=None): #, root=None):
  48. self.root = root = turtle._root = Tk()
  49. root.wm_protocol("WM_DELETE_WINDOW", self._destroy)
  50. #################
  51. self.mBar = Frame(root, relief=RAISED, borderwidth=2)
  52. self.mBar.pack(fill=X)
  53. self.ExamplesBtn = self.makeLoadDemoMenu()
  54. self.OptionsBtn = self.makeHelpMenu()
  55. self.mBar.tk_menuBar(self.ExamplesBtn, self.OptionsBtn) #, QuitBtn)
  56. root.title('Python turtle-graphics examples')
  57. #################
  58. self.left_frame = left_frame = Frame(root)
  59. self.text_frame = text_frame = Frame(left_frame)
  60. self.vbar = vbar =Scrollbar(text_frame, name='vbar')
  61. self.text = text = Text(text_frame,
  62. name='text', padx=5, wrap='none',
  63. width=45)
  64. vbar['command'] = text.yview
  65. vbar.pack(side=LEFT, fill=Y)
  66. #####################
  67. self.hbar = hbar =Scrollbar(text_frame, name='hbar', orient=HORIZONTAL)
  68. hbar['command'] = text.xview
  69. hbar.pack(side=BOTTOM, fill=X)
  70. #####################
  71. text['yscrollcommand'] = vbar.set
  72. text.config(font=txtfont)
  73. text.config(xscrollcommand=hbar.set)
  74. text.pack(side=LEFT, fill=Y, expand=1)
  75. #####################
  76. self.output_lbl = Label(left_frame, height= 1,text=" --- ", bg = "#ddf",
  77. font = ("Arial", 16, 'normal'))
  78. self.output_lbl.pack(side=BOTTOM, expand=0, fill=X)
  79. #####################
  80. text_frame.pack(side=LEFT, fill=BOTH, expand=0)
  81. left_frame.pack(side=LEFT, fill=BOTH, expand=0)
  82. self.graph_frame = g_frame = Frame(root)
  83. turtle._Screen._root = g_frame
  84. turtle._Screen._canvas = turtle.ScrolledCanvas(g_frame, 800, 600, 1000, 800)
  85. #xturtle.Screen._canvas.pack(expand=1, fill="both")
  86. self.screen = _s_ = turtle.Screen()
  87. turtle.TurtleScreen.__init__(_s_, _s_._canvas)
  88. self.scanvas = _s_._canvas
  89. #xturtle.RawTurtle.canvases = [self.scanvas]
  90. turtle.RawTurtle.screens = [_s_]
  91. self.scanvas.pack(side=TOP, fill=BOTH, expand=1)
  92. self.btn_frame = btn_frame = Frame(g_frame, height=100)
  93. self.start_btn = Button(btn_frame, text=" START ", font=btnfont, fg = "white",
  94. disabledforeground = "#fed", command=self.startDemo)
  95. self.start_btn.pack(side=LEFT, fill=X, expand=1)
  96. self.stop_btn = Button(btn_frame, text=" STOP ", font=btnfont, fg = "white",
  97. disabledforeground = "#fed", command = self.stopIt)
  98. self.stop_btn.pack(side=LEFT, fill=X, expand=1)
  99. self.clear_btn = Button(btn_frame, text=" CLEAR ", font=btnfont, fg = "white",
  100. disabledforeground = "#fed", command = self.clearCanvas)
  101. self.clear_btn.pack(side=LEFT, fill=X, expand=1)
  102. self.btn_frame.pack(side=TOP, fill=BOTH, expand=0)
  103. self.graph_frame.pack(side=TOP, fill=BOTH, expand=1)
  104. Percolator(text).insertfilter(ColorDelegator())
  105. self.dirty = False
  106. self.exitflag = False
  107. if filename:
  108. self.loadfile(filename)
  109. self.configGUI(NORMAL, DISABLED, DISABLED, DISABLED,
  110. "Choose example from menu", "black")
  111. self.state = STARTUP
  112. def _destroy(self):
  113. self.root.destroy()
  114. sys.exit()
  115. def configGUI(self, menu, start, stop, clear, txt="", color="blue"):
  116. self.ExamplesBtn.config(state=menu)
  117. self.start_btn.config(state=start)
  118. if start==NORMAL:
  119. self.start_btn.config(bg="#d00")
  120. else:
  121. self.start_btn.config(bg="#fca")
  122. self.stop_btn.config(state=stop)
  123. if stop==NORMAL:
  124. self.stop_btn.config(bg="#d00")
  125. else:
  126. self.stop_btn.config(bg="#fca")
  127. self.clear_btn.config(state=clear)
  128. self.clear_btn.config(state=clear)
  129. if clear==NORMAL:
  130. self.clear_btn.config(bg="#d00")
  131. else:
  132. self.clear_btn.config(bg="#fca")
  133. self.output_lbl.config(text=txt, fg=color)
  134. def makeLoadDemoMenu(self):
  135. CmdBtn = Menubutton(self.mBar, text='Examples', underline=0, font=menufont)
  136. CmdBtn.pack(side=LEFT, padx="2m")
  137. CmdBtn.menu = Menu(CmdBtn)
  138. for entry in getExampleEntries():
  139. def loadexample(x):
  140. def emit():
  141. self.loadfile(x)
  142. return emit
  143. if isinstance(entry,str):
  144. CmdBtn.menu.add_command(label=entry[6:-3], underline=0, font=menufont,
  145. command=loadexample(entry))
  146. else:
  147. _dir, entries = entry[0], entry[1:]
  148. CmdBtn.menu.choices = Menu(CmdBtn.menu)
  149. for e in entries:
  150. CmdBtn.menu.choices.add_command(label=e[6:-3], underline=0, font=menufont,
  151. command = loadexample(os.path.join(_dir,e)))
  152. CmdBtn.menu.add_cascade(label=_dir[6:],
  153. menu = CmdBtn.menu.choices, font=menufont )
  154. CmdBtn['menu'] = CmdBtn.menu
  155. return CmdBtn
  156. def makeHelpMenu(self):
  157. CmdBtn = Menubutton(self.mBar, text='Help', underline=0, font = menufont)
  158. CmdBtn.pack(side=LEFT, padx='2m')
  159. CmdBtn.menu = Menu(CmdBtn)
  160. CmdBtn.menu.add_command(label='About turtle.py', font=menufont, command=showAboutTurtle)
  161. CmdBtn.menu.add_command(label='turtleDemo - Help', font=menufont, command=showDemoHelp)
  162. CmdBtn.menu.add_command(label='About turtleDemo', font=menufont, command=showAboutDemo)
  163. CmdBtn['menu'] = CmdBtn.menu
  164. return CmdBtn
  165. def refreshCanvas(self):
  166. if not self.dirty: return
  167. self.screen.clear()
  168. #self.screen.mode("standard")
  169. self.dirty=False
  170. def loadfile(self,filename):
  171. self.refreshCanvas()
  172. if os.path.exists(filename) and not os.path.isdir(filename):
  173. # load and display file text
  174. f = open(filename,'r')
  175. chars = f.read()
  176. f.close()
  177. self.text.delete("1.0", "end")
  178. self.text.insert("1.0",chars)
  179. direc, fname = os.path.split(filename)
  180. self.root.title(fname[6:-3]+" - an xturtle example")
  181. self.module = __import__(fname[:-3])
  182. reload(self.module)
  183. self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED,
  184. "Press start button", "red")
  185. self.state = READY
  186. def startDemo(self):
  187. self.refreshCanvas()
  188. self.dirty = True
  189. turtle.TurtleScreen._RUNNING = True
  190. self.configGUI(DISABLED, DISABLED, NORMAL, DISABLED,
  191. "demo running...", "black")
  192. self.screen.clear()
  193. self.screen.mode("standard")
  194. self.state = RUNNING
  195. try:
  196. result = self.module.main()
  197. if result == "EVENTLOOP":
  198. self.state = EVENTDRIVEN
  199. else:
  200. self.state = DONE
  201. except turtle.Terminator:
  202. self.state = DONE
  203. result = "stopped!"
  204. if self.state == DONE:
  205. self.configGUI(NORMAL, NORMAL, DISABLED, NORMAL,
  206. result)
  207. elif self.state == EVENTDRIVEN:
  208. self.exitflag = True
  209. self.configGUI(DISABLED, DISABLED, NORMAL, DISABLED,
  210. "use mouse/keys or STOP", "red")
  211. def clearCanvas(self):
  212. self.refreshCanvas()
  213. self.scanvas.config(cursor="")
  214. self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED)
  215. def stopIt(self):
  216. if self.exitflag:
  217. self.clearCanvas()
  218. self.exitflag = False
  219. self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED,
  220. "STOPPED!", "red")
  221. turtle.TurtleScreen._RUNNING = False
  222. #print "stopIT: exitflag = True"
  223. else:
  224. turtle.TurtleScreen._RUNNING = False
  225. #print "stopIt: exitflag = False"
  226. if __name__ == '__main__':
  227. demo = DemoWindow()
  228. RUN = True
  229. while RUN:
  230. try:
  231. print "ENTERING mainloop"
  232. demo.root.mainloop()
  233. except AttributeError:
  234. print "CRASH!!!- WAIT A MOMENT!"
  235. time.sleep(0.3)
  236. print "GOING ON .."
  237. demo.refreshCanvas()
  238. ## time.sleep(1)
  239. except:
  240. RUN = FALSE