tooltip positioning... base tooltip class...

custom tooltip in notif. area
This commit is contained in:
Dimitur Kirov 2005-07-31 19:21:11 +00:00
parent f51c2b0f95
commit f4bacf0989
3 changed files with 188 additions and 62 deletions

View File

@ -516,32 +516,33 @@ class InformationDialog(HigDialog):
self, None, pritext, sectext, gtk.STOCK_DIALOG_INFO,
[ [ gtk.STOCK_OK, gtk.RESPONSE_OK ] ]
)
class RosterTooltip:
def __init__(self, plugin):
self.plugin = plugin
self.image = gtk.Image()
self.image.set_alignment(0.5, 0.025)
self.account = None
self.table = None
self.current_row = 1
class BaseTooltip:
''' Base Tooltip . Usage:
tooltip = BaseTooltip()
....
tooltip.show_tooltip('', window_postions, widget_postions)
....
if tooltip.timeout != 0:
tooltip.hide_tooltip()
'''
def __init__(self):
self.timeout = 0
self.prefered_position = [0, 0]
self.path = None
self.win = None
self.id = None
def populate(self, data):
''' this method must be overridenby all extenders '''
self.create_window()
self.win.add(gtk.Label(data))
def create_window(self):
''' create a popup window each time tooltip is requested '''
self.win = gtk.Window(gtk.WINDOW_POPUP)
self.win.set_border_width(3)
self.win.set_resizable(False)
self.win.set_name('gtk-tooltips')
self.hbox = gtk.HBox()
self.hbox.set_border_width(6)
self.hbox.set_homogeneous(False)
self.win.add(self.hbox)
self.hbox.pack_start(self.image, False, False)
self.win.set_events(gtk.gdk.POINTER_MOTION_MASK)
self.win.connect_after('expose_event', self.expose)
@ -561,8 +562,10 @@ class RosterTooltip:
self.prefered_position[0] = screen.get_width() - requisition.width
else:
self.prefered_position[0] -= half_width
screen.get_height()
if self.prefered_position[1] + requisition.height > screen.get_height():
self.prefered_position[1] -= requisition.height + 25
# flip tooltip up
self.prefered_position[1] -= requisition.height + self.widget_height + 8
if self.prefered_position[1] < 0:
self.prefered_position[1] = 0
self.win.move(self.prefered_position[0], self.prefered_position[1])
@ -580,11 +583,12 @@ class RosterTooltip:
self.win, 'tooltip', size[0] - 1, 0, 1, -1)
return True
def show_tooltip(self, contact, pointer_position, win_size):
self.populate(contact)
new_x = win_size[0] + pointer_position[0]
new_y = win_size[1] + pointer_position[1] + 35
def show_tooltip(self, data, widget_pos, win_size):
self.populate(data)
new_x = win_size[0] + widget_pos[0]
new_y = win_size[1] + widget_pos[1] + 4
self.prefered_position = [new_x, new_y]
self.widget_height = widget_pos[1]
self.win.ensure_style()
self.win.show_all()
@ -592,11 +596,37 @@ class RosterTooltip:
if(self.timeout > 0):
gobject.source_remove(self.timeout)
self.timeout = 0
if self.win:
self.win.destroy()
self.path = None
self.win = None
self.id = None
class StatusTable:
''' Contains methods for creating status table. This
is used in Roster and NotificationArea tooltips '''
def __init__(self):
self.current_row = 1
self.table = None
self.text_lable = None
def add_status(self, file_path, resource, priority, show, status):
def create_table(self):
self.table = gtk.Table(3, 1)
self.table.set_property('column-spacing', 6)
self.text_lable = gtk.Label()
self.text_lable.set_line_wrap(True)
self.text_lable.set_alignment(0, 0)
self.text_lable.set_selectable(False)
self.table.attach(self.text_lable, 1, 4, 1, 2)
def get_status_info(self, resource, priority, show, status):
str_status = resource + ' ('+str(priority)+')'
if status:
status = status.strip()
if status != '':
str_status += ' - ' + status
return gtkgui_helpers.escape_for_pango_markup(str_status)
def add_status_row(self, file_path, show, str_status):
''' appends a new row with status icon to the table '''
self.current_row += 1
state_file = show.replace(' ', '_')
@ -616,29 +646,91 @@ class RosterTooltip:
self.table.attach(image,2,3,self.current_row,
self.current_row + 1, 0, 0, 3, 0)
image.set_alignment(0.01, 1)
str_status = resource + ' ('+str(priority)+')'
if status:
status = status.strip()
if status != '':
str_status += ' - ' + status
status_label = gtk.Label(str_status)
status_label = gtk.Label()
status_label.set_markup(str_status)
status_label.set_alignment(00, 0)
self.table.attach(status_label, 3, 4, self.current_row,
self.current_row + 1, gtk.EXPAND | gtk.FILL, 0, 0, 0)
class NotificationAreaTooltip(BaseTooltip, StatusTable):
''' Tooltip that is shown in the notification area '''
def __init__(self, plugin):
self.plugin = plugin
BaseTooltip.__init__(self)
StatusTable.__init__(self)
def populate(self, data):
self.create_window()
self.create_table()
self.hbox = gtk.HBox()
self.table.set_property('column-spacing', 1)
text, single_line, accounts = '', '', []
if gajim.contacts:
for account in gajim.contacts.keys():
status_idx = gajim.connections[account].connected
# uncomment the following to hide offline accounts
# if status_idx == 0: continue
from common.connection import STATUS_LIST
status = STATUS_LIST[status_idx]
message = gajim.connections[account].status
single_line = helpers.get_uf_show(status)
if message is None:
message = ''
else:
message = message.strip()
if message != '':
single_line += ': ' + message
else:
message = helpers.get_uf_show(status)
accounts.append({'name':account, 'status_line':single_line,
'show':status, 'message':message})
unread_messages_no = self.plugin.roster.nb_unread
if unread_messages_no > 1:
text = _('Gajim - %s unread messages') % unread_messages_no
elif unread_messages_no == 1:
text = _('Gajim - 1 unread message')
elif len(accounts) > 1:
text = _('Gajim')
self.current_row = 1
self.table.resize(2,1)
iconset = gajim.config.get('iconset')
if not iconset:
iconset = 'sun'
file_path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16')
for acct in accounts:
self.add_status_row(file_path, acct['show'], '<span weight="bold">' +
gtkgui_helpers.escape_for_pango_markup(acct['name']) + '</span>'
+ ' - ' + gtkgui_helpers.escape_for_pango_markup(acct['message']))
elif len(accounts) == 1:
text = _('Gajim - %s') % accounts[0]['status_line']
else:
text = _('Gajim - %s') % helpers.get_uf_show('offline')
self.text_lable.set_markup(text)
self.hbox.add(self.table)
self.win.add(self.hbox)
class RosterTooltip(BaseTooltip, StatusTable):
''' Tooltip that is shown in the roster treeview '''
def __init__(self, plugin):
self.account = None
self.plugin = plugin
self.image = gtk.Image()
self.image.set_alignment(0.5, 0.025)
BaseTooltip.__init__(self)
StatusTable.__init__(self)
def populate(self, contacts):
if not contacts or len(contacts) == 0:
return
self.create_window()
self.table = gtk.Table(3, 1)
self.table.set_property('column-spacing', 6)
self.account = gtk.Label()
self.account.set_line_wrap(True)
self.account.set_alignment(0, 0)
self.account.set_selectable(False)
self.table.attach(self.account, 1, 4, 1, 2)
self.hbox.pack_start(self.table, True, True)
# default resource of the contact
self.hbox = gtk.HBox()
#~ self.hbox.set_border_width(6)
self.hbox.set_homogeneous(False)
self.create_table()
prim_contact = None # primary contact
for contact in contacts:
if prim_contact == None or contact.priority > prim_contact.priority:
@ -693,8 +785,9 @@ class RosterTooltip:
info += '\n<span weight="bold">' + _('Status: ') + '</span>'
for contact in contacts:
if contact.resource:
self.add_status(file_path, contact.resource, contact.priority,
status_line = self.get_status_info(contact.resource, contact.priority,
contact.show, contact.status)
self.add_status_row(file_path, contact.show, status_line)
else: # only one resource
if contact.resource:
@ -710,7 +803,10 @@ class RosterTooltip:
# escape markup entities. Is it posible to have markup in status?
info += ' - ' + gtkgui_helpers.escape_for_pango_markup(status)
self.account.set_markup(info)
self.text_lable.set_markup(info)
self.hbox.pack_start(self.image, False, False)
self.hbox.pack_start(self.table, True, True)
self.win.add(self.hbox)
class InputDialog:
'''Class for Input dialog'''

View File

@ -642,11 +642,14 @@ class RosterWindow:
def show_tooltip(self, contact):
pointer = self.tree.get_pointer()
props = self.tree.get_path_at_pos(pointer[0], pointer[1])
if props and self.tooltip.path == props[0]:
if props and self.tooltip.id == props[0]:
# check if the current pointer is at the same path
# as it was before setting the timeout
self.tooltip.show_tooltip(contact, self.window.get_pointer(),
self.window.get_position())
rect = self.tree.get_cell_area(props[0],props[1])
position = self.tree.window.get_origin()
pointer = self.window.get_pointer()
self.tooltip.show_tooltip(contact, (pointer[0], rect.height ),
(position[0], position[1] + rect.y))
else:
self.tooltip.hide_tooltip()
@ -654,14 +657,14 @@ class RosterWindow:
model = widget.get_model()
props = widget.get_path_at_pos(int(event.x), int(event.y))
if self.tooltip.timeout > 0:
if not props or self.tooltip.path == props[0]:
if not props or self.tooltip.id == props[0]:
self.tooltip.hide_tooltip()
def on_roster_treeview_motion_notify_event(self, widget, event):
model = widget.get_model()
props = widget.get_path_at_pos(int(event.x), int(event.y))
if self.tooltip.timeout > 0:
if not props or self.tooltip.path != props[0]:
if not props or self.tooltip.id != props[0]:
self.tooltip.hide_tooltip()
if props:
[row, col, x, y] = props
@ -670,8 +673,8 @@ class RosterWindow:
account = model[iter][4]
jid = model[iter][3]
img = model[iter][0]
if self.tooltip.timeout == 0 or self.tooltip.path != props[0]:
self.tooltip.path = row
if self.tooltip.timeout == 0 or self.tooltip.id != props[0]:
self.tooltip.id = row
self.tooltip.timeout = gobject.timeout_add(500,
self.show_tooltip, gajim.contacts[account][jid])

View File

@ -4,6 +4,7 @@
## - Yann Le Boulanger <asterix@lagaule.org>
## - Vincent Hanquez <tab@snarc.org>
## - Nikos Kouremenos <kourem@gmail.com>
## - Dimitur Kirov <dkirov@gmail.com>
##
## Copyright (C) 2003-2005 Gajim Team
##
@ -19,6 +20,7 @@
import gtk
import gtk.glade
import gobject
import dialogs
import os
@ -50,7 +52,7 @@ class Systray:
self.jids = []
self.new_message_handler_id = None
self.t = None
self.tip = gtk.Tooltips()
#~ self.tip = gtk.Tooltips()
self.img_tray = gtk.Image()
self.status = 'offline'
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'systray_context_menu', APP)
@ -132,7 +134,7 @@ class Systray:
if global_status is not None and self.status != global_status:
self.status = global_status
self.set_img()
self.tip.set_tip(self.t, text)
#~ self.tip.set_tip(self.t, text)
def start_chat(self, widget, account, jid):
if self.plugin.windows[account]['chats'].has_key(jid):
@ -270,8 +272,8 @@ class Systray:
def on_clicked(self, widget, event):
# hide the tooltip
self.tip.disable()
self.tip.enable()
#~ self.tip.disable()
#~ self.tip.enable()
win = self.plugin.roster.window
if event.button == 1: # Left click
if len(self.jids) == 0:
@ -311,14 +313,43 @@ class Systray:
index = l.index(show)
self.plugin.roster.status_combobox.set_active(index)
def show_tooltip(self, widget):
position = widget.window.get_origin()
if self.tooltip.id == position:
size = widget.window.get_size()
self.tooltip.show_tooltip('',
(widget.window.get_pointer()[0], size[1]), position)
def on_tray_motion_notify_event(self, widget, event):
wireq=widget.size_request()
position = widget.window.get_origin()
if self.tooltip.timeout > 0:
if self.tooltip.id != position:
self.tooltip.hide_tooltip()
if self.tooltip.timeout == 0 and \
self.tooltip.id != position:
self.tooltip.id = position
self.tooltip.timeout = gobject.timeout_add(500,
self.show_tooltip, widget)
def on_tray_leave_notify_event(self, widget, event):
position = widget.window.get_origin()
if self.tooltip.timeout > 0 and \
self.tooltip.id == position:
self.tooltip.hide_tooltip()
def show_icon(self):
if not self.t:
self.t = trayicon.TrayIcon('Gajim')
eb = gtk.EventBox()
# avoid draw seperate bg color in some gtk themes
eb.set_visible_window(False)
eb.set_events(gtk.gdk.POINTER_MOTION_MASK)
eb.connect('button-press-event', self.on_clicked)
self.set_tooltip()
eb.connect('motion-notify-event', self.on_tray_motion_notify_event)
eb.connect('leave-notify-event', self.on_tray_leave_notify_event)
self.tooltip = dialogs.NotificationAreaTooltip(self.plugin)
#~ self.set_tooltip()
self.img_tray = gtk.Image()
eb.add(self.img_tray)
self.t.add(eb)
@ -326,14 +357,10 @@ class Systray:
self.t.show_all()
def set_tooltip(self, unread_messages_no=None):
# we look for the number of unread messages
# and we set the appropriate tooltip
if unread_messages_no > 1:
text = _('Gajim - %s unread messages') % unread_messages_no
self.tip.set_tip(self.t, text)
elif unread_messages_no == 1:
text = _('Gajim - 1 unread message')
self.tip.set_tip(self.t, text)
else: # it's None or 0
self.change_status()