0001import Tkinter
0002import Pmw
0003import threading
0004from pylogo import reader
0005from Queue import Queue, Empty
0006
0007root = Pmw.initialise()
0008
0009class IDE:
0010 def __init__(self, parent):
0011 self.incoming_history = Queue()
0012 self.incoming_commands = Queue()
0013 self.parent = parent
0014
0015 self.menuBar = Pmw.MainMenuBar(parent)
0016 parent.configure(menu=self.menuBar)
0017 self.menuBar.addmenu('File', '')
0018 self.menuBar.addmenuitem('File', 'command', label='Exit',
0019 command=self.exit)
0020 self.parent.protocol('WM_DELETE_WINDOW', self.exit)
0021 self.menuBar.addmenu('Help', '')
0022 self.menuBar.addmenuitem('Help', 'command', label='About',
0023 command=self.about)
0024
0025
0026
0027
0028
0029 self.pw = Pmw.PanedWidget(
0030 parent,
0031 hull_borderwidth=1,
0032 hull_relief='sunken')
0033 pane = self.pw.add('canvas', size=.5)
0034 self.scroller = TurtleSpace(
0035 pane,
0036 canvas_width=1000,
0037 canvas_height=1000,
0038 canvas_background="white")
0039 self.scroller.pack(side='top', expand=1)
0040
0041 pane3 = self.pw.add('history', size=.4)
0042 self.history = Pmw.ScrolledText(
0043 pane3,
0044 borderframe=1,
0045 vscrollmode='static',
0046 text_width=70)
0047 self.history.pack(side='top', expand=1)
0048
0049 pane2 = self.pw.add('entry', size=.1)
0050 self.input = Pmw.EntryField(
0051 pane2,
0052 command=self.feed_input,
0053 entry_width=72)
0054 self.input.pack(side='top', expand=1)
0055
0056 self.pw.pack(expand=1, fill='both')
0057 self.canvas = canvas = self.scroller.component('canvas')
0058 self.parent.after(100, self.idle_updates)
0059 return
0060
0061 def feed_input(self):
0062 value = self.input.getvalue() + '\n'
0063 self.logo_communicator.add_input(value)
0064 self.input.clear()
0065 self.update_history()
0066 self.update_commands()
0067
0068 def idle_updates(self):
0069
0070 self.update_history()
0071 self.update_commands()
0072 self.parent.after(100, self.idle_updates)
0073
0074 def add_history(self, val):
0075
0076
0077
0078 self.incoming_history.put(val)
0079
0080 def update_history(self):
0081 history = []
0082 while 1:
0083 try:
0084 history.append(self.incoming_history.get_nowait())
0085 except Empty:
0086 break
0087 for line in history:
0088 if line.endswith('\n') and 0:
0089
0090
0091
0092 line = line[:-1]
0093 self.history.appendtext(line)
0094
0095 def exit(self):
0096 print "Exiting!"
0097 self.parent.destroy()
0098 self.logo_communicator.exit()
0099 return
0100
0101 def about(self):
0102 Pmw.aboutversion('0.2')
0103 Pmw.aboutcopyright('Copyright Ian Bicking 2003')
0104 Pmw.aboutcontact('For more information:\n http://pylogo.org')
0105 about = Pmw.AboutDialog(self.parent, applicationname='PyLogo')
0106 about.show()
0107
0108 def update_commands(self):
0109 while 1:
0110 try:
0111 command = self.incoming_commands.get_nowait()
0112 except Empty:
0113 return
0114 if command == 'quit':
0115 self.exit()
0116 try:
0117 val = command[1](*command[2], **command[3])
0118 except Exception, e:
0119 if command[0]:
0120 command[0].put([True, e])
0121 else:
0122 if command[0]:
0123 command[0].put([False, val])
0124
0125 def run_command(self, func, *args, **kw):
0126 if kw.has_key('_nowait'):
0127 nowait = kw['_nowait']
0128 del kw['_nowait']
0129 else:
0130 nowait = 0
0131 if nowait:
0132 out = None
0133 else:
0134 out = Queue(1)
0135 self.incoming_commands.put((out, func, args, kw))
0136 if out:
0137 error, result = out.get()
0138 if error:
0139 raise result
0140 else:
0141 return result
0142
0143 def add_command(self, func, *args, **kw):
0144 kw['_nowait'] = 1
0145 return self.run_command(func, *args, **kw)
0146
0147class TurtleSpace(Pmw.ScrolledCanvas):
0148
0149 def __init__(self, *args, **kw):
0150 Pmw.ScrolledCanvas.__init__(self, *args, **kw)
0151
0152
0153class LogoCommunicator:
0154
0155 def __init__(self, app, interp):
0156 self.interp = interp
0157 self.app = app
0158 app.logo_communicator = self
0159 interp.canvas = app.canvas
0160 interp.app = app
0161 self.pending_input = Queue()
0162 self.pendingOutput = Queue()
0163 self.input_event = threading.Event()
0164
0165 def start(self):
0166 self.logoThread = threading.Thread(
0167 target=self.interp.input_loop,
0168 args=(reader.TrackingStream(self), self))
0169 self.logoThread.start()
0170
0171 def exit(self):
0172 self.add_input('bye\n')
0173
0174 def add_input(self, value):
0175 if not value.endswith('\n'):
0176 value += '\n'
0177 self.app.add_history(value)
0178 self.pending_input.put(value)
0179 self.input_event.set()
0180
0181 def readline(self):
0182 result = self.pending_input.get()
0183 return result
0184
0185 def write(self, value):
0186 self.app.add_history(value)
0187
0188 def flush(self):
0189 pass
0190
0191 name = '<ide>'
0192
0193
0194
0195from pylogo import interpreter
0196
0197def add_command(command, *args, **kw):
0198 TheApp.add_command(command, *args, **kw)
0199 return TheApp
0200
0201def get_canvas():
0202 return TheApp.canvas
0203
0204def main():
0205 import sys
0206 from pylogo import logo_turtle
0207 global TheApp
0208 TheApp = IDE(root)
0209 TheApp.input.component('entry').focus_force()
0210 comm = LogoCommunicator(TheApp, interpreter.Logo)
0211 sys.stdout = comm
0212 interpreter.Logo.import_module(logo_turtle)
0213 logo_turtle.createturtle(interpreter.Logo)
0214
0215
0216
0217 comm.start()
0218
0219 root.mainloop()
0220
0221if __name__ == '__main__':
0222 main()