/usr/local/CPAN/Tk-MDI/Tk/MDI/Menu.pm
package Tk::MDI::Menu;
use strict;
my %_fixedMenuEntries = (
'Tile Horizontally' => [\&_tile, 'h'],
'Tile Vertically' => [\&_tile, 'v'],
'Cascade', => [\&_cascade],
'Minimize All', => [\&_minimizeAll],
'Restore All', => [\&_restoreAll],
);
sub new {
my $self = shift;
my $class = ref($self) || $self;
my $obj = bless {} => $class;
my %args = @_;
$obj->{PARENT} = $args{-parent};
$obj->{PARENTOBJ} = $args{-parentobj};
$obj->{MW} = $args{-mw};
$obj->{MENUTYPE} = $args{-type};
$obj->_createMenuBar;
return $obj;
}
# possible values for -type are:
# none - no menus
# popup - menu accessible only through right mouse button.
# menubar - menu accessible only through menu bar.
# both - menu accessible through both menu bar and right mouse button.
# menu obj ref - use this menu object as the menu.
#
# PS. I don't like the way I coded this! But it works!
sub _createMenuBar {
my $obj = shift;
return if $obj->{MENUTYPE} eq 'none';
my $popup = my $menubar = 0;
if (ref $obj->{MENUTYPE}) {
$obj->{MENU} = $obj->{MENUTYPE};
} elsif ($obj->{MENUTYPE} eq 'popup') {
$popup = 1;
} elsif ($obj->{MENUTYPE} eq 'menubar') {
$menubar = 1;
} else {
$popup = $menubar = 1;
}
if ($menubar) {
if (defined (my $menu = $obj->{MW}->cget('-menu'))) {
$obj->{MENU} = $menu;
} else {
$obj->{MENU} = $obj->{MW}->Menu(qw/-type menubar/);
$obj->{MW}->configure(-menu => $obj->{MENU});
}
}
if ($popup && !$menubar) {
$obj->{MENU} = $obj->{MW}->Menu;
}
$obj->_populateMenuBar;
if ($popup) {
$obj->{PARENTOBJ}->_bindToMenu($obj->{CASCADEMENU});
}
}
sub _populateMenuBar {
my $obj = shift;
$obj->{CASCADEMENU} = $obj->{MW}->Menu(
-tearoff => 0,
-postcommand => sub { $obj->_menuPostCommand }
);
$obj->{MENU}->add('cascade',
-label => 'Window',
-menu => $obj->{CASCADEMENU},
);
for my $key (keys %_fixedMenuEntries) {
# do I need to sort the above in any way?
$obj->{CASCADEMENU}->command(
-label => $key,
-command => [@{$_fixedMenuEntries{$key}}, $obj],
);
}
$obj->{CASCADEMENU}->separator;
$obj->{INDEX} = 0;
$obj->{WINDOWSLISTED} = 0;
}
# Not sure why this is here-should probably delete?
#sub _newWindow {
# $_[0]->newWindow;
#}
sub _tile {
$_[1]->{PARENTOBJ}->_tile($_[0]);
}
sub _cascade {
$_[0]->{PARENTOBJ}->_cascade($_[0]);
}
sub _minimizeAll {
$_[0]->{PARENTOBJ}->_minimizeAll($_[0]);
}
sub _restoreAll {
$_[0]->{PARENTOBJ}->_restoreAll($_[0]);
}
sub _addWindowToList {
my ($obj, $ref) = @_;
$obj->{WINDOWLIST}[$obj->{INDEX}++] = $ref;
}
sub _deleteWindowFromList {
my ($obj, $ref) = @_;
for my $i (0 .. $obj->{INDEX}) {
if (defined $obj->{WINDOWLIST}[$i] && $obj->{WINDOWLIST}[$i] eq $ref) {
$obj->{WINDOWLIST}[$i] = undef;
last;
}
}
}
sub _menuPostCommand {
my $obj = shift;
my $w = $obj->{CASCADEMENU};
if ($obj->{WINDOWSLISTED}) {
# if we have any windows already in the menu .. delete them.
my $count = 1 + scalar keys %_fixedMenuEntries; #for the separator
$w->delete($count, $count + $obj->{WINDOWSLISTED});
$obj->{WINDOWSLISTED} = 0;
}
# Now add the window names to the menu.
my $j=1; #Counts on left hand side should always be 1..whatever.
for my $i (0 .. $obj->{INDEX}) {
my $ref = $obj->{WINDOWLIST}[$i];
next unless defined $ref;
my $name = $ref->_name;
$name = "($name)" if $ref->_isMin;
$obj->{WINDOWSLISTED}++;
$w->command(-label => "$j. $name",
-command => sub {
$ref->_menuFocus;
});
$j++;
}
}
1;