Ticket #1271: Plack.pm.patch

File Plack.pm.patch, 29.8 KB (added by bowtie, 3 years ago)
  • usr/src/Padre/Padre-Plugin-Plack/lib/Padre/Plugin/Plack.pm

     
    77 
    88use utf8; 
    99 
    10 use Padre::Util ('_T'); 
     10use Padre::Plugin (); 
     11use Padre::Util   ('_T'); 
    1112use Padre::Logger; 
    1213 
    1314our $VERSION = "0.01"; 
     
    1920 
    2021=cut 
    2122 
     23####### 
     24# Define Padre Interfaces required 
     25####### 
    2226sub padre_interfaces { 
    23     'Padre::Plugin'     => 0.43, 
    24       'Padre::Document' => 0.82; 
     27    return ( 
     28        'Padre::Plugin'         => '0.90', 
     29        'Padre::Document'       => '0.90', 
     30        'Padre::Wx'             => '0.90', 
     31        'Padre::Wx::Main'       => '0.90', 
     32        'Padre::Wx::Role::Main' => '0.90', 
     33        'Padre::Logger'         => '0.90', 
     34    ); 
    2535} 
    2636 
    2737 
     38 
    2839sub plugin_name { 
    29     'Plack'; 
     40    return Wx::gettext('Plack'); 
    3041} 
     42 
    3143=method registered_documents 
    3244 
    3345Declare ourselves as the handler for .psgi files 
     
    3547=cut 
    3648 
    3749sub registered_documents { 
    38     'application/x-psgi' => 'Padre::Document::PSGI'; 
     50    'application/x-psgi' => 'Padre::Document::PSGI'; 
    3951} 
    4052 
    4153# Static cache for the dot-psgi examples (read off disk) 
     
    4860=cut 
    4961 
    5062sub menu_plugins { 
    51     my $self = shift; 
    52     my $main = shift; 
     63    my $self = shift; 
     64    my $main = shift; 
    5365 
    54     my $menu = Wx::Menu->new; 
     66    my $menu = Wx::Menu->new; 
    5567 
    56     my $app_menu = Wx::Menu->new; 
    57     $menu->Append( -1, _T('New PSGI App'), $app_menu ); 
     68    my $app_menu = Wx::Menu->new; 
     69    $menu->Append( -1, _T('New PSGI App'), $app_menu ); 
    5870 
    59     for my $basename ( sort keys %PSGI_EXAMPLES ) { 
    60         Wx::Event::EVT_MENU( 
    61             $main, 
    62             $app_menu->Append( -1, $basename ), 
    63             sub { 
    64                 $self->on_app_load( $PSGI_EXAMPLES{$basename} ); 
    65                 return; 
    66             }, 
    67         ); 
    68     } 
     71    for my $basename ( sort keys %PSGI_EXAMPLES ) { 
     72        Wx::Event::EVT_MENU( 
     73            $main, 
     74            $app_menu->Append( -1, $basename ), 
     75            sub { 
     76                $self->on_app_load( $PSGI_EXAMPLES{$basename} ); 
     77                return; 
     78            }, 
     79        ); 
     80    } 
    6981 
    70     my $docs_menu = Wx::Menu->new; 
    71     $menu->Append( -1, _T('Online References'), $docs_menu ); 
     82    my $docs_menu = Wx::Menu->new; 
     83    $menu->Append( -1, _T('Online References'), $docs_menu ); 
    7284 
    73     Wx::Event::EVT_MENU( 
    74         $main, 
    75         $docs_menu->Append( -1, 'plackperl.org' ), 
    76         sub { 
    77             Padre::Wx::launch_browser('http://plackperl.org'); 
    78         } 
    79     ); 
     85    Wx::Event::EVT_MENU( 
     86        $main, 
     87        $docs_menu->Append( -1, 'plackperl.org' ), 
     88        sub { 
     89            Padre::Wx::launch_browser('http://plackperl.org'); 
     90        } 
     91    ); 
    8092 
    81     Wx::Event::EVT_MENU( 
    82         $main, 
    83         $docs_menu->Append( -1, _T('Plack Advent Calendar') ), 
    84         sub { 
    85             Padre::Wx::launch_browser('http://advent.plackperl.org'); 
    86         }, 
    87     ); 
     93    Wx::Event::EVT_MENU( 
     94        $main, 
     95        $docs_menu->Append( -1, _T('Plack Advent Calendar') ), 
     96        sub { 
     97            Padre::Wx::launch_browser('http://advent.plackperl.org'); 
     98        }, 
     99    ); 
    88100 
    89     Wx::Event::EVT_MENU( $main, $menu->Append( -1, _T('About') ), sub { $self->on_about_load }, ); 
     101    Wx::Event::EVT_MENU( $main, $menu->Append( -1, _T('About') ), sub { $self->on_about_load }, ); 
    90102 
    91     # Return it and the label for our plug-in 
    92     return ( $self->plugin_name => $menu ); 
     103    # Return it and the label for our plug-in 
     104    return ( $self->plugin_name => $menu ); 
    93105} 
    94106 
    95107=method on_app_load 
     
    99111=cut 
    100112 
    101113sub on_app_load { 
    102     my $self = shift; 
    103     my $file = shift; 
     114    my $self = shift; 
     115    my $file = shift; 
    104116 
    105     my $main = $self->main; 
     117    my $main = $self->main; 
    106118 
    107     # Slurp in the new app content from the template file 
    108     my $template = Padre::Util::slurp($file); 
    109     unless ($template) { 
     119    # Slurp in the new app content from the template file 
     120    my $template = Padre::Util::slurp($file); 
     121    unless ($template) { 
    110122 
    111         # Rare failure, no need to translate 
    112         $self->main->error( sprintf( _T('Failed to open template file %s'), $file ) ); 
    113         return; 
    114     } 
     123        # Rare failure, no need to translate 
     124        $self->main->error( sprintf( _T('Failed to open template file %s'), $file ) ); 
     125        return; 
     126    } 
    115127 
    116     # Create new document editor tab 
    117     $main->new_document_from_string( $$template, 'application/x-psgi' ); 
    118     my $editor = $main->current->editor; 
    119     my $doc    = $editor->{Document}; 
     128    # Create new document editor tab 
     129    $main->new_document_from_string( $$template, 'application/x-psgi' ); 
     130    my $editor = $main->current->editor; 
     131    my $doc    = $editor->{Document}; 
    120132 
    121     # N.B. It used to be necessary to deliberately use application/x-perl mime type and then rebless as 
    122     # a hack to make syntax highlighting work off the bat, but it seems to work now 
    123     #    $doc->set_mimetype('application/x-psgi'); 
    124     #    $doc->rebless; 
    125     $self->on_doc_load($doc); 
     133    # N.B. It used to be necessary to deliberately use application/x-perl mime type and then rebless as 
     134    # a hack to make syntax highlighting work off the bat, but it seems to work now 
     135    #    $doc->set_mimetype('application/x-psgi'); 
     136    #    $doc->rebless; 
     137    $self->on_doc_load($doc); 
    126138 
    127     # The tab exists, so trigger set_tab_icon 
    128     $doc->set_tab_icon; 
     139    # The tab exists, so trigger set_tab_icon 
     140    $doc->set_tab_icon; 
    129141} 
    130142 
    131143=method is_psgi_doc 
     
    133145=cut 
    134146 
    135147sub is_psgi_doc { 
    136     my $self = shift; 
    137     my $doc  = shift; 
     148    my $self = shift; 
     149    my $doc  = shift; 
    138150 
    139     return $doc->isa('Padre::Document::PSGI') && $doc->can('mimetype') && $doc->mimetype eq 'application/x-psgi'; 
     151    return $doc->isa('Padre::Document::PSGI') && $doc->can('mimetype') && $doc->mimetype eq 'application/x-psgi'; 
    140152} 
    141153 
    142154=method editor_enable 
     
    144156=cut 
    145157 
    146158sub editor_enable { 
    147     my $self   = shift; 
    148     my $editor = shift; 
    149     my $doc    = shift; 
     159    my $self   = shift; 
     160    my $editor = shift; 
     161    my $doc    = shift; 
    150162 
    151     # Only respond to event on psgi docs 
    152     return unless $self->is_psgi_doc($doc); 
     163    # Only respond to event on psgi docs 
     164    return unless $self->is_psgi_doc($doc); 
    153165 
    154     TRACE('->editor_enable') if DEBUG; 
     166    TRACE('->editor_enable') if DEBUG; 
    155167 
    156     $self->on_doc_load($doc); 
     168    $self->on_doc_load($doc); 
    157169 
    158     # Deliberately don't trigger Padre::Document::PSGI::set_tab_icon here because the tab doesn't exist yet 
    159     # (it gets triggered by our tomfoolery in Padre::Document::PSGI::restore_cursor_position) 
     170    # Deliberately don't trigger Padre::Document::PSGI::set_tab_icon here because the tab doesn't exist yet 
     171    # (it gets triggered by our tomfoolery in Padre::Document::PSGI::restore_cursor_position) 
    160172} 
    161173 
    162174=method editor_changed 
     
    164176=cut 
    165177 
    166178sub editor_changed { 
    167     my $self = shift; 
     179    my $self = shift; 
    168180 
    169     my $main   = $self->main            or return; 
    170     my $editor = $main->current->editor or return; 
    171     my $doc    = $editor->{Document}    or return; 
     181    my $main   = $self->main            or return; 
     182    my $editor = $main->current->editor or return; 
     183    my $doc    = $editor->{Document}    or return; 
    172184 
    173     # Only respond to event on psgi docs 
    174     return unless $self->is_psgi_doc($doc); 
     185    # Only respond to event on psgi docs 
     186    return unless $self->is_psgi_doc($doc); 
    175187 
    176     TRACE('->editor_changed') if DEBUG; 
     188    TRACE('->editor_changed') if DEBUG; 
    177189 
    178     ## TODO: add check that doc is now selected (for safety).. 
    179     $self->on_panel_load($doc); 
     190    ## TODO: add check that doc is now selected (for safety).. 
     191    $self->on_panel_load($doc); 
    180192} 
    181193 
    182194=method on_panel_load 
     
    184196=cut 
    185197 
    186198sub on_panel_load { 
    187     my $self = shift; 
    188     my $doc  = shift; 
     199    my $self = shift; 
     200    my $doc  = shift; 
    189201 
    190     if ( !$doc->panel ) { 
    191         TRACE('->on_panel_load creating panel') if DEBUG; 
    192         require Padre::Plugin::Plack::Panel; 
    193         $doc->panel( Padre::Plugin::Plack::Panel->new($doc) ); 
    194     } 
     202    if ( !$doc->panel ) { 
     203        TRACE('->on_panel_load creating panel') if DEBUG; 
     204        require Padre::Plugin::Plack::Panel; 
     205        $doc->panel( Padre::Plugin::Plack::Panel->new($doc) ); 
     206    } 
    195207 
    196     # Show the panel, and pass an onclose callback 
    197     Padre::Current->main->bottom->show( 
    198         $doc->panel, 
    199         sub { 
     208    # Show the panel, and pass an onclose callback 
     209    Padre::Current->main->bottom->show( 
     210        $doc->panel, 
     211        sub { 
    200212 
    201             # Closing the panel causes bad things to happen 
    202             $self->main->error( 
    203                 _T(q{'Sorry Dave, I can't do that - you need to close the corresponding file tab to close this panel}) 
    204             ); 
     213            # Closing the panel causes bad things to happen 
     214            $self->main->error( 
     215                _T(q{'Sorry Dave, I can't do that - you need to close the corresponding file tab to close this panel}) 
     216            ); 
    205217 
    206             # We can't actually cancel the close, so re-create it 
    207             $self->plackdown($doc); 
    208             $doc->panel(undef); 
    209             $self->on_panel_load($doc); 
    210         } 
    211     ); 
    212     Padre::Current->main->refresh; 
     218            # We can't actually cancel the close, so re-create it 
     219            $self->plackdown($doc); 
     220            $doc->panel(undef); 
     221            $self->on_panel_load($doc); 
     222        } 
     223    ); 
     224    Padre::Current->main->refresh; 
    213225} 
    214226 
    215227=method on_panel_close 
     
    217229=cut 
    218230 
    219231sub on_panel_close { 
    220     my $self = shift; 
    221     my $doc  = shift; 
     232    my $self = shift; 
     233    my $doc  = shift; 
    222234 
    223     return unless $doc && $doc->panel; 
     235    return unless $doc && $doc->panel; 
    224236 
    225     if ( my $panel = $doc->panel ) { 
    226         $self->plackdown($doc); 
    227         $self->main->bottom->hide($panel); 
    228         $doc->panel(undef); 
    229     } 
     237    if ( my $panel = $doc->panel ) { 
     238        $self->plackdown($doc); 
     239        $self->main->bottom->hide($panel); 
     240        $doc->panel(undef); 
     241    } 
    230242} 
    231243 
    232244=method on_doc_load 
     
    238250=cut 
    239251 
    240252sub on_doc_load { 
    241     my $self = shift; 
    242     my $doc  = shift; 
     253    my $self = shift; 
     254    my $doc  = shift; 
    243255 
    244     TRACE('->on_doc_load') if DEBUG; 
     256    TRACE('->on_doc_load') if DEBUG; 
    245257 
    246     if ( !$doc->isa('Padre::Document::PSGI') ) { 
    247         $self->error( sprintf( _T('Expected a PSGI document, but instead got: %s'), ref $doc ) ); 
    248         return; 
    249     } 
     258    if ( !$doc->isa('Padre::Document::PSGI') ) { 
     259        $self->error( sprintf( _T('Expected a PSGI document, but instead got: %s'), ref $doc ) ); 
     260        return; 
     261    } 
    250262 
    251     # Set the icon path, but don't actually trigger set_icon_tab() just yet 
    252     $doc->icon_path( $self->plugin_directory_share . "/icons/16x16/logo.png" ); 
    253     $doc->plugin($self); 
     263    # Set the icon path, but don't actually trigger set_icon_tab() just yet 
     264    $doc->icon_path( $self->plugin_directory_share . "/icons/16x16/logo.png" ); 
     265    $doc->plugin($self); 
    254266 
    255     # Trigger the Document's general setup event 
    256     $doc->on_load; 
     267    # Trigger the Document's general setup event 
     268    $doc->on_load; 
    257269 
    258     # Show the panel 
    259     $self->on_panel_load($doc); 
     270    # Show the panel 
     271    $self->on_panel_load($doc); 
    260272} 
    261273 
    262274=method on_doc_close 
     
    264276=cut 
    265277 
    266278sub on_doc_close { 
    267     my $self = shift; 
    268     my $doc  = shift; 
     279    my $self = shift; 
     280    my $doc  = shift; 
    269281 
    270     TRACE('->on_doc_close') if DEBUG; 
     282    TRACE('->on_doc_close') if DEBUG; 
    271283 
    272     if ( !$doc->isa('Padre::Document::PSGI') ) { 
    273         $self->error( sprintf( _T('Expected a PSGI document, but instead got: %s'), ref $doc ) ); 
    274         return; 
    275     } 
     284    if ( !$doc->isa('Padre::Document::PSGI') ) { 
     285        $self->error( sprintf( _T('Expected a PSGI document, but instead got: %s'), ref $doc ) ); 
     286        return; 
     287    } 
    276288 
    277     $self->on_panel_close($doc); 
     289    $self->on_panel_close($doc); 
    278290} 
    279291 
    280292=method on_about_load 
     
    282294=cut 
    283295 
    284296sub on_about_load { 
    285     require Plack; 
    286     require Class::Unload; 
    287     my $about = Wx::AboutDialogInfo->new; 
    288     $about->SetName("Padre::Plugin::Plack"); 
    289     $about->SetDescription( _T('PSGI/Plack support for Padre') . "\n" 
    290           . _T('by') . "\n" 
    291           . 'Patrick Donelan (pat@patspam.com)' . "\n\n" 
    292           . _T('This system is running Plack version') 
    293           . " $Plack::VERSION\n" 
    294           . 'http://plackperl.org' ); 
    295     $about->SetVersion($Padre::Plugin::Plack::VERSION); 
    296     Class::Unload->unload('Plack'); 
     297    require Plack; 
     298    require Class::Unload; 
     299    my $about = Wx::AboutDialogInfo->new; 
     300    $about->SetName("Padre::Plugin::Plack"); 
     301    $about->SetDescription( _T('PSGI/Plack support for Padre') . "\n" 
     302            . _T('by') . "\n" 
     303            . 'Patrick Donelan (pat@patspam.com)' . "\n\n" 
     304            . _T('This system is running Plack version') 
     305            . " $Plack::VERSION\n" 
     306            . 'http://plackperl.org' ); 
     307    $about->SetVersion($Padre::Plugin::Plack::VERSION); 
     308    Class::Unload->unload('Plack'); 
    297309 
    298     Wx::AboutBox($about); 
    299     return; 
     310    Wx::AboutBox($about); 
     311    return; 
    300312} 
    301313 
    302314=method load_dot_psgi_examples 
     
    304316=cut 
    305317 
    306318sub load_dot_psgi_examples { 
    307     my $self = shift; 
     319    my $self = shift; 
    308320 
    309     require File::Find::Rule; 
    310     %PSGI_EXAMPLES = 
    311       map { File::Basename::basename($_) => $_ } 
    312       File::Find::Rule->file()->name('*.psgi')->in( $self->plugin_directory_share . '/dot-psgi' ); 
     321    require File::Find::Rule; 
     322    %PSGI_EXAMPLES = 
     323        map { File::Basename::basename($_) => $_ } 
     324        File::Find::Rule->file()->name('*.psgi')->in( $self->plugin_directory_share . '/dot-psgi' ); 
    313325} 
    314326 
    315327=method plugin_enable 
     
    319331 
    320332 
    321333sub plugin_enable { 
    322     my $self = shift; 
     334    my $self = shift; 
    323335 
    324     $self->load_dot_psgi_examples; 
     336    $self->load_dot_psgi_examples; 
    325337} 
    326338 
    327339=method plugin_enable 
     
    329341=cut 
    330342 
    331343sub plugin_disable { 
    332     my $self = shift; 
     344    my $self = shift; 
    333345 
    334     # TODO: Loop over all docs and turn off their psgi goodies: panel, stop server, etc.. 
     346    # TODO: Loop over all docs and turn off their psgi goodies: panel, stop server, etc.. 
    335347 
    336     # cleanup loaded classes 
    337     require Class::Unload; 
    338     Class::Unload->unload('Padre::Document::PSGI'); 
    339     Class::Unload->unload('Padre::Plugin::Plack::Panel'); 
     348    # Unload all our child classes 
     349    $self->unload( 
     350        qw{ 
     351            Padre::Document::PSGI 
     352            Padre::Plugin::Plack::Panel 
     353            } 
     354    ); 
     355 
     356    $self->SUPER::plugin_disable(@_); 
     357 
     358    return; 
    340359} 
    341360 
    342361=method plackup 
     
    344363=cut 
    345364 
    346365sub plackup { 
    347     my $self = shift; 
    348     my $doc  = shift; 
     366    my $self = shift; 
     367    my $doc  = shift; 
    349368 
    350     return unless $doc; 
    351     TRACE('->plackup') if DEBUG; 
     369    return unless $doc; 
     370    TRACE('->plackup') if DEBUG; 
    352371 
    353     my $main     = $self->main; 
    354     my $filename = $doc->filename; 
     372    my $main     = $self->main; 
     373    my $filename = $doc->filename; 
    355374 
    356     if ( !$filename ) { 
    357         $main->on_save; 
    358         $filename = $doc->filename; 
    359         return unless $filename; 
    360     } 
     375    if ( !$filename ) { 
     376        $main->on_save; 
     377        $filename = $doc->filename; 
     378        return unless $filename; 
     379    } 
    361380 
    362     my $pwd = Cwd::cwd(); 
    363     chdir $doc->dirname; 
     381    my $pwd = Cwd::cwd(); 
     382    chdir $doc->dirname; 
    364383 
    365     # Server ("Let plackup guess" means leave as unspecified) 
    366     my $server = $doc->panel->{server}->GetValue; 
    367     $server = $server eq _T('Let plackup guess') ? '' : "-s $server"; 
     384    # Server ("Let plackup guess" means leave as unspecified) 
     385    my $server = $doc->panel->{server}->GetValue; 
     386    $server = $server eq _T('Let plackup guess') ? '' : "-s $server"; 
    368387 
    369     # Port (required for browser url) 
    370     my $port = $doc->panel->{port}->GetValue || 5000; 
    371     $port = "-p $port"; 
     388    # Port (required for browser url) 
     389    my $port = $doc->panel->{port}->GetValue || 5000; 
     390    $port = "-p $port"; 
    372391 
    373     my $restart = $doc->panel->{restart}->GetValue ? '-r' : ''; 
    374     my $plackup_options = $doc->panel->{plackup_options}->GetValue; 
     392    my $restart = $doc->panel->{restart}->GetValue ? '-r' : ''; 
     393    my $plackup_options = $doc->panel->{plackup_options}->GetValue; 
    375394 
    376     require File::Which; 
    377     my $plackup = File::Which::which('plackup'); 
    378     if ( !$plackup ) { 
    379         $main->error( _T('plackup command not found, please check your Plack installation and $PATH') ); 
    380         return; 
    381     } 
     395    require File::Which; 
     396    my $plackup = File::Which::which('plackup'); 
     397    if ( !$plackup ) { 
     398        $main->error( _T('plackup command not found, please check your Plack installation and $PATH') ); 
     399        return; 
     400    } 
    382401 
    383     my $cmd = qq{$plackup $port $restart $server $plackup_options "$filename"}; 
    384     TRACE("->plackup $cmd") if DEBUG; 
    385     $self->run_command( $doc, $cmd ); 
     402    my $cmd = qq{$plackup $port $restart $server $plackup_options "$filename"}; 
     403    TRACE("->plackup $cmd") if DEBUG; 
     404    $self->run_command( $doc, $cmd ); 
    386405 
    387     # restore previous dir 
    388     chdir $pwd; 
     406    # restore previous dir 
     407    chdir $pwd; 
    389408} 
    390409 
    391410=method plackdown 
     
    393412=cut 
    394413 
    395414sub plackdown { 
    396     my $self = shift; 
    397     my $doc  = shift; 
     415    my $self = shift; 
     416    my $doc  = shift; 
    398417 
    399     return unless $doc; 
     418    return unless $doc; 
    400419 
    401     TRACE('->plackdown') if DEBUG; 
     420    TRACE('->plackdown') if DEBUG; 
    402421 
    403     my $process = $doc->process; 
    404     return unless $process; 
     422    my $process = $doc->process; 
     423    return unless $process; 
    405424 
    406     # sanity check 
    407     if ( !$process->IsAlive ) { 
    408         TRACE('->plackdown process was dead but not undef, strange') if DEBUG; 
    409         $doc->process(undef); 
    410     } 
     425    # sanity check 
     426    if ( !$process->IsAlive ) { 
     427        TRACE('->plackdown process was dead but not undef, strange') if DEBUG; 
     428        $doc->process(undef); 
     429    } 
    411430 
    412     my $processid = $process->GetProcessId(); 
    413     my $panel     = $doc->panel; 
     431    my $processid = $process->GetProcessId(); 
     432    my $panel     = $doc->panel; 
    414433 
    415     require Proc::Killfam; 
    416     my @signals = qw(INT TERM QUIT KILL STOP); 
    417     for my $sig (@signals) { 
    418         TRACE("Sending $sig to PID: $processid") if DEBUG; 
    419         my $signalled = Proc::Killfam::killfam( $sig, $processid ); 
     434    require Proc::Killfam; 
     435    my @signals = qw(INT TERM QUIT KILL STOP); 
     436    for my $sig (@signals) { 
     437        TRACE("Sending $sig to PID: $processid") if DEBUG; 
     438        my $signalled = Proc::Killfam::killfam( $sig, $processid ); 
    420439 
    421         if ( $panel->{restart}->GetValue ) { 
     440        if ( $panel->{restart}->GetValue ) { 
    422441 
    423             # with auto-restart, we expect 3 processes 
    424             return if $signalled > 1; 
    425         } 
    426         else { 
     442            # with auto-restart, we expect 3 processes 
     443            return if $signalled > 1; 
     444        } else { 
    427445 
    428             # otherwise, just one 
    429             return if $signalled > 0; 
    430         } 
    431     } 
     446            # otherwise, just one 
     447            return if $signalled > 0; 
     448        } 
     449    } 
    432450 
    433     $panel->output->AppendText( "\n" . "Process PID $processid did not respond, you may need to kill it manually\n" ); 
     451    $panel->output->AppendText( "\n" . "Process PID $processid did not respond, you may need to kill it manually\n" ); 
    434452} 
    435453 
    436454=method run_command 
     
    438456=cut 
    439457 
    440458sub run_command { 
    441     my ( $self, $doc, $command ) = (@_); 
     459    my ( $self, $doc, $command ) = (@_); 
    442460 
    443     my $panel = $doc->panel; 
     461    my $panel = $doc->panel; 
    444462 
    445     # clear the panel 
    446     $panel->output->Remove( 0, $panel->output->GetLastPosition ); 
     463    # clear the panel 
     464    $panel->output->Remove( 0, $panel->output->GetLastPosition ); 
    447465 
    448     # If this is the first time a command has been run, set up the ProcessStream bindings. 
    449     unless ( $panel->{bound} ) { 
    450         TRACE(' setting up ProcessStream bindings') if DEBUG; 
     466    # If this is the first time a command has been run, set up the ProcessStream bindings. 
     467    unless ( $panel->{bound} ) { 
     468        TRACE(' setting up ProcessStream bindings') if DEBUG; 
    451469 
    452         require Wx::Perl::ProcessStream; 
    453         if ( $Wx::Perl::ProcessStream::VERSION < .20 ) { 
    454             $self->main->error( 
    455                 sprintf( 
    456                     _T( 
    457                             'Wx::Perl::ProcessStream is version %s' 
    458                           . ' which is known to cause problems. Get at least 0.20 by typing' 
    459                           . "\ncpan Wx::Perl::ProcessStream" 
    460                     ), 
    461                     $Wx::Perl::ProcessStream::VERSION 
    462                 ) 
    463             ); 
    464             return 1; 
    465         } 
     470        require Wx::Perl::ProcessStream; 
     471        if ( $Wx::Perl::ProcessStream::VERSION < .20 ) { 
     472            $self->main->error( 
     473                sprintf( 
     474                    _T(       'Wx::Perl::ProcessStream is version %s' 
     475                            . ' which is known to cause problems. Get at least 0.20 by typing' 
     476                            . "\ncpan Wx::Perl::ProcessStream" 
     477                    ), 
     478                    $Wx::Perl::ProcessStream::VERSION 
     479                ) 
     480            ); 
     481            return 1; 
     482        } 
    466483 
    467         Wx::Perl::ProcessStream::EVT_WXP_PROCESS_STREAM_STDOUT( 
    468             $panel->output, 
    469             sub { 
    470                 $_[1]->Skip(1); 
    471                 my $outpanel = $_[0]; 
    472                 $outpanel->style_good; 
    473                 $outpanel->AppendText( $_[1]->GetLine . "\n" ); 
    474                 return; 
    475             }, 
    476         ); 
    477         Wx::Perl::ProcessStream::EVT_WXP_PROCESS_STREAM_STDERR( 
    478             $panel->output, 
    479             sub { 
    480                 $_[1]->Skip(1); 
    481                 my $outpanel = $_[0]; 
    482                 $outpanel->style_neutral; 
    483                 $outpanel->AppendText( $_[1]->GetLine . "\n" ); 
     484        Wx::Perl::ProcessStream::EVT_WXP_PROCESS_STREAM_STDOUT( 
     485            $panel->output, 
     486            sub { 
     487                $_[1]->Skip(1); 
     488                my $outpanel = $_[0]; 
     489                $outpanel->style_good; 
     490                $outpanel->AppendText( $_[1]->GetLine . "\n" ); 
     491                return; 
     492            }, 
     493        ); 
     494        Wx::Perl::ProcessStream::EVT_WXP_PROCESS_STREAM_STDERR( 
     495            $panel->output, 
     496            sub { 
     497                $_[1]->Skip(1); 
     498                my $outpanel = $_[0]; 
     499                $outpanel->style_neutral; 
     500                $outpanel->AppendText( $_[1]->GetLine . "\n" ); 
    484501 
    485                 return; 
    486             }, 
    487         ); 
    488         Wx::Perl::ProcessStream::EVT_WXP_PROCESS_STREAM_EXIT( 
    489             $panel->output, 
    490             sub { 
    491                 $_[1]->Skip(1); 
    492                 $_[1]->GetProcess->Destroy; 
     502                return; 
     503            }, 
     504        ); 
     505        Wx::Perl::ProcessStream::EVT_WXP_PROCESS_STREAM_EXIT( 
     506            $panel->output, 
     507            sub { 
     508                $_[1]->Skip(1); 
     509                $_[1]->GetProcess->Destroy; 
    493510 
    494                 TRACE(' PROCESS_STREAM_EXIT') if DEBUG; 
     511                TRACE(' PROCESS_STREAM_EXIT') if DEBUG; 
    495512 
    496                 my $outpanel = $_[0]; 
    497                 $outpanel->style_neutral; 
    498                 $outpanel->AppendText("\nProcess terminated\n"); 
    499                 $panel->set_as_stopped; 
     513                my $outpanel = $_[0]; 
     514                $outpanel->style_neutral; 
     515                $outpanel->AppendText("\nProcess terminated\n"); 
     516                $panel->set_as_stopped; 
    500517 
    501                 $doc->process(undef); 
    502             }, 
    503         ); 
    504         $panel->{bound} = 1; 
    505     } 
     518                $doc->process(undef); 
     519            }, 
     520        ); 
     521        $panel->{bound} = 1; 
     522    } 
    506523 
    507     # Start the command 
    508     my $process = Wx::Perl::ProcessStream::Process->new( $command, "Run $command", $panel->output ); 
    509     $doc->process( $process->Run ); 
     524    # Start the command 
     525    my $process = Wx::Perl::ProcessStream::Process->new( $command, "Run $command", $panel->output ); 
     526    $doc->process( $process->Run ); 
    510527 
    511     # Check if we started the process or not 
    512     if ( $doc->process ) { 
    513         $panel->set_as_started; 
     528    # Check if we started the process or not 
     529    if ( $doc->process ) { 
     530        $panel->set_as_started; 
    514531 
    515     } 
    516     else { 
     532    } else { 
    517533 
    518         # Failed to start the command. Clean up. 
    519         $panel->set_as_stopped;    # should already be stopped, but just in case 
    520         Wx::MessageBox( sprintf( _T("Failed to start server via '%s'"), $command ), _T("Error"), Wx::wxOK, $self ); 
    521     } 
     534        # Failed to start the command. Clean up. 
     535        $panel->set_as_stopped; # should already be stopped, but just in case 
     536        Wx::MessageBox( sprintf( _T("Failed to start server via '%s'"), $command ), _T("Error"), Wx::wxOK, $self ); 
     537    } 
    522538 
    523     return; 
     539    return; 
    524540} 
    525541 
    526542=method build_panel 
     
    531547=cut 
    532548 
    533549sub build_panel { 
    534     my $self  = shift; 
    535     my $doc   = shift; 
    536     my $panel = shift; 
     550    my $self  = shift; 
     551    my $doc   = shift; 
     552    my $panel = shift; 
    537553 
    538     require Scalar::Util; 
    539     $panel->{doc} = $doc; 
    540     Scalar::Util::weaken( $panel->{doc} ); 
     554    require Scalar::Util; 
     555    $panel->{doc} = $doc; 
     556    Scalar::Util::weaken( $panel->{doc} ); 
    541557 
    542     # main container 
    543     my $box = Wx::BoxSizer->new(Wx::wxVERTICAL); 
     558    # main container 
     559    my $box = Wx::BoxSizer->new(Wx::wxVERTICAL); 
    544560 
    545     # top box, holding buttons, icons and checkboxes 
    546     my $top_box = Wx::BoxSizer->new(Wx::wxHORIZONTAL); 
     561    # top box, holding buttons, icons and checkboxes 
     562    my $top_box = Wx::BoxSizer->new(Wx::wxHORIZONTAL); 
    547563 
    548     # LED showing process status 
    549     $panel->{led} = Wx::StaticBitmap->new( $panel, -1, Wx::wxNullBitmap ); 
    550     $top_box->Add( $panel->{led}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
     564    # LED showing process status 
     565    $panel->{led} = Wx::StaticBitmap->new( $panel, -1, Wx::wxNullBitmap ); 
     566    $top_box->Add( $panel->{led}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
    551567 
    552     # Servers 
    553     my @servers = sort qw( 
    554       Standalone 
    555       Apache1 
    556       Apache2 
    557       Apache2::RegistryAnyEvent 
    558       AnyEvent::HTTPD 
    559       AnyEvent::ReverseHTTP 
    560       AnyEvent::SCGI 
    561       AnyEvent::Server::Starter 
    562       CGI 
    563       Corona 
    564       FCGI 
    565       FCGI::Engine 
    566       HTTP::Server::PSGI 
    567       HTTP::Server::Simple 
    568       Server::Simple 
    569       SCGI 
    570       Starman 
    571       Starlet 
    572       Twiggy 
    573       POE 
    574       ReverseHTTP 
    575     ); 
    576     unshift @servers, _T('Let plackup guess'); 
    577     $top_box->AddSpacer(5); 
    578     $top_box->Add( Wx::StaticText->new( $panel, -1, _T('Server') . ':' ), 0, Wx::wxALIGN_CENTER_VERTICAL ); 
    579     $panel->{server} = 
    580       Wx::ComboBox->new( $panel, -1, 'Standalone', Wx::wxDefaultPosition, Wx::wxDefaultSize, [@servers], 
    581         Wx::wxCB_DROPDOWN ); 
    582     $top_box->Add( $panel->{server}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
     568    # Servers 
     569    my @servers = sort qw( 
     570        Standalone 
     571        Apache1 
     572        Apache2 
     573        Apache2::RegistryAnyEvent 
     574        AnyEvent::HTTPD 
     575        AnyEvent::ReverseHTTP 
     576        AnyEvent::SCGI 
     577        AnyEvent::Server::Starter 
     578        CGI 
     579        Corona 
     580        FCGI 
     581        FCGI::Engine 
     582        HTTP::Server::PSGI 
     583        HTTP::Server::Simple 
     584        Server::Simple 
     585        SCGI 
     586        Starman 
     587        Starlet 
     588        Twiggy 
     589        POE 
     590        ReverseHTTP 
     591    ); 
     592    unshift @servers, _T('Let plackup guess'); 
     593    $top_box->AddSpacer(5); 
     594    $top_box->Add( Wx::StaticText->new( $panel, -1, _T('Server') . ':' ), 0, Wx::wxALIGN_CENTER_VERTICAL ); 
     595    $panel->{server} = Wx::ComboBox->new( 
     596        $panel, -1, 'Standalone', Wx::wxDefaultPosition, Wx::wxDefaultSize, [@servers], 
     597        Wx::wxCB_DROPDOWN 
     598    ); 
     599    $top_box->Add( $panel->{server}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
    583600 
    584     # Port 
    585     $top_box->AddSpacer(5); 
    586     $top_box->Add( Wx::StaticText->new( $panel, -1, _T('Port') . ':' ), 0, Wx::wxALIGN_CENTER_VERTICAL ); 
    587     $panel->{port} = Wx::TextCtrl->new( $panel, -1, '5000' ); 
    588     $top_box->Add( $panel->{port}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
     601    # Port 
     602    $top_box->AddSpacer(5); 
     603    $top_box->Add( Wx::StaticText->new( $panel, -1, _T('Port') . ':' ), 0, Wx::wxALIGN_CENTER_VERTICAL ); 
     604    $panel->{port} = Wx::TextCtrl->new( $panel, -1, '5000' ); 
     605    $top_box->Add( $panel->{port}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
    589606 
    590     # Plackup Options 
    591     $top_box->AddSpacer(5); 
    592     $top_box->Add( Wx::StaticText->new( $panel, -1, _T('Options') . ':' ), 0, Wx::wxALIGN_CENTER_VERTICAL ); 
    593     $panel->{plackup_options} = Wx::TextCtrl->new( $panel, -1, '' ); 
    594     $top_box->Add( $panel->{plackup_options}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
     607    # Plackup Options 
     608    $top_box->AddSpacer(5); 
     609    $top_box->Add( Wx::StaticText->new( $panel, -1, _T('Options') . ':' ), 0, Wx::wxALIGN_CENTER_VERTICAL ); 
     610    $panel->{plackup_options} = Wx::TextCtrl->new( $panel, -1, '' ); 
     611    $top_box->Add( $panel->{plackup_options}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
    595612 
    596     # Restart 
    597     $top_box->AddSpacer(5); 
    598     $panel->{restart} = Wx::CheckBox->new( $panel, -1, _T('Auto-Restart') ); 
    599     $panel->{restart}->SetValue(1); 
    600     $top_box->Add( $panel->{restart}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
     613    # Restart 
     614    $top_box->AddSpacer(5); 
     615    $panel->{restart} = Wx::CheckBox->new( $panel, -1, _T('Auto-Restart') ); 
     616    $panel->{restart}->SetValue(1); 
     617    $top_box->Add( $panel->{restart}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
    601618 
    602     # Start/stop button 
    603     $top_box->AddSpacer(5); 
    604     $panel->{start_stop} = Wx::Button->new( $panel, -1, '' ); 
    605     Wx::Event::EVT_BUTTON( 
    606         $panel, 
    607         $panel->{start_stop}, 
    608         sub { 
    609             my $panel = shift; 
     619    # Start/stop button 
     620    $top_box->AddSpacer(5); 
     621    $panel->{start_stop} = Wx::Button->new( $panel, -1, '' ); 
     622    Wx::Event::EVT_BUTTON( 
     623        $panel, 
     624        $panel->{start_stop}, 
     625        sub { 
     626            my $panel = shift; 
    610627 
    611             # Trigger plackup/down 
    612             if ( $panel->{start_stop}->GetLabel eq _T('Start') ) { 
    613                 $doc->plugin->plackup($doc); 
    614             } 
    615             else { 
    616                 $doc->plugin->plackdown($doc); 
    617             } 
    618         }, 
    619     ); 
    620     $top_box->Add( $panel->{start_stop}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
     628            # Trigger plackup/down 
     629            if ( $panel->{start_stop}->GetLabel eq _T('Start') ) { 
     630                $doc->plugin->plackup($doc); 
     631            } else { 
     632                $doc->plugin->plackdown($doc); 
     633            } 
     634        }, 
     635    ); 
     636    $top_box->Add( $panel->{start_stop}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
    621637 
    622     # Browser 
    623     $top_box->AddSpacer(5); 
    624     $panel->{browse} = Wx::Button->new( $panel, -1, _T('View in Browser') ); 
    625     Wx::Event::EVT_BUTTON( 
    626         $panel, 
    627         $panel->{browse}, 
    628         sub { 
    629             my $panel = shift; 
    630             my $port = $panel->{port}->GetValue || 5000; 
    631             Padre::Wx::launch_browser("http://0:$port"); 
    632         }, 
    633     ); 
    634     $top_box->Add( $panel->{browse}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
     638    # Browser 
     639    $top_box->AddSpacer(5); 
     640    $panel->{browse} = Wx::Button->new( $panel, -1, _T('View in Browser') ); 
     641    Wx::Event::EVT_BUTTON( 
     642        $panel, 
     643        $panel->{browse}, 
     644        sub { 
     645            my $panel = shift; 
     646            my $port = $panel->{port}->GetValue || 5000; 
     647            Padre::Wx::launch_browser("http://0:$port"); 
     648        }, 
     649    ); 
     650    $top_box->Add( $panel->{browse}, 0, Wx::wxALIGN_CENTER_VERTICAL ); 
    635651 
    636     # finishing up the top_box 
    637     $box->Add( $top_box, 0, Wx::wxALIGN_LEFT | Wx::wxALIGN_CENTER_VERTICAL ); 
     652    # finishing up the top_box 
     653    $box->Add( $top_box, 0, Wx::wxALIGN_LEFT | Wx::wxALIGN_CENTER_VERTICAL ); 
    638654 
    639     # output panel for server 
    640     require Padre::Wx::Output; 
    641     my $output = Padre::Wx::Output->new( $self->main, $panel ); 
     655    # output panel for server 
     656    require Padre::Wx::Output; 
     657    my $output = Padre::Wx::Output->new( $self->main, $panel ); 
    642658 
    643     $box->Add( $output, 1, Wx::wxGROW ); 
     659    $box->Add( $output, 1, Wx::wxGROW ); 
    644660 
    645     # wrapping it up 
    646     $panel->SetSizer($box); 
     661    # wrapping it up 
     662    $panel->SetSizer($box); 
    647663 
    648     # holding on to some objects we'll need to manipulate later on 
    649     $panel->{output} = $output; 
     664    # holding on to some objects we'll need to manipulate later on 
     665    $panel->{output} = $output; 
    650666 
    651     $panel->set_as_stopped; 
     667    $panel->set_as_stopped; 
    652668} 
    653669 
    654670=method TRACE