package Padre::Wx::Dialog::PluginManager;
use 5.010;
use strict;
use warnings;
no if $] > 5.017010, warnings => 'experimental::smartmatch';
use Padre::Wx::Util ();
use Padre::Wx::Icon ();
use Padre::Wx::FBP::PluginManager ();
use Padre::Locale::T;
use Try::Tiny;
our $VERSION = '1.00';
our @ISA = 'Padre::Wx::FBP::PluginManager';
use constant {
RED => Wx::Colour->new('red'),
DARK_GREEN => Wx::Colour->new( 0x00, 0x90, 0x00 ),
BLUE => Wx::Colour->new('blue'),
GRAY => Wx::Colour->new('gray'),
DARK_GRAY => Wx::Colour->new( 0x7f, 0x7f, 0x7f ),
BLACK => Wx::Colour->new('black'),
};
######################################################################
# Class Methods
#####
sub run {
my $class = shift;
my $self = $class->new(@_);
$self->ShowModal;
$self->Destroy;
return 1;
}
######################################################################
# Constructor
#####
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->{handle} = 'empty';
# This is a core dialog so apply the Padre icon
$self->SetIcon(Padre::Wx::Icon::PADRE);
# Prepare to be shown
$self->SetSize( [ 760, 480 ] );
$self->CenterOnParent;
# TODO Active should be droped, just on show for now
# Setup columns names, Active should be droped, just and order here
# my @column_headers = qw( Path Line Active ); do not remove
my @column_headers = ( 'Plug-in Name', 'Version', 'Status', 'Plug-in Class' );
my $index = 0;
for my $column_header (@column_headers) {
$self->{list}->InsertColumn( $index++, Wx::gettext($column_header) );
}
# Select the first item in CrtList
$self->{list_focus} = 0;
# Image List
$self->{imagelist} = Wx::ImageList->new( 16, 16, 1 );
$self->{list}->AssignImageList(
$self->{imagelist},
Wx::IMAGE_LIST_SMALL,
);
# Do an initial refresh of the plugin list_two
$self->refresh;
$self->refresh_plugin;
return $self;
}
######################################################################
# Event Handlers
sub refresh_plugin {
my $self = shift;
my $handle = $self->selected or return;
# Update the basic fields
SCOPE: {
my $lock = $self->lock_update;
# Update the details fields
$self->{plugin_name}->SetLabel( $handle->plugin_name );
$self->{plugin_version}->SetLabel( $handle->plugin_version );
$self->{plugin_status}->SetLabel( $handle->status_localized );
# Only show the preferences button if the plugin has them
if ( $handle->plugin_can('plugin_preferences') ) {
$self->{preferences}->Show;
} else {
$self->{preferences}->Hide;
}
# Update the action button
if ( $handle->error or $handle->incompatible ) {
$self->{action}->{method} = 'explain_selected';
$self->{action}->SetLabel( Wx::gettext('&Show Error Message') );
$self->{action}->Enable;
$self->{preferences}->Disable;
} elsif ( $handle->enabled ) {
$self->{action}->{method} = 'disable_selected';
$self->{action}->SetLabel( Wx::gettext('&Disable') );
$self->{action}->Enable;
$self->{preferences}->Disable;
} elsif ( $handle->can_enable ) {
$self->{action}->{method} = 'enable_selected';
$self->{action}->SetLabel( Wx::gettext('&Enable') );
$self->{action}->Enable;
$self->{preferences}->Enable;
} else {
$self->{action}->{method} = 'enable_selected';
$self->{action}->SetLabel( Wx::gettext('&Enable') );
$self->{action}->Disable;
$self->{preferences}->Disable;
}
# Update the layout for the changed interface
$self->{details}->Layout;
}
# Find the documentation
require Padre::Browser;
my $browser = Padre::Browser->new;
my $class = $handle->class // 'Padre::Plugin::My';
my $doc = $browser->resolve($class);
# Render the documentation.
# TODO Convert this to a background task later
local $@;
my $output = eval { $browser->browse($doc) };
my $html =
$@
? sprintf(
Wx::gettext("Error loading pod for class '%s': %s"),
$class,
$@,
)
: $output->body;
$self->{whtml}->SetPage($html);
return 1;
}
sub action_clicked {
my $self = shift;
# say 'in action_clicked';
my $method = $self->{action}->{method} or return;
# p $method;
# p $self->$method();
$self->$method();
}
sub preferences_clicked {
my $self = shift;
my $handle = $self->selected or return;
# p $handle;
# my $handle = $self->handle or return;
$handle->plugin_preferences;
}
######################################################################
# Main Methods
sub refresh {
my $self = shift;
# Clear image list & fill it again
$self->{imagelist}->RemoveAll;
# Default plug-in icon
$self->{imagelist}->Add( Padre::Wx::Icon::find('status/padre-plugin') );
# Clear ListCtrl items
$self->{list}->DeleteAllItems;
my $index = 0;
# Fill the list_two from the plugin handles
foreach my $handle ( $self->ide->plugin_manager->handles ) {
if ( $self->{handle} eq 'empty' ) {
if ( $handle->plugin_name eq 'My Plugin' ) {
$self->{handle} = $handle;
}
}
# Check if plug-in is supplying its own icon
my $position = 0;
my $icon = $handle->plugin_icon;
if ( defined $icon ) {
$self->{imagelist}->Add($icon);
$position = $self->{imagelist}->GetImageCount - 1;
}
# Inserting the plug-in in the list
$self->{list}->InsertStringImageItem(
$index,
$handle->plugin_name,
$position,
);
given ( $handle->status ) {
when ( $_ eq 'enabled' ) { $self->{list}->SetItemTextColour( $index, BLUE ); }
when ( $_ eq 'disabled' ) { $self->{list}->SetItemTextColour( $index, BLACK ); }
when ( $_ eq 'incompatible' ) { $self->{list}->SetItemTextColour( $index, DARK_GRAY ); }
when ( $_ eq 'error' ) { $self->{list}->SetItemTextColour( $index, RED ); }
}
# $self->{list}->SetItem( $index, 0, $handle->plugin_name );
$self->{list}->SetItem( $index, 1, $handle->plugin_version || '???' );
$self->{list}->SetItem( $index, 2, $handle->status );
$self->{list}->SetItem( $index++, 3, $handle->class );
# Tidy the list
Padre::Wx::Util::tidy_list( $self->{list} );
}
# Select the current list item
if ( $self->{list}->GetItemCount > 0 ) {
$self->{list}->SetItemState( $self->{list_focus}, Wx::LIST_STATE_SELECTED, Wx::LIST_STATE_SELECTED );
$self->{list}->EnsureVisible( $self->{list_focus} );
}
return 1;
}
sub enable_selected {
my $self = shift;
my $handle = $self->selected or return;
my $lock = $self->main->lock( 'DB', 'refresh_menu_plugins' );
$self->ide->plugin_manager->user_enable($handle);
$self->refresh;
$self->refresh_plugin;
}
sub disable_selected {
my $self = shift;
my $handle = $self->selected or return;
my $lock = $self->main->lock( 'DB', 'refresh_menu_plugins' );
$self->ide->plugin_manager->user_disable($handle);
$self->refresh;
$self->refresh_plugin;
}
sub explain_selected {
my $self = shift;
my $handle = $self->selected or return;
# @INC gets printed out between () remove that for now
my $message = $handle->errstr;
$message =~ s/\(\@INC.*\)//;
# Show the message box
Wx::MessageBox(
$message,
Wx::gettext('Error'),
Wx::OK | Wx::CENTRE,
$self,
);
}
#######
# Event Handler _on_list_item_selected
#######
sub _on_list_item_selected {
my $self = shift;
my $event = shift;
$self->{list_focus} = $event->GetIndex; # zero based
my $plugin_name = $event->GetText;
my $module_name;
# Find the plugin module given plugin name
foreach my $handle ( $self->ide->plugin_manager->handles ) {
if ( $handle->plugin_name eq $plugin_name ) {
$module_name = $handle->class;
}
}
$self->{handle} = $self->ide->plugin_manager->handle($module_name);
$self->refresh_plugin;
return 1;
}
######################################################################
# Support Methods
sub selected {
my $self = shift;
if ( defined $self->{handle} ) {
return $self->{handle};
} else {
return 0;
}
}
1;
__END__
=pod
=head1 NAME
Padre::Wx::Dialog::PluginManager - Padre Plug-in Manager Dialog
=head1 SYNOPSIS
Padre::Wx::Dialog::PluginManager->run($main);
=head1 DESCRIPTION
Padre will have a lot of plug-ins. First plug-in manager was not taking
this into account, and the first plug-in manager window was too small &
too crowded to show them all properly.
This revamped plug-in manager is now using a list_two control, and thus can
show lots of plug-ins in an effective manner.
Upon selection, the right pane will be updated with the plug-in name &
plug-in documentation. Two buttons will allow to de/activate the plug-in
(or see plug-in error message) and set plug-in preferences.
=head1 COPYRIGHT & LICENSE
Copyright 2008-2013 The Padre development team as listed in Padre.pm.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl 5 itself.
=cut
# Copyright 2008-2013 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.