1076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl#!/usr/bin/env python3 294ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 394ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy""" 494ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy ---------------------------------------------- 594ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy turtleDemo - Help 694ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy ---------------------------------------------- 794ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 894ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy This document has two sections: 994ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 1094ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy (1) How to use the demo viewer 1194ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy (2) How to add your own demos to the demo repository 1294ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 1394ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 1494ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy (1) How to use the demo viewer. 1594ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 1694ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy Select a demoscript from the example menu. 17867579972d9a1e9e077626de6d6d083e30fea110Terry Jan Reedy The (syntax colored) source code appears in the left 1894ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy source code window. IT CANNOT BE EDITED, but ONLY VIEWED! 1994ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 20c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy The demo viewer windows can be resized. The divider between text 21c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy and canvas can be moved by grabbing it with the mouse. The text font 22d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy size can be changed from the menu and with Control/Command '-'/'+'. 23d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy It can also be changed on most systems with Control-mousewheel 24d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy when the mouse is over the text. 2594ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 26c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy Press START button to start the demo. 27c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy Stop execution by pressing the STOP button. 28c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy Clear screen by pressing the CLEAR button. 29c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy Restart by pressing the START button again. 30c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy 31c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy SPECIAL demos, such as clock.py are those which run EVENTDRIVEN. 3294ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 3394ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy Press START button to start the demo. 3494ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 3594ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy - Until the EVENTLOOP is entered everything works 3694ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy as in an ordinary demo script. 3794ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 3894ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy - When the EVENTLOOP is entered, you control the 3994ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy application by using the mouse and/or keys (or it's 4094ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy controlled by some timer events) 4194ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy To stop it you can and must press the STOP button. 4294ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 4394ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy While the EVENTLOOP is running, the examples menu is disabled. 4494ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 4594ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy - Only after having pressed the STOP button, you may 4694ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy restart it or choose another example script. 4794ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 4894ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy * * * * * * * * 4994ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy In some rare situations there may occur interferences/conflicts 5094ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy between events concerning the demo script and those concerning the 5194ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy demo-viewer. (They run in the same process.) Strange behaviour may be 5294ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy the consequence and in the worst case you must close and restart the 5394ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy viewer. 5494ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy * * * * * * * * 5594ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 5694ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 5794ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy (2) How to add your own demos to the demo repository 5894ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 5994ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy - Place the file in the same directory as turtledemo/__main__.py 6094ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy IMPORTANT! When imported, the demo should not modify the system 6194ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy by calling functions in other modules, such as sys, tkinter, or 6294ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy turtle. Global variables should be initialized in main(). 6394ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 6494ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy - The code must contain a main() function which will 6594ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy be executed by the viewer (see provided example scripts). 6694ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy It may return a string which will be displayed in the Label below 6794ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy the source code window (when execution has finished.) 6894ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 6994ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy - In order to run mydemo.py by itself, such as during development, 7094ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy add the following at the end of the file: 7194ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 7294ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy if __name__ == '__main__': 7394ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy main() 7494ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy mainloop() # keep window open 7594ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 7694ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy python -m turtledemo.mydemo # will then run it 7794ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 7894ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy - If the demo is EVENT DRIVEN, main must return the string 7994ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy "EVENTLOOP". This informs the demo viewer that the script is 8094ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy still running and must be stopped by the user! 8194ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy 8294ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy If an "EVENTLOOP" demo runs by itself, as with clock, which uses 8394ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy ontimer, or minimal_hanoi, which loops by recursion, then the 8494ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy code should catch the turtle.Terminator exception that will be 8594ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy raised when the user presses the STOP button. (Paint is not such 8694ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy a demo; it only acts in response to mouse clicks and movements.) 8794ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy""" 88076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandlimport sys 89076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandlimport os 90076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 91076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandlfrom tkinter import * 922bac3b778f0a3efe374334b9694e99ed48431414Terry Jan Reedyfrom idlelib.colorizer import ColorDelegator, color_config 936fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedyfrom idlelib.percolator import Percolator 946fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedyfrom idlelib.textview import view_text 9594ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedyfrom turtledemo import __doc__ as about_turtledemo 96076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 97076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandlimport turtle 98076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 99076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandldemo_dir = os.path.dirname(os.path.abspath(__file__)) 100c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedydarwin = sys.platform == 'darwin' 101076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 102076cbae4b97cfb7764321f92d8506ef38366facaGeorg BrandlSTARTUP = 1 103076cbae4b97cfb7764321f92d8506ef38366facaGeorg BrandlREADY = 2 104076cbae4b97cfb7764321f92d8506ef38366facaGeorg BrandlRUNNING = 3 105076cbae4b97cfb7764321f92d8506ef38366facaGeorg BrandlDONE = 4 106076cbae4b97cfb7764321f92d8506ef38366facaGeorg BrandlEVENTDRIVEN = 5 107076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 108076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandlmenufont = ("Arial", 12, NORMAL) 109076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandlbtnfont = ("Arial", 12, 'bold') 110c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedytxtfont = ['Lucida Console', 10, 'normal'] 111c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy 112c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan ReedyMINIMUM_FONT_SIZE = 6 113c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan ReedyMAXIMUM_FONT_SIZE = 100 114c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedyfont_sizes = [8, 9, 10, 11, 12, 14, 18, 20, 22, 24, 30] 115076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 116076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandldef getExampleEntries(): 117076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl return [entry[:-3] for entry in os.listdir(demo_dir) if 118076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl entry.endswith(".py") and entry[0] != '_'] 119076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 12094ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedyhelp_entries = ( # (help_label, help_doc) 12194ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy ('Turtledemo help', __doc__), 12294ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy ('About turtledemo', about_turtledemo), 12394ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy ('About turtle module', turtle.__doc__), 124280aace067e7df3b706c09e27b044dfea3bacaffTerry Jan Reedy ) 125076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 1262bac3b778f0a3efe374334b9694e99ed48431414Terry Jan Reedy 1272bac3b778f0a3efe374334b9694e99ed48431414Terry Jan Reedy 128076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandlclass DemoWindow(object): 129076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 130b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy def __init__(self, filename=None): 131076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.root = root = turtle._root = Tk() 132b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy root.title('Python turtle-graphics examples') 133076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl root.wm_protocol("WM_DELETE_WINDOW", self._destroy) 134076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 135c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy if darwin: 1367e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy import subprocess 1377e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy # Make sure we are the currently activated OS X application 1387e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy # so that our menu bar appears. 1397e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy p = subprocess.Popen( 1407e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy [ 1417e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy 'osascript', 1427e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy '-e', 'tell application "System Events"', 1437e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy '-e', 'set frontmost of the first process whose ' 1447e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy 'unix id is {} to true'.format(os.getpid()), 1457e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy '-e', 'end tell', 1467e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy ], 1477e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy stderr=subprocess.DEVNULL, 148c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy stdout=subprocess.DEVNULL,) 1497e55db2bc566381bfda3ddcd44c048f0c627880fTerry Jan Reedy 150f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy root.grid_rowconfigure(0, weight=1) 151b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy root.grid_columnconfigure(0, weight=1) 152b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy root.grid_columnconfigure(1, minsize=90, weight=1) 153b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy root.grid_columnconfigure(2, minsize=90, weight=1) 154b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy root.grid_columnconfigure(3, minsize=90, weight=1) 155076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 156f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy self.mBar = Menu(root, relief=RAISED, borderwidth=2) 157f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy self.mBar.add_cascade(menu=self.makeLoadDemoMenu(self.mBar), 158c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy label='Examples', underline=0) 159c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy self.mBar.add_cascade(menu=self.makeFontMenu(self.mBar), 160c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy label='Fontsize', underline=0) 161f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy self.mBar.add_cascade(menu=self.makeHelpMenu(self.mBar), 162c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy label='Help', underline=0) 163f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy root['menu'] = self.mBar 164b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy 165b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy pane = PanedWindow(orient=HORIZONTAL, sashwidth=5, 166b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy sashrelief=SOLID, bg='#ddd') 167b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy pane.add(self.makeTextFrame(pane)) 168b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy pane.add(self.makeGraphFrame(pane)) 169f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy pane.grid(row=0, columnspan=4, sticky='news') 170b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy 171b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.output_lbl = Label(root, height= 1, text=" --- ", bg="#ddf", 172b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy font=("Arial", 16, 'normal'), borderwidth=2, 173b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy relief=RIDGE) 174b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.start_btn = Button(root, text=" START ", font=btnfont, 175b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy fg="white", disabledforeground = "#fed", 176b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy command=self.startDemo) 177b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.stop_btn = Button(root, text=" STOP ", font=btnfont, 178b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy fg="white", disabledforeground = "#fed", 179b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy command=self.stopIt) 180b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.clear_btn = Button(root, text=" CLEAR ", font=btnfont, 181b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy fg="white", disabledforeground="#fed", 182b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy command = self.clearCanvas) 183f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy self.output_lbl.grid(row=1, column=0, sticky='news', padx=(0,5)) 184f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy self.start_btn.grid(row=1, column=1, sticky='ew') 185f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy self.stop_btn.grid(row=1, column=2, sticky='ew') 186f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy self.clear_btn.grid(row=1, column=3, sticky='ew') 187b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy 188b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy Percolator(self.text).insertfilter(ColorDelegator()) 189b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.dirty = False 190b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.exitflag = False 191b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy if filename: 192b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.loadfile(filename) 1932ced87f3e6f61b777a5cc4368527e6fc8928464fTerry Jan Reedy self.configGUI(DISABLED, DISABLED, DISABLED, 194b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy "Choose example from menu", "black") 195b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.state = STARTUP 196076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 197b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy 198b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy def onResize(self, event): 199b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy cwidth = self._canvas.winfo_width() 200b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy cheight = self._canvas.winfo_height() 201b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self._canvas.xview_moveto(0.5*(self.canvwidth-cwidth)/self.canvwidth) 202b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self._canvas.yview_moveto(0.5*(self.canvheight-cheight)/self.canvheight) 203b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy 204b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy def makeTextFrame(self, root): 205b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.text_frame = text_frame = Frame(root) 206b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.text = text = Text(text_frame, name='text', padx=5, 207b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy wrap='none', width=45) 2082bac3b778f0a3efe374334b9694e99ed48431414Terry Jan Reedy color_config(text) 209b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy 210b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.vbar = vbar = Scrollbar(text_frame, name='vbar') 211076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl vbar['command'] = text.yview 212076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl vbar.pack(side=LEFT, fill=Y) 213b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.hbar = hbar = Scrollbar(text_frame, name='hbar', orient=HORIZONTAL) 214076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl hbar['command'] = text.xview 215076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl hbar.pack(side=BOTTOM, fill=X) 216076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl text['yscrollcommand'] = vbar.set 217b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy text['xscrollcommand'] = hbar.set 218d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy 219d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy text['font'] = tuple(txtfont) 220d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy shortcut = 'Command' if darwin else 'Control' 221d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy text.bind_all('<%s-minus>' % shortcut, self.decrease_size) 222d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy text.bind_all('<%s-underscore>' % shortcut, self.decrease_size) 223d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy text.bind_all('<%s-equal>' % shortcut, self.increase_size) 224d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy text.bind_all('<%s-plus>' % shortcut, self.increase_size) 225d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy text.bind('<Control-MouseWheel>', self.update_mousewheel) 226d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy text.bind('<Control-Button-4>', self.increase_size) 227d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy text.bind('<Control-Button-5>', self.decrease_size) 228d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy 229b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy text.pack(side=LEFT, fill=BOTH, expand=1) 230b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy return text_frame 231b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy 232b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy def makeGraphFrame(self, root): 233b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy turtle._Screen._root = root 234b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.canvwidth = 1000 235b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.canvheight = 800 236b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy turtle._Screen._canvas = self._canvas = canvas = turtle.ScrolledCanvas( 237b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy root, 800, 600, self.canvwidth, self.canvheight) 238b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy canvas.adjustScrolls() 239d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy canvas._rootwindow.bind('<Configure>', self.onResize) 240b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy canvas._canvas['borderwidth'] = 0 241b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy 242076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.screen = _s_ = turtle.Screen() 243076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl turtle.TurtleScreen.__init__(_s_, _s_._canvas) 244076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.scanvas = _s_._canvas 245076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl turtle.RawTurtle.screens = [_s_] 246b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy return canvas 247076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 248c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy def set_txtsize(self, size): 249c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy txtfont[1] = size 250c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy self.text['font'] = tuple(txtfont) 251c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy self.output_lbl['text'] = 'Font size %d' % size 252c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy 253c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy def decrease_size(self, dummy=None): 254c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy self.set_txtsize(max(txtfont[1] - 1, MINIMUM_FONT_SIZE)) 255d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy return 'break' 256c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy 257c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy def increase_size(self, dummy=None): 258c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy self.set_txtsize(min(txtfont[1] + 1, MAXIMUM_FONT_SIZE)) 259d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy return 'break' 260c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy 261c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy def update_mousewheel(self, event): 262c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy # For wheel up, event.delte = 120 on Windows, -1 on darwin. 263c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy # X-11 sends Control-Button-4 event instead. 264d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy if (event.delta < 0) == (not darwin): 265d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy return self.decrease_size() 266d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy else: 267d43ffc9aba8d3a594486d2488bf3e3dfb50a43b2Terry Jan Reedy return self.increase_size() 268c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy 2692ced87f3e6f61b777a5cc4368527e6fc8928464fTerry Jan Reedy def configGUI(self, start, stop, clear, txt="", color="blue"): 2708b95d5e0bf00d9d0098579d29fd6bb9322071879Terry Jan Reedy self.start_btn.config(state=start, 2718b95d5e0bf00d9d0098579d29fd6bb9322071879Terry Jan Reedy bg="#d00" if start == NORMAL else "#fca") 2728b95d5e0bf00d9d0098579d29fd6bb9322071879Terry Jan Reedy self.stop_btn.config(state=stop, 2738b95d5e0bf00d9d0098579d29fd6bb9322071879Terry Jan Reedy bg="#d00" if stop == NORMAL else "#fca") 2748b95d5e0bf00d9d0098579d29fd6bb9322071879Terry Jan Reedy self.clear_btn.config(state=clear, 2758b95d5e0bf00d9d0098579d29fd6bb9322071879Terry Jan Reedy bg="#d00" if clear == NORMAL else"#fca") 276076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.output_lbl.config(text=txt, fg=color) 277076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 278f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy def makeLoadDemoMenu(self, master): 279f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy menu = Menu(master) 280076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 281076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl for entry in getExampleEntries(): 282c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy def load(entry=entry): 283c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy self.loadfile(entry) 284f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy menu.add_command(label=entry, underline=0, 285c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy font=menufont, command=load) 286c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy return menu 287076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 288c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy def makeFontMenu(self, master): 289c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy menu = Menu(master) 290c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy menu.add_command(label="Decrease (C-'-')", command=self.decrease_size, 291c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy font=menufont) 292c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy menu.add_command(label="Increase (C-'+')", command=self.increase_size, 293c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy font=menufont) 294c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy menu.add_separator() 295c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy 296c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy for size in font_sizes: 297c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy def resize(size=size): 298c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy self.set_txtsize(size) 299c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy menu.add_command(label=str(size), underline=0, 300c6a1c02cce3a12683cd951193c8f9ce30d79f6dcTerry Jan Reedy font=menufont, command=resize) 301f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy return menu 302076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 303f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy def makeHelpMenu(self, master): 304f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy menu = Menu(master) 305076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 306280aace067e7df3b706c09e27b044dfea3bacaffTerry Jan Reedy for help_label, help_file in help_entries: 307280aace067e7df3b706c09e27b044dfea3bacaffTerry Jan Reedy def show(help_label=help_label, help_file=help_file): 30894ee51ed9ee1df1890b9d2493a64bc484a522da2Terry Jan Reedy view_text(self.root, help_label, help_file) 309f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy menu.add_command(label=help_label, font=menufont, command=show) 310f819ef74da8d5fc915e9fab672ba592efa190f0cTerry Jan Reedy return menu 311076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 312076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl def refreshCanvas(self): 3138450c5331548e396d31639776c91e191a5f3147eTerry Jan Reedy if self.dirty: 3148450c5331548e396d31639776c91e191a5f3147eTerry Jan Reedy self.screen.clear() 3158450c5331548e396d31639776c91e191a5f3147eTerry Jan Reedy self.dirty=False 316076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 317076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl def loadfile(self, filename): 3188450c5331548e396d31639776c91e191a5f3147eTerry Jan Reedy self.clearCanvas() 3198450c5331548e396d31639776c91e191a5f3147eTerry Jan Reedy turtle.TurtleScreen._RUNNING = False 320076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl modname = 'turtledemo.' + filename 321076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl __import__(modname) 322076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.module = sys.modules[modname] 323076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl with open(self.module.__file__, 'r') as f: 324076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl chars = f.read() 325076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.text.delete("1.0", "end") 326076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.text.insert("1.0", chars) 327076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.root.title(filename + " - a Python turtle graphics example") 3282ced87f3e6f61b777a5cc4368527e6fc8928464fTerry Jan Reedy self.configGUI(NORMAL, DISABLED, DISABLED, 329076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl "Press start button", "red") 330076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.state = READY 331076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 332076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl def startDemo(self): 333076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.refreshCanvas() 334076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.dirty = True 335076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl turtle.TurtleScreen._RUNNING = True 3362ced87f3e6f61b777a5cc4368527e6fc8928464fTerry Jan Reedy self.configGUI(DISABLED, NORMAL, DISABLED, 337076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl "demo running...", "black") 338076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.screen.clear() 339076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.screen.mode("standard") 340076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.state = RUNNING 341076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 342076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl try: 343076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl result = self.module.main() 344076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl if result == "EVENTLOOP": 345076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.state = EVENTDRIVEN 346076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl else: 347076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.state = DONE 348076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl except turtle.Terminator: 34980a1803193bcaef7a50324974117c3aa3fb0e48fSerhiy Storchaka if self.root is None: 35080a1803193bcaef7a50324974117c3aa3fb0e48fSerhiy Storchaka return 351076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.state = DONE 352076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl result = "stopped!" 353076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl if self.state == DONE: 3542ced87f3e6f61b777a5cc4368527e6fc8928464fTerry Jan Reedy self.configGUI(NORMAL, DISABLED, NORMAL, 355076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl result) 356076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl elif self.state == EVENTDRIVEN: 357076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.exitflag = True 3582ced87f3e6f61b777a5cc4368527e6fc8928464fTerry Jan Reedy self.configGUI(DISABLED, NORMAL, DISABLED, 359076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl "use mouse/keys or STOP", "red") 360076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 361076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl def clearCanvas(self): 362076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.refreshCanvas() 363076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.screen._delete("all") 364076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.scanvas.config(cursor="") 3652ced87f3e6f61b777a5cc4368527e6fc8928464fTerry Jan Reedy self.configGUI(NORMAL, DISABLED, DISABLED) 366076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 367076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl def stopIt(self): 368076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl if self.exitflag: 369076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.clearCanvas() 370076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl self.exitflag = False 3712ced87f3e6f61b777a5cc4368527e6fc8928464fTerry Jan Reedy self.configGUI(NORMAL, DISABLED, DISABLED, 372076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl "STOPPED!", "red") 3738450c5331548e396d31639776c91e191a5f3147eTerry Jan Reedy turtle.TurtleScreen._RUNNING = False 374b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy 375b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy def _destroy(self): 37680a1803193bcaef7a50324974117c3aa3fb0e48fSerhiy Storchaka turtle.TurtleScreen._RUNNING = False 377b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy self.root.destroy() 37880a1803193bcaef7a50324974117c3aa3fb0e48fSerhiy Storchaka self.root = None 379b03f0422c57ef9a19c3d62728a949020fbf608cbTerry Jan Reedy 380076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl 381b8352e7253e61e24f6ba3f06cda6135a3c976884Terry Jan Reedydef main(): 382076cbae4b97cfb7764321f92d8506ef38366facaGeorg Brandl demo = DemoWindow() 383b8352e7253e61e24f6ba3f06cda6135a3c976884Terry Jan Reedy demo.root.mainloop() 384b8352e7253e61e24f6ba3f06cda6135a3c976884Terry Jan Reedy 385b8352e7253e61e24f6ba3f06cda6135a3c976884Terry Jan Reedyif __name__ == '__main__': 386b8352e7253e61e24f6ba3f06cda6135a3c976884Terry Jan Reedy main() 387