File Coverage

blib/lib/POE/Loop/Wx.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             #############################################################################
2             ## Name: Wx.pm
3             ## Purpose: POE::Loop::Wx, wxPerl event loop for POE
4             ## Author: Mattia Barbon,
5             ## Created: 26/05/2003
6             ## Updated by: Mike Schroeder - to be compatible with POE 3.003
7             ## Updated: 21/12/2004
8             ## RCS-ID: $Id: Wx.pm,v 1.9 2007/11/29 16:33:19 mike Exp $
9             ## Copyright: (c) 2003 Mattia Barbon
10             ## Note: Part of the code comes almost straight from
11             ## POE::Loop::Gtk and POE::Loop::Select
12             ## Licence: This program is free software; you can redistribute it and/or
13             ## modify it under the same terms as Perl itself
14             #############################################################################
15              
16             package POE::Loop::Wx;
17              
18 1     1   320941 use Wx;
  0            
  0            
19             use strict;
20             use vars qw($VERSION);
21             use POE::Loop::PerlSignals;
22              
23             $VERSION = "0.04";
24              
25             package POE::Kernel;
26              
27             use strict;
28              
29             # Declare which event loop bridge is being used, but first ensure that
30             # no other bridge has been loaded.
31              
32             BEGIN {
33             die( "POE can't use Wx and " . &POE_LOOP_NAME . "\n" )
34             if defined &POE_LOOP;
35             };
36              
37             sub POE_LOOP () { LOOP_WX }
38              
39             my @loop_vectors = ("", "", "");
40             my %loop_filenos;
41             my $time_watcher_timer;
42             my $file_watcher_timer;
43              
44             ###############################################################################
45             # Administrative functions
46             ###############################################################################
47              
48             sub loop_initialize {
49             my $self = shift;
50              
51             # Initialize the vectors as vectors.
52             @loop_vectors = ( "", "", "" );
53             vec($loop_vectors[MODE_RD], 0, 1) = 0;
54             vec($loop_vectors[MODE_WR], 0, 1) = 0;
55             vec($loop_vectors[MODE_EX], 0, 1) = 0;
56              
57             # start file polling timer
58             $file_watcher_timer = POE::Loop::Wx::PollTimer->new;
59             $file_watcher_timer->Start( 50, 0 );
60             }
61              
62             sub loop_finalize {
63             my $self = shift;
64              
65             # This is "clever" in that it relies on each symbol on the left to
66             # be stringified by the => operator.
67             my %kernel_modes =
68             ( MODE_RD => MODE_RD,
69             MODE_WR => MODE_WR,
70             MODE_EX => MODE_EX,
71             );
72              
73             while (my ($mode_name, $mode_offset) = each(%kernel_modes)) {
74             my $bits = unpack("b*", $loop_vectors[$mode_offset]);
75             if (index($bits, "1") >= 0) {
76             warn " LOOP VECTOR LEAK: $mode_name = $bits\a\n";
77             }
78             }
79              
80             $time_watcher_timer->Destroy;
81             $file_watcher_timer->Destroy;
82             undef $time_watcher_timer;
83             undef $file_watcher_timer;
84             }
85              
86             sub loop_do_timeslice {
87             die "doing timeslices currently not supported in the Wx loop";
88             }
89              
90             sub loop_run {
91             Wx::wxTheApp()->MainLoop;
92             }
93              
94             sub loop_halt {
95             Wx::wxTheApp->ExitMainLoop if Wx::wxTheApp;
96             }
97              
98             sub loop_attach_uidestroy {
99             my( $self, $window ) = @_;
100              
101             # Don"t bother posting the signal if there are no sessions left. I
102             # think this is a bit of a kludge: the situation where a window
103             # lasts longer than POE::Kernel should never occur.
104             Wx::Event::EVT_CLOSE( $window,
105             sub {
106             if( $self->_data_ses_count() ) {
107             $self->_dispatch_event
108             ( $self, $self,
109             EN_SIGNAL, ET_SIGNAL, [ "UIDESTROY" ],
110             __FILE__, __LINE__, time(), -__LINE__
111             );
112             }
113             return undef;
114             }
115             );
116             }
117              
118             ###############################################################################
119             # Alarm or timer functions
120             ###############################################################################
121              
122             sub loop_reset_time_watcher {
123             my( $self, $next_time ) = @_;
124              
125             if( $time_watcher_timer ) {
126             $time_watcher_timer->Destroy;
127             undef $time_watcher_timer;
128             }
129              
130             $time_watcher_timer = POE::Loop::Wx::Timer->new;
131             $self->loop_resume_time_watcher( $next_time );
132             }
133              
134             BEGIN {
135             if( $^O eq "MSWin32" or $^O eq 'darwin' ) {
136             eval "sub MIN_TIME() { 1 }";
137             } else {
138             eval "sub MIN_TIME() { 0 }";
139             }
140             }
141              
142             sub loop_resume_time_watcher {
143             my( $self, $next_time ) = @_;
144             $time_watcher_timer = POE::Loop::Wx::Timer->new
145             unless $time_watcher_timer;
146              
147             $next_time -= time();
148             $next_time *= 1000;
149             $next_time = MIN_TIME if $next_time <= MIN_TIME;
150              
151             $time_watcher_timer->Start( $next_time, 1 );
152             }
153              
154             sub loop_pause_time_watcher {
155             $time_watcher_timer->Stop;
156             }
157              
158             ###############################################################################
159             # File activity functions; similar to POE::Loop::Select
160             ###############################################################################
161              
162             #------------------------------------------------------------------------------
163             # Maintain filehandle watchers.
164              
165             sub loop_watch_filehandle {
166             my( $self, $handle, $mode ) = @_;
167             my $fileno = fileno( $handle );
168              
169             vec( $loop_vectors[$mode], $fileno, 1 ) = 1;
170             $loop_filenos{$fileno} |= ( 1 << $mode );
171             }
172              
173             sub loop_ignore_filehandle {
174             my( $self, $handle, $mode ) = @_;
175             my $fileno = fileno( $handle );
176              
177             vec( $loop_vectors[$mode], $fileno, 1 ) = 0;
178             $loop_filenos{$fileno} &= ~ ( 1 << $mode );
179             }
180              
181             sub loop_pause_filehandle {
182             my( $self, $handle, $mode ) = @_;
183             my $fileno = fileno( $handle );
184              
185             vec( $loop_vectors[$mode], $fileno, 1 ) = 0;
186             $loop_filenos{$fileno} &= ~ ( 1 << $mode );
187             }
188              
189             sub loop_resume_filehandle {
190             my( $self, $handle, $mode ) = @_;
191             my $fileno = fileno( $handle );
192              
193             vec( $loop_vectors[$mode], $fileno, 1 ) = 1;
194             $loop_filenos{$fileno} |= ( 1 << $mode );
195             }
196              
197             # End of stuff similar to POE::Loop::Select
198              
199             package POE::Loop::Wx::Timer;
200              
201             use strict;
202             use base "Wx::Timer";
203              
204             sub Notify {
205             package POE::Kernel;
206              
207             my $self = $poe_kernel;
208              
209             $self->_data_ev_dispatch_due();
210             $self->_test_if_kernel_is_idle();
211              
212             # Register the next timeout if there are events left.
213             if( $self->get_event_count() ) {
214             $self->loop_resume_time_watcher( $self->get_next_event_time() );
215             }
216             }
217              
218             package POE::Loop::Wx::PollTimer;
219              
220             use strict;
221             use base "Wx::Timer";
222              
223             sub Notify {
224             package POE::Kernel;
225              
226             my $self = $poe_kernel;
227              
228             # Determine which files are being watched.
229             my @filenos = ();
230             while( my( $fd, $mask ) = each( %loop_filenos ) ) {
231             push( @filenos, $fd ) if $mask;
232             }
233              
234             return unless @filenos;
235              
236             # Check filehandles, or wait for a period of time to elapse.
237             my $hits = CORE::select( my $rout = $loop_vectors[MODE_RD],
238             my $wout = $loop_vectors[MODE_WR],
239             my $eout = $loop_vectors[MODE_EX],
240             0,
241             );
242              
243             return unless $hits > 0;
244              
245             # This is where they"re gathered. It"s a variant on a neat
246             # hack Silmaril came up with.
247             my( @rd_selects, @wr_selects, @ex_selects );
248             foreach ( @filenos ) {
249             push( @rd_selects, $_ ) if vec( $rout, $_, 1 );
250             push( @wr_selects, $_ ) if vec( $wout, $_, 1 );
251             push( @ex_selects, $_ ) if vec( $eout, $_, 1 );
252             }
253              
254             @rd_selects and
255             $self->_data_handle_enqueue_ready( MODE_RD, @rd_selects );
256             @wr_selects and
257             $self->_data_handle_enqueue_ready( MODE_WR, @wr_selects );
258             @ex_selects and
259             $self->_data_handle_enqueue_ready( MODE_EX, @ex_selects );
260             }
261              
262             1;
263              
264             __END__