Source

Kephra / lib / Kephra / App / Menu.pm

use strict;
use warnings;
use v5.10;
use Wx;

use Kephra::API;


package Kephra::App::Menu;

my $lowest_free_menu_ID = 1000;
my %storage;

# build ready to compile data structure from menu definitions (list of commandID)
sub assemble {
	my ($menu_def, $parents) = @_;
	Kephra::Log::warning('got no array ref as definition') unless ref $menu_def eq 'ARRAY';
	my $menu_name = '';
	my @menu_data;
	$parents = [] unless ref $parents eq 'ARRAY' and $parents->[0];

	for my $item_def (@$menu_def) {
		if    (ref $item_def eq 'ARRAY') { 
			push  @menu_data, assemble($item_def, [@$parents, $menu_name]) 
		}
		elsif (ref $item_def eq 'HASH') {
			$menu_name = $item_def->{'section_name'}
				if defined $item_def->{'section_name'} and not $menu_name;
			push  @menu_data, $item_def;
		}
		elsif (not defined $item_def or not $item_def) {
			push  @menu_data, {'type' => 'separator'};
		} else  {
			my $first_chr = substr($item_def, 0, 1);
			if    ($first_chr eq '+') {$item_def = join('-', @$parents, $menu_name).substr($item_def, 1)}
			elsif ($first_chr eq '-') {$item_def = join('-', @$parents)          .substr($item_def, 1)}

			my $cmd_data = Kephra::API::Command::all_properties( $item_def );
			next unless ref $cmd_data;
			push @menu_data, {
				'type' => 'item',
				'label'=> ucfirst $cmd_data->{'label'},
				'coderef' => $cmd_data->{'coderef'},
			};
		}
	}
	return \@menu_data;
}

# make real menus from assembled  datastructure
sub compile {
	my $menu_data = shift;
	Kephra::Log::warning('got no array ref') unless ref $menu_data eq 'ARRAY';
	my $item_ID = $lowest_free_menu_ID += 100;
	my $win = Kephra::API::main_window();
	my $menu = Wx::Menu->new();

	for my $item_data (@$menu_data) {
		if (ref $item_data eq 'ARRAY') {
			my ($submenu, $name) = compile( $item_data );
			my $item = Wx::MenuItem->new(
				$menu, $item_ID++, $name, ' ', &Wx::wxITEM_NORMAL, $submenu
			);
			$menu->Append( $item );
		}
		elsif (ref $item_data eq 'HASH' and exists $item_data->{'type'}) {
			if ($item_data->{'type'} eq 'item'){
				my $item = Wx::MenuItem->new(
					$menu, $item_ID, $item_data->{'label'}, ' ', &Wx::wxITEM_NORMAL
				);
				if (defined $item_data->{'bitmap'}) {
					$item->SetBitmap( $item_data->{'bitmap'} ) 
						if ref $item_data->{'bitmap'} eq 'Wx::Bitmap' and not Wx::wxMAC();
				}
				Wx::Event::EVT_MENU( $win, $item_ID, $item_data->{'coderef'} );
				$menu->Append( $item );
				$item_ID++;
			} elsif ($item_data->{'type'} eq 'separator'){
				$menu->AppendSeparator;
			} else { }
		}
	}
	return wantarray
		? ($menu, ucfirst $menu_data->[0]{'section_name'})
		:  $menu;
}

1;
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.