# ----------------------------------------------------------------------
# Curses::UI::Menubar
# Curses::UI::MenuListbox
#
# (c) 2001-2002 by Maurice Makaay. All rights reserved.
# This file is part of Curses::UI. Curses::UI is free software.
# You can redistribute it and/or modify it under the same terms
# as perl itself.
#
# Currently maintained by Marcus Thiesen
# e-mail: marcus@cpan.thiesenweb.de
# ----------------------------------------------------------------------
# TODO: fix dox
# ----------------------------------------------------------------------
# MenuListbox package
# ----------------------------------------------------------------------
package Curses::UI::MenuListbox;
use strict;
use Curses;
use Curses::UI::Common;
use Curses::UI::Container;
use Curses::UI::Window;
use Curses::UI::Listbox;
use Curses::UI::Widget;
use vars qw(
$VERSION
@ISA
);
$VERSION = '1.10';
@ISA = qw(
Curses::UI::Listbox
Curses::UI::Common
Curses::UI::Window
);
sub new()
{
my $class = shift;
my %userargs = @_;
keys_to_lowercase(\%userargs);
my %args = (
-menu => {}, # The menu contents
-is_topmenu => 0, # First pulldown or not?
-menubar => undef, # Ref to menubar object
-prevobject => undef, # Ref to "parent" object (the real parent
# is the rootwindow, but we need to know
# which menulistbox or menubar is parent).
-bg => -1,
-fg => -1,
-bbg => -1,
-bfg => -1,
%userargs,
-vscrollbar => 1, # Always use a vscrollbar
-border => 1, # Always show a border
-wraparound => 1, # Use listbox wraparound
-returnaction => undef, # Is set by other MenuListboxes
);
# First determine the longest label.
my $longest = 0;
foreach my $item (@{$args{-menu}})
{
my $l = $item->{-label};
$args{-parent}->root->fatalerror(
"Missing argument: -label for the MenuListbox"
) unless defined $l;
$longest = length($l) if length($l) > $longest;
}
# Increase $longest for some whitespace on the
# right side of the labels.
$longest++;
# Now create the values and labels for the listbox.
my @values = ();
my %labels = ();
my $has_submenu = 0;
foreach my $item (@{$args{-menu}})
{
my $l = $item->{-label};
if (defined($item->{-submenu}))
{
$l = sprintf("%-${longest}s >>", $l);
$has_submenu++;
}
push @values, $l;
}
# If there are submenu's, make the $longest variable higher.
$longest += 4 if $has_submenu;
$args{-values} = \@values;
# Determine the needed width and hight for the listbox.
my $w = width_by_windowscrwidth($longest, %args);
my $h = height_by_windowscrheight(@values, %args);
$args{-width} = $w;
$args{-height} = $h;
# Check if the menu does fit on the right. If not, try to
# shift it to the left as far as needed.
if ($args{-x} + $w > $ENV{COLS}) {
$args{-x} = $ENV{COLS} - $w;
$args{-x} = 0 if $args{-x} < 0;
}
my $this = $class->SUPER::new(%args);
$this->root->fatalerror(
"Missing or illegal argument: -menubar"
) unless defined $args{-menubar} and
$args{-menubar}->isa('Curses::UI::Menubar');
# Clear 'loose-focus' binding, so loosing focus through
# the key does not work.
$this->clear_binding('loose-focus');
# Create binding routines.
$this->set_routine('cursor-left', \&cursor_left);
$this->set_routine('cursor-right', \&cursor_right);
$this->set_routine('option-select',\&option_select);
$this->set_routine('escape', \&escape_key);
# Create bindings.
$this->set_binding('escape', CUI_ESCAPE);
$this->set_binding('cursor-left', KEY_LEFT(), 'h');
$this->set_binding('cursor-right', KEY_RIGHT(), 'l');
if ($Curses::UI::ncurses_mouse) {
$this->set_mouse_binding(\&mouse_button1, BUTTON1_CLICKED());
}
return $this;
}
sub escape_key()
{
my $this = shift;
$this->{-prevobject}->{-returnaction} = 'COLLAPSE';
$this->loose_focus;
}
sub active_item()
{
my $this = shift;
$this->{-menu}->[$this->{-ypos}];
}
sub cursor_left()
{
my $this = shift;
$this->{-prevobject}->{-returnaction} = 'CURSOR_LEFT';
$this->loose_focus;
}
sub cursor_right()
{
my $this = shift;
# Get the current menu-item.
my $item = $this->active_item;
# This item has a submenu. Open it.
if (defined $item->{-submenu})
{
# Compute the (x,y)-position of the new menu.
my $x = $this->{-x} + $this->borderwidth;
my $y = $this->{-y} + $this->{-ypos};
# Create the submenu.
my $id = "__submenu_$this";
my $submenu = $this->root->add(
$id, 'MenuListbox',
-prevobject => $this,
-menubar => $this->{-menubar},
-x => $x,
-y => $y,
-menu => $this->{-menu}->[$this->{-ypos}]->{-submenu},
-bg => $this->{-bg},
-fg => $this->{-fg},
-bbg => $this->{-bbg},
-bfg => $this->{-bfg},
);
# Show the submenu and wait for it to return.
$this->{-returnaction} = undef;
$submenu->modalfocus;
$this->root->delete($id);
$this->root->draw;
# Data set by the previous modal focused menulistbox.
my $return = $this->{-returnaction};
my $event = $this->{-mouse_event};
if (defined $return)
{
# COLLAPSE: