décembre
2009
Le présent article explique comment afficher une icône dans la zone de notification à l’aide de la bibliothèque ruby/Gtk2.
Les fonctionnalités présentées dans cet article sont implémentées par la classe StatusIcon. Cette classe est documentée, en anglais, sur le hiki du projet ruby-gnome2. Un code fonctionnel, récapitulant les notions abordées, est donné en fin d’article.
Afficher une icône
Nous allons tout d’abord afficher une icône dans la zone de notification.
2
3 require 'gtk2'
4 si=Gtk::StatusIcon.new
5 si.stock=Gtk::Stock::DIALOG_INFO
6 si.tooltip='StatusIcon'
7
8 Gtk.main
Après avoir lancé le code ci-dessus dans une console, il est nécessaire d’utiliser Ctrl+C pour récupérer la main.
Analysons le code. Nous chargeons tout d’abord la bibliothèque ruby/Gtk2 (ligne 1), puis un objet icône est créé (ligne 4). L’image utilisée pour afficher l’icône est définie à la ligne suivante. Ici, une image commune est utilisée. Nous aurions pu utiliser une image personnelle grâce à la méthode pixbuf=() (si.pixbuf=Gdk::Pixbuf.new('/chemin/vers/image.svg')
). La méthode tooltip=() permet d’indiquer le texte à afficher lorsque la souris survole l’icône.
Intéragir avec l’icône
Nous allons maintenant voir comment implémenter l’intéraction entre la souris et l’icône.
Intéractions avec le bouton gauche de la souris
si.signal_connect('activate'){|icon| icon.blinking=!(icon.blinking?)}
La méthode signal_connect permet de guetter l’émission d’un signal. Le signal activate est émis lors d’un clic gauche sur l’icône. Le bloc appelé ({|icon| icon.blinking=!(icon.blinking?)}) modifie l’état de l’icône qui clignotera ou pas suivant le nombre de clics.
Ajouter un menu
Il est possible d’ajouter un menu qui apparait lors d’un clic droit sur l’icône.
info.signal_connect('activate'){p "Zone de notification : #{si.embedded?}"; p "Visible : #{si.visible?}"; p "Clignotant : #{si.blinking?}"}
quit=Gtk::ImageMenuItem.new(Gtk::Stock::QUIT)
quit.signal_connect('activate'){Gtk.main_quit}
menu=Gtk::Menu.new
menu.append(info)
menu.append(Gtk::SeparatorMenuItem.new)
menu.append(quit)
menu.show_all
si.signal_connect('popup-menu'){|tray, button, time| menu.popup(nil, nil, button, time)}
Nous construisons un menu auquel nous ajoutons deux éléments (info et quit). Le menu est affiché par la méthode popup lorsque le signal popup-menu, indiquant un clic droit, est émis. L’élément quit permet de quitter la boucle principale proprement. Un clic sur l’élément info affiche en console trois informations. La méthode embedded? permet de vérifier la présence d’une zone de notification. Certains bureaux n’utilisent pas de zone de notification. Notre icône n’est alors pas visible par l’utilisateur.
Intéractions avec la molette de la souris
Si votre bibliothèque gtk est récente, vous pouvez surveiller les mouvements de la molette au niveau de l’icône.
case event.direction
when Gdk::EventScroll::UP
p 'haut'
when Gdk::EventScroll::DOWN
p 'bas'
end
}
Surveillons le signal scroll-event. L’objet event retourné appartient à la classe Gdk::EventScroll. La méthode direction de cet objet permet d’obtenir le sens dans lequel la molette tourne.
Il est aussi possible de contrôler quels modificateurs (control, shift, alt, meta…) sont actifs lors de l’intéraction. Remplacez le code précédent par le suivant.
modifier=event.state
ctrl_shift=(Gdk::Window::CONTROL_MASK|Gdk::Window::SHIFT_MASK)
mod=modifier&ctrl_shift
case mod
when 0
p 'Aucun modificateur'
when Gdk::Window::CONTROL_MASK
p 'Control'
when Gdk::Window::SHIFT_MASK
p 'Shift'
when (Gdk::Window::CONTROL_MASK|Gdk::Window::SHIFT_MASK)
p 'Control+Shif'
end
}
event.state est masque représentant l’état de l’ensemble des modificateurs, par exemple du clavier. Dans le cas présent, nous nous intéressons seulement aux modificateurs control et shift. À cet usage, nous filtrons les modificateurs complets avec un masque des modificateurs que nous voulons gérer. Puis nous comparons le résultat aux différents cas possibles.
Récapitulatif
Le code suivant est un exemple complet reprenant les notions vues dans cet article. N’hésitez pas à réagir à cet article en laissant un commentaire.
require 'gtk2'
###Icône
si=Gtk::StatusIcon.new
si.stock=Gtk::Stock::DIALOG_INFO
#si.pixbuf=Gdk::Pixbuf.new('/path/to/image.svg')
si.tooltip='StatusIcon'
###Intéractions avec le bouton gauche de la souris
si.signal_connect('activate'){|icon| icon.blinking=!(icon.blinking?)}
###Intéractions avec le bouton droit de la souris
#Construction d'un menu
info=Gtk::ImageMenuItem.new(Gtk::Stock::INFO)
info.signal_connect('activate'){p "Présent : #{si.embedded?}"; p "Visible : #{si.visible?}"; p "Clignotant : #{si.blinking?}"}
quit=Gtk::ImageMenuItem.new(Gtk::Stock::QUIT)
quit.signal_connect('activate'){Gtk.main_quit}
menu=Gtk::Menu.new
menu.append(info)
menu.append(Gtk::SeparatorMenuItem.new)
menu.append(quit)
menu.show_all
#Intéractions
si.signal_connect('popup-menu'){|tray, button, time| menu.popup(nil, nil, button, time)}
###Intéractions avec la molette de la souris
si.signal_connect('scroll-event'){|icon, event|
#Vérifier quels modificateurs ont été utilisés parmi control et shift. Les autres modificateurs ne sont pas pris en compte.
mod=event.state&(Gdk::Window::CONTROL_MASK|Gdk::Window::SHIFT_MASK)
case mod
when 0
p print_direction(event.direction)
when Gdk::Window::CONTROL_MASK
p 'Control+'+print_direction(event.direction)
when Gdk::Window::SHIFT_MASK
p 'Shift+'+print_direction(event.direction)
when (Gdk::Window::CONTROL_MASK|Gdk::Window::SHIFT_MASK)
p 'Control+Shift+'+print_direction(event.direction)
end
}
def print_direction(direction)
#Donne la direction de la molette
case direction
when Gdk::EventScroll::UP
'haut'
when Gdk::EventScroll::DOWN
'bas'
end
end
Gtk.main
Merci de votre commentaire.
J’ai écrit l’interface dans le code car j’apprend/apprennais ruby. Çà me semblait une bonne façon de commencer. Je ne vois pas ce que glade peut apporter sinon un code plus léger et peut-être une meilleure séparation entre interface et méthodes. Je ne suis pas sûr que le fichier glade soit plus lisible que du code ruby mais bon je suis mauvais juge car je n’ai jamais utilisé glade.
Vinc.
merci pour l’exemple dont je me suis inspiré!
juste une remarque: le menu pop à l’endroit de la souris sur l’icône, ce qui est assez moche. pour remédier à ça, il suffit de remplacer:
si.signal_connect('popup-menu'){|tray, button, time| menu.popup(nil, nil, button, time)} <br />
par
si.signal_connect('popup-menu'){ |tray, button, time| <br />
menu.popup(nil, nil, button, time) { |menu, x, y, push_in| si.position_menu(menu) } <br />
} <br />
ce qui fait que le menu s’aligne sous la barre (si le tray en en haut, ce qui est mon cas).
et bonne continuation pour zik! (d’ailleurs je me demande pourquoi tu as fait toute l’interface à la main dans le code plutôt que d’utiliser glade designer?)
Tres instructif…