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