use threads; use threads::shared; use Thread::Queue; use strict; use Wx; package TheApp; use base 'Wx::App'; sub OnInit { my $self = shift; my $frame = MFrame->new(); $frame->Show(1); $self->SetTopWindow($frame); return 1; } package SFrame; use base 'Wx::Frame'; use Wx qw(wxTE_MULTILINE wxTE_READONLY wxVERTICAL wxID_DEFAULT); use Wx::Event qw(EVT_CLOSE); sub new { my $class = shift; my $self = $class->SUPER::new(undef, -1, "A Server"); $self->{text} = Wx::TextCtrl->new($self, -1, "", [-1,-1], [300, 300], wxTE_MULTILINE|wxTE_READONLY); my $sizer = Wx::BoxSizer->new(wxVERTICAL); $sizer->Add($self->{text}); $self->SetSizer($sizer); $self->Fit; return $self; } package MFrame; use base 'Wx::Frame'; use Wx qw(wxTE_MULTILINE wxTE_READONLY wxVERTICAL wxID_DEFAULT); use Wx::Event qw(EVT_COMMAND EVT_CLOSE EVT_BUTTON EVT_SIZE); my $done_event : shared = Wx::NewEventType; sub new { my $class = shift; my $self = $class->SUPER::new(undef, -1, "EvHelper"); $self->{text} = Wx::TextCtrl->new($self, -1, "", [-1,-1], [500,500], wxTE_MULTILINE|wxTE_READONLY ); $self->{button} = Wx::Button->new($self, -1, "&Start"); $self->{button2} = Wx::Button->new($self, -1, "&Zip it"); my $sizer = Wx::BoxSizer->new(wxVERTICAL); $sizer->Add($self->{text}); $sizer->Add($self->{button}); $sizer->Add($self->{button2}); $self->SetSizer($sizer); my ($sec,$min,$hour,$mday,$mon,$year,$wday, $yday,$isdst)=localtime(time); my $dt=sprintf "%4d-%02d-%02d %02d:%02d:%02d\n", $year+1900,$mon+1,$mday,$hour,$min,$sec; $self->{text}->AppendText("Program started at " . $dt . "\n"); EVT_COMMAND($self, -1, $done_event, \&done); EVT_CLOSE($self, \&on_close); EVT_BUTTON($self,$self->{button}, \&on_button ); EVT_BUTTON($self,$self->{button2}, \&on_button2 ); my $sendqueue = Thread::Queue->new(); my $worker = threads->create(\&worker, $self, $sendqueue ); $self->{queue} = $sendqueue; $self->{worker} = $worker; $self->Fit; return $self; } sub on_button { my ($self, $event) = @_; if ($self->{button}->Wx::Button::GetLabel() eq "&Start") { $self->{button}->Wx::Button::SetLabel("&Stop"); $self->{queue}->enqueue('GO'); } else { $self->{button}->Wx::Button::SetLabel("&Start"); $self->{queue}->enqueue('PAUSE'); } } sub on_button2 { my ($self, $event) = @_; if ($self->{button2}->Wx::Button::GetLabel() eq "&Zip it") { my $wcount=scalar(keys %{$self->{SFrame}})+1; my $SFrameID="SVR" . $wcount; $self->{SFrame}{$SFrameID} = SFrame->new(); EVT_CLOSE($self->{SFrame}{$SFrameID}, \&on_sframe_close); $self->{SFrame}{$SFrameID}->SetTitle("Server " . $SFrameID); $self->{SFrame}{$SFrameID}->Show(1); } } sub on_close { my ($self, $event) = @_; $self->{queue}->enqueue('STOP'); $self->{worker}->join; my $key; foreach $key (keys %{$self->{SFrame}}) { $self->{SFrame}{$key}->Destroy(); } $event->Skip(1); } sub on_sframe_close { my ($self, $event) = @_; print "WTF!\n"; } sub done { my ($self, $event) = @_; my $text = $event->GetData; my ($trash, $blipcount) = split /\ /,$text; $self->{text}->AppendText("$text\n"); my $wcount=scalar(keys %{$self->{SFrame}} ); if ($wcount>0) { my $wdest=($blipcount % $wcount); my @SFrameIDs=keys %{$self->{SFrame}}; my $SFrameID=$SFrameIDs[$wdest]; if (defined($self->{SFrame}{$SFrameID}->{text})) { $self->{SFrame}{$SFrameID}->{text}->AppendText("$text\n"); } else { print "WTF! Deleting\n"; delete $self->{SFrame}{$SFrameID}; } } } sub worker { my($handler, $queue) = @_; my $status='PAUSE'; my $blipcount=0; while (1) { my $message; if ($queue->pending > 0) { $message=$queue->dequeue; } return 1 if $message eq 'STOP'; if ($message eq 'PAUSE') { $status='PAUSE'; } if ($message eq 'GO') { $status='GO'; } if ($status eq 'GO') { $blipcount++; my $title : shared = "blip " . $blipcount; print "$title\n"; my $thread_event = Wx::PlThreadEvent->new(-1, $done_event,$title); Wx::PostEvent($handler, $thread_event); } sleep 1; } } package main; TheApp->new->MainLoop;