1package UI::Dialog::Screen::Menu; 2############################################################################### 3# Copyright (C) 2004-2016 Kevin C. Krinke <kevin@krinke.ca> 4# 5# This library is free software; you can redistribute it and/or 6# modify it under the terms of the GNU Lesser General Public 7# License as published by the Free Software Foundation; either 8# version 2.1 of the License, or (at your option) any later version. 9# 10# This library is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13# Lesser General Public License for more details. 14# 15# You should have received a copy of the GNU Lesser General Public 16# License along with this library; if not, write to the Free Software 17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18############################################################################### 19use 5.006; 20use strict; 21use warnings; 22use constant { TRUE => 1, FALSE => 0 }; 23 24BEGIN { 25 use vars qw($VERSION); 26 $VERSION = '1.21'; 27} 28 29use UI::Dialog; 30 31# Example Usage 32# 33# my $screen = new UI::Dialog::Screen::Menu ( dialog => $d ); 34# $screen->add_menu_item( "Label", \&func ); 35# $screen->loop(); 36# 37 38sub new { 39 my ($class, %args) = @_; 40 $args{__loop_active} = FALSE; 41 unless (exists $args{dialog}) { 42 $args{dialog} = new UI::Dialog 43 ( 44 title => (defined $args{title}) ? $args{title} : '', 45 backtitle => (defined $args{backtitle}) ? $args{backtitle} : '', 46 height => (defined $args{height}) ? $args{height} : 20, 47 width => (defined $args{width}) ? $args{width} : 65, 48 listheight => (defined $args{listheight}) ? $args{listheight} : 5, 49 order => (defined $args{order}) ? $args{order} : undef, 50 PATH => (defined $args{PATH}) ? $args{PATH} : undef, 51 beepbefore => (defined $args{beepbefore}) ? $args{beepbefore} : undef, 52 beepafter => (defined $args{beepafter}) ? $args{beepafter} : undef, 53 'trust-input' => (defined $args{'trust-input'} && $args{'trust-input'} == 1) ? 1 : 0, 54 ); 55 } 56 unless (exists $args{menu}) { 57 $args{menu} = []; 58 } 59 return bless { %args }, $class; 60} 61 62#: $screen->add_menu_item( "Label", \&func ); 63#: Add an item to the menu with a label and a callback func 64# 65sub add_menu_item { 66 my ($self,$label,$func) = @_; 67 push(@{$self->{menu}},{label=>$label,func=>$func}); 68 return @{$self->{menu}} - 1; 69} 70 71#: @list_of_menu_items = $screen->get_menu_items(); 72#: Return a list of all the menu items in order. Each item is a hash 73#: with a label and a func reference. 74# 75sub get_menu_items { 76 my ($self) = @_; 77 return @{$self->{menu}}; 78} 79 80#: %item = $screen->del_menu_item( $index ); 81#: Remove a menu item and return it. The item will no longer show in the 82#: list of avaliable menu items. 83# 84sub del_menu_item { 85 my ($self,$index) = @_; 86 if (defined $index && $index >= 0 && $index < @{$self->{menu}}) { 87 return splice(@{$self->{menu}}, $index, 1); 88 } 89 return undef; 90} 91 92#: $screen->set_menu_item( $index, $label||undef, $func||undef ); 93#: Update a menu item's properties. If a field is "undef", no action 94#: is performed on that item's field. Returns the menu_item before 95#: modification. 96#: Note: $index starts from 0. 97# 98sub set_menu_item { 99 my ($self,$index,$label,$func) = @_; 100 if (defined $index && $index >= 0 && $index < @{$self->{menu}}) { 101 my $item = $self->{menu}->[$index]; 102 my $orig = { label => $item->{label}, func => $item->{func} }; 103 $self->{menu}->[$index]->{label} = $label if defined $label; 104 $self->{menu}->[$index]->{func} = $func if defined $func; 105 return $orig; 106 } 107 return undef; 108} 109 110 111#: $screen->run(); 112#: Blocking call, display the menu and react once. Returns 0 if cancelled, 113#: returns 1 if an item was selected and the function called. 114# 115sub run { 116 my ($self) = @_; 117 my @menu_list = (); 118 my $c = 1; 119 foreach my $data (@{$self->{menu}}) { 120 push(@menu_list,$c,$data->{label}); 121 $c++; 122 } 123 my $sel = $self->{dialog}->menu 124 ( 125 title => (defined $self->{title}) ? $self->{title} : '', 126 text => (defined $self->{text}) ? $self->{text} : '', 127 list => \@menu_list 128 ); 129 if ($self->{dialog}->state() eq "OK") { 130 my $data = $self->{menu}->[$sel-1]; 131 my $func = $data->{func}; 132 &{$func}($self,$self->{dialog},$sel-1) if defined $func and ref($func) eq "CODE"; 133 return 1; 134 } else { 135 if (exists $self->{cancel}) { 136 my $func = $self->{cancel}; 137 &{$func}($self,$self->{dialog},-1) if defined $func and ref($func) eq "CODE"; 138 } 139 } 140 return 0; 141} 142 143#: $screen->loop(); 144#: Blocking call, execute $screen->run() indefinitely. If run() was cancelled, 145#: the loop will break. 146sub loop { 147 my ($self) = @_; 148 $self->{__loop_active} = TRUE; 149 while ($self->{__loop_active}) { 150 last unless $self->run(); 151 } 152} 153 154#: $screen->break_loop(); 155#: Notify loop() to break instead of re-iterate regardless of user input. 156# 157sub break_loop { 158 my ($self) = @_; 159 $self->{__loop_active} = FALSE; 160} 161 162#: $screen->is_looping(); 163#: Returns TRUE if currently looping, FALSE otherwise 164# 165sub is_looping { 166 my ($self) = @_; 167 return ($self->{__loop_active}) ? TRUE : FALSE; 168} 169 1701; # END OF UI::Dialog::Screen::Menu 171