Hi Ed, Nice work of yours!
Herewith some improvements (real menus on top, support for "foreign" Windows CE versions like my German one, where the installation is in C:\\Programme\\Python\\lib, support for VGA screen with HI_RES_AWARE python, hide ugly additional Tkinter titlebar below PDA top taskbar). Please give it a try on a real 240x320 PDA -- I can test it only in the 240x320 emulation mode of my VGA PDA. Regards, Sebastian Wangnick -----Ursprungliche Nachricht----- Von: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Auftrag von Ed Blake Gesendet: Donnerstag, 30. Dezember 2004 23:09 An: pythonce@python.org Betreff: [PythonCE] Minature IDLE for PythonCE Something fun, and maybe usefull. Since popup-menus work I will probably move most of the edit menu there.
#IdleCE import sys for p in sys.path: if p[-12:].lower()=="python23.zip": sys.path.append(p+"\\lib-tk") break import os import re from Tkinter import * import tkMessageBox import tkFileDialog import keyword from string import ascii_letters, digits, punctuation OS = os.name.lower() #Should be 'ce' on WinCE class idle: """The base class for the mini idle.""" def __init__(self,root): self.root = root root.grid_rowconfigure(1, weight=1) root.grid_columnconfigure(0, weight=1) frame = Frame(root) frame.grid(row=0,column=0,columnspan=2,sticky=NSEW) self.editor = SyntaxHighlightingText(root) self.editor.grid(row=1,column=0,columnspan=2,sticky=N+S) panbar = Scrollbar(root,orient=HORIZONTAL) panbar.grid(row=2,column=0,columnspan=2,sticky=E+W) scrollbar = Scrollbar(root) scrollbar.grid(row=1,column=2,sticky=N+S) self.editor.configure(xscrollcommand=panbar.set) self.editor.configure(yscrollcommand=scrollbar.set) scrollbar.config(command=self.editor.yview) panbar.config(command=self.editor.xview) btn = Menubutton(frame,text="File",padx=1,pady=1) btn.pack(side=LEFT) submenu = Menu(btn,tearoff=False) btn["menu"] = submenu submenu.add_command(label="New",command=self.new) submenu.add_command(label="Open",command=self.open) submenu.add_command(label="Save",command=self.save) submenu.add_command(label="Save as",command=self.saveas) submenu.add_command(label="Exit",command=self.exit) btn = Menubutton(frame,text="Edit",padx=1,pady=1) btn.pack(side=LEFT) submenu = Menu(btn,tearoff=False) btn["menu"] = submenu submenu.add_command(label="Undo",command=self.editor.edit_undo) submenu.add_command(label="Redo",command=self.editor.edit_redo) submenu.add_command(label="Cut",command=self.editor.cut) submenu.add_command(label="Copy",command=self.editor.copy) submenu.add_command(label="Paste",command=self.editor.paste) btn = Menubutton(frame,text="Help",padx=1,pady=1) btn.pack(side=LEFT) submenu = Menu(btn,tearoff=False) btn["menu"] = submenu submenu.add_command(label="About",command=self.about_dialog) self.root.protocol("WM_DELETE_WINDOW", self.exit) def about_dialog(self): """Sillyness""" top = Toplevel() top.title("about") top.resizable(0,0) top.focus_set() about = """ IdleCE v0.6.1 A miniaturized imitation of the python ide: idle. This software is distibuted under the Gnu-GPL. Please Visit http://www.gnu.org/licenses/gpl.txt to see the license. """ info = Label(top,text=about) info.pack(side=TOP,padx=6) button = Button(top, text="Dismiss", command=top.destroy) button.pack(side=BOTTOM,fill=X) def open(self): # Opens a file and colorizes it self.filename = tkFileDialog.askopenfilename() if OS == 'ce': # Just passing filename fails... self.filename = self.filename.replace('/','\\') try: file = open(self.filename) self.editor.delete("1.0",END) text = file.readlines() file.close() for i in range(len(text)-1): self.editor.insert(END,text[i]) self.editor.colorize(i+1,len(text[i])) #colorize(textline,lastcolumn) self.editor.see("1.0") except IOError: print self.filename def saveas(self): # Called if no filename is set or Saveas is picked self.filename = tkFileDialog.asksaveasfilename() if OS == 'ce': self.filename = self.filename.replace('/','\\') try: file = open(self.filename,'w') text = self.editor.get("1.0",END) file.write(text) file.flush() file.close() except Exception, info: tkMessageBox.showerror('Exception!',info) def save(self): try: file = open(self.filename,'w') text = self.editor.get("1.0",END) file.write(text) file.flush() file.close() except: self.saveas() # If no file has been accessed def new(self): if len(self.editor.get("1.0",END)) >= 2: if tkMessageBox.askokcancel("New File","Discard current file?"): self.editor.delete("1.0",END) self.filename = "" else: self.editor.delete("1.0",END) self.filename = "" def exit(self): # End the program firmly. root.destroy() root.quit() class SyntaxHighlightingText(Text): """A syntax highlighting text widget from the web customized with some methods from Idle and some special methods.""" tags = {'com':'#C00', #comment 'str':'#0A0', #string 'kw': 'orange', #keyword 'obj':'#00F', #function/class name 'int': 'blue' #integers } def __init__(self, root): if OS == 'ce': w = 40 h = 10 else: w = 80 h = 25 Text.__init__(self,root,wrap=NONE,bd=0,width=w,height=h,undo=1,maxundo=50,padx=0,pady=0) # Non-wrapping, no border, undo turned on, max undo 50 self.text = self # For the methods taken from IDLE self.root = root self.config_tags() self.characters = ascii_letters + digits + punctuation self.tabwidth = 8 # for IDLE use, must remain 8 until Tk is fixed self.indentwidth = 4 # Should perhaps be 2 due to the small screen?? self.indention = 0 # The current indention level self.set_tabwidth(self.indentwidth) # IDLE... # create a popup menu self.menu = Menu(root, tearoff=0) self.menu.add_command(label="Undo", command=self.edit_undo) self.menu.add_command(label="Redo", command=self.edit_redo) #self.menu.add_command(type="separator") self.menu.add_command(label="Cut", command=self.cut) self.menu.add_command(label="Copy", command=self.copy) self.menu.add_command(label="Paste", command=self.paste) self.bind('<Key>', self.key_press) # For scanning input self.bind('<Return>',self.autoindent) # Overides default binding self.bind('<Tab>',self.autoindent) # increments self.indention self.bind('<BackSpace>',self.autoindent)# decrements self.indention self.bind('<Double-Button-1>',self.paste)# decrements self.indention self.tag_bind(SEL,'<Button-1>',self.popup) def popup(self, event): """Edit popup menu with a special attribute for cut and copy.""" Selection=self.get_selection_indices() if len(Selection)>0: SelectedText = self.get(Selection[0],Selection[1]) self.sel_store = list(Selection) self.sel_store.extend([SelectedText]) self.menu.post(event.x_root, event.y_root) def get_tabwidth(self): # From IDLE current = self['tabs'] or 5000 return int(current) def set_tabwidth(self, newtabwidth): # From IDLE text = self if self.get_tabwidth() != newtabwidth: pixels = text.tk.call("font", "measure", text["font"], "-displayof", text.master, "n" * newtabwidth) text.configure(tabs=pixels) def config_tags(self): # Sets up the tags and their colors for tag, val in self.tags.items(): self.tag_config(tag, foreground=val) def remove_tags(self, start, end): for tag in self.tags.keys(): self.tag_remove(tag, start, end) def get_selection_indices(self): # If a selection is defined in the text widget, return (start, # end) as Tkinter text indices, otherwise return (None, None) try: first = self.text.index("sel.first") last = self.text.index("sel.last") return first, last except TclError: return None, None def cut(self,event=0): self.clipboard_clear() if self.sel_store: # Sent by the popup self.delete(self.sel_store[0],self.sel_store[1]) self.clipboard_append(self.sel_store[2]) self.sel_store = [] else: # Sent by menu Selection=self.get_selection_indices() if len(Selection)>0: SelectedText = self.get(Selection[0],Selection[1]) self.delete(Selection[0],Selection[1]) self.clipboard_append(SelectedText) def copy(self,event=0): self.clipboard_clear() if self.sel_store: # Sent by the popup self.clipboard_append(self.sel_store[2]) self.sel_store = [] else: # Sent by menu Selection=self.get_selection_indices() if len(Selection)>0: SelectedText = self.get(Selection[0],Selection[1]) self.clipboard_append(SelectedText) def paste(self,event=0): # This should call colorize for the pasted lines. SelectedText = self.root.selection_get(selection='CLIPBOARD') self.insert(INSERT, SelectedText) return "break" def autoindent(self,event): if event.keysym == 'Return': self.edit_separator() # For undo/redo index = self.index(INSERT).split('.') print index line = int(index[0]) column = int(index[1]) if self.get('%s.%d'%(line, column-1)) == ':': self.indention += 1 print '\n', print '\t'*self.indention self.insert(INSERT,'\n') self.insert(INSERT,'\t'*self.indention) return 'break' # Overides standard bindings elif event.keysym == 'Tab': self.edit_separator() self.indention += 1 print self.indention elif event.keysym == 'BackSpace': self.edit_separator() index = self.index(INSERT).split('.') print index line = int(index[0]) column = int(index[1]) if self.get('%s.%d'%(line, column-1)) == '\t': self.indention -= 1 def key_press(self, key): """This function was origonaly the home of the colorize code. Now it is mostly useless unless you want to watch for a certain character.""" if key.char in ' :[(]),"\'': self.edit_separator() # For undo/redo cline = self.index(INSERT).split('.')[0] lastcol = 0 char = self.get('%s.%d'%(cline, lastcol)) while char != '\n': lastcol += 1 char = self.get('%s.%d'%(cline, lastcol)) self.colorize(cline,lastcol) def colorize(self,cline,lastcol): """Not so simple syntax highlighting.""" buffer = self.get('%s.%d'%(cline,0),'%s.%d'%(cline,lastcol)) tokenized = buffer.split(' ') self.remove_tags('%s.%d'%(cline, 0), '%s.%d'%(cline, lastcol)) quotes = 0 start = 0 for i in range(len(buffer)): if buffer[i] in ['"',"'"]: # Doesn't distinguish between single and double quotes... if quotes: self.tag_add('str', '%s.%d'%(cline, start), '%s.%d'%(cline, i+1)) quotes = 0 else: start = i quotes = 1 elif buffer[i] == '#': self.tag_add('com', '%s.%d'%(cline, i), '%s.%d'%(cline, len(buffer))) break start, end = 0, 0 obj_flag = 0 for token in tokenized: end = start + len(token) if obj_flag: self.tag_add('obj', '%s.%d'%(cline, start), '%s.%d'%(cline, end)) obj_flag = 0 if token.strip() in keyword.kwlist: self.tag_add('kw', '%s.%d'%(cline, start), '%s.%d'%(cline, end)) if token.strip() in ['def','class']: obj_flag = 1 else: for index in range(len(token)): try: int(token[index]) except ValueError: pass else: self.tag_add('int', '%s.%d'%(cline, start+index)) start += len(token)+1 if __name__ == '__main__': root = Tk() root.title('IdleCE') if OS=='ce': sizex, sizey = root.wm_maxsize() root.wm_geometry("%dx%d+0+%d"%(sizex-6,sizey*37/64+1,sizey/90)) app = idle(root) root.mainloop()
_______________________________________________ PythonCE mailing list PythonCE@python.org http://mail.python.org/mailman/listinfo/pythonce