Howdy fellow monks:
I'm making a little tray app in perl Gtk2 that puts up a menu of different hosts that I might want a shell window to. The only problem I have with it is that the submenu arrows show up on the right instead of the left like you would expect from a tray app.
I know this is probably a setting on the menu, but I can't find an example anywhere of how to set it. Can anybody help?
If it helps, the following is my current code:
#!/usr/bin/perl -w
use Glib qw/TRUE FALSE/;
use Gtk2; # load the Gtk-Perl module
use Gtk2::TrayIcon;
use strict; # a good idea for all non-trivial Perl scripts
use Data::Dumper;
#
# To Do: perhaps submenus for hosts within clusters? DONE!!
#
set_locale Gtk2; # internationalize
init Gtk2; # initialize Gtk-Perl
# convenience variables for true and false
my $false = 0;
my $true = 1;
# widget creation
my $top_menu = new Gtk2::Menu();
my $menu_item;
my $new_submenu;
my $button;
my %hosts;
my %proggies;
my $cur_host;
my $img_dir="/opt/gnome/share/icons/hicolor/16x16/stock/net/";
my $menu_x;
my $menu_y;
my @menu_stack;
# start a new submenu
sub new_submenu
{
# get the highest menu in the stack
my $name = shift;
my $cur_submenu = $menu_stack[$#menu_stack];
$new_submenu = new Gtk2::Menu();
$menu_item = Gtk2::MenuItem->new_with_label($name);
$menu_item->set_submenu($new_submenu);
$menu_item->show;
$cur_submenu->append($menu_item);
push(@menu_stack,$new_submenu);
}
# stop adding stuff to the most nested menu
sub end_submenu
{
pop(@menu_stack);
}
sub add_new_menu_entry
{
my $name = shift;
my $cur_menu = $menu_stack[$#menu_stack];
$menu_item = Gtk2::MenuItem->new_with_label($name);
$menu_item->signal_connect(activate => \&new_shell_cb, $name);
$menu_item->show;
# push this item on the current menu
$cur_menu->append($menu_item);
}
sub new_shell_cb
{
my $button_clicked = shift;
#my $cur_item = $menu->get_active;
my $host;
my $label;
$label = $button_clicked->get_child;
if ($label->isa('Gtk2::Label')) {
$cur_host = $label->get_label;
}
if (exists($hosts{$cur_host})) {
$host = $hosts{$cur_host};
} else {
$host = $cur_host;
}
# start the shell
unless (fork) {
if (defined($proggies{$cur_host})) {
exec("$ENV{HOME}/shell.csh","\#0000ff",$host,"root",
$proggies{$cur_host});
} else {
exec("$ENV{HOME}/shell.csh","\#0000ff",$host,"root");
}
}
}
my $tray_img = Gtk2::Image->new_from_file($img_dir."stock_internet.png
+");
my $tray = Gtk2::TrayIcon->new("shells");
my $eventbox = Gtk2::EventBox->new;
$eventbox->add($tray_img);
$tray->add($eventbox);
$tray->show_all;
$eventbox->signal_connect("button-press-event", \&handle_tray_press);
open(SHELLS,"<$ENV{HOME}/.shells");
my $host_info;
my $name;
my $ip;
my $first = 1;
my $proggie;
my $cur_menu;
push(@menu_stack,$top_menu);
$cur_menu = $menu_stack[$#menu_stack];
$menu_item = Gtk2::MenuItem->new_with_label("Exit");
$menu_item->signal_connect(activate => sub { exit(0); }, "Exit");
$menu_item->show;
$cur_menu->append($menu_item);
while ($host_info = <SHELLS>) {
chomp($host_info);
# ignore leading spaces to make config file prettier
$host_info =~ s/^\s+//g;
($name, $proggie, $ip) = split(/\s+/,$host_info);
# never pop the top menu
if ($name eq "end" && scalar(@menu_stack) > 1) {
end_submenu();
next;
}
if ($name eq "submenu") {
new_submenu($proggie);
next;
}
if ($first == 1) {
$cur_host = $name;
$first = 0;
}
if (defined($ip)) {
$hosts{$name} = $ip;
}
if (defined($proggie)) {
$proggies{$name} = $proggie;
}
add_new_menu_entry($name);
}
close(SHELLS);
# Gtk event loop
Gtk2->main;
# Should never get here
exit( 0 );
sub handle_tray_press
{
my $widget = shift;
my $event = shift;
$menu_x = $event->x_root - $event->x;
$menu_y = $event->y_root - $event->y;
$top_menu->popup(undef, undef,
\&position_menu, 0,
$event->button,
$event->time);
}
sub position_menu {
# Shamlessly stolen from Muine :-)
my $x = $menu_x;
my $y = $menu_y;
my $monitor = $top_menu->get_screen->get_monitor_at_point($x,$y);
my $rect = $top_menu->get_screen->get_monitor_geometry($monitor);
my $space_above = $y - $rect->y;
my $space_below = $rect->y + $rect->height - $y;
my $requisition = $top_menu->size_request();
if ($requisition->height <= $space_above ||
$requisition->height <= $space_below) {
if ($requisition->height <= $space_below) {
$y = $y + $eventbox->allocation->height;
}
else {
$y = $y - $requisition->height;
}
}
elsif ($requisition->height > $space_below and
$requisition->height > $space_above) {
if ($space_below >= $space_above) {
$y = $rect->y + $rect->height - $requisition->height;
}
else {
$y = $rect->y;
}
}
else {
$y = $rect->y;
}
return ($x,$y,1);
}
Thanks in advance!
----
My mission: To boldy split infinitives that have never been split before!