1ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# general purpose 'tooltip' routines - currently unused in idlefork 2ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# (although the 'calltips' extension is partly based on this code) 3ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# may be useful for some purposes in (or almost in ;) the current project scope 4ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# Ideas gleaned from PySol 5ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 6ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotfrom Tkinter import * 7ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 8ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass ToolTipBase: 9ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 10ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, button): 11ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.button = button 12ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.tipwindow = None 13ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.id = None 14ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.x = self.y = 0 15ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._id1 = self.button.bind("<Enter>", self.enter) 16ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._id2 = self.button.bind("<Leave>", self.leave) 17ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._id3 = self.button.bind("<ButtonPress>", self.leave) 18ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 19ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def enter(self, event=None): 20ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.schedule() 21ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 22ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def leave(self, event=None): 23ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.unschedule() 24ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.hidetip() 25ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 26ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def schedule(self): 27ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.unschedule() 28ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.id = self.button.after(1500, self.showtip) 29ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 30ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def unschedule(self): 31ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot id = self.id 32ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.id = None 33ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if id: 34ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.button.after_cancel(id) 35ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 36ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def showtip(self): 37ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.tipwindow: 38ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return 39ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # The tip window must be completely outside the button; 40ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # otherwise when the mouse enters the tip window we get 41ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # a leave event and it disappears, and then we get an enter 42ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # event and it reappears, and so on forever :-( 43ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot x = self.button.winfo_rootx() + 20 44ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot y = self.button.winfo_rooty() + self.button.winfo_height() + 1 45ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.tipwindow = tw = Toplevel(self.button) 46ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot tw.wm_overrideredirect(1) 47ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot tw.wm_geometry("+%d+%d" % (x, y)) 48ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.showcontents() 49ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 50ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def showcontents(self, text="Your text here"): 51ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Override this in derived class 52ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot label = Label(self.tipwindow, text=text, justify=LEFT, 53ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot background="#ffffe0", relief=SOLID, borderwidth=1) 54ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot label.pack() 55ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 56ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def hidetip(self): 57ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot tw = self.tipwindow 58ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.tipwindow = None 59ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if tw: 60ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot tw.destroy() 61ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 62ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass ToolTip(ToolTipBase): 63ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, button, text): 64ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot ToolTipBase.__init__(self, button) 65ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.text = text 66ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def showcontents(self): 67ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot ToolTipBase.showcontents(self, self.text) 68ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 69ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass ListboxToolTip(ToolTipBase): 70ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, button, items): 71ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot ToolTipBase.__init__(self, button) 72ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.items = items 73ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def showcontents(self): 74ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot listbox = Listbox(self.tipwindow, background="#ffffe0") 75ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot listbox.pack() 76ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot for item in self.items: 77ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot listbox.insert(END, item) 78ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 79ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotdef main(): 80ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Test code 81ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot root = Tk() 82ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot b = Button(root, text="Hello", command=root.destroy) 83ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot b.pack() 84ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot root.update() 85ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot tip = ListboxToolTip(b, ["Hello", "world"]) 86ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot root.mainloop() 87ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 88ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotif __name__ == '__main__': 89ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot main() 90