/usr/lib/python2.7/idlelib/CallTipWindow.py is in idle-python2.7 2.7.3-0ubuntu3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | """A CallTip window class for Tkinter/IDLE.
After ToolTip.py, which uses ideas gleaned from PySol
Used by the CallTips IDLE extension.
"""
from Tkinter import *
HIDE_VIRTUAL_EVENT_NAME = "<<calltipwindow-hide>>"
HIDE_SEQUENCES = ("<Key-Escape>", "<FocusOut>")
CHECKHIDE_VIRTUAL_EVENT_NAME = "<<calltipwindow-checkhide>>"
CHECKHIDE_SEQUENCES = ("<KeyRelease>", "<ButtonRelease>")
CHECKHIDE_TIME = 100 # miliseconds
MARK_RIGHT = "calltipwindowregion_right"
class CallTip:
def __init__(self, widget):
self.widget = widget
self.tipwindow = self.label = None
self.parenline = self.parencol = None
self.lastline = None
self.hideid = self.checkhideid = None
def position_window(self):
"""Check if needs to reposition the window, and if so - do it."""
curline = int(self.widget.index("insert").split('.')[0])
if curline == self.lastline:
return
self.lastline = curline
self.widget.see("insert")
if curline == self.parenline:
box = self.widget.bbox("%d.%d" % (self.parenline,
self.parencol))
else:
box = self.widget.bbox("%d.0" % curline)
if not box:
box = list(self.widget.bbox("insert"))
# align to left of window
box[0] = 0
box[2] = 0
x = box[0] + self.widget.winfo_rootx() + 2
y = box[1] + box[3] + self.widget.winfo_rooty()
self.tipwindow.wm_geometry("+%d+%d" % (x, y))
def showtip(self, text, parenleft, parenright):
"""Show the calltip, bind events which will close it and reposition it.
"""
# truncate overly long calltip
if len(text) >= 79:
textlines = text.splitlines()
for i, line in enumerate(textlines):
if len(line) > 79:
textlines[i] = line[:75] + ' ...'
text = '\n'.join(textlines)
self.text = text
if self.tipwindow or not self.text:
return
self.widget.mark_set(MARK_RIGHT, parenright)
self.parenline, self.parencol = map(
int, self.widget.index(parenleft).split("."))
self.tipwindow = tw = Toplevel(self.widget)
self.position_window()
# remove border on calltip window
tw.wm_overrideredirect(1)
try:
# This command is only needed and available on Tk >= 8.4.0 for OSX
# Without it, call tips intrude on the typing process by grabbing
# the focus.
tw.tk.call("::tk::unsupported::MacWindowStyle", "style", tw._w,
"help", "noActivates")
except TclError:
pass
self.label = Label(tw, text=self.text, justify=LEFT,
background="#ffffe0", relief=SOLID, borderwidth=1,
font = self.widget['font'])
self.label.pack()
self.checkhideid = self.widget.bind(CHECKHIDE_VIRTUAL_EVENT_NAME,
self.checkhide_event)
for seq in CHECKHIDE_SEQUENCES:
self.widget.event_add(CHECKHIDE_VIRTUAL_EVENT_NAME, seq)
self.widget.after(CHECKHIDE_TIME, self.checkhide_event)
self.hideid = self.widget.bind(HIDE_VIRTUAL_EVENT_NAME,
self.hide_event)
for seq in HIDE_SEQUENCES:
self.widget.event_add(HIDE_VIRTUAL_EVENT_NAME, seq)
def checkhide_event(self, event=None):
if not self.tipwindow:
# If the event was triggered by the same event that unbinded
# this function, the function will be called nevertheless,
# so do nothing in this case.
return
curline, curcol = map(int, self.widget.index("insert").split('.'))
if curline < self.parenline or \
(curline == self.parenline and curcol <= self.parencol) or \
self.widget.compare("insert", ">", MARK_RIGHT):
self.hidetip()
else:
self.position_window()
self.widget.after(CHECKHIDE_TIME, self.checkhide_event)
def hide_event(self, event):
if not self.tipwindow:
# See the explanation in checkhide_event.
return
self.hidetip()
def hidetip(self):
if not self.tipwindow:
return
for seq in CHECKHIDE_SEQUENCES:
self.widget.event_delete(CHECKHIDE_VIRTUAL_EVENT_NAME, seq)
self.widget.unbind(CHECKHIDE_VIRTUAL_EVENT_NAME, self.checkhideid)
self.checkhideid = None
for seq in HIDE_SEQUENCES:
self.widget.event_delete(HIDE_VIRTUAL_EVENT_NAME, seq)
self.widget.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hideid)
self.hideid = None
self.label.destroy()
self.label = None
self.tipwindow.destroy()
self.tipwindow = None
self.widget.mark_unset(MARK_RIGHT)
self.parenline = self.parencol = self.lastline = None
def is_active(self):
return bool(self.tipwindow)
###############################
#
# Test Code
#
class container: # Conceptually an editor_window
def __init__(self):
root = Tk()
text = self.text = Text(root)
text.pack(side=LEFT, fill=BOTH, expand=1)
text.insert("insert", "string.split")
root.update()
self.calltip = CallTip(text)
text.event_add("<<calltip-show>>", "(")
text.event_add("<<calltip-hide>>", ")")
text.bind("<<calltip-show>>", self.calltip_show)
text.bind("<<calltip-hide>>", self.calltip_hide)
text.focus_set()
root.mainloop()
def calltip_show(self, event):
self.calltip.showtip("Hello world")
def calltip_hide(self, event):
self.calltip.hidetip()
def main():
# Test code
c=container()
if __name__=='__main__':
main()
|