Mercurial > repos > rliterman > csp2
diff CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/idlelib/calltip_w.py @ 68:5028fdace37b
planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author | jpayne |
---|---|
date | Tue, 18 Mar 2025 16:23:26 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/idlelib/calltip_w.py Tue Mar 18 16:23:26 2025 -0400 @@ -0,0 +1,201 @@ +"""A call-tip window class for Tkinter/IDLE. + +After tooltip.py, which uses ideas gleaned from PySol. +Used by calltip.py. +""" +from tkinter import Label, LEFT, SOLID, TclError + +from idlelib.tooltip import TooltipBase + +HIDE_EVENT = "<<calltipwindow-hide>>" +HIDE_SEQUENCES = ("<Key-Escape>", "<FocusOut>") +CHECKHIDE_EVENT = "<<calltipwindow-checkhide>>" +CHECKHIDE_SEQUENCES = ("<KeyRelease>", "<ButtonRelease>") +CHECKHIDE_TIME = 100 # milliseconds + +MARK_RIGHT = "calltipwindowregion_right" + + +class CalltipWindow(TooltipBase): + """A call-tip widget for tkinter text widgets.""" + + def __init__(self, text_widget): + """Create a call-tip; shown by showtip(). + + text_widget: a Text widget with code for which call-tips are desired + """ + # Note: The Text widget will be accessible as self.anchor_widget + super(CalltipWindow, self).__init__(text_widget) + + self.label = self.text = None + self.parenline = self.parencol = self.lastline = None + self.hideid = self.checkhideid = None + self.checkhide_after_id = None + + def get_position(self): + """Choose the position of the call-tip.""" + curline = int(self.anchor_widget.index("insert").split('.')[0]) + if curline == self.parenline: + anchor_index = (self.parenline, self.parencol) + else: + anchor_index = (curline, 0) + box = self.anchor_widget.bbox("%d.%d" % anchor_index) + if not box: + box = list(self.anchor_widget.bbox("insert")) + # align to left of window + box[0] = 0 + box[2] = 0 + return box[0] + 2, box[1] + box[3] + + def position_window(self): + "Reposition the window if needed." + curline = int(self.anchor_widget.index("insert").split('.')[0]) + if curline == self.lastline: + return + self.lastline = curline + self.anchor_widget.see("insert") + super(CalltipWindow, self).position_window() + + def showtip(self, text, parenleft, parenright): + """Show the call-tip, bind events which will close it and reposition it. + + text: the text to display in the call-tip + parenleft: index of the opening parenthesis in the text widget + parenright: index of the closing parenthesis in the text widget, + or the end of the line if there is no closing parenthesis + """ + # Only called in calltip.Calltip, where lines are truncated + self.text = text + if self.tipwindow or not self.text: + return + + self.anchor_widget.mark_set(MARK_RIGHT, parenright) + self.parenline, self.parencol = map( + int, self.anchor_widget.index(parenleft).split(".")) + + super(CalltipWindow, self).showtip() + + self._bind_events() + + def showcontents(self): + """Create the call-tip widget.""" + self.label = Label(self.tipwindow, text=self.text, justify=LEFT, + background="#ffffd0", foreground="black", + relief=SOLID, borderwidth=1, + font=self.anchor_widget['font']) + self.label.pack() + + def checkhide_event(self, event=None): + """Handle CHECK_HIDE_EVENT: call hidetip or reschedule.""" + if not self.tipwindow: + # If the event was triggered by the same event that unbound + # this function, the function will be called nevertheless, + # so do nothing in this case. + return None + + # Hide the call-tip if the insertion cursor moves outside of the + # parenthesis. + curline, curcol = map(int, self.anchor_widget.index("insert").split('.')) + if curline < self.parenline or \ + (curline == self.parenline and curcol <= self.parencol) or \ + self.anchor_widget.compare("insert", ">", MARK_RIGHT): + self.hidetip() + return "break" + + # Not hiding the call-tip. + + self.position_window() + # Re-schedule this function to be called again in a short while. + if self.checkhide_after_id is not None: + self.anchor_widget.after_cancel(self.checkhide_after_id) + self.checkhide_after_id = \ + self.anchor_widget.after(CHECKHIDE_TIME, self.checkhide_event) + return None + + def hide_event(self, event): + """Handle HIDE_EVENT by calling hidetip.""" + if not self.tipwindow: + # See the explanation in checkhide_event. + return None + self.hidetip() + return "break" + + def hidetip(self): + """Hide the call-tip.""" + if not self.tipwindow: + return + + try: + self.label.destroy() + except TclError: + pass + self.label = None + + self.parenline = self.parencol = self.lastline = None + try: + self.anchor_widget.mark_unset(MARK_RIGHT) + except TclError: + pass + + try: + self._unbind_events() + except (TclError, ValueError): + # ValueError may be raised by MultiCall + pass + + super(CalltipWindow, self).hidetip() + + def _bind_events(self): + """Bind event handlers.""" + self.checkhideid = self.anchor_widget.bind(CHECKHIDE_EVENT, + self.checkhide_event) + for seq in CHECKHIDE_SEQUENCES: + self.anchor_widget.event_add(CHECKHIDE_EVENT, seq) + self.anchor_widget.after(CHECKHIDE_TIME, self.checkhide_event) + self.hideid = self.anchor_widget.bind(HIDE_EVENT, + self.hide_event) + for seq in HIDE_SEQUENCES: + self.anchor_widget.event_add(HIDE_EVENT, seq) + + def _unbind_events(self): + """Unbind event handlers.""" + for seq in CHECKHIDE_SEQUENCES: + self.anchor_widget.event_delete(CHECKHIDE_EVENT, seq) + self.anchor_widget.unbind(CHECKHIDE_EVENT, self.checkhideid) + self.checkhideid = None + for seq in HIDE_SEQUENCES: + self.anchor_widget.event_delete(HIDE_EVENT, seq) + self.anchor_widget.unbind(HIDE_EVENT, self.hideid) + self.hideid = None + + +def _calltip_window(parent): # htest # + from tkinter import Toplevel, Text, LEFT, BOTH + + top = Toplevel(parent) + top.title("Test call-tips") + x, y = map(int, parent.geometry().split('+')[1:]) + top.geometry("250x100+%d+%d" % (x + 175, y + 150)) + text = Text(top) + text.pack(side=LEFT, fill=BOTH, expand=1) + text.insert("insert", "string.split") + top.update() + + calltip = CalltipWindow(text) + def calltip_show(event): + calltip.showtip("(s='Hello world')", "insert", "end") + def calltip_hide(event): + calltip.hidetip() + text.event_add("<<calltip-show>>", "(") + text.event_add("<<calltip-hide>>", ")") + text.bind("<<calltip-show>>", calltip_show) + text.bind("<<calltip-hide>>", calltip_hide) + + text.focus_set() + +if __name__ == '__main__': + from unittest import main + main('idlelib.idle_test.test_calltip_w', verbosity=2, exit=False) + + from idlelib.idle_test.htest import run + run(_calltip_window)