File Coverage

blib/lib/POE/XUL/State.pm
Criterion Covered Total %
statement 121 141 85.8
branch 27 32 84.3
condition 13 22 59.0
subroutine 32 45 71.1
pod 0 40 0.0
total 193 280 68.9


line stmt bran cond sub pod time code
1             package POE::XUL::State;
2             # $Id: State.pm 1566 2010-11-03 03:13:32Z fil $
3             # Copyright Philip Gwyn 2007-2010. All rights reserved.
4             # Based on code Copyright 2003-2004 Ran Eilam. All rights reserved.
5              
6             #
7             # ROLE: Track all the changes to a node so they may be sent to the browser.
8             # All normal responses are generated here, either by ->flush. Or in
9             # some cases calling the make_command directly.
10             #
11             # {buffer} is list of attribute key/value pairs set on state since last flush
12             # {is_new} is true if we have never been flushed before
13             # {is_destroyed} true after node has been destroyed
14             #
15              
16 19     19   60 use strict;
  19         21  
  19         430  
17 19     19   53 use warnings;
  19         24  
  19         411  
18              
19 19     19   64 use Scalar::Util qw( blessed );
  19         27  
  19         644  
20 19     19   59 use Carp;
  19         19  
  19         691  
21              
22 19     19   65 use constant DEBUG => 0;
  19         24  
  19         22979  
23              
24             our $VERSION = '0.0601';
25             our $ID = 0;
26              
27              
28             ##############################################################
29             sub new
30             {
31 42     42 0 44 my( $package, $node ) = @_;
32 42         167 my $self = bless {
33             buffer => [],
34             deferred_buffer => [],
35             is_new => 1,
36             is_destroyed => 0,
37             is_textnode => 0
38             }, $package;
39              
40 42         37 my $id;
41 42 100 66     393 if( blessed $node and $node->can( 'getAttribute' ) and
      66        
42             $node->getAttribute( 'id' ) ) {
43 28         51 $id = $node->getAttribute( 'id' );
44             }
45             else {
46 14         25 $id = 'PX' . $ID++;
47 14 50       24 if( $node ) {
48             # set the nodes attribute to the generated ID
49             # 2008/10 do NOT use setAttribute, it will call the CM which will
50             # try to build a new State. Infinite recursion.
51 14   33     57 $node->{attributes}{id} ||= $id;
52             }
53             }
54 42         96 $self->{orig_id} = $self->{id} = $id;
55              
56 42         73 return $self;
57             }
58              
59             ##############################################################
60             sub flush
61             {
62 176     176 0 124 my( $self ) = @_;
63 176         177 my @out = $self->as_command;
64 176         169 $self->{is_new} = 0;
65 176 50       234 $self->{index} = delete $self->{trueindex} if defined $self->{trueindex};
66 176         194 $self->clear_buffer;
67 176         289 return @out;
68             }
69              
70             # command building ------------------------------------------------------------
71              
72             sub as_command {
73 176     176 0 131 my $self = shift;
74              
75 176         132 my $is_new = $self->{is_new};
76 176         115 my $is_destroyed = $self->{is_destroyed};
77              
78             # TODO: this is probably a bad idea
79 176 50 66     329 return if $is_new && $is_destroyed;
80              
81 176 100       260 if( $is_destroyed ) {
    100          
    100          
82 3         5 return $self->get_buffer_as_commands;
83             }
84             elsif( $self->is_textnode ) {
85 42         53 return $self->make_command_textnode;
86             }
87             elsif( $self->{cdata} ) {
88 8 100       14 return unless $self->{is_new};
89 5         8 return $self->make_command_cdata;
90             }
91             else {
92 123         144 return $self->make_command_new, $self->get_buffer_as_commands;
93             }
94             }
95              
96             sub as_deferred_command {
97 173     173 0 133 my $self = shift;
98              
99 173         144 my $is_new = $self->{is_new};
100 173         124 my $is_destroyed = $self->{is_destroyed};
101              
102             # TODO: this is probably a bad idea
103 173 50       211 return if $is_destroyed;
104 173         188 return $self->get_buffer_as_deferred_commands;
105             }
106              
107             ##############################################################
108             sub make_command_new
109             {
110 123     123 0 96 my( $self ) = @_;
111 123 100       240 return unless $self->{is_new};
112             # return unless $self->get_tag;
113            
114             my @cmd = ( 'new',
115             $self->{orig_id},
116 26   100     50 $self->get_tag,
117             ( $self->get_parent_id || '' )
118             );
119 26 100       56 if( exists $self->{index} ) {
120 21         31 push @cmd, $self->{index};
121             }
122              
123 26         34 delete $self->{orig_id};
124              
125 26         52 return \@cmd;
126             }
127              
128             ##############################################################
129             sub make_command_bye
130             {
131 2     2 0 3 my( $self, $parent_id, $index ) = @_;
132 2         6 return [ bye => $self->{id} ] #, $parent_id, $index ];
133             }
134              
135             ##############################################################
136             sub make_command_textnode
137             {
138 42     42 0 30 my( $self ) = @_;
139 42 100 33     121 return unless $self->{buffer} and $self->{buffer}[-1];
140             my $ret = [ 'textnode',
141             $self->get_parent_id,
142             $self->{index},
143 14         17 $self->{buffer}[-1][-1]
144             ];
145 14         23 return $ret;
146             }
147              
148             ##############################################################
149             sub make_command_textnode_bye
150             {
151 1     1 0 2 my( $self, $parent_id, $index ) = @_;
152 1         3 return [ 'bye-textnode', $parent_id, $index ];
153             }
154              
155             ##############################################################
156             sub make_command_cdata
157             {
158 5     5 0 5 my( $self ) = @_;
159             # use Data::Dumper;
160             # warn Dumper $self->{buffer};
161             my $ret = [ 'cdata',
162             $self->get_parent_id,
163             $self->{index},
164             $self->{cdata}
165 5         6 ];
166 5         10 return $ret;
167             }
168              
169             ##############################################################
170             sub make_command_cdata_bye
171             {
172 0     0 0 0 my( $self, $parent_id, $index ) = @_;
173 0         0 return [ 'bye-cdata', $parent_id, $index ];
174             }
175              
176              
177             ##############################################################
178             sub make_command_SID
179             {
180 0     0 0 0 my( $package, $SID ) = @_;
181 0         0 return [ 'SID', $SID ];
182             }
183              
184             ##############################################################
185             sub make_command_boot
186             {
187 0     0 0 0 my( $package, $msg ) = @_;
188 0         0 return [ 'boot', $msg ];
189             }
190              
191             #############################################################
192             sub make_command_set
193             {
194 39     39 0 32 my($self, $key, $value) = @_;
195              
196 39         88 return [ 'set', $self->{id}, $key, $value ];
197             }
198              
199             #############################################################
200             sub make_command_method
201             {
202 1     1 0 2 my($self, $key, $args) = @_;
203              
204 1         3 return [ 'method', $self->{id}, $key, $args ];
205             }
206              
207             #############################################################
208             sub make_command_style
209             {
210 8     8 0 7 my($self, $property, $value) = @_;
211              
212 8         15 $property =~ s/-([a-z])/\U$1/g;
213 8         21 return [ 'style', $self->{id}, $property, $value ];
214             }
215              
216             #############################################################
217             sub make_command_remove
218             {
219 2     2 0 4 my($self, $key) = @_;
220 2         7 return [ 'remove', $self->{id}, $key ];
221             }
222              
223              
224              
225             #############################################################
226             sub get_buffer_as_commands
227             {
228 126     126 0 93 my( $self ) = @_;
229 126         136 return $self->get_buffer;
230             }
231              
232             #############################################################
233             sub get_buffer_as_deferred_commands
234             {
235 173     173 0 123 my( $self ) = @_;
236              
237             # Just in case the ID changed since the command was added
238             # to the deferred buffer
239 173         193 foreach my $cmd ( $self->get_deferred_buffer ) {
240 1         2 $cmd->[1] = $self->{id};
241             }
242 173         173 return $self->get_deferred_buffer;
243             }
244              
245             sub set_trueindex
246             {
247 0     0 0 0 my( $self, $index ) = @_;
248              
249 0         0 $self->{trueindex} = $index;
250             }
251              
252              
253             #############################################################
254             sub set_attribute
255             {
256 39     39 0 40 my( $self, $key, $value ) = @_;
257 39 50 50     89 if( $key eq 'id' and ($self->{orig_id}||'' ) eq $value ) {
      66        
258 0         0 return;
259             }
260 39         65 my $cmd = $self->make_command_set( $key, $value );
261 39 100       57 if( $key eq 'selectedIndex' ) {
262 1         1 push @{ $self->{deferred_buffer} }, $cmd;
  1         2  
263             }
264             else {
265 38         29 push @{$self->{buffer}}, $cmd;
  38         68  
266             }
267 39         64 return;
268             }
269              
270             #############################################################
271             sub remove_attribute
272             {
273 2     2 0 5 my( $self, $key ) = @_;
274              
275 2         3 push @{$self->{buffer}}, $self->make_command_remove( $key );
  2         9  
276 2         5 return;
277             }
278              
279             #############################################################
280             sub method_call
281             {
282 1     1 0 2 my( $self, $key, $args ) = @_;
283 1         2 push @{$self->{buffer}}, $self->make_command_method( $key, $args );
  1         3  
284 1         2 return;
285             }
286              
287             #############################################################
288             sub style_change
289             {
290 8     8 0 8 my( $self, $property, $value ) = @_;
291 8         7 push @{$self->{buffer}}, $self->make_command_style( $property, $value );
  8         16  
292 8         16 return;
293             }
294              
295             #############################################################
296             sub is_destroyed
297             {
298 3     3 0 3 my( $self, $parent, $index ) = @_;
299 3         3 $self->{is_destroyed} = 1;
300              
301 3         4 my $cmd;
302 3 100       5 if( $self->{is_textnode} ) {
303 1         5 $cmd = $self->make_command_textnode_bye( $parent->id, $index );
304             }
305             else {
306 2         8 $cmd = $self->make_command_bye( $parent->id, $index );
307             }
308             # 2007/05 -- If the node disapears, we want to skip all other commands
309             # that might be sent. However, there might be a case were a commands
310             # side effects are desired, so we are pushing. However that breaks when
311             # something is a "late" command.
312 3         4 push @{ $self->{buffer} }, $cmd;
  3         6  
313 3         5 return;
314             }
315              
316             #############################################################
317             sub dispose
318             {
319 0     0 0 0 my( $self ) = @_;
320 0         0 $self->clear_buffer;
321             }
322              
323             # accessors -------------------------------------------------------------------
324              
325 0     0 0 0 sub get_id { $_[0]->{id} }
326 82     82 0 213 sub id { $_[0]->{id} }
327 26     26 0 50 sub get_tag { $_[0]->{tag} }
328 0     0 0 0 sub is_new { $_[0]->{is_new} }
329 126     126 0 78 sub get_buffer { @{$_[0]->{buffer}} }
  126         233  
330 346     346 0 195 sub get_deferred_buffer { @{ $_[0]->{deferred_buffer} } }
  346         548  
331 173     173 0 341 sub is_textnode { $_[0]->{is_textnode} }
332             sub get_parent_id {
333 45     45 0 39 my( $self ) = @_;
334 45 100       89 return unless $self->{parent};
335 40         60 $self->{parent}->id;
336             }
337              
338             # modifiers -------------------------------------------------------------------
339              
340 0     0 0 0 sub set_id { delete $_[0]->{default_id}; $_[0]->{id} = $_[1] }
  0         0  
341 0     0 0 0 sub set_tag { $_[0]->{tag} = lc $_[1] }
342 0     0 0 0 sub set_old { $_[0]->{is_new} = 0 }
343 0     0 0 0 sub set_index { $_[0]->{index} = $_[1] }
344 176     176 0 158 sub clear_buffer { $_[0]->{buffer} = [];
345 176         178 $_[0]->{deferred_buffer} = []; }
346 0     0 0   sub set_destroyed { $_[0]->{is_destroyed} = 1 }
347 0     0 0   sub set_textnode { $_[0]->{is_textnode} = 1 }
348             # sub set_parent_id { $_[0]->{parent_id} = $_[1] }
349              
350              
351             1;