Sign In/My Account | View Cart  
advertisement


Listen Print Discuss

Making Menus with wxPerl
by Roberto Alamos | Pages: 1, 2, 3, 4, 5, 6

Example

With all of that explained, I can show a full, working example. As before, add this code to the base code in the blank spot in the WxPerlComExampleFrame constructor.

# Create menus
# Action's sub menu
my $submenu = Wx::Menu->new();
$submenu->Append($id[2], "New normal item");
$submenu->Append($id[3], "Delete normal item");
$submenu->AppendSeparator();
$submenu->Append($id[4], "New check item");
$submenu->Append($id[5], "Delete check item");
$submenu->AppendSeparator();
$submenu->Append($id[6], "New radio item");
$submenu->Append($id[7], "Delete radio item");

# Disable items for this submenu
for(2..7) {
    $submenu->Enable($id[$_], 0);
}

# Actions menu
my $actionmenu = Wx::Menu->new();
$actionmenu->Append($id[0], "Create Menu"); # Create new menu
$actionmenu->Append($id[1], "Delete Menu"); # Delete New Menu
$actionmenu->AppendSeparator();
$actionmenu->AppendSubMenu($id[100], "New Item", $submenu); # Create item submenu
$actionmenu->AppendSeparator();
$actionmenu->Append(wxID_EXIT, "Exit\tCtrl+X"); # Exit

# At first, disable the Delete Menu option
$actionmenu->Enable($id[1], 0);

# Create menu bar
$self->{MENU} = Wx::MenuBar->new();
$self->{MENU}->Append($actionmenu, "Actions");

# Attach menubar to the window
$self->SetMenuBar($self->{MENU});
$self->SetAutoLayout(1);

# Handle events
EVT_MENU($self, $id[0], \&MakeActionMenu);
EVT_MENU($self, $id[1], \&MakeActionMenu);
EVT_MENU($self, $id[2], \&MakeActionNormal);
EVT_MENU($self, $id[3], \&MakeActionNormal);
EVT_MENU($self, $id[4], \&MakeActionCheck);
EVT_MENU($self, $id[5], \&MakeActionCheck);
EVT_MENU($self, $id[6], \&MakeActionRadio);
EVT_MENU($self, $id[7], \&MakeActionRadio);

EVT_MENU($self, wxID_EXIT, sub {$_[0]->Close(1)});

This code creates a menu called Actions with the following options inside:

  • Create Menu: When a user clicks this option, the program creates a new menu called New Menu at the right side of the Actions menu. The Create Menu option is enabled by default, but creating the menu disables this option.
  • Delete Menu: Deletes the menu created with Create Menu. This option is disabled by default and is enabled when New Menu exists.
  • New normal item: This option creates the Normal item option on New Menu when it exists. It is disabled by default.
  • Delete normal item: Deletes Normal item when it exists. It is disabled by default.
  • New check item: Creates the Check item option on New Menu when it exists. It is disabled by default. Check item is unchecked by default.
  • Delete check item: Deletes Check item when it exists. It is disabled by default.
  • New radio item: Creates the Radio item option on New Menu when it exists. It is disabled by default. Radio item is checked by default.
  • Delete radio item: Deletes Radio item when it exists. It is disabled by default.
  • Exit: Exits the program.

Once the code has created the menu, it attaches the menu to the menu bar saved on $self->{MENU}, then calls the EVT_MENU subroutine eight times to handle all of the menu events from Action's menu items. Add the following code to the base code where it says ### PUT SUBROUTINES HERE ###:

# Subroutine that handles menu creation/erasure
sub MakeActionMenu {
    my($self, $event) = @_;

    # Get Actions menu
    my $actionmenu    = $self->{MENU}->GetMenu(0);

    # Now check if we have to create or delete the New Menu
    if ($self->{MENU}->GetMenuCount() == 1) {
        # New Menu doesn't exist

        # Create menu
        my $newmenu = Wx::Menu->new();
        $self->{MENU}->Append($newmenu, "New Menu");       

        # Disable and Enable options
        $actionmenu->Enable($id[0], 0); # New menu
        $actionmenu->Enable($id[1], 1); # Delete menu
        $actionmenu->Enable($id[2], 1); # New normal item
        $actionmenu->Enable($id[3], 0); # Delete normal item
        $actionmenu->Enable($id[4], 1); # New check item
        $actionmenu->Enable($id[5], 0); # Delete check item
        $actionmenu->Enable($id[6], 1); # New radio item
        $actionmenu->Enable($id[7], 0); # Delete radio item
    } else {
        # New Menu exists

        # Remove menu
       $self->{MENU}->Remove(1);

        # Enable and disable options
        $actionmenu->Enable($id[0], 1);

        for(1..7) {
               $actionmenu->Enable($id[$_], 0);
        }
    }

    return 1;
}

# Subroutine that handles normal item creation/erasure
sub MakeActionNormal {
    my($self, $event) = @_;
    # Check if New Menu exists
    if($self->{MENU}->GetMenuCount() == 2) {
        # New menu exists

        # Get Action menu
        my $actionmenu = $self->{MENU}->GetMenu(0);
        my $newmenu    = $self->{MENU}->GetMenu(1);

        # Check if we have to create or delete a menu item
        if($actionmenu->IsEnabled($id[2])) {
            # Create normal menu item
            $newmenu->Append($id[50], "Normal item");           

            # Disable and Enable options
            $actionmenu->Enable($id[2], 0);
            $actionmenu->Enable($id[3], 1);
        } else {
            # Delete menu item
               $newmenu->Delete($id[50]);

            # Enable and disable options
            $actionmenu->Enable($id[2], 1);
            $actionmenu->Enable($id[3], 0);
        }
    }

    return 1;
}

# Subroutine that handles check item creation/erasure
sub MakeActionCheck {
    my($self, $event) = @_;

    # Check if New Menu exists
    if($self->{MENU}->GetMenuCount() == 2) {
        # New menu exists

        # Get Action menu
        my $actionmenu = $self->{MENU}->GetMenu(0);
        my $newmenu    = $self->{MENU}->GetMenu(1);

        # Check if we have to create or delete a menu item
        if($actionmenu->IsEnabled($id[4])) {
            # Create check item
               $newmenu->AppendCheckItem($id[51], "Check item");

           # Disable and Enable options
           $actionmenu->Enable($id[4], 0);
           $actionmenu->Enable($id[5], 1);
        } else {
           # Delete menu item
           $newmenu->Delete($id[51]);

              # Enable and disable options
              $actionmenu->Enable($id[4], 1);
              $actionmenu->Enable($id[5], 0);
        }
    }

    return 1;
}

# Subroutine that handles radio item creation/erasure

sub MakeActionRadio {
    my($self, $event) = @_;

    # Check if New Menu exists
    if($self->{MENU}->GetMenuCount() == 2) {
        # New menu exists

        # Get Action menu
        my $actionmenu = $self->{MENU}->GetMenu(0);
        my $newmenu    = $self->{MENU}->GetMenu(1);

        # Check if we have to create or delete a menu item
        if ($actionmenu->IsEnabled($id[6])) {
               # Create radio item
              $newmenu->AppendRadioItem($id[52], "Radio item");

              # Disable and Enable options
              $actionmenu->Enable($id[6], 0);
              $actionmenu->Enable($id[7], 1);
        } else {
              # Delete menu item
              $newmenu->Delete($id[52]);

              # Enable and disable options
              $actionmenu->Enable($id[6], 1);
              $actionmenu->Enable($id[7], 0);
        }
    }

    return 1;
}

The MakeActionMenu subroutine handles events for the New Menu and Delete Menu items. It first gets the Actions menu and checks whether the New Menu exists by retrieving the number of menus attached to the $self->{MENU} menu bar. If the new menu doesn't exist, the number of menus in the menu bar is equal to 1, and the subroutine then creates New Menu. If it exists, the subroutine deletes New Menu.

The MakeActionNormal, MakeActionCheck, and MakeActionRadio subroutines are almost identical. They differ only in the involved identifier numbers. These subroutines handle events for New normal item, Delete normal item, New check item, Delete check item, New radio item, and Delete radio item, respectively. They first check if New Menu exists (the number of menus attached to the menu bar is equal to 2). If so, they check if the options to create normal, check, or radio items are enabled, respectively. If the corresponding option is enabled, then the corresponding item doesn't exist on New Menu, and the subroutine creates it. If the option to create an item is disabled, then that item exists on New Menu and hence it must be deleted. If New Menu doesn't exist, the subroutines do nothing. Figure 3 shows how there are no options available if New Menu does not exist, and Figure 4 shows New Menu with two options added.

no available options without New Menu
Figure 3. No available options without New Menu

New Menu has menu options
Figure 4. New Menu has menu options

Conclusion

As this article has shown, menu programming with wxPerl is an extremely simple task. Wx::MenuBar and Wx::Menu's methods are very easy to use and remember. If you understood this article, you can do anything possible with menus in your wxPerl programs.

I have covered almost all of the available methods in Wx::Menu and Wx::MenuBar. I left out some methods related to pop-up menus, but I hope to cover these topics in future articles. WxPerl is a really great module, but its lack of adoption is due to its severe lack of documentation. This situation must be reversed, and this article is a small contribution to that cause.

See Also