blob: 12b4355c19c8c1f34cc7485ea6e35f8a041635d8 [file] [log] [blame]
Benjamin Peterson9cf41d02010-03-11 22:33:25 +00001#!/usr/bin/env python
Martin v. Löwis87184592008-06-04 06:29:55 +00002import sys
3import os
4
5from Tkinter import *
6from idlelib.Percolator import Percolator
7from idlelib.ColorDelegator import ColorDelegator
Terry Jan Reedyed6820d2014-06-22 02:32:26 -04008from idlelib.textView import view_file
Martin v. Löwis87184592008-06-04 06:29:55 +00009
10import turtle
11import time
12
Terry Jan Reedyed6820d2014-06-22 02:32:26 -040013demo_dir = os.getcwd()
14if "turtleDemo.py" not in os.listdir(demo_dir):
15 print "Directory of turtleDemo must be current working directory!"
16 print "But in your case this is", demo_dir
17 sys.exit()
18
Martin v. Löwis87184592008-06-04 06:29:55 +000019STARTUP = 1
20READY = 2
21RUNNING = 3
22DONE = 4
23EVENTDRIVEN = 5
24
25menufont = ("Arial", 12, NORMAL)
26btnfont = ("Arial", 12, 'bold')
27txtfont = ('Lucida Console', 8, 'normal')
28
29def getExampleEntries():
Terry Jan Reedyed6820d2014-06-22 02:32:26 -040030 entries1 = [entry for entry in os.listdir(demo_dir) if
Martin v. Löwis87184592008-06-04 06:29:55 +000031 entry.startswith("tdemo_") and
32 not entry.endswith(".pyc")]
33 entries2 = []
34 for entry in entries1:
35 if entry.endswith(".py"):
36 entries2.append(entry)
37 else:
Terry Jan Reedyed6820d2014-06-22 02:32:26 -040038 path = os.path.join(demo_dir, entry)
Martin v. Löwis87184592008-06-04 06:29:55 +000039 sys.path.append(path)
40 subdir = [entry]
41 scripts = [script for script in os.listdir(path) if
42 script.startswith("tdemo_") and
43 script.endswith(".py")]
44 entries2.append(subdir+scripts)
45 return entries2
46
Terry Jan Reedy8ac01bf2014-07-25 01:56:17 -040047help_entries = ( # (help_label, help_file)
48 ('Turtledemo help', "demohelp.txt"),
49 ('About turtledemo', "about_turtledemo.txt"),
50 ('About turtle module', "about_turtle.txt"),
51 )
Martin v. Löwis87184592008-06-04 06:29:55 +000052
53class DemoWindow(object):
54
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -040055 def __init__(self, filename=None):
Martin v. Löwis87184592008-06-04 06:29:55 +000056 self.root = root = turtle._root = Tk()
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -040057 root.title('Python turtle-graphics examples')
Martin v. Löwis87184592008-06-04 06:29:55 +000058 root.wm_protocol("WM_DELETE_WINDOW", self._destroy)
59
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -040060 root.grid_rowconfigure(1, weight=1)
61 root.grid_columnconfigure(0, weight=1)
62 root.grid_columnconfigure(1, minsize=90, weight=1)
63 root.grid_columnconfigure(2, minsize=90, weight=1)
64 root.grid_columnconfigure(3, minsize=90, weight=1)
Martin v. Löwis87184592008-06-04 06:29:55 +000065
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -040066 self.mBar = Frame(root, relief=RAISED, borderwidth=2)
Martin v. Löwis87184592008-06-04 06:29:55 +000067 self.ExamplesBtn = self.makeLoadDemoMenu()
68 self.OptionsBtn = self.makeHelpMenu()
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -040069 self.mBar.grid(row=0, columnspan=4, sticky='news')
Martin v. Löwis87184592008-06-04 06:29:55 +000070
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -040071 pane = PanedWindow(orient=HORIZONTAL, sashwidth=5,
72 sashrelief=SOLID, bg='#ddd')
73 pane.add(self.makeTextFrame(pane))
74 pane.add(self.makeGraphFrame(pane))
75 pane.grid(row=1, columnspan=4, sticky='news')
Martin v. Löwis87184592008-06-04 06:29:55 +000076
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -040077 self.output_lbl = Label(root, height= 1, text=" --- ", bg="#ddf",
78 font=("Arial", 16, 'normal'), borderwidth=2,
79 relief=RIDGE)
80 self.start_btn = Button(root, text=" START ", font=btnfont,
81 fg="white", disabledforeground = "#fed",
82 command=self.startDemo)
83 self.stop_btn = Button(root, text=" STOP ", font=btnfont,
84 fg="white", disabledforeground = "#fed",
85 command=self.stopIt)
86 self.clear_btn = Button(root, text=" CLEAR ", font=btnfont,
87 fg="white", disabledforeground="#fed",
88 command = self.clearCanvas)
89 self.output_lbl.grid(row=2, column=0, sticky='news', padx=(0,5))
90 self.start_btn.grid(row=2, column=1, sticky='ew')
91 self.stop_btn.grid(row=2, column=2, sticky='ew')
92 self.clear_btn.grid(row=2, column=3, sticky='ew')
Martin v. Löwis87184592008-06-04 06:29:55 +000093
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -040094 Percolator(self.text).insertfilter(ColorDelegator())
Martin v. Löwis87184592008-06-04 06:29:55 +000095 self.dirty = False
96 self.exitflag = False
97 if filename:
98 self.loadfile(filename)
99 self.configGUI(NORMAL, DISABLED, DISABLED, DISABLED,
100 "Choose example from menu", "black")
101 self.state = STARTUP
102
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -0400103
104 def onResize(self, event):
105 cwidth = self._canvas.winfo_width()
106 cheight = self._canvas.winfo_height()
107 self._canvas.xview_moveto(0.5*(self.canvwidth-cwidth)/self.canvwidth)
108 self._canvas.yview_moveto(0.5*(self.canvheight-cheight)/self.canvheight)
109
110 def makeTextFrame(self, root):
111 self.text_frame = text_frame = Frame(root)
112 self.text = text = Text(text_frame, name='text', padx=5,
113 wrap='none', width=45)
114
115 self.vbar = vbar = Scrollbar(text_frame, name='vbar')
116 vbar['command'] = text.yview
117 vbar.pack(side=LEFT, fill=Y)
118 self.hbar = hbar = Scrollbar(text_frame, name='hbar', orient=HORIZONTAL)
119 hbar['command'] = text.xview
120 hbar.pack(side=BOTTOM, fill=X)
121
122 text['font'] = txtfont
123 text['yscrollcommand'] = vbar.set
124 text['xscrollcommand'] = hbar.set
125 text.pack(side=LEFT, fill=BOTH, expand=1)
126 return text_frame
127
128 def makeGraphFrame(self, root):
129 turtle._Screen._root = root
130 self.canvwidth = 1000
131 self.canvheight = 800
132 turtle._Screen._canvas = self._canvas = canvas = turtle.ScrolledCanvas(
133 root, 800, 600, self.canvwidth, self.canvheight)
134 canvas.adjustScrolls()
135 canvas._rootwindow.bind('<Configure>', self.onResize)
136 canvas._canvas['borderwidth'] = 0
137
138 self.screen = _s_ = turtle.Screen()
139 turtle.TurtleScreen.__init__(_s_, _s_._canvas)
140 self.scanvas = _s_._canvas
141 turtle.RawTurtle.screens = [_s_]
142 return canvas
Martin v. Löwis87184592008-06-04 06:29:55 +0000143
144 def configGUI(self, menu, start, stop, clear, txt="", color="blue"):
145 self.ExamplesBtn.config(state=menu)
146
Terry Jan Reedy87355a72014-07-27 03:00:47 -0400147 self.start_btn.config(state=start,
148 bg="#d00" if start == NORMAL else "#fca")
149 self.stop_btn.config(state=stop,
150 bg="#d00" if stop == NORMAL else "#fca")
151 self.clear_btn.config(state=clear,
152 bg="#d00" if clear == NORMAL else"#fca")
Martin v. Löwis87184592008-06-04 06:29:55 +0000153 self.output_lbl.config(text=txt, fg=color)
154
Martin v. Löwis87184592008-06-04 06:29:55 +0000155 def makeLoadDemoMenu(self):
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -0400156 CmdBtn = Menubutton(self.mBar, text='Examples',
157 underline=0, font=menufont)
Martin v. Löwis87184592008-06-04 06:29:55 +0000158 CmdBtn.pack(side=LEFT, padx="2m")
159 CmdBtn.menu = Menu(CmdBtn)
160
161 for entry in getExampleEntries():
162 def loadexample(x):
163 def emit():
164 self.loadfile(x)
165 return emit
166 if isinstance(entry,str):
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -0400167 CmdBtn.menu.add_command(label=entry[6:-3], underline=0,
168 font=menufont,
Martin v. Löwis87184592008-06-04 06:29:55 +0000169 command=loadexample(entry))
170 else:
171 _dir, entries = entry[0], entry[1:]
172 CmdBtn.menu.choices = Menu(CmdBtn.menu)
173 for e in entries:
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -0400174 CmdBtn.menu.choices.add_command(
175 label=e[6:-3], underline=0, font=menufont,
176 command = loadexample(os.path.join(_dir,e)))
177 CmdBtn.menu.add_cascade(
178 label=_dir[6:], menu = CmdBtn.menu.choices, font=menufont)
Martin v. Löwis87184592008-06-04 06:29:55 +0000179
180 CmdBtn['menu'] = CmdBtn.menu
181 return CmdBtn
182
Martin v. Löwis87184592008-06-04 06:29:55 +0000183 def makeHelpMenu(self):
184 CmdBtn = Menubutton(self.mBar, text='Help', underline=0, font = menufont)
185 CmdBtn.pack(side=LEFT, padx='2m')
186 CmdBtn.menu = Menu(CmdBtn)
187
Terry Jan Reedy8ac01bf2014-07-25 01:56:17 -0400188 for help_label, help_file in help_entries:
189 def show(help_label=help_label, help_file=help_file):
190 view_file(self.root, help_label, os.path.join(demo_dir, help_file))
191 CmdBtn.menu.add_command(label=help_label, font=menufont, command=show)
Martin v. Löwis87184592008-06-04 06:29:55 +0000192
193 CmdBtn['menu'] = CmdBtn.menu
194 return CmdBtn
195
196 def refreshCanvas(self):
197 if not self.dirty: return
198 self.screen.clear()
Martin v. Löwis87184592008-06-04 06:29:55 +0000199 self.dirty=False
200
201 def loadfile(self,filename):
202 self.refreshCanvas()
203 if os.path.exists(filename) and not os.path.isdir(filename):
204 # load and display file text
205 f = open(filename,'r')
206 chars = f.read()
207 f.close()
208 self.text.delete("1.0", "end")
209 self.text.insert("1.0",chars)
210 direc, fname = os.path.split(filename)
Georg Brandl574a8572010-05-24 21:37:54 +0000211 self.root.title(fname[6:-3]+" - a Python turtle graphics example")
Martin v. Löwis87184592008-06-04 06:29:55 +0000212 self.module = __import__(fname[:-3])
Martin v. Löwis87184592008-06-04 06:29:55 +0000213 self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED,
214 "Press start button", "red")
215 self.state = READY
216
217 def startDemo(self):
218 self.refreshCanvas()
219 self.dirty = True
220 turtle.TurtleScreen._RUNNING = True
221 self.configGUI(DISABLED, DISABLED, NORMAL, DISABLED,
222 "demo running...", "black")
223 self.screen.clear()
224 self.screen.mode("standard")
225 self.state = RUNNING
226
227 try:
228 result = self.module.main()
229 if result == "EVENTLOOP":
230 self.state = EVENTDRIVEN
231 else:
232 self.state = DONE
233 except turtle.Terminator:
Serhiy Storchakacc49aa12015-02-22 17:22:53 +0200234 if self.root is None:
235 return
Martin v. Löwis87184592008-06-04 06:29:55 +0000236 self.state = DONE
237 result = "stopped!"
238 if self.state == DONE:
239 self.configGUI(NORMAL, NORMAL, DISABLED, NORMAL,
240 result)
241 elif self.state == EVENTDRIVEN:
242 self.exitflag = True
243 self.configGUI(DISABLED, DISABLED, NORMAL, DISABLED,
244 "use mouse/keys or STOP", "red")
245
246 def clearCanvas(self):
247 self.refreshCanvas()
248 self.scanvas.config(cursor="")
249 self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED)
250
251 def stopIt(self):
252 if self.exitflag:
253 self.clearCanvas()
254 self.exitflag = False
255 self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED,
256 "STOPPED!", "red")
257 turtle.TurtleScreen._RUNNING = False
Martin v. Löwis87184592008-06-04 06:29:55 +0000258 else:
259 turtle.TurtleScreen._RUNNING = False
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -0400260
261 def _destroy(self):
Serhiy Storchakacc49aa12015-02-22 17:22:53 +0200262 turtle.TurtleScreen._RUNNING = False
Terry Jan Reedye2fbf4f2014-07-23 15:01:07 -0400263 self.root.destroy()
Serhiy Storchakacc49aa12015-02-22 17:22:53 +0200264 self.root = None
Terry Jan Reedycbe6d242014-07-23 17:27:51 -0400265 #sys.exit()
266
267def main():
268 demo = DemoWindow()
269 demo.root.mainloop()
Martin v. Löwis87184592008-06-04 06:29:55 +0000270
271if __name__ == '__main__':
Terry Jan Reedycbe6d242014-07-23 17:27:51 -0400272 main()