AW: [PythonCE] Minature IDLE for PythonCE
Anne Wangnick
anne.wangnick at t-online.de
Wed Jan 5 20:31:39 CET 2005
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: pythonce-bounces at python.org [mailto:pythonce-bounces at python.org]Im
Auftrag von Ed Blake
Gesendet: Mittwoch, 5. Januar 2005 01:58
An: pythonce at 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: pythonce-bounces at python.org [mailto:pythonce-bounces at python.org]Im
Auftrag von Anne Wangnick
Gesendet: Mittwoch, 5. Januar 2005 19:12
An: Ed Blake
Cc: pythonce at 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: pythonce-bounces at python.org [mailto:pythonce-bounces at python.org]Im
Auftrag von Ed Blake
Gesendet: Donnerstag, 30. Dezember 2004 23:09
An: pythonce at 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.
-------------- next part --------------
#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()
More information about the PythonCE
mailing list