Dear all, I've managed to find a workaround for the Tkinter text widget selection problems. I've filed the issue also to http://wiki.tcl.tk/9184 to get it solved in the long run. You have to add something like the following code to your applications using text widgets:
b1motion = root.bind_class('Text','<B1-Motion>') root.bind_class('Text','<B1-Motion>','if {![info exists ::tk::Priv(ignoreB1Motion)]} {%s}'%b1motion) root.bind_class('Text','<B1-Leave>','set ::tk::Priv(ignoreB1Motion) 1') root.bind_class('Text','<B1-Enter>','array unset ::tk::Priv ignoreB1Motion') Ed, an updated version of your most recent distribution of IdleCE is attached. Regards, Sebastian -----Ursprungliche Nachricht----- Von: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Auftrag von Ed Blake Gesendet: Mittwoch, 5. Januar 2005 01:58 An: pythonce@python.org Betreff: [PythonCE] Mini IDLE update and response. I've managed to get popup menus that work. Highlight some text, tap the selection and a menu will appear. It is equivalent to the edit menu/window but seems to work better for cut/copy. I have a problem with this though on my own device (HP Ipaq, WinCE 2003). When I try to highlight text the selection flickers and changes, like the selection is being made over and over. If anyone can figure out what causes this I would be interested in hearing about it. RE the license: I think the example code I based most of this app on was released GPL so unless I can track down the example again and verify its license... I suppose if I verify that the example was other than GPL I should use the python license as that is the license used on IDLE. -----Ursprungliche Nachricht----- Von: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Auftrag von Anne Wangnick Gesendet: Mittwoch, 5. Januar 2005 19:12 An: Ed Blake Cc: pythonce@python.org Betreff: AW: [PythonCE] Minature IDLE for PythonCE 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.2 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)) b1motion = root.bind_class('Text','<B1-Motion>') root.bind_class('Text','<B1-Motion>','if {![info exists ::tk::Priv(ignoreB1Motion)]} {%s}'%b1motion) root.bind_class('Text','<B1-Leave>','set ::tk::Priv(ignoreB1Motion) 1') root.bind_class('Text','<B1-Enter>','array unset ::tk::Priv ignoreB1Motion') app = idle(root) root.mainloop()
_______________________________________________ PythonCE mailing list PythonCE@python.org http://mail.python.org/mailman/listinfo/pythonce