Skip to content

The Menu

Saif Ahmed edited this page Dec 18, 2022 · 5 revisions

menu

The Menu in Term::Graille::Menu is (probably) the simplest dropdown menu creation system possible on any platform. It mimics a standard drop down menu found in many GUI Apps, and is navigated simply by the arrow keys and Enter. It is a Term::Graille::Interact widget which means that is harnesses its key capture engine.

A menu object is created using something like:-

my $menu=new Term::Graille::Menu(  # no object offered so id will be o0 
          menu=>[["File","New","Load","Insert","Save","Quit"],
                 ["Edit",["Select","All","Start","End"],["Selection","Copy","Cut","Paste"],"Search","Replace"],
                 ["Run","Logo","Perl","Python"],
                 "About"],
          redraw=>\&refreshScreen,        # this is the function that redraws the main window
          dispatcher=>\&menuDispatch,     # this is the function that dispatches actions based on menu item selected
          );

The Menu Tree

You can see that the menu tree is created in a readable, intuitive manner. Each item of the menu is either a string or an arrayRef. A string represent a leaf in the menu tree and selecting a leak item immediately closes the menu, redraws the screen, calls the dispatcher with the leaf string and a breadcrumb ArrayRef. An ArrayRef contains first the Branch Name, then is followed by strings or ArrayRefs. so something like this:

my $menuTree=[["File","New","Load","Insert","Save","Quit"],
                 ["Edit",["Select","All","Start","End"],["Selection","Copy","Cut","Paste"],"Search","Replace"],
                 ["Run","Logo","Perl","Python"],
                 "About"];

produces a menu tree like:

File      Edit                Run      Test   About
New       Select->All         Logo     Death
Load              Start       Perl     Message
Insert            End         Python   Input
Save      Selection->Copy              Selector
Quit                 Cut
                     Paste
          Search
          Replace

Because the tree is structured like this one can easily create dynamically changing menus: For instance if you want be able to select from list of sound cards available, you could use {"Select Card",<function_that_returns_available_cards()>]

image

The redraw function

The redraw function is a function defined in the main program that (naturally) redraws the main screen as the widget is drawn redrawn or removed

The dispatcher

This is a function the Menu object calls after the user has selected a menu Item. Two items are passed to the dispatcher function: the string in the leaf and an ArrayRef that describes the bread crumb tgrail to the leaf (this is present to allow for multi[ple leafs with the same name).

There are many ways a dispatcher may work; all it has to to do is decide on the parameter supplied as the menu item is selected what action to perform.

One way, for example is to use a number of if statements. Another is to use a for statement structured like a switch :-

sub menuDispatch{
   my ($action,$breadCrumds)=@_;
   for ($action){
      /Save/ and do { saveCurrentFile();last;}
      /Load/ and do { loadNewFile();    last;}
      #...etc
      # behaviour for as-yet undefined actions can go here
   }
}

Another way is to have dispatcher use a separate hashRef of subroutines;

my $menuActions={
    Save => sub{ saveCurrentFile();},
    Load => sub( loadNewFile(); },
}

sub menuDispatcher{
   my ($action,$breadCrumbs)=@_;
   if (exists $menuActions->{$action}){
     $menuActions->{$action}->();
   }
   else {
     printAt (2,60,$action);
   }
}