Changeset 2226


Ignore:
Timestamp:
12/28/08 15:59:41 (3 years ago)
Author:
adamk
Message:

Third refactoring pass over the PluginManager?. This pass kills the unweildy state hash that caused lots of expressions like if ( $self->{plugins}->{$name} and $self->{plugins}->{$name}->{status} and $self->{plugins}->{$name}->{status} eq 'loaded' ).

The state hash is replaced with a full blown PluginHandle? object, that encapsulates the PluginManager?'s interactions with a single Plugin (leaving the PluginManager? to deal with interactions between plugins and the rest of the applications).

Location:
trunk/Padre/lib/Padre
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Padre/lib/Padre/PluginManager.pm

    r2184 r2226  
    11package Padre::PluginManager; 
     2 
     3# API NOTES: 
     4# This class uses english-style verb_noun method naming 
    25 
    36=pod 
     
    1821use strict; 
    1922use warnings; 
    20 use Carp                     qw(croak); 
     23use Carp                     qw{croak}; 
    2124use File::Path               (); 
    2225use File::Spec               (); 
    23 use Params::Util             qw{_INSTANCE}; 
     26use Scalar::Util             (); 
     27use Params::Util             qw{_IDENTIFIER _CLASS _INSTANCE}; 
    2428use Padre::Util              (); 
     29use Padre::PluginHandle      (); 
    2530use Padre::Wx                (); 
    2631use Padre::Wx::Menu::Plugins (); 
     
    5762 
    5863    my $self = bless { 
    59         parent     => $parent, 
    60         plugins    => {}, 
    61         plugin_dir => Padre::Config->default_plugin_dir, 
    62         par_loaded => 0, 
     64        parent       => $parent, 
     65        plugins      => {}, 
     66        plugin_names => [], 
     67        plugin_dir   => Padre::Config->default_plugin_dir, 
     68        par_loaded   => 0, 
    6369        @_, 
    6470    }, $class; 
     
    8187=head2 plugins 
    8288 
    83 Returns a hash (reference) of plugin names associated with a plugin manager 
    84 internal structure describing the state of the plugin in the current 
    85 editor. The contents are somewhat in flux and considered mostly B<PRIVATE>, 
    86 but the following will likely stay: 
    87  
    88 =over 2 
    89  
    90 =item module 
    91  
    92 Full name of the module that implements the plugin, i.e. C<Padre::Plugin::Foo>. 
    93  
    94 =item status 
    95  
    96 The status of the plugin. C<failed> indicates failure while trying to load 
    97 the module. C<new> indicates it was detected as a new plugin. 
    98 C<loaded> indicates that the module has been successfully loaded, and 
    99 C<disabled> indicates that it isn't being used as it's been disabled 
    100 in the configuration. 
    101  
    102 Note that this concerns the status of the module in memory. Whether or 
    103 not to load the plugin is kept in the B<configuration> instead to make 
    104 it persistent. To check whether a given plugin is enabled, do this: 
    105  
    106   if ( Padre->ide->config->{plugins}->{$name}->{enabled} ) {...} 
    107  
    108 =item object 
    109  
    110 The actual C<Padre::Plugin::Foo> object. Availability depends on the C<status>, 
    111 of course. The other keys are kept separate since the plugin object is the 
    112 sole domain of the plugin writer. We don't want them to wreak havoc on 
    113 our meta data, now do we? 
    114  
    115 =back 
     89Returns a hash (reference) of plugin names associated with a 
     90L<Padre::PluginHandle>. 
    11691 
    11792This hash is only populated after C<load_plugins()> was called. 
     
    126101    }; 
    127102 
     103# Get the prefered plugin order. 
     104# The order calculation cost is higher than we might like, 
     105# so cache the result. 
     106sub plugin_names { 
     107    my $self = shift; 
     108    unless ( $self->{plugin_names} ) { 
     109        $self->{plugin_names} = [ 
     110            sort { 
     111                ($b->name eq 'My') <=> ($a->name eq 'My') 
     112                or 
     113                $a->name cmp $b->name 
     114            } 
     115            values %{ $self->{plugins} } 
     116        ]; 
     117    } 
     118    return @{ $self->{plugin_names} }; 
     119} 
     120 
     121sub plugin_objects { 
     122    grep { $_[0]->{plugins}->{$_} } $_[0]->plugin_names; 
     123} 
     124 
    128125 
    129126 
     
    131128 
    132129##################################################################### 
    133 # Configuration and Startup 
    134  
    135 =pod 
    136  
    137 =head2 plugin_config 
    138  
    139 Given a plugin name or namespace, returns a hash reference 
    140 which corresponds to the configuration section in the Padre 
    141 YAML configuration of that plugin. Any modifications of that 
    142 hash reference will, on normal exit, be written to the 
    143 configuration file. 
    144  
    145 If the plugin name is omitted and this method is called from 
    146 a plugin namespace, the plugin name is determine automatically. 
    147  
    148 =cut 
    149  
    150 sub plugin_config { 
    151     my $self   = shift; 
    152     my $plugin = shift; 
    153  
    154     # infer the plugin name from caller 
    155     unless ( defined $plugin ) { 
    156         my ($package) = caller(); 
    157         croak("Cannot infer the name of the plugin for which the configuration has been requested") 
    158             if $package !~ /^Padre::Plugin::/; 
    159         $plugin = $package; 
    160     } 
    161  
    162     $plugin =~ s/^Padre::Plugin:://; 
    163     my $config  = $self->parent->config; 
    164     my $plugins = $config->{plugins}; 
    165     $plugins->{$plugin} ||= {}; 
    166     return $plugins->{$plugin}; 
     130# Bulk Plugin Operations 
     131 
     132=pod 
     133 
     134=head2 reload_plugins 
     135 
     136For all registered plugins, unload them if they were loaded 
     137and then reload them. 
     138 
     139=cut 
     140 
     141sub reload_plugins { 
     142    my $self    = shift; 
     143    my $plugins = $self->plugins; 
     144    foreach my $name ( sort keys %$plugins ) { 
     145        # do not use the reload_plugin method since that 
     146        # refreshes the menu every time. 
     147        $self->_unload_plugin($name); 
     148        $self->_load_plugin($name); 
     149        $self->enable_editors($name); 
     150    } 
     151    $self->_refresh_plugin_menu; 
     152    return 1; 
    167153} 
    168154 
     
    208194    # Try the plugin directory first: 
    209195    my $plugin_dir = $self->plugin_dir; 
    210     unshift @INC, $plugin_dir unless grep { $_ eq $plugin_dir } @INC; 
    211      
    212     my @dirs = grep {-d $_} map {File::Spec->catdir($_, 'Padre', 'Plugin')} @INC; 
     196    unless ( grep { $_ eq $plugin_dir } @INC ) { 
     197        unshift @INC, $plugin_dir; 
     198    } 
     199 
     200    my @dirs = grep { -d $_ } map { File::Spec->catdir($_, 'Padre', 'Plugin') } @INC; 
    213201 
    214202    require File::Find::Rule; 
    215203    my @files = File::Find::Rule->file->name('*.pm')->maxdepth(1)->in( @dirs ); 
    216     foreach my $file (@files) { 
     204    foreach my $file ( @files ) { 
    217205        # Full path filenames 
    218206        my $module = $file; 
     
    229217        } 
    230218 
    231         # caller must refresh plugin menu 
    232         $self->_load_plugin_norefresh_menu($module); 
     219        # Caller must refresh plugin menu 
     220        $self->_load_plugin($module); 
    233221    } 
    234222 
    235223    return; 
    236224} 
     225 
     226=pod 
     227 
     228=head2 alert_new 
     229 
     230The C<alert_new> method is called by the main window post-init and 
     231checks for new plugins. If any are found, it presents a message to 
     232the user. 
     233 
     234=cut 
     235 
     236sub alert_new { 
     237    my $self    = shift; 
     238    my $plugins = $self->plugins; 
     239    my @loaded  = sort 
     240        map  { $_->plugin_name } 
     241        grep { $_->loaded      } 
     242        values %$plugins; 
     243    if ( @loaded and not $ENV{HARNESS_ACTIVE} ) { 
     244        my $msg = Wx::gettext(<<"END_MSG") . join("\n", @loaded); 
     245We found several new plugins. 
     246In order to configure and enable them go to 
     247Plugins -> Plugin Manager 
     248 
     249List of new plugins: 
     250 
     251END_MSG 
     252 
     253        $self->parent->wx->main_window->message( $msg, 
     254            Wx::gettext('New plugins detected') 
     255        ); 
     256    } 
     257 
     258    return 1; 
     259} 
     260 
     261=pod 
     262 
     263=head2 failed 
     264 
     265Returns the plugin names (without C<Padre::Plugin::> prefixed) of all plugins 
     266that the editor attempted to load but failed. Note that after a failed 
     267attempt, the plugin is usually disabled in the configuration and not loaded 
     268again when the editor is restarted. 
     269 
     270=cut 
     271 
     272sub failed { 
     273    my $self    = shift; 
     274    my $plugins = $self->plugins; 
     275    return grep { 
     276        $plugins->{$_}->{status} eq 'failed' 
     277    } keys %$plugins; 
     278} 
     279 
     280 
     281 
     282 
     283 
     284###################################################################### 
     285# PAR Integration 
    237286 
    238287# Attempt to load all plugins that sit as .par files in the 
     
    252301            $file =~ s/-/::/g; 
    253302 
    254             # caller must refresh plugin menu 
    255             $self->_load_plugin_norefresh_menu($file); 
     303            # Caller must refresh plugin menu 
     304            $self->_load_plugin($file); 
    256305        } 
    257306    } 
     
    266315    return if $self->{par_loaded}; 
    267316 
     317    # Setup the PAR environment: 
    268318    require PAR; 
    269     # setup the PAR environment: 
    270319    my $plugin_dir = $self->plugin_dir; 
    271320    my $cache_dir  = File::Spec->catdir($plugin_dir, 'cache'); 
     
    275324 
    276325    $self->{par_loaded} = 1; 
    277     return(); 
    278 } 
     326} 
     327 
     328 
     329 
     330 
     331###################################################################### 
     332# Loading and Unloading a Plugin 
    279333 
    280334=pod 
     
    290344sub load_plugin { 
    291345    my $self = shift; 
    292     my $ret = $self->_load_plugin_norefresh_menu(@_); 
     346    my $ret = $self->_load_plugin(@_); 
    293347    $self->_refresh_plugin_menu; 
    294348    return $ret; 
    295349} 
    296350 
    297 # The guts of load_plugin which don't refresh the menu 
    298 sub _load_plugin_norefresh_menu { 
    299     my $self    = shift; 
    300     my $name    = shift; 
    301     my $config  = $self->parent->config; 
    302     my $plugins = $self->plugins; 
    303  
    304     # Skip if that plugin was already loaded 
     351# This method implements the actual mechanics of loading a plugin, 
     352# without regard to the context it is being called from. 
     353# So this method doesn't do stuff like refresh the plugin menu. 
     354# 
     355# MAINTAINER NOTE: This method looks fairly long, but it's doing 
     356# a very specific and controlled series of steps. Splitting this up 
     357# would just make the process hardner to understand, so please don't. 
     358sub _load_plugin { 
     359    my $self = shift; 
     360    my $name = shift; 
     361 
     362    # If this plugin is already loaded, shortcut and skip 
    305363    $name =~ s/^Padre::Plugin:://; 
    306     if ( $plugins->{$name} and $plugins->{$name}->{status} eq 'enabled' ) { 
    307         return; 
    308     } 
    309  
    310     $plugins->{$name} ||= {}; 
    311     my $state  = $plugins->{$name}; 
    312     my $module = $state->{module} = "Padre::Plugin::$name"; 
     364    if ( $self->plugins->{$name} ) { 
     365        return; 
     366    } 
     367 
     368    # Create the plugin object (and flush the old sort order) 
     369    my $module = "Padre::Plugin::$name"; 
     370    my $plugin = $self->{plugins}->{$name} = Padre::PluginHandle->new( 
     371        name  => $name, 
     372        class => $module, 
     373    ); 
     374    delete $self->{plugin_names}; 
    313375 
    314376    # Does the plugin load without error 
    315     eval "use $module"; ## no critic 
     377    my $code = "use $module ();"; 
     378    eval $code; ## no critic 
    316379    if ( $@ ) { 
    317380        $self->{errstr} = sprintf( 
     
    322385            $@, 
    323386        ); 
    324         $state->{status} = 'failed'; 
     387        $plugin->status('failed'); 
    325388        return; 
    326389    } 
     
    334397            ), $name, 
    335398        ); 
    336         $state->{status} = 'failed'; 
     399        $plugin->status('failed'); 
    337400        return; 
    338401    } 
     
    346409            ), $name, 
    347410        ); 
    348         $state->{status} = 'failed'; 
     411        $plugin->status('failed'); 
    349412        return; 
    350413    } 
     
    359422            $name, 
    360423        ); 
    361         $state->{status} = 'failed'; 
     424        $plugin->status('failed'); 
    362425        return; 
    363426    } 
     
    368431        # TODO report error in a nicer way 
    369432        $self->{errstr} = $@; 
    370         $state->{status} = 'failed'; 
     433        $plugin->status('failed'); 
    371434        return; 
    372435    } 
     
    379442            $name, 
    380443        ); 
    381         $state->{status} = 'failed'; 
    382         return; 
    383     } 
    384     $state->{object} = $object; 
     444        $plugin->status('failed'); 
     445        return; 
     446    } 
     447    $self->{object} = $object; 
    385448 
    386449    # Should we try to enable the plugin 
    387     unless ( $config->{plugins}->{$name} ) { 
     450    my $config = $self->plugin_config($plugin); 
     451    unless ( defined $config->{enabled} ) { 
    388452        # Do not enable by default 
    389         $config->{plugins}->{$name}->{enabled} = 0; 
    390         $state->{status} = 'new'; 
    391         return; 
    392     } 
    393     unless ( $config->{plugins}->{$name}->{enabled} ) { 
    394         $state->{status} = 'disabled'; 
     453        $config->{enabled} = 0; 
     454        $plugin->status('unloaded'); 
     455        return; 
     456    } 
     457    unless ( $config->{enabled} ) { 
     458        $plugin->status('disabled'); 
    395459        return; 
    396460    } 
    397461 
    398462    # FINALLY we are clear to enable the plugin 
    399     $self->_plugin_enable($name); 
    400  
    401     return 1; 
    402 } 
    403  
    404 # Assume the named plugin exists, enable it 
    405 sub _plugin_enable { 
    406     my $self   = shift; 
    407     my $name   = shift; 
    408     my $plugin = $self->plugins->{$name}->{object}; 
    409  
    410     # Call the plugin's own enable method 
    411     $plugin->plugin_enable; 
    412  
    413     # If the plugin defines document types, register them 
    414     my @documents = $plugin->registered_documents; 
    415     if ( @documents ) { 
    416         Class::Autouse->load('Padre::Document'); 
    417     } 
    418     while ( @documents ) { 
    419         my $type  = shift @documents; 
    420         my $class = shift @documents; 
    421         $Padre::Document::MIME_CLASS{$type} = $class; 
    422     } 
    423  
    424     # Update the status 
    425     $self->plugins->{$name}->{status} = 'enabled'; 
    426  
    427     return 1; 
    428 } 
    429  
    430 # Assume the named plugin exists, disable it 
    431 sub _plugin_disable { 
    432     my $self = shift; 
    433     my $name = shift; 
    434     my $plugin = $self->plugins->{$name}->{object}; 
    435  
    436     # If the plugin defines document types, deregister them 
    437     my @documents = $plugin->registered_documents; 
    438     while ( @documents ) { 
    439         my $type  = shift @documents; 
    440         my $class = shift @documents; 
    441         delete $Padre::Document::MIME_CLASS{$type}; 
    442     } 
    443  
    444     # Call the plugin's own disable method 
    445     $plugin->plugin_disable; 
    446  
    447     # Update the status 
    448     $self->plugins->{$name}->{status} = 'disabled'; 
     463    $plugin->enable; 
    449464 
    450465    return 1; 
     
    470485# the guts of unload_plugin which don't refresh the menu 
    471486sub _unload_plugin { 
     487    my $self   = shift; 
     488    my $handle = $self->_plugin(shift); 
     489 
     490    # Remember if we are enabled or not 
     491    $self->plugin_config($handle)->{enabled} = $handle->enabled ? 1 : 0; 
     492     
     493    # Disable if needed 
     494    if ( $handle->enabled ) { 
     495        $handle->disable; 
     496    } 
     497 
     498    # Destruct the plugin 
     499    if ( defined $handle->{object} ) { 
     500        $handle->{object} = undef; 
     501    } 
     502 
     503    # Unload the plugin class itself 
     504    require Class::Unload; 
     505    Class::Unload->unload($handle->module); 
     506 
     507    # Finally, remove the handle (and flush the sort order) 
     508    delete $self->{plugins}->{$handle->name}; 
     509    delete $self->{plugin_names}; 
     510 
     511    return 1; 
     512} 
     513 
     514=pod 
     515 
     516=head2 reload_plugin 
     517 
     518Reload a single plugin whose name (without C<Padre::Plugin::>) 
     519is passed in as first argument. 
     520 
     521=cut 
     522 
     523sub reload_plugin { 
    472524    my $self = shift; 
    473525    my $name = shift; 
    474  
    475     # normalize to plugin name only 
    476     $name =~ s/^Padre::Plugin:://; 
    477     my $config = $self->parent->config; 
    478     my $plugins = $self->plugins; 
    479  
    480     return if not defined $plugins->{$name}->{object}; 
    481  
    482     eval { 
    483         $plugins->{$name}->{object}->plugin_disable; 
    484     }; 
    485     if ($@) { 
    486         warn $self->{errstr} = $@; 
    487         $plugins->{$name}->{status} = 'failed'; 
    488         # automatically disable the plugin 
    489         $config->{plugins}->{$name}->{enabled} = 0; # persistent! 
    490     } else { 
    491         $plugins->{$name}->{status} = 'disabled'; 
    492     } 
    493      
    494  
    495     delete $plugins->{$name}; 
    496  
    497     require Class::Unload; 
    498     Class::Unload->unload("Padre::Plugin::$name"); 
    499  
     526    $self->_unload_plugin($name); 
     527    $self->load_plugin($name)    or return; 
     528    $self->enable_editors($name) or return; 
    500529    return 1; 
    501530} 
    502531 
    503 =pod 
    504  
    505 =head2 reload_plugins 
    506  
    507 For all registered plugins, unload them if they were loaded 
    508 and then reload them. 
    509  
    510 =cut 
    511  
    512 sub reload_plugins { 
    513     my $self    = shift; 
    514     my $plugins = $self->plugins; 
    515  
    516     foreach my $name (sort keys %$plugins) { 
    517         # do not use the reload_plugin method since that 
    518         # refreshes the menu every time 
    519         $self->_unload_plugin($name); 
    520         $self->_load_plugin_norefresh_menu($name); 
    521         $self->enable_editors($name); 
    522     } 
    523     $self->_refresh_plugin_menu(); 
    524     return 1; 
    525 } 
    526  
    527 =pod 
    528  
    529 =head2 alert_new 
    530  
    531 The C<alert_new> method is called by the main window post-init and 
    532 checks for new plugins. If any are found, it presents a message to 
    533 the user. 
    534  
    535 =cut 
    536  
    537 sub alert_new { 
    538     my $self    = shift; 
    539     my $plugins = $self->plugins; 
    540  
    541     my $new_plugins  = ''; 
    542     foreach my $name ( sort keys %$plugins ) { 
    543         if ( $plugins->{$name}->{status} eq 'new' ) { 
    544             $new_plugins .= "$name\n"; 
     532 
     533 
     534 
     535 
     536##################################################################### 
     537# Enabling and Disabling a Plugin 
     538 
     539# Assume the named plugin exists, enable it 
     540sub _plugin_enable { 
     541    $_[0]->_plugin($_[1])->enable; 
     542} 
     543 
     544# Assume the named plugin exists, disable it 
     545sub _plugin_disable { 
     546    $_[0]->_plugin($_[1])->disable; 
     547} 
     548 
     549=pod 
     550 
     551=head2 plugin_config 
     552 
     553Given a plugin name or namespace, returns a hash reference 
     554which corresponds to the configuration section in the Padre 
     555YAML configuration of that plugin. Any modifications of that 
     556hash reference will, on normal exit, be written to the 
     557configuration file. 
     558 
     559If the plugin name is omitted and this method is called from 
     560a plugin namespace, the plugin name is determine automatically. 
     561 
     562=cut 
     563 
     564sub plugin_config { 
     565    my $self = shift; 
     566 
     567    # Infer the plugin name from caller if not provided 
     568    my $param = shift; 
     569    unless ( defined $param ) { 
     570        my ($package) = caller(); 
     571        unless ( $package =~ /^Padre::Plugin::/ ) { 
     572            croak("Cannot infer the name of the plugin for which the configuration has been requested"); 
    545573        } 
    546     } 
    547     if ( $new_plugins and not $ENV{HARNESS_ACTIVE} ) { 
    548         my $msg = Wx::gettext(<<"END_MSG"); 
    549 We found several new plugins. 
    550 In order to configure and enable them go to 
    551 Plugins -> Plugin Manager 
    552  
    553 List of new plugins: 
    554  
    555 END_MSG 
    556         $msg .= $new_plugins; 
    557  
    558         $self->parent->wx->main_window->message($msg, Wx::gettext('New plugins detected')); 
    559     } 
    560  
    561     return 1; 
    562 } 
    563  
    564  
    565  
    566  
    567  
    568 ##################################################################### 
    569 # Enable and Disable 
     574        $param = $package; 
     575    } 
     576 
     577    # Get the plugin, and from there he config 
     578    my $plugin  = $self->_plugin($param); 
     579    my $config  = $self->parent->config; 
     580    return( $config->{plugins} ||= {} ); 
     581} 
    570582 
    571583# enable all the plugins for a single editor 
     
    612624} 
    613625 
    614 =pod 
    615  
    616 =head2 reload_plugin 
    617  
    618 Reload a single plugin whose name (without C<Padre::Plugin::>) 
    619 is passed in as first argument. 
    620  
    621 =cut 
    622  
    623 sub reload_plugin { 
    624     my $self = shift; 
    625     my $name = shift; 
    626     $self->_unload_plugin($name); 
    627     $self->load_plugin($name)    or return; 
    628     $self->enable_editors($name) or return; 
    629     return 1; 
    630 } 
    631  
    632 # refresh the Plugins menu 
    633 sub _refresh_plugin_menu { 
    634     my $self = shift; 
    635      
    636         $self->parent->wx->main_window->menu->plugins->refresh; 
    637 } 
    638  
    639 =pod 
    640  
    641 =head2 failed 
    642  
    643 Returns the plugin names (without C<Padre::Plugin::> prefixed) of all plugins 
    644 that the editor attempted to load but failed. Note that after a failed 
    645 attempt, the plugin is usually disabled in the configuration and not loaded 
    646 again when the editor is restarted. 
    647  
    648 =cut 
    649  
    650 sub failed { 
     626 
     627 
     628 
     629 
     630###################################################################### 
     631# Menu Integration 
     632 
     633# Generate the menu for a plugin 
     634sub get_menu { 
    651635    my $self    = shift; 
    652     my $plugins = $self->plugins; 
    653     return grep { 
    654         $plugins->{$_}->{status} eq 'failed' 
    655     } keys %$plugins; 
     636    my $main    = shift; 
     637    my $name    = shift; 
     638    my $plugin  = $self->plugins->{$name}; 
     639    unless ( $plugin and $plugin->{status} eq 'enabled' ) { 
     640        return (); 
     641    } 
     642    unless ( $plugin->{object}->can('menu_plugins') ) { 
     643        return (); 
     644    } 
     645    my ($label, $menu) = eval { 
     646        $plugin->{object}->menu_plugins($main) 
     647    }; 
     648    if ( $@ ) { 
     649        $self->{errstr} = "Error when calling menu for plugin '$name' $@"; 
     650        return (); 
     651    } 
     652    unless ( defined $label and defined $menu ) { 
     653        return (); 
     654    } 
     655    return ($label, $menu); 
    656656} 
    657657 
     
    704704} 
    705705 
    706 sub get_menu { 
    707     my $self    = shift; 
    708     my $main    = shift; 
    709     my $name    = shift; 
    710     my $plugin  = $self->plugins->{$name}; 
    711     unless ( $plugin and $plugin->{status} eq 'enabled' ) { 
    712         return (); 
    713     } 
    714     unless ( $plugin->{object}->can('menu_plugins') ) { 
    715         return (); 
    716     } 
    717     my ($label, $menu) = eval { $plugin->{object}->menu_plugins($main) }; 
    718     if ( $@ ) { 
    719         $self->{errstr} = "Error when calling menu for plugin '$name' $@"; 
    720         return (); 
    721     } 
    722     unless ( defined $label and defined $menu ) { 
    723         return (); 
    724     } 
    725     return ($label, $menu); 
     706# Refresh the Plugins menu 
     707sub _refresh_plugin_menu {   
     708        $_[0]->parent->wx->main_window->menu->plugins->refresh; 
     709} 
     710 
     711 
     712 
     713 
     714 
     715###################################################################### 
     716# Support Functions 
     717 
     718sub _plugin { 
     719    my ($self, $it) = @_; 
     720    if ( _INSTANCE($it, 'Padre::PluginHandle') ) { 
     721        my $current = $self->{plugins}->{$it->name}; 
     722        unless ( defined $current ) { 
     723            croak("Unknown plugin '$it' provided to PluginManager"); 
     724        } 
     725        unless ( 
     726            Scalar::Util::refaddr($it) 
     727            == 
     728            Scalar::Util::refaddr($current) 
     729        ) { 
     730            croak("Duplicate plugin '$it' provided to PluginManager"); 
     731        } 
     732        return $it; 
     733    } 
     734    if ( defined _CLASS($it) ) { 
     735        # Convert from class to name if needed 
     736        $it =~ s/^Padre::Plugin:://; 
     737    } 
     738    if ( _IDENTIFIER($it) ) { 
     739        unless ( defined $self->{plugins}->{$it} ) { 
     740            croak("Plugin '$it' does not exist in PluginManager"); 
     741        } 
     742        return $self->{plugins}->{$it}; 
     743    } 
     744    croak("Missing or invalid plugin provided to Padre::PluginManager"); 
    726745} 
    727746 
Note: See TracChangeset for help on using the changeset viewer.