14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# general purpose 'tooltip' routines - currently unused in idlefork 24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# (although the 'calltips' extension is partly based on this code) 34adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# may be useful for some purposes in (or almost in ;) the current project scope 44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Ideas gleaned from PySol 54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom Tkinter import * 74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 84adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass ToolTipBase: 94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, button): 114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.button = button 124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.tipwindow = None 134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.id = None 144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.x = self.y = 0 154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._id1 = self.button.bind("<Enter>", self.enter) 164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._id2 = self.button.bind("<Leave>", self.leave) 174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._id3 = self.button.bind("<ButtonPress>", self.leave) 184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def enter(self, event=None): 204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.schedule() 214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def leave(self, event=None): 234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.unschedule() 244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.hidetip() 254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def schedule(self): 274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.unschedule() 284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.id = self.button.after(1500, self.showtip) 294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unschedule(self): 314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao id = self.id 324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.id = None 334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if id: 344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.button.after_cancel(id) 354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def showtip(self): 374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self.tipwindow: 384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # The tip window must be completely outside the button; 404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # otherwise when the mouse enters the tip window we get 414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # a leave event and it disappears, and then we get an enter 424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # event and it reappears, and so on forever :-( 434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao x = self.button.winfo_rootx() + 20 444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao y = self.button.winfo_rooty() + self.button.winfo_height() + 1 454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.tipwindow = tw = Toplevel(self.button) 464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao tw.wm_overrideredirect(1) 474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao tw.wm_geometry("+%d+%d" % (x, y)) 484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.showcontents() 494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def showcontents(self, text="Your text here"): 514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Override this in derived class 524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao label = Label(self.tipwindow, text=text, justify=LEFT, 534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao background="#ffffe0", relief=SOLID, borderwidth=1) 544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao label.pack() 554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def hidetip(self): 574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao tw = self.tipwindow 584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.tipwindow = None 594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if tw: 604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao tw.destroy() 614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass ToolTip(ToolTipBase): 634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, button, text): 644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ToolTipBase.__init__(self, button) 654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.text = text 664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def showcontents(self): 674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ToolTipBase.showcontents(self, self.text) 684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass ListboxToolTip(ToolTipBase): 704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, button, items): 714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ToolTipBase.__init__(self, button) 724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.items = items 734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def showcontents(self): 744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao listbox = Listbox(self.tipwindow, background="#ffffe0") 754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao listbox.pack() 764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for item in self.items: 774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao listbox.insert(END, item) 784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef main(): 804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Test code 814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao root = Tk() 824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao b = Button(root, text="Hello", command=root.destroy) 834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao b.pack() 844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao root.update() 854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao tip = ListboxToolTip(b, ["Hello", "world"]) 864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao root.mainloop() 874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoif __name__ == '__main__': 894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao main() 90