The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Padre::Wx::Menu;

# Implements additional functionality to support richer menus

use 5.008;
use strict;
use warnings;
use Padre::Current    ();
use Padre::Wx::Action ();
use Padre::Wx         ();

use Class::Adapter::Builder
	ISA      => 'Wx::Menu',
	NEW      => 'Wx::Menu',
	AUTOLOAD => 'PUBLIC';

our $VERSION = '0.96';

use Class::XSAccessor {
	getters => {
		wx => 'OBJECT',
	}
};

# Default implementation of refresh
sub refresh {1}

# Overrides and then calls XS wx Menu::Append.
# Adds any hotkeys to global registry of bound keys
sub Append {
	my $self  = shift;
	my $item  = $self->wx->Append(@_);
	my $label = $item->GetLabel;
	my ($underlined) = ( $label =~ m/(\&\w)/ );
	my ($accel)      = ( $label =~ m/(Ctrl-.+|Alt-.+)/ );
	if ( $underlined or $accel ) {
		$self->{main}->{accel_keys} ||= {};
		if ($underlined) {
			$underlined =~ s/&(\w)/$1/;
			$self->{main}->{accel_keys}->{underlined}->{$underlined} = $item;
		}
		if ($accel) {
			my ( $mod, $mod2, $key ) = ( $accel =~ m/(Ctrl|Alt)(-Shift)?\-(.)/ );
			$mod .= $mod2 if ($mod2);
			$self->{main}->{accel_keys}->{hotkeys}->{ uc($mod) }->{ ord( uc($key) ) } = $item;
		}
	}
	return $item;
}

# Add a normal menu item to menu from a existing Padre action
sub add_menu_action {
	my $self    = shift;
	my $menu    = ( @_ > 1 ) ? shift : $self;
	my $name    = shift;
	my $actions = $self->{main}->ide->actions;
	my $action  = $actions->{$name} or return 0;
	my $method  = $action->menu_method || 'Append';

	my $item = $menu->$method(
		$action->id,
		$action->label_menu,
	);

	my $comment = $action->comment;
	$item->SetHelp($comment) if $comment;

	Wx::Event::EVT_MENU(
		$self->{main},
		$item,
		$action->menu_event,
	);

	return $item;
}

# Add a series of radio menu items for a configuration variable
sub append_config_options {
	my $self   = shift;
	my $menu   = shift;
	my $name   = shift;
	my $config = $self->{main}->config;
	my $old    = $config->$name();

	# Get the set of (sorted) options
	my $options = $config->meta($name)->options;
	my @list = sort { $a->[1] cmp $b->[1] } map { [ $_, Wx::gettext( $options->{$_} ) ] } keys %$options;

	# Add the menu items
	foreach my $option (@list) {
		my $radio = $menu->AppendRadioItem( -1, $option->[1] );
		my $new = $option->[0];
		if ( $new eq $old ) {
			$radio->Check(1);
		}
		Wx::Event::EVT_MENU(
			$self->{main},
			$radio,
			sub {
				$_[0]->config->apply( $name => $new );
			},
		);
	}

	return;
}

# Add a normal menu item to change a configuration variable, not in use.
sub append_config_option {
	my $self  = shift;
	my $menu  = shift;
	my $name  = shift;
	my $new   = shift;
	my $label = shift;

	# Create the menu item
	my $item = $menu->Append( -1, $label );

	# Are we already set to this value?
	my $old = $self->{main}->config->$name();
	if ( $new eq $old ) {
		$item->Enable(0);

	} else {
		Wx::Event::EVT_MENU(
			$self->{main},
			$item,
			sub {
				$_[0]->config->apply( $name => $new );
			},
		);
	}

	return $item;
}

sub build_menu_from_actions {
	my $self    = shift;
	my $main    = shift;
	my $actions = shift;
	my $label   = $actions->[0];
	$self->{main} = $main;
	$self->_menu_actions_submenu( $main, $self->wx, $actions->[1] );
	return ( $label, $self->wx );
}

# Very Experimental !!!
sub _menu_actions_submenu {
	my $self  = shift;
	my $main  = shift;
	my $menu  = shift;
	my $items = shift;
	unless ( $items and ref $items and ref $items eq 'ARRAY' ) {
		Carp::cluck("Invalid list of actions in plugin");
		return;
	}

	# Fill the menu
	while (@$items) {
		my $value = shift @$items;

		# Separator
		if ( $value eq '---' ) {
			$menu->AppendSeparator;
			next;
		}

		# Array Reference (submenu)
		if ( Params::Util::_ARRAY0($value) ) {
			my $label = shift @$value;
			if ( not defined $label ) {
				Carp::cluck("No label in action sublist");
				next;
			}

			my $submenu = Wx::Menu->new;
			$menu->Append( -1, $label, $submenu );
			$self->_menu_actions_submenu( $main, $submenu, $value );
			next;
		}

		# Action name
		$self->{"menu_$value"} = $self->add_menu_action(
			$menu,
			$value,
		);
	}

	return;
}

1;

# Copyright 2008-2012 The Padre development team as listed in Padre.pm.
# LICENSE
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl 5 itself.