#!/usr/bin/perl -w
#############################################################################
## Name: example/psexample.pl
## Purpose: example for Wx::Perl::ProcessStream
## Author: Mark Dootson
## Modified by:
## Created: 25/03/2007
## Copyright: (c) 2007 Mark Dootson
## Licence: This program is free software; you can redistribute it and/or
## modify it under the same terms as Perl itself
#############################################################################
package ExecApp;
use Wx qw( :everything );
use base qw( Wx::App );
sub OnInit {
my $self = shift;
#----------------------------------------------------------------------
# some non specific initialisation
#----------------------------------------------------------------------
Wx::InitAllImageHandlers;
#----------------------------------------------------------------------
# set application details
#----------------------------------------------------------------------
$self->SetAppName('My Exec Process Test Application');
$self->SetVendorName('My Name');
$self->SetClassName( $self->GetVendorName() . ' - ' . $self->GetAppName() );
#----------------------------------------------------------------------
# create and show mainwindow
#----------------------------------------------------------------------
my $mwin = MainWindow->new(undef, -1); # parent = undef, ID = auto generated (-1)
$self->SetTopWindow($mwin);
$mwin->Centre;
$mwin->Show(1);
return 1;
}
##########################
package main;
my $app = ExecApp->new();
$app->MainLoop;
##########################
package MainWindow;
use Wx qw( :everything );
use Wx::Event qw( :everything );
use base qw( Wx::Frame );
use Wx::Perl::ProcessStream qw(
EVT_WXP_PROCESS_STREAM_STDOUT
EVT_WXP_PROCESS_STREAM_STDERR
EVT_WXP_PROCESS_STREAM_EXIT
wxpSIGKILL
);
sub new {
#----------------------------------------------------------------------
# some defaults & SUPER constructor
#----------------------------------------------------------------------
$_[1] = undef if not exists $_[1]; # parent
$_[2] = -1 if not exists $_[2]; # id
$_[3] = wxTheApp->GetAppName() if not exists $_[3]; # title
$_[4] = wxDefaultPosition if not exists $_[4]; # position
$_[5] = wxDefaultSize if not exists $_[5]; # size
$_[6] = wxDEFAULT_FRAME_STYLE if not exists $_[6]; # style
my $self = shift->SUPER::new(@_);
$self->{menuindex} = {};
$self->{menucount} = 0;
$self->{controls} = {};
#----------------------------------------------------------------------
# menus with some keyboard shortcuts
#----------------------------------------------------------------------
my ($menu, $menuitem);
# FILE MENU
$menu = $self->add_menu('File', '&File');
$menu->AppendSeparator();
$menuitem = $self->add_menu_item('File', 'Exit', 'E&xit', \&evt_menu_file_exit);
#----------------------------------------------------------------------
# controls
#----------------------------------------------------------------------
# a panel as a parent for everything
my $panelmain = Wx::Panel->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxNO_BORDER);
# Wx::Panel->new(parent, id, position, size, flags);
# add a TextCtrl to enter command line plus a label
my $commandlbl = Wx::StaticText->new($panelmain, -1, 'Command Line', wxDefaultPosition, wxDefaultSize );
my $commandtext = Wx::TextCtrl->new($panelmain, -1, '', wxDefaultPosition, wxDefaultSize );
my $pointsize = $commandtext->GetFont->GetPointSize();
$commandtext->SetFont(Wx::Font->new($pointsize, wxMODERN, wxNORMAL, wxNORMAL )); # fixed pitch
# add an 'Execute' button
my $execbutton = Wx::Button->new($panelmain, -1, 'Execute', wxDefaultPosition, wxDefaultSize );
# add a TextCtrl to display results
my $resulttext = Wx::TextCtrl->new($panelmain, -1, '', wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxTE_DONTWRAP);
$pointsize = $resulttext->GetFont->GetPointSize();
$resulttext->SetFont(Wx::Font->new($pointsize, wxMODERN, wxNORMAL, wxNORMAL )); # fixed pitch
# store refs to the controls
$self->add_control('PnlMain', $panelmain);
$self->add_control('LblCommand', $commandlbl);
$self->add_control('TxtCommand', $commandtext);
$self->add_control('BtnExecute', $execbutton);
$self->add_control('TxtResults', $resulttext);
#------------------------------------------------------------------
# Events
#------------------------------------------------------------------
EVT_BUTTON( $self, $self->get_control('BtnExecute'), \&evt_button_execute );
EVT_WXP_PROCESS_STREAM_STDOUT( $self, \&evt_process_stdout);
EVT_WXP_PROCESS_STREAM_STDERR( $self, \&evt_process_stderr);
EVT_WXP_PROCESS_STREAM_EXIT( $self, \&evt_process_exit);
Wx::Perl::ProcessStream->SetDefaultAppCloseAction( wxpSIGKILL );
#----------------------------------------------------------------------
# layout
#----------------------------------------------------------------------
my ($fillproportion, $flags, $bordersize);
# create a main sizer for the frame
$self->SetSizer( Wx::BoxSizer->new(wxVERTICAL) );
$fillproportion = 1;
$bordersize = 0;
$flags = wxALL|wxEXPAND;
$self->GetSizer->Add($panelmain, $fillproportion, $flags, $bordersize);
# create a main sizer for the panel
$panelmain->SetSizer( Wx::BoxSizer->new(wxVERTICAL) );
# StaticBoxSizer for result text (framed box sizer with title)
my $sizer_results = Wx::StaticBoxSizer->new(Wx::StaticBox->new($panelmain,-1,'Command Results'),wxVERTICAL);
# FlexGridSizer for command text and label
my $sizer_command = Wx::FlexGridSizer->new(0,2,0,10); # (rows, cols, vertical-spacing, horizontal-spacing)
# zero rows indicates grow dynamically
$sizer_command->AddGrowableCol(1,1); # (column, proportion) - column index is zero based
# BoxSizer for command buttons
my $sizer_buttons = Wx::BoxSizer->new(wxHORIZONTAL);
$fillproportion = 1;
$bordersize = 3;
$flags = wxALL|wxEXPAND;
$sizer_command->Add($commandlbl, $fillproportion, $flags, $bordersize);
$sizer_command->Add($commandtext, $fillproportion, $flags, $bordersize);
$sizer_buttons->Add($execbutton, $fillproportion, $flags, $bordersize);
$sizer_results->Add($resulttext, $fillproportion, $flags, $bordersize);
$bordersize = 5;
$panelmain->GetSizer->Add($sizer_command, 0, $flags, $bordersize);
$flags = wxALL|wxALIGN_RIGHT;
$panelmain->GetSizer->Add($sizer_buttons, 0, $flags, $bordersize);
$flags = wxALL|wxEXPAND;
$panelmain->GetSizer->Add($sizer_results, $fillproportion, $flags, $bordersize);
# layout the controls
$self->SetAutoLayout(1);
$self->Layout;
# reference the panel using our method instead of scalar ref
$self->get_control('PnlMain')->SetAutoLayout(1);
$self->get_control('PnlMain')->Layout;
# set a minimum size
$self->SetSizeHints(500,400);
# set default button
$self->get_control('BtnExecute')->SetDefault();
# -- constructor complete
return $self;
}
#----------------------------------------------------------------------
# Event Handlers
#----------------------------------------------------------------------
sub evt_menu_file_exit {
my ($self, $event) = @_;
$event->Skip(1); # allow event to be processed by further handlers
$self->Close;
}
sub evt_button_execute {
my ($self, $event) = @_;
$event->Skip(1); # allow event to be processed by further handlers
my $cmd = $self->get_control('TxtCommand')->GetValue();
my $process = Wx::Perl::ProcessStream::Process->new($cmd, 'Perl Version', $self)->Run;
}
sub evt_process_stdout {
my ($self, $event) = @_;
$event->Skip(1); # allow event to be processed by further handlers
my $procname = $event->GetProcess->GetProcessName();
my $line = $event->GetLine;
my $apptext = '';
$apptext .= qq(STDOUT: $procname: $line\n);
$self->get_control('TxtResults')->AppendText($apptext);
}
sub evt_process_stderr {
my ($self, $event) = @_;
$event->Skip(1); # allow event to be processed by further handlers
my $procname = $event->GetProcess->GetProcessName();
my $line = $event->GetLine;
my $apptext = '';
$apptext .= qq(STDERR: $procname: $line\n);
$self->get_control('TxtResults')->AppendText($apptext);
}
sub evt_process_exit {
my ($self, $event) = @_;
$event->Skip(1); # allow event to be processed by further handlers
my $exitcode = $event->GetProcess->GetExitCode();
my $procname = $event->GetProcess->GetProcessName();
$event->GetProcess->Destroy;
my $apptext = qq(EXIT: $procname: $exitcode\n);
$self->get_control('TxtResults')->AppendText($apptext);
}
#----------------------------------------------------------------------
# some crufty menu subs that save access to menus and controls for me
#----------------------------------------------------------------------
sub add_menu_item {
my $self = shift;
my ($menuname, $itemname, $itemstring, $coderef) = @_;
$self->{menuitems}->{$menuname}->{$itemname} = Wx::MenuItem->new($self->{menus}->{$menuname}, -1, $itemstring, '', 0);
$self->{menus}->{$menuname}->AppendItem($self->{menuitems}->{$menuname}->{$itemname});
EVT_MENU($self, $self->{menuitems}->{$menuname}->{$itemname}->GetId(), $coderef);
return $self->{menuitems}->{$menuname}->{$itemname};
}
sub add_menu {
my $self = shift;
my($menuname, $menustring) = @_;
my $setmenubar = 0;
if(!defined($self->{menubar})) {
$self->{menubar}= Wx::MenuBar->new;
$setmenubar = 1;
}
$self->{menus}->{$menuname} = Wx::Menu->new;
$self->{menubar}->Append($self->{menus}->{$menuname},$menustring);
if($setmenubar) { $self->SetMenuBar($self->{menubar}); }
$self->{menuindex}->{$menuname} = $self->{menucount};
$self->{menucount} ++;
return $self->{menus}->{$menuname};
}
sub add_submenu {
my $self = shift;
my($menuname, $submenuname, $submenustring) = @_;
$self->{menus}->{$submenuname} = Wx::Menu->new;
$self->{menus}->{$menuname}->AppendSubMenu($self->{menus}->{$submenuname}, $submenustring );
$self->{menuindex}->{$menuname} = $self->{menucount};
$self->{menucount} ++;
return $self->{menus}->{$menuname};
}
sub add_control {
my $self = shift;
my ($controlname, $control) = @_;
$self->{controls}->{$controlname} = $control;
}
sub get_control {
my($self, $controlname) = @_;
$self->{controls}->{$controlname};
}
1;