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 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
# File: treetips.py
# Author: Toshio Kuratomi <toshio@tiki-lounge.com>
# Date: 6 April, 2004
# Copyright: Toshio Kuratomi
# License: GPL
# Id: $Id: treetips.py 188 2005-06-14 00:55:59Z badger $
"""A tooltip class for TreeViews
"""
__revision__ = "$Rev: 188 $"
import gtk
import gobject
class TreeTips(gtk.Widget):
''' A tooltips widget specialized to work with gtk.TreeView's.
TreeTips associates a column in a TreeStore with tooltips that will be
displayed when the mouse is over the row the column is for. Each row can
have one treetip.
'''
__gproperties__ = {
'tip_window' : (gobject.TYPE_PYOBJECT,
'The window that the tooltip is displayed in.',
'The window that the tooltip is displayed in.',
gobject.PARAM_READABLE),
'tip_label' : (gobject.TYPE_PYOBJECT,
'The label that displays the tooltip text.',
'The label that displays the tooltip text.',
gobject.PARAM_READABLE),
'active_tips_data' : (gobject.TYPE_PYOBJECT,
'The data associated with the active tooltip.',
'The data associated with the active tooltip.',
gobject.PARAM_READABLE),
'delay' : (gobject.TYPE_INT,
'MSecs before displaying the tooltip.',
'The delay between the mouse pausing over the widget and the'
' display of the tooltip in msec.',
0, 60000, 500,
gobject.PARAM_READWRITE),
'enabled' : (gobject.TYPE_BOOLEAN,
'If TRUE the tooltips are enabled',
'If TRUE the tooltips are enabled',
True,
gobject.PARAM_READABLE),
'view' : (gobject.TYPE_PYOBJECT,
'gtk.TreeView that we get our data from.',
'The tip data comes from a column in a gtk.TreeView.',
gobject.PARAM_READWRITE),
'column' : (gobject.TYPE_INT,
'Column from the gtk.TreeView that holds tip data.',
'The tip data for each row is held by a column in the row.'
' This specifies which column that data is in.',
0, 32000, 0,
gobject.PARAM_READWRITE)
}
def __init__(self, treeview=None, column=None):
'''Create a new TreeTips Group.
:Parameters:
treeview : gtk.TreeView === Treeview for which the tips display,
default is None.
column : integer === Column id in the Treemodel holding the treetip
text, default is None.
'''
if treeview:
try:
treeview.connect('leave-notify-event', self.__tree_leave_notify)
treeview.connect('motion-notify-event',
self.__tree_motion_notify)
except (AttributeError, TypeError):
raise TypeError, ('The value of view must be an object that'
'implements leave-notify-event and motion-notify-event '
'gsignals such as gtk.TreeStore.')
gobject.GObject.__init__(self)
self.view = treeview or None
self.delay = 500
self.enabled = True
self.column = column or 0
self.tip_window = gtk.Window(gtk.WINDOW_POPUP)
self.tip_window.set_app_paintable(True)
self.tip_window.set_border_width(4)
self.tip_window.connect('expose-event', self.__paint_window)
self.tip_label = gtk.Label('')
self.tip_label.set_line_wrap(True)
self.tip_label.set_alignment(0.5, 0.5)
self.active_tips_data = ''
self.tip_window.add(self.tip_label)
self.unique = 1 # Unique number used for timeouts
self.timeoutID = 0
self.path = None
self.screenWidth = gtk.gdk.screen_width()
self.screenHeight = gtk.gdk.screen_height()
def enable(self):
'''Enable showing of tooltips'''
self.enabled = True
def disable(self):
'''Disable showing tooltips'''
self.enabled = False
def do_get_property(self, prop):
'''Return the gproperty's value.'''
if prop.name == 'delay':
return self.delay
elif prop.name == 'enabled':
return self.enabled
elif prop.name == 'view':
return self.view
elif prop.name == 'column':
return self.column
elif prop.name == 'active-tips-data':
return self.active_tips_data
elif prop.name == 'tip-label':
return self.tip_label
elif prop.name == 'tip-window':
return self.tip_window
else:
raise AttributeError, 'unknown property %s' % prop.name
def do_set_property(self, prop, value):
'''Set the property of writable properties.
'''
if prop.name == 'delay':
self.delay = value
elif prop.name == 'view':
try:
value.connect('leave-notify-event', self.__tree_leave_notify)
value.connect('motion-notify-event', self.__tree_motion_notify)
except (AttributeError, TypeError):
raise TypeError, ('The value of view must be an object that'
'implements leave-notify-event and motion-notify-event '
'gsignals')
self.view = value
elif prop.name == 'column':
self.column = value
else:
raise AttributeError, 'unknown or read only property %s' % prop.name
def __paint_window(self, window, event):
window.style.paint_flat_box(window.window, gtk.STATE_NORMAL,
gtk.SHADOW_OUT, None, window,
'tooltip', 0, 0, -1, -1)
def __tree_leave_notify(self, tree, event):
'''Hide tooltips when we leave the tree.'''
self.timeoutID = 0
self.path = None
self.tip_window.hide()
def __tree_motion_notify(self, tree, event):
'''Decide which tooltip to display when we move within the tree.'''
if not self.enabled:
return
self.tip_window.hide()
self.path = None
self.unique += 1
self.timeoutID = self.unique
gobject.timeout_add(self.delay, self.__treetip_show, tree,
int(event.x), int(event.y), self.timeoutID)
def __treetip_show(self, tree, xEvent, yEvent, ID):
'''Show the treetip window.'''
if self.timeoutID != ID:
return False
pathReturn = tree.get_path_at_pos(xEvent, yEvent)
model = tree.get_model()
if pathReturn == None:
self.path = None
elif self.path != pathReturn[0]:
self.path = pathReturn[0]
rowIter = model.get_iter(self.path)
text = model.get_value(rowIter, self.column)
self.active_tips_data = text
if not text:
self.tip_label.set_text('')
return False
self.tip_label.set_text(text)
x, y = self.tip_label.size_request()
self.tip_window.resize(x, y)
windowWidth, windowHeight = self.tip_window.get_size()
cellInfo = tree.get_cell_area(self.path, pathReturn[1])
x, y = self.__compute_tooltip_position(cellInfo, windowWidth,
windowHeight)
self.tip_window.move(int(x), int(y))
self.tip_window.show_all()
return False
def __compute_tooltip_position(self, cellInfo, popupWidth, popupHeight):
'''Figures out where the tooltip should be placed on the page::
[p] = pointer
x = [p]
+---------+
(half on each side)
y = [p]
+------------+
|____________|
If it fits else:
+------------+
|____________|
[p]
'''
xOrigin, yOrigin = self.view.get_bin_window().get_origin()
x = xOrigin + cellInfo.x + cellInfo.width/2 - popupWidth/2
if x < 0:
x = 0
elif x + popupWidth > self.screenWidth:
x = self.screenWidth - popupWidth
y = yOrigin + cellInfo.y + cellInfo.height + 3
if y + popupHeight > self.screenHeight:
y = yOrigin + cellInfo.y - 3 - popupHeight
if y < 0:
y = 0
return x, y
gobject.type_register(TreeTips)
|