class SplashScreen: root = None win = None img = 'images/splash-screen' flag = 0 def __init__(self, root): self.root = root self.width = 500 self.height = 300 self.flag = config.preferences.show_splash def show(self): self.root.withdraw() if self.flag: img_file = os.path.join(app.config.sk_share_dir, self.img + '.png') from sk1sdk.tkpng import load_icon load_icon(self.root, img_file, self.img) scrnWt = self.root.winfo_screenwidth() scrnHt = self.root.winfo_screenheight() winXPos = (scrnWt / 2) - (self.width / 2) winYPos = (scrnHt / 2) - (self.height / 2) self.win = Toplevel() self.win.overrideredirect(1) self.win.configure(background='black') self.banner = Label(self.win, image=self.img, cursor='watch', borderwidth=0) self.banner.pack() self.verlb = Label(self.win, text='version %s' % (config.version, ), bg='white') self.verlb.place(x=10, y=240) self.verlb['font'] += ' bold' self.txtlb = Label(self.win, text='Start...', bg='white') self.txtlb.place(x=10, y=265) self.progress_bar = SS_ProgressBar(self.win) self.progress_bar.pack(fill=X, side=TOP) geom = (self.width, self.height, winXPos, winYPos) self.win.geometry('%dx%d+%d+%d' % geom) self.win.update() def hide(self): if self.flag and self.win: self.win.withdraw() self.win.destroy() def set_val(self, val, txt=''): self.progress_bar.set_val(val) if txt: self.txtlb['text'] = txt self.win.update()
class SplashScreen: root = None win = None img = 'images/splash-screen' flag = 0 def __init__(self, root): self.root = root self.width = 500 self.height = 300 self.flag = config.preferences.show_splash def show(self): self.root.withdraw() if self.flag: img_file = os.path.join(app.config.sk_share_dir, self.img + '.png') from sk1sdk.tkpng import load_icon load_icon(self.root, img_file, self.img) scrnWt = self.root.winfo_screenwidth() scrnHt = self.root.winfo_screenheight() winXPos = (scrnWt / 2) - (self.width / 2) winYPos = (scrnHt / 2) - (self.height / 2) self.win = Toplevel() self.win.overrideredirect(1) self.win.configure(background='black') self.banner = Label(self.win, image=self.img, cursor='watch', borderwidth=0) self.banner.pack() self.verlb = Label(self.win, text='version %s' % (config.version,), bg='white') self.verlb.place(x=10, y=240) self.verlb['font'] += ' bold' self.txtlb = Label(self.win, text='Start...', bg='white') self.txtlb.place(x=10, y=265) self.progress_bar = SS_ProgressBar(self.win) self.progress_bar.pack(fill=X, side=TOP) geom = (self.width, self.height, winXPos, winYPos) self.win.geometry('%dx%d+%d+%d' % geom) self.win.update() def hide(self): if self.flag and self.win: self.win.withdraw() self.win.destroy() def set_val(self, val, txt=''): self.progress_bar.set_val(val) if txt: self.txtlb['text'] = txt self.win.update()
class PypeTkPad(object): def __init__(self, master, queue, pypeOutput): self.queue = queue self.pypeOutput = pypeOutput self.master = master self.master.title('PypePad') self.master.geometry("%dx%d%+d%+d" % (700, 500, 0, 0)) self.master.minsize(300, 100) self.output_file_name = None self.BuildMainFrame() self.UpdateOutput() def NewCommand(self): self.ClearAllCommand() def OpenCommand(self): import tkFileDialog from Tkinter import END openfile = tkFileDialog.askopenfile() if not openfile: return for line in openfile.readlines(): self.text_input.insert(END, line) def SaveCommand(self): import tkFileDialog from Tkinter import END saveasfile = tkFileDialog.asksaveasfile() if not saveasfile: return alltext = self.text_input.get("1.0", END) saveasfile.write(alltext) def QuitCommand(self): self.master.quit() def ClearInputCommand(self): from Tkinter import END self.text_input.delete("1.0", END) def ClearOutputCommand(self): from Tkinter import NORMAL, END, DISABLED self.text_output["state"] = NORMAL self.text_output.delete("1.0", END) self.text_output["state"] = DISABLED self.text_output.see(END) self.text_output.update() def ClearAllCommand(self): self.ClearInputCommand() self.ClearOutputCommand() def OutputFileCommand(self): import tkFileDialog outputfilename = tkFileDialog.asksaveasfilename() if sys.platform == 'win32' and len(outputfilename.split()) > 1: outputfilename = '"%s"' % outputfilename self.output_file_name = outputfilename def AboutCommand(self): self.OutputText('\n') self.OutputText( '* PypePad, Copyright (c) Luca Antiga, David Steinman. *\n') self.OutputText('\n') def UpdateOutput(self): if self.pypeOutput: text = self.pypeOutput.pop(0) self.output_stream.write(text) self.master.after(10, self.UpdateOutput) def RunPype(self, arguments): if not arguments: return if self.output_to_file.get() is not 'n' and self.output_file_name: self.output_stream.output_to_file = True self.output_stream.output_file = open(self.output_file_name, self.output_to_file.get()) else: self.output_stream.output_to_file = False self.queue.append(arguments) def GetWordUnderCursor(self): from Tkinter import CURRENT splitindex = self.text_input.index(CURRENT).split('.') line = self.text_input.get(splitindex[0] + ".0", splitindex[0] + ".end") wordstart = line.rfind(' ', 0, int(splitindex[1]) - 1) + 1 wordend = line.find(' ', int(splitindex[1])) if wordend == -1: wordend = len(line) word = line[wordstart:wordend] return word def GetWordIndex(self): startindex = self.text_input.index("insert-1c wordstart") endindex = self.text_input.index("insert-1c wordend") if self.text_input.get(startindex + '-1c') == '-' and self.text_input.get( startindex + '-2c') == '-': startindex = self.text_input.index("insert-1c wordstart -2c") elif self.text_input.get(startindex + '-1c') == '-' and self.text_input.get( startindex + '-2c') == ' ': startindex = self.text_input.index("insert-1c wordstart -1c") self.wordIndex[0] = startindex self.wordIndex[1] = endindex word = self.text_input.get(self.wordIndex[0], self.wordIndex[1]) return word def GetLogicalLine(self, physicallineid): indexes, lines = self.GetLogicalLines() return lines[indexes[physicallineid]] def GetLogicalLineRange(self, physicallinefirstid, physicallinelastid): indexes, lines = self.GetLogicalLines() return lines[indexes[physicallinefirstid]:indexes[physicallinelastid] + 1] def GetAllLogicalLines(self): return self.GetLogicalLines()[1] def GetLogicalLines(self): from Tkinter import END physicallines = self.text_input.get("1.0", END).split('\n') lines = [] indexes = [0] * len(physicallines) lineid = 0 previousline = "" join = 0 for line in physicallines: if line.startswith('#'): if join: indexes[lineid] = indexes[lineid - 1] elif join: if line.endswith('\\'): lines[-1] = lines[-1] + " " + line[:-1] join = 1 else: lines[-1] = lines[-1] + " " + line join = 0 indexes[lineid] = indexes[lineid - 1] else: if line.endswith('\\'): join = 1 lines.append(line[:-1]) else: lines.append(line) join = 0 if lineid > 0: indexes[lineid] = indexes[lineid - 1] + 1 lineid += 1 return indexes, lines def GetLineUnderCursor(self): from Tkinter import INSERT currentlineid = int(self.text_input.index(INSERT).split('.')[0]) - 1 return self.GetLogicalLine(currentlineid) def RunAllCommand(self): lines = self.GetAllLogicalLines() for line in lines: if line and line.strip(): self.RunPype(line) def RunLineCommand(self): line = self.GetLineUnderCursor() if line and line.strip(): self.RunPype(line) def RunSelectionCommand(self): from Tkinter import TclError, SEL_FIRST, SEL_LAST try: firstlineid = int( self.text_input.index(SEL_FIRST).split('.')[0]) - 1 lastlineid = int(self.text_input.index(SEL_LAST).split('.')[0]) - 1 lines = self.GetLogicalLineRange(firstlineid, lastlineid) for line in lines: self.RunPype(line) except TclError: pass def GetSuggestionsList(self, word): list = [] try: exec('import vmtkscripts') except ImportError: return None if word.startswith('--'): list = ['--pipe', '--help'] elif word.startswith('-'): optionlist = [] scriptindex = self.text_input.search('vmtk', self.wordIndex[0], backwards=1) moduleName = self.text_input.get(scriptindex, scriptindex + ' wordend') try: exec('import ' + moduleName) exec('scriptObjectClassName = ' + moduleName + '.' + moduleName) exec('scriptObject = ' + moduleName + '.' + scriptObjectClassName + '()') members = scriptObject.InputMembers + scriptObject.OutputMembers for member in members: optionlist.append('-' + member.OptionName) exec( 'list = [option for option in optionlist if option.count(word)]' ) except: return list else: exec( 'list = [scriptname for scriptname in vmtkscripts.__all__ if scriptname.count(word) ]' ) return list def FillSuggestionsList(self, word): from Tkinter import END self.suggestionslist.delete(0, END) suggestions = self.GetSuggestionsList(word) for suggestion in suggestions: self.suggestionslist.insert(END, suggestion) def ReplaceTextCommand(self, word): self.text_input.delete(self.wordIndex[0], self.wordIndex[1]) self.text_input.insert(self.wordIndex[0], word) self.text_input.focus_set() def ShowHelpCommand(self): word = self.GetWordUnderCursor() self.OutputText(word) if word: self.RunPype(word + ' --help') else: self.OutputText('Enter your vmtk Pype above and Run.\n') def AutoCompleteCommand(self): word = self.GetWordIndex() self.suggestionswindow.withdraw() if word: self.FillSuggestionsList(word) self.suggestionswindow.geometry( "%dx%d%+d%+d" % (400, 150, self.text_output.winfo_rootx(), self.text_output.winfo_rooty())) self.suggestionswindow.deiconify() self.suggestionswindow.lift() def InsertScriptName(self, scriptname): from Tkinter import INSERT self.text_input.insert(INSERT, scriptname + ' ') def InsertFileName(self): from Tkinter import INSERT import tkFileDialog openfilename = tkFileDialog.askopenfilename() if not openfilename: return if len(openfilename.split()) > 1: openfilename = '"%s"' % openfilename self.text_input.insert(INSERT, openfilename + ' ') def KeyPressHandler(self, event): if event.keysym == "Tab": self.AutoCompleteCommand() self.suggestionslist.focus_set() self.suggestionslist.selection_set(0) return "break" else: self.text_input.focus_set() def TopKeyPressHandler(self, event): from Tkinter import ACTIVE, INSERT if event.keysym in ['Down', 'Up']: self.suggestionslist.focus_set() elif event.keysym == "Return": word = self.suggestionslist.get(ACTIVE) self.ReplaceTextCommand(word) self.suggestionswindow.withdraw() self.text_input.focus_set() elif len(event.keysym) == 1: self.suggestionswindow.withdraw() self.text_input.insert(INSERT, event.keysym) self.text_input.focus_set() else: self.suggestionswindow.withdraw() self.text_input.focus_set() def NewHandler(self, event): self.NewCommand() def OpenHandler(self, event): self.OpenCommand() def SaveHandler(self, event): self.SaveCommand() def InsertFileNameHandler(self, event): self.InsertFileName() return "break" def QuitHandler(self, event): self.QuitCommand() def ShowHelpHandler(self, event): self.ShowHelpCommand() def RunKeyboardHandler(self, event): from Tkinter import SEL_FIRST, TclError try: self.text_input.index(SEL_FIRST) self.RunSelectionCommand() except TclError: self.RunLineCommand() return "break" def RunAllHandler(self, event): self.RunAllCommand() def PopupHandler(self, event): try: self.popupmenu.tk_popup(event.x_root, event.y_root, 0) finally: self.popupmenu.grab_release() def OutputText(self, text): from Tkinter import NORMAL, END, DISABLED self.text_output["state"] = NORMAL self.text_output.insert(END, text) self.text_output["state"] = DISABLED def BuildScriptMenu(self, parentmenu, modulename): from Tkinter import Menu menu = Menu(parentmenu, bd=1, activeborderwidth=0) try: exec('import ' + modulename) except ImportError: return None scriptnames = [] exec('scriptnames = [scriptname for scriptname in ' + modulename + '.__all__]') menulength = 20 for i in range(len(scriptnames) / menulength + 1): subscriptnames = scriptnames[i * menulength:(i + 1) * menulength] if not subscriptnames: break submenu = Menu(menu, bd=1, activeborderwidth=0) menu.add_cascade(label=subscriptnames[0] + "...", menu=submenu) for scriptname in subscriptnames: callback = CallbackShim(self.InsertScriptName, scriptname) submenu.add_command(label=scriptname, command=callback) return menu def BuildMainFrame(self): from Tkinter import Menu, IntVar, StringVar, Toplevel, Listbox, Frame, PanedWindow, Text, Scrollbar, Entry from Tkinter import X, N, S, W, E, VERTICAL, TOP, END, DISABLED, RAISED menu = Menu(self.master, activeborderwidth=0, bd=0) self.master.config(menu=menu) filemenu = Menu(menu, tearoff=0, bd=1, activeborderwidth=0) menu.add_cascade(label="File", underline=0, menu=filemenu) filemenu.add_command(label="New", accelerator='Ctrl+N', command=self.NewCommand) filemenu.add_command(label="Open...", accelerator='Ctrl+O', command=self.OpenCommand) filemenu.add_command(label="Save as...", accelerator='Ctrl+S', command=self.SaveCommand) filemenu.add_separator() filemenu.add_command(label="Quit", accelerator='Ctrl+Q', command=self.QuitCommand) self.log_on = IntVar() self.log_on.set(1) self.output_to_file = StringVar() self.output_to_file.set('n') scriptmenu = Menu(menu, tearoff=0, bd=1, activeborderwidth=0) modulenames = ['vmtkscripts'] for modulename in modulenames: scriptsubmenu = self.BuildScriptMenu(menu, modulename) if scriptsubmenu: scriptmenu.add_cascade(label=modulename, menu=scriptsubmenu) editmenu = Menu(menu, tearoff=0, bd=1, activeborderwidth=0) menu.add_cascade(label="Edit", underline=0, menu=editmenu) editmenu.add_cascade(label="Insert script", menu=scriptmenu) editmenu.add_command(label="Insert file name", accelerator='Ctrl+F', command=self.InsertFileName) editmenu.add_separator() editmenu.add_command(label="Clear input", command=self.ClearInputCommand) editmenu.add_command(label="Clear output", command=self.ClearOutputCommand) editmenu.add_command(label="Clear all", command=self.ClearAllCommand) editmenu.add_separator() editmenu.add_checkbutton(label="Log", variable=self.log_on) editmenu.add_separator() editmenu.add_radiobutton(label="No output to file", variable=self.output_to_file, value='n') editmenu.add_radiobutton(label="Write output to file", variable=self.output_to_file, value='w') editmenu.add_radiobutton(label="Append output to file", variable=self.output_to_file, value='a') editmenu.add_command(label="Output file...", command=self.OutputFileCommand) runmenu = Menu(menu, tearoff=0, bd=1, activeborderwidth=0) menu.add_cascade(label="Run", underline=0, menu=runmenu) runmenu.add_command(label="Run all", command=self.RunAllCommand) runmenu.add_command(label="Run current line", command=self.RunLineCommand) runmenu.add_command(label="Run selection", command=self.RunSelectionCommand) helpmenu = Menu(menu, tearoff=0, bd=1, activeborderwidth=0) menu.add_cascade(label="Help", underline=0, menu=helpmenu) helpmenu.add_command(label="Help", underline=0, accelerator='F1', command=self.ShowHelpCommand) helpmenu.add_command(label="About", underline=0, command=self.AboutCommand) self.master.bind("<Control-KeyPress-q>", self.QuitHandler) self.master.bind("<Control-KeyPress-n>", self.NewHandler) self.master.bind("<Control-KeyPress-o>", self.OpenHandler) self.master.bind("<Control-KeyPress-s>", self.SaveHandler) self.master.bind("<Control-KeyPress-f>", self.InsertFileNameHandler) self.master.bind("<KeyPress-F1>", self.ShowHelpHandler) self.master.bind("<KeyPress>", self.KeyPressHandler) self.wordIndex = ['1.0', '1.0'] self.suggestionswindow = Toplevel(bg='#ffffff', bd=0, height=50, width=600, highlightthickness=0, takefocus=True) self.suggestionswindow.overrideredirect(1) self.suggestionslist = Listbox(self.suggestionswindow, bg='#ffffff', bd=1, fg='#336699', activestyle='none', highlightthickness=0, height=9) self.suggestionslist.insert(END, "foo") self.suggestionslist.pack(side=TOP, fill=X) self.suggestionswindow.bind("<KeyPress>", self.TopKeyPressHandler) self.suggestionswindow.withdraw() self.master.rowconfigure(0, weight=1) self.master.columnconfigure(0, weight=1) content = Frame(self.master, bd=0, padx=2, pady=2) content.grid(row=0, column=0, sticky=N + S + W + E) content.rowconfigure(0, weight=1, minsize=50) content.rowconfigure(1, weight=0) content.columnconfigure(0, weight=1) panes = PanedWindow(content, orient=VERTICAL, bd=1, sashwidth=8, sashpad=0, sashrelief=RAISED, showhandle=True) panes.grid(row=0, column=0, sticky=N + S + W + E) frame1 = Frame(panes, bd=0) frame1.grid(row=0, column=0, sticky=N + S + W + E) frame1.columnconfigure(0, weight=1) frame1.columnconfigure(1, weight=0) frame1.rowconfigure(0, weight=1) panes.add(frame1, height=300, minsize=20) frame2 = Frame(panes, bd=0) frame2.grid(row=1, column=0, sticky=N + S + W + E) frame2.columnconfigure(0, weight=1) frame2.columnconfigure(1, weight=0) frame2.rowconfigure(0, weight=1) panes.add(frame2, minsize=20) self.text_input = Text(frame1, bg='#ffffff', bd=1, highlightthickness=0) self.text_input.bind("<KeyPress>", self.KeyPressHandler) self.text_input.bind("<Button-3>", self.PopupHandler) self.text_input.bind("<Control-Return>", self.RunKeyboardHandler) self.input_scrollbar = Scrollbar(frame1, orient=VERTICAL, command=self.text_input.yview) self.text_input["yscrollcommand"] = self.input_scrollbar.set self.text_output = Text(frame2, state=DISABLED, bd=1, bg='#ffffff', highlightthickness=0) self.output_scrollbar = Scrollbar(frame2, orient=VERTICAL, command=self.text_output.yview) self.text_output["yscrollcommand"] = self.output_scrollbar.set self.text_entry = Entry(content, bd=1, bg='#ffffff', state=DISABLED, highlightthickness=0) self.text_input.focus_set() self.text_input.grid(row=0, column=0, sticky=N + S + W + E) self.input_scrollbar.grid(row=0, column=1, sticky=N + S + W + E) self.text_output.grid(row=0, column=0, sticky=N + S + W + E) self.output_scrollbar.grid(row=0, column=1, sticky=N + S + W + E) self.text_entry.grid(row=1, column=0, sticky=N + S + W + E) self.popupmenu = Menu(self.text_input, tearoff=1, bd=0) self.popupmenu.add_command(label="Context help", command=self.ShowHelpCommand) self.popupmenu.add_cascade(label="Insert script", menu=scriptmenu) self.popupmenu.add_command(label="Insert file name...", command=self.InsertFileName) self.popupmenu.add_separator() self.popupmenu.add_command(label="Run all", command=self.RunAllCommand) self.popupmenu.add_command(label="Run current line", command=self.RunLineCommand) self.popupmenu.add_command(label="Run selection", command=self.RunSelectionCommand) self.output_stream = TkPadOutputStream(self.text_output) self.input_stream = TkPadInputStream(self.text_entry, self.output_stream)
class KeyboardEntry: """Mixin class that can be used to add the ability to type values for widget. When the cursor enters the widget the focus is set to the widget and the widget that had the focus previousy is saved in .lastFocus. When the cursor leaves the widget focus is restored to self.lastFocus. key_cb(event) is called upon KeyRelease events. If this is the first keytroke an undecorated window is created next to the cursor and handleKeyStroke(event) is called. This method should be subclassed to modify the way the string is typed in (see thumbwheel.py for an example of handling numbers only). When the Return key is pressed, the entry window is destroyed and if the typed striong is not empty self.callSet(self.typedValue) is called. If the cursor moves out of the widget before Rrturn is pressed the value in the entry window is discarded and the entry window is destroyed. """ def __init__(self, widgets, callSet): # callSet is a function taking one argument (string) which will be # when the Returnm key is hit (if the typed string is not empty) # widgets is a list of Tkinter wigets for which <Enter>, <Leave> # <Return> and <KeyRelease> are handled. These widgets has to exist # before thsi constructor can be called assert callable(callSet) self.callSet = callSet for w in widgets: w.bind("<Enter>", self.enter_cb) w.bind("<Leave>", self.leave_cb) w.bind("<Return>", self.return_cb) w.bind("<KeyRelease>", self.key_cb) self.typedValue = '' # string accumulating valuescharacters typed self.lastFocus = None # widget to which the focus will be restored # when the mouse leaves the widget self.topEntry = None # top level for typing values self.typedValueTK = None #Tk label used as entry for value def key_cb(self, event=None): # call back function for keyboard events (except for Return) # handle numbers to set value key = event.keysym if key == 'Return': return #print 'Key:', key if len(self.typedValue) == 0 and self.topEntry is None: # create Tk label showing typed value x = event.x y = event.y #print 'create entry' self.topEntry = Toplevel() self.topEntry.overrideredirect(1) w = event.widget if event.x >= 0: self.topEntry.geometry('+%d+%d' % (w.winfo_rootx() + event.x + 10, w.winfo_rooty() + event.y)) else: self.topEntry.geometry('+%d+%d' % (w.winfo_rootx() + 10, w.winfo_rooty())) self.typedValueTK = Label(master=self.topEntry, text='', relief='sunken', bg='yellow') self.typedValueTK.pack() self.handleKeyStroke(event) def leave_cb(self, event=None): # make sure widget gets keyboard events # print 'leave', event.widget if self.topEntry: self.typedValueTK.destroy() self.topEntry.destroy() self.topEntry = None self.typedValue = '' if self.lastFocus: #print 'restoring focus' if widgetsOnBackWindowsCanGrabFocus is False: lActiveWindow = self.lastFocus.focus_get() if lActiveWindow is not None \ and ( lActiveWindow.winfo_toplevel() != self.lastFocus.winfo_toplevel() ): return self.lastFocus.focus_set() self.lastFocus = None event.widget.config(cursor='') def enter_cb(self, event=None): # make sure widget gets keyboard events #print 'enter', event.widget if widgetsOnBackWindowsCanGrabFocus is False: lActiveWindow = event.widget.focus_get() if lActiveWindow is not None \ and ( lActiveWindow.winfo_toplevel() != event.widget.winfo_toplevel() ): return if self.lastFocus is None: #print 'setting focus' self.lastFocus = self.focus_lastfor() event.widget.focus_set() event.widget.config(cursor='xterm') def return_cb(self, event): # return should destroy the topEntry #print "return_cb" if self.typedValueTK is not None: self.typedValueTK.destroy() if self.topEntry is not None: self.topEntry.destroy() self.topEntry = None if len(self.typedValue): #print 'setting to', self.type(self.typedValue) self.callSet(self.typedValue) self.typedValue = '' ## TO BE SUBCLASSED def handleKeyStroke(self, event): # by default we handle delete character keys key = event.keysym if key == 'BackSpace' or key == 'Delete': self.typedValue = self.typedValue[:-1] self.typedValueTK.configure(text=self.typedValue)
class Tooltips: tooltip_delay = 100 def __init__(self): self.descriptions = {} self.balloon = None self.balloon_label = None self.last_widget = '' self.after_id = None self.root = None def AddDescription(self, widget, description): self.descriptions[widget._w] = description if widget._w == self.last_widget: self.balloon_label['text'] = description def RemoveDescription(self, widget): if type(widget) == InstanceType: widget = widget._w if self.descriptions.has_key(widget): del self.descriptions[widget] def GetDescription(self, widget): if type(widget) == InstanceType: widget = widget._w if self.descriptions.has_key(widget): return self.descriptions[widget] return '' def create_balloon(self, root): self.root = root self.balloon = Toplevel(self.root) self.balloon.withdraw() self.balloon.overrideredirect(1) self.balloon["relief"] = 'flat' label = TLabel(self.balloon, text='Tooltip', style='Tooltips') label.pack(ipadx=2, ipady=2) self.balloon_label = label def popup_balloon(self, widget_name, x, y, text): self.last_widget = widget_name self.balloon.withdraw() self.balloon_label['text'] = text width = self.balloon_label.winfo_reqwidth() height = self.balloon_label.winfo_reqheight() screenwidth = self.root.winfo_screenwidth() screenheight = self.root.winfo_screenheight() x = self.root.winfo_pointerx() y = self.root.winfo_pointery() + 20 if screenwidth < (x + width): x = x - width if screenheight < (y + height): y = y - height - 25 self.balloon.geometry('%+d%+d' % (x, y)) self.balloon.update() self.balloon.deiconify() self.balloon.tkraise() def popup_delayed(self, widget_name, x, y, text, *args): self.after_id = None self.popup_balloon(widget_name, x, y, text) def enter_widget(self, event): widget_name = event.widget text = self.GetDescription(widget_name) if text: x = event.x y = event.y if self.after_id: print 'after_id in enter' self.root.after_cancel(self.after_id) self.after_id = self.root.after(self.tooltip_delay, self.popup_delayed, widget_name, x, y, text) def leave_widget(self, event): global last_widget, after_id if self.after_id is not None: self.root.after_cancel(self.after_id) self.after_id = None self.last_widget = '' last_widget = '' self.balloon.withdraw() button_press = leave_widget def destroy_widget(self, event): self.RemoveDescription(event.widget)
class PypeTkPad(object): def __init__(self, master, queue, pypeOutput): self.queue = queue self.pypeOutput = pypeOutput self.master = master self.master.title('PypePad') self.master.geometry("%dx%d%+d%+d" % (700, 500, 0, 0)) self.master.minsize(300, 100) self.output_file_name = None self.BuildMainFrame() self.UpdateOutput() def NewCommand(self): self.ClearAllCommand() def OpenCommand(self): import tkFileDialog from Tkinter import END openfile = tkFileDialog.askopenfile() if not openfile: return for line in openfile.readlines(): self.text_input.insert(END,line) def SaveCommand(self): import tkFileDialog from Tkinter import END saveasfile = tkFileDialog.asksaveasfile() if not saveasfile: return alltext = self.text_input.get("1.0",END) saveasfile.write(alltext) def QuitCommand(self): self.master.quit() def ClearInputCommand(self): from Tkinter import END self.text_input.delete("1.0",END) def ClearOutputCommand(self): from Tkinter import NORMAL, END, DISABLED self.text_output["state"] = NORMAL self.text_output.delete("1.0",END) self.text_output["state"] = DISABLED self.text_output.see(END) self.text_output.update() def ClearAllCommand(self): self.ClearInputCommand() self.ClearOutputCommand() def OutputFileCommand(self): import tkFileDialog outputfilename = tkFileDialog.asksaveasfilename() if sys.platform == 'win32' and len(outputfilename.split()) > 1: outputfilename = '"%s"' % outputfilename self.output_file_name = outputfilename def AboutCommand(self): self.OutputText('\n') self.OutputText('* PypePad, Copyright (c) Luca Antiga, David Steinman. *\n') self.OutputText('\n') def UpdateOutput(self): if self.pypeOutput: text = self.pypeOutput.pop(0) self.output_stream.write(text) self.master.after(10,self.UpdateOutput) def RunPype(self,arguments): if not arguments: return if self.output_to_file.get() is not 'n' and self.output_file_name: self.output_stream.output_to_file = True self.output_stream.output_file = open(self.output_file_name,self.output_to_file.get()) else: self.output_stream.output_to_file = False self.queue.append(arguments) def GetWordUnderCursor(self): from Tkinter import CURRENT splitindex = self.text_input.index(CURRENT).split('.') line = self.text_input.get(splitindex[0]+".0",splitindex[0]+".end") wordstart = line.rfind(' ',0,int(splitindex[1])-1)+1 wordend = line.find(' ',int(splitindex[1])) if wordend == -1: wordend = len(line) word = line[wordstart:wordend] return word def GetWordIndex(self): startindex = self.text_input.index("insert-1c wordstart") endindex = self.text_input.index("insert-1c wordend") if self.text_input.get(startindex+'-1c') == '-' and self.text_input.get(startindex+'-2c') == '-': startindex = self.text_input.index("insert-1c wordstart -2c") elif self.text_input.get(startindex+'-1c') == '-' and self.text_input.get(startindex+'-2c') == ' ': startindex = self.text_input.index("insert-1c wordstart -1c") self.wordIndex[0] = startindex self.wordIndex[1] = endindex word = self.text_input.get(self.wordIndex[0],self.wordIndex[1]) return word def GetLogicalLine(self,physicallineid): indexes, lines = self.GetLogicalLines() return lines[indexes[physicallineid]] def GetLogicalLineRange(self,physicallinefirstid,physicallinelastid): indexes, lines = self.GetLogicalLines() return lines[indexes[physicallinefirstid]:indexes[physicallinelastid]+1] def GetAllLogicalLines(self): return self.GetLogicalLines()[1] def GetLogicalLines(self): from Tkinter import END physicallines = self.text_input.get("1.0",END).split('\n') lines = [] indexes = [0] * len(physicallines) lineid = 0 previousline = "" join = 0 for line in physicallines: if line.startswith('#'): if join: indexes[lineid] = indexes[lineid-1] elif join: if line.endswith('\\'): lines[-1] = lines[-1] + " " + line[:-1] join = 1 else: lines[-1] = lines[-1] + " " + line join = 0 indexes[lineid] = indexes[lineid-1] else: if line.endswith('\\'): join = 1 lines.append(line[:-1]) else: lines.append(line) join = 0 if lineid > 0: indexes[lineid] = indexes[lineid-1]+1 lineid += 1 return indexes, lines def GetLineUnderCursor(self): from Tkinter import INSERT currentlineid = int(self.text_input.index(INSERT).split('.')[0]) - 1 return self.GetLogicalLine(currentlineid) def RunAllCommand(self): lines = self.GetAllLogicalLines() for line in lines: if line and line.strip(): self.RunPype(line) def RunLineCommand(self): line = self.GetLineUnderCursor() if line and line.strip(): self.RunPype(line) def RunSelectionCommand(self): from Tkinter import TclError, SEL_FIRST, SEL_LAST try: firstlineid = int(self.text_input.index(SEL_FIRST).split('.')[0]) - 1 lastlineid = int(self.text_input.index(SEL_LAST).split('.')[0]) - 1 lines = self.GetLogicalLineRange(firstlineid,lastlineid) for line in lines: self.RunPype(line) except TclError: pass def GetSuggestionsList(self,word): list = [] try: exec('import vmtkscripts') except ImportError: return None if word.startswith('--'): list = ['--pipe','--help'] elif word.startswith('-'): optionlist = [] scriptindex = self.text_input.search('vmtk',self.wordIndex[0],backwards=1) moduleName = self.text_input.get( scriptindex,scriptindex+' wordend' ) try: exec('import '+moduleName) exec('scriptObjectClassName = '+moduleName+'.'+moduleName) exec ('scriptObject = '+moduleName+'.'+scriptObjectClassName +'()') members = scriptObject.InputMembers + scriptObject.OutputMembers for member in members: optionlist.append('-'+member.OptionName) exec('list = [option for option in optionlist if option.count(word)]') except: return list else: exec('list = [scriptname for scriptname in vmtkscripts.__all__ if scriptname.count(word) ]') return list def FillSuggestionsList(self,word): from Tkinter import END self.suggestionslist.delete(0,END) suggestions = self.GetSuggestionsList(word) for suggestion in suggestions: self.suggestionslist.insert(END,suggestion) def ReplaceTextCommand(self,word): self.text_input.delete(self.wordIndex[0],self.wordIndex[1]) self.text_input.insert(self.wordIndex[0],word) self.text_input.focus_set() def ShowHelpCommand(self): word = self.GetWordUnderCursor() self.OutputText(word) if word: self.RunPype(word+' --help') else: self.OutputText('Enter your vmtk Pype above and Run.\n') def AutoCompleteCommand(self): word = self.GetWordIndex() self.suggestionswindow.withdraw() if word: self.FillSuggestionsList(word) self.suggestionswindow.geometry("%dx%d%+d%+d" % (400, 150, self.text_output.winfo_rootx(),self.text_output.winfo_rooty())) self.suggestionswindow.deiconify() self.suggestionswindow.lift() def InsertScriptName(self,scriptname): from Tkinter import INSERT self.text_input.insert(INSERT,scriptname+' ') def InsertFileName(self): from Tkinter import INSERT import tkFileDialog openfilename = tkFileDialog.askopenfilename() if not openfilename: return if len(openfilename.split()) > 1: openfilename = '"%s"' % openfilename self.text_input.insert(INSERT,openfilename+' ') def KeyPressHandler(self,event): if event.keysym == "Tab" : self.AutoCompleteCommand() self.suggestionslist.focus_set() self.suggestionslist.selection_set(0) return "break" else: self.text_input.focus_set() def TopKeyPressHandler(self,event): from Tkinter import ACTIVE, INSERT if event.keysym in ['Down','Up'] : self.suggestionslist.focus_set() elif event.keysym == "Return": word = self.suggestionslist.get(ACTIVE) self.ReplaceTextCommand(word) self.suggestionswindow.withdraw() self.text_input.focus_set() elif len(event.keysym) == 1 : self.suggestionswindow.withdraw() self.text_input.insert(INSERT,event.keysym) self.text_input.focus_set() else : self.suggestionswindow.withdraw() self.text_input.focus_set() def NewHandler(self,event): self.NewCommand() def OpenHandler(self,event): self.OpenCommand() def SaveHandler(self,event): self.SaveCommand() def InsertFileNameHandler(self,event): self.InsertFileName() return "break" def QuitHandler(self,event): self.QuitCommand() def ShowHelpHandler(self,event): self.ShowHelpCommand() def RunKeyboardHandler(self,event): from Tkinter import SEL_FIRST, TclError try: self.text_input.index(SEL_FIRST) self.RunSelectionCommand() except TclError: self.RunLineCommand() return "break" def RunAllHandler(self,event): self.RunAllCommand() def PopupHandler(self,event): try: self.popupmenu.tk_popup(event.x_root, event.y_root, 0) finally: self.popupmenu.grab_release() def OutputText(self,text): from Tkinter import NORMAL, END, DISABLED self.text_output["state"] = NORMAL self.text_output.insert(END,text) self.text_output["state"] = DISABLED def BuildScriptMenu(self,parentmenu,modulename): from Tkinter import Menu menu = Menu(parentmenu,bd=1,activeborderwidth=0) try: exec('import '+ modulename) except ImportError: return None scriptnames = [] exec ('scriptnames = [scriptname for scriptname in '+modulename+'.__all__]') menulength = 20 for i in range(len(scriptnames)/menulength+1): subscriptnames = scriptnames[i*menulength:(i+1)*menulength] if not subscriptnames: break submenu = Menu(menu,bd=1,activeborderwidth=0) menu.add_cascade(label=subscriptnames[0]+"...",menu=submenu) for scriptname in subscriptnames: callback = CallbackShim(self.InsertScriptName,scriptname) submenu.add_command(label=scriptname,command=callback) return menu def BuildMainFrame(self): from Tkinter import Menu, IntVar, StringVar, Toplevel, Listbox, Frame, PanedWindow, Text, Scrollbar, Entry from Tkinter import X, N, S, W, E, VERTICAL, TOP, END, DISABLED, RAISED menu = Menu(self.master,activeborderwidth=0,bd=0) self.master.config(menu=menu) filemenu = Menu(menu,tearoff=0,bd=1,activeborderwidth=0) menu.add_cascade(label="File", underline=0, menu=filemenu) filemenu.add_command(label="New", accelerator='Ctrl+N',command=self.NewCommand) filemenu.add_command(label="Open...",accelerator='Ctrl+O', command=self.OpenCommand) filemenu.add_command(label="Save as...",accelerator='Ctrl+S', command=self.SaveCommand) filemenu.add_separator() filemenu.add_command(label="Quit",accelerator='Ctrl+Q', command=self.QuitCommand) self.log_on = IntVar() self.log_on.set(1) self.output_to_file = StringVar() self.output_to_file.set('n') scriptmenu = Menu(menu,tearoff=0,bd=1,activeborderwidth=0) modulenames = ['vmtkscripts'] for modulename in modulenames: scriptsubmenu = self.BuildScriptMenu(menu,modulename) if scriptsubmenu: scriptmenu.add_cascade(label=modulename,menu=scriptsubmenu) editmenu = Menu(menu,tearoff=0,bd=1,activeborderwidth=0) menu.add_cascade(label="Edit",underline=0, menu=editmenu) editmenu.add_cascade(label="Insert script",menu=scriptmenu) editmenu.add_command(label="Insert file name", accelerator='Ctrl+F',command=self.InsertFileName) editmenu.add_separator() editmenu.add_command(label="Clear input", command=self.ClearInputCommand) editmenu.add_command(label="Clear output", command=self.ClearOutputCommand) editmenu.add_command(label="Clear all", command=self.ClearAllCommand) editmenu.add_separator() editmenu.add_checkbutton(label="Log", variable=self.log_on) editmenu.add_separator() editmenu.add_radiobutton(label="No output to file", variable=self.output_to_file,value='n') editmenu.add_radiobutton(label="Write output to file", variable=self.output_to_file,value='w') editmenu.add_radiobutton(label="Append output to file", variable=self.output_to_file,value='a') editmenu.add_command(label="Output file...", command=self.OutputFileCommand) runmenu = Menu(menu,tearoff=0,bd=1,activeborderwidth=0) menu.add_cascade(label="Run", underline=0, menu=runmenu) runmenu.add_command(label="Run all", command=self.RunAllCommand) runmenu.add_command(label="Run current line", command=self.RunLineCommand) runmenu.add_command(label="Run selection", command=self.RunSelectionCommand) helpmenu = Menu(menu,tearoff=0,bd=1,activeborderwidth=0) menu.add_cascade(label="Help", underline=0, menu=helpmenu) helpmenu.add_command(label="Help", underline=0, accelerator='F1',command=self.ShowHelpCommand) helpmenu.add_command(label="About", underline=0, command=self.AboutCommand) self.master.bind("<Control-KeyPress-q>", self.QuitHandler) self.master.bind("<Control-KeyPress-n>", self.NewHandler) self.master.bind("<Control-KeyPress-o>", self.OpenHandler) self.master.bind("<Control-KeyPress-s>", self.SaveHandler) self.master.bind("<Control-KeyPress-f>", self.InsertFileNameHandler) self.master.bind("<KeyPress-F1>", self.ShowHelpHandler) self.master.bind("<KeyPress>", self.KeyPressHandler) self.wordIndex = ['1.0','1.0'] self.suggestionswindow = Toplevel(bg='#ffffff',bd=0,height=50,width=600,highlightthickness=0,takefocus=True) self.suggestionswindow.overrideredirect(1) self.suggestionslist = Listbox(self.suggestionswindow,bg='#ffffff',bd=1,fg='#336699',activestyle='none',highlightthickness=0,height=9) self.suggestionslist.insert(END,"foo") self.suggestionslist.pack(side=TOP,fill=X) self.suggestionswindow.bind("<KeyPress>", self.TopKeyPressHandler) self.suggestionswindow.withdraw() self.master.rowconfigure(0,weight=1) self.master.columnconfigure(0,weight=1) content = Frame(self.master,bd=0,padx=2,pady=2) content.grid(row=0,column=0,sticky=N+S+W+E) content.rowconfigure(0,weight=1,minsize=50) content.rowconfigure(1,weight=0) content.columnconfigure(0,weight=1) panes = PanedWindow(content,orient=VERTICAL,bd=1,sashwidth=8,sashpad=0,sashrelief=RAISED,showhandle=True) panes.grid(row=0,column=0,sticky=N+S+W+E) frame1 = Frame(panes,bd=0) frame1.grid(row=0,column=0,sticky=N+S+W+E) frame1.columnconfigure(0,weight=1) frame1.columnconfigure(1,weight=0) frame1.rowconfigure(0,weight=1) panes.add(frame1,height=300,minsize=20) frame2 = Frame(panes,bd=0) frame2.grid(row=1,column=0,sticky=N+S+W+E) frame2.columnconfigure(0,weight=1) frame2.columnconfigure(1,weight=0) frame2.rowconfigure(0,weight=1) panes.add(frame2,minsize=20) self.text_input = Text(frame1, bg='#ffffff',bd=1,highlightthickness=0) self.text_input.bind("<KeyPress>", self.KeyPressHandler) self.text_input.bind("<Button-3>", self.PopupHandler) self.text_input.bind("<Control-Return>", self.RunKeyboardHandler) self.input_scrollbar = Scrollbar(frame1,orient=VERTICAL,command=self.text_input.yview) self.text_input["yscrollcommand"] = self.input_scrollbar.set self.text_output = Text(frame2,state=DISABLED,bd=1,bg='#ffffff',highlightthickness=0) self.output_scrollbar = Scrollbar(frame2,orient=VERTICAL,command=self.text_output.yview) self.text_output["yscrollcommand"] = self.output_scrollbar.set self.text_entry = Entry(content,bd=1,bg='#ffffff',state=DISABLED,highlightthickness=0) self.text_input.focus_set() self.text_input.grid(row=0,column=0,sticky=N+S+W+E) self.input_scrollbar.grid(row=0,column=1,sticky=N+S+W+E) self.text_output.grid(row=0,column=0,sticky=N+S+W+E) self.output_scrollbar.grid(row=0,column=1,sticky=N+S+W+E) self.text_entry.grid(row=1,column=0,sticky=N+S+W+E) self.popupmenu = Menu(self.text_input, tearoff=1, bd=0) self.popupmenu.add_command(label="Context help", command=self.ShowHelpCommand) self.popupmenu.add_cascade(label="Insert script",menu=scriptmenu) self.popupmenu.add_command(label="Insert file name...", command=self.InsertFileName) self.popupmenu.add_separator() self.popupmenu.add_command(label="Run all", command=self.RunAllCommand) self.popupmenu.add_command(label="Run current line", command=self.RunLineCommand) self.popupmenu.add_command(label="Run selection", command=self.RunSelectionCommand) self.output_stream = TkPadOutputStream(self.text_output) self.input_stream = TkPadInputStream(self.text_entry,self.output_stream)
epics['write_amp'] = cs_checkbox(lf_results, 1, 1, '', False) epics['amp'] = 'FKC00V' epics['write_tau'] = cs_checkbox(lf_results, 3, 1, '', False) epics['tau'] = 'FKC01V' epics['write_tswa'] = cs_checkbox(lf_results, 5, 1, '', False) epics['tswa'] = 'FKC02V' class pv: fill = PV('CUMZR:MBcurrent') curt = PV('TOPUPCC:rdCurCS') ampl = PV(epics['amp']) tau = PV(epics['tau']) tswa = PV(epics['tswa']) popup = Toplevel(bg='') popup.overrideredirect(True) popup.withdraw() popupstr, popuplab = cp_label(popup, '', label_conf={'bg':'black', 'fg':'green', 'font':'Mono 15'}, pack_conf={'side':'right'}) def b2click(event, text): # get epics var name text = epics[text] # create popup displaying epics name popupstr.set(text) popup.update() w, h = popuplab.winfo_width() + 15, popuplab.winfo_height() x, y = root.winfo_pointerx(), root.winfo_pointery()
class Tooltips: tooltip_delay = 100 def __init__(self): self.descriptions = {} self.balloon = None self.balloon_label = None self.last_widget = '' self.after_id = None self.root = None def AddDescription(self, widget, description): self.descriptions[widget._w] = description if widget._w == self.last_widget: self.balloon_label['text'] = description def RemoveDescription(self, widget): if type(widget) == InstanceType: widget = widget._w if self.descriptions.has_key(widget): del self.descriptions[widget] def GetDescription(self, widget): if type(widget) == InstanceType: widget = widget._w if self.descriptions.has_key(widget): return self.descriptions[widget] return '' def create_balloon(self, root): self.root = root self.balloon = Toplevel(self.root) self.balloon.withdraw() self.balloon.overrideredirect(1) self.balloon["relief"] = 'flat' label = TLabel(self.balloon, text='Tooltip', style='Tooltips') label.pack(ipadx=2, ipady=2) self.balloon_label = label def popup_balloon(self, widget_name, x, y, text): self.last_widget = widget_name self.balloon.withdraw() self.balloon_label['text'] = text width = self.balloon_label.winfo_reqwidth() height = self.balloon_label.winfo_reqheight() screenwidth = self.root.winfo_screenwidth() screenheight = self.root.winfo_screenheight() x = self.root.winfo_pointerx() y = self.root.winfo_pointery() + 20 if screenwidth < (x + width): x = x - width if screenheight < (y + height): y = y - height - 25 self.balloon.geometry('%+d%+d' % (x, y)) self.balloon.update() self.balloon.deiconify() self.balloon.tkraise() def popup_delayed(self, widget_name, x, y, text, *args): self.after_id = None self.popup_balloon(widget_name, x, y, text) def enter_widget(self, event): widget_name = event.widget text = self.GetDescription(widget_name) if text: x = event.x;y = event.y if self.after_id: print 'after_id in enter' self.root.after_cancel(self.after_id) self.after_id = self.root.after(self.tooltip_delay, self.popup_delayed, widget_name, x, y, text) def leave_widget(self, event): global last_widget, after_id if self.after_id is not None: self.root.after_cancel(self.after_id) self.after_id = None self.last_widget = '' last_widget = '' self.balloon.withdraw() button_press = leave_widget def destroy_widget(self, event): self.RemoveDescription(event.widget)
class KeyboardEntry: """Mixin class that can be used to add the ability to type values for widget. When the cursor enters the widget the focus is set to the widget and the widget that had the focus previousy is saved in .lastFocus. When the cursor leaves the widget focus is restored to self.lastFocus. key_cb(event) is called upon KeyRelease events. If this is the first keytroke an undecorated window is created next to the cursor and handleKeyStroke(event) is called. This method should be subclassed to modify the way the string is typed in (see thumbwheel.py for an example of handling numbers only). When the Return key is pressed, the entry window is destroyed and if the typed striong is not empty self.callSet(self.typedValue) is called. If the cursor moves out of the widget before Rrturn is pressed the value in the entry window is discarded and the entry window is destroyed. """ def __init__(self, widgets, callSet): # callSet is a function taking one argument (string) which will be # when the Returnm key is hit (if the typed string is not empty) # widgets is a list of Tkinter wigets for which <Enter>, <Leave> # <Return> and <KeyRelease> are handled. These widgets has to exist # before thsi constructor can be called assert callable(callSet) self.callSet = callSet for w in widgets: w.bind("<Enter>", self.enter_cb) w.bind("<Leave>", self.leave_cb) w.bind("<Return>", self.return_cb) w.bind("<KeyRelease>", self.key_cb) self.typedValue = '' # string accumulating valuescharacters typed self.lastFocus = None # widget to which the focus will be restored # when the mouse leaves the widget self.topEntry = None # top level for typing values self.typedValueTK = None #Tk label used as entry for value def key_cb(self, event=None): # call back function for keyboard events (except for Return) # handle numbers to set value key = event.keysym if key=='Return': return #print 'Key:', key if len(self.typedValue)==0 and self.topEntry is None: # create Tk label showing typed value x = event.x y = event.y #print 'create entry' self.topEntry = Toplevel() self.topEntry.overrideredirect(1) w = event.widget if event.x >= 0: self.topEntry.geometry('+%d+%d'%(w.winfo_rootx() + event.x+10, w.winfo_rooty() + event.y)) else: self.topEntry.geometry('+%d+%d'%(w.winfo_rootx() +10, w.winfo_rooty() )) self.typedValueTK = Label( master=self.topEntry, text='', relief='sunken', bg='yellow') self.typedValueTK.pack() self.handleKeyStroke(event) def leave_cb(self, event=None): # make sure widget gets keyboard events # print 'leave', event.widget if self.topEntry: self.typedValueTK.destroy() self.topEntry.destroy() self.topEntry = None self.typedValue = '' if self.lastFocus: #print 'restoring focus' if widgetsOnBackWindowsCanGrabFocus is False: lActiveWindow = self.lastFocus.focus_get() if lActiveWindow is not None \ and ( lActiveWindow.winfo_toplevel() != self.lastFocus.winfo_toplevel() ): return self.lastFocus.focus_set() self.lastFocus = None event.widget.config(cursor='') def enter_cb(self, event=None): # make sure widget gets keyboard events #print 'enter', event.widget if widgetsOnBackWindowsCanGrabFocus is False: lActiveWindow = event.widget.focus_get() if lActiveWindow is not None \ and ( lActiveWindow.winfo_toplevel() != event.widget.winfo_toplevel() ): return if self.lastFocus is None: #print 'setting focus' self.lastFocus = self.focus_lastfor() event.widget.focus_set() event.widget.config(cursor='xterm') def return_cb(self, event): # return should destroy the topEntry #print "return_cb" if self.typedValueTK is not None: self.typedValueTK.destroy() if self.topEntry is not None: self.topEntry.destroy() self.topEntry = None if len(self.typedValue): #print 'setting to', self.type(self.typedValue) self.callSet(self.typedValue) self.typedValue = '' ## TO BE SUBCLASSED def handleKeyStroke(self, event): # by default we handle delete character keys key = event.keysym if key=='BackSpace' or key=='Delete': self.typedValue = self.typedValue[:-1] self.typedValueTK.configure(text=self.typedValue)
class Tooltips: def __init__(self): self.descriptions = {} self.balloon = None self.balloon_label = None self.last_widget = '' self.after_id = None def AddDescription(self, widget, description): self.descriptions[widget._w] = description if widget._w == self.last_widget: self.balloon_label['text'] = description def RemoveDescription(self, widget): if type(widget) == InstanceType: widget = widget._w if self.descriptions.has_key(widget): del self.descriptions[widget] def GetDescription(self, widget): if type(widget) == InstanceType: widget = widget._w if self.descriptions.has_key(widget): return self.descriptions[widget] return '' def create_balloon(self, root): self.root = root self.balloon = Toplevel(self.root, name = 'tooltips') self.balloon.withdraw() self.balloon.overrideredirect(1) label = Label(self.balloon, name = 'label', text = 'Tooltip') label.pack() self.balloon_label = label def popup_balloon(self, widget_name, x, y, text): self.last_widget = widget_name self.balloon.withdraw() self.balloon_label['text'] = text x = x - self.balloon_label.winfo_reqwidth() / 2 self.balloon.geometry('%+d%+d' % (x, y)) self.balloon.update() self.balloon.deiconify() self.balloon.tkraise() def popup_delayed(self, widget_name, x, y, text, *args): self.after_id = None self.popup_balloon(widget_name, x, y, text) def enter_widget(self, widget_name): text = self.GetDescription(widget_name) if text: widget = self.root.nametowidget(widget_name) x = widget.winfo_rootx() + widget.winfo_width() / 2 y = widget.winfo_rooty() + widget.winfo_height() #y = y + height #x = x + width / 2 if self.after_id: print 'after_id in enter' self.root.after_cancel(self.after_id) self.after_id = self.root.after(config.preferences.tooltip_delay, self.popup_delayed, widget_name, x, y, text) def leave_widget(self, widget_name): global last_widget, after_id if self.after_id is not None: self.root.after_cancel(self.after_id) self.after_id = None self.last_widget = '' last_widget = '' self.balloon.withdraw() button_press = leave_widget def destroy_widget(self, event): self.RemoveDescription(event.widget)