File Coverage

blib/lib/Grid/Layout.pm
Criterion Covered Total %
statement 123 126 97.6
branch 23 36 63.8
condition n/a
subroutine 25 25 100.0
pod 0 11 0.0
total 171 198 86.3


line stmt bran cond sub pod time code
1             #_{ Encoding and name
2             =encoding utf8
3             =head1 NAME
4             Grid::Layout - Create grid based layouts.
5             =cut
6             #_}
7             package Grid::Layout;
8             #_{ use …
9 2     2   122963 use warnings;
  2         4  
  2         59  
10 2     2   10 use strict;
  2         4  
  2         42  
11 2     2   751 use utf8;
  2         28  
  2         7  
12              
13 2     2   51 use Carp;
  2         3  
  2         108  
14              
15 2     2   508 use Grid::Layout::Area;
  2         11  
  2         50  
16 2     2   442 use Grid::Layout::Cell;
  2         4  
  2         45  
17 2     2   451 use Grid::Layout::Line;
  2         4  
  2         45  
18 2     2   462 use Grid::Layout::Track;
  2         4  
  2         1814  
19             #_}
20             our $VERSION = 0.01;
21             #_{ Synopsis
22              
23             =head1 SYNOPSIS
24              
25             =cut
26             #_}
27             #_{ Description
28              
29             =head1 DESCRIPTION
30             =cut
31             #_}
32             #_{ Methods
33             #_{ POD
34             =head1 METHODS
35             =cut
36             #_}
37             sub new { #_{
38             #_{ POD
39             =head2 new
40              
41             use Grid::Layout;
42              
43             my $gl = Grid::Layout->new();
44              
45             =cut
46             #_}
47              
48              
49 1     1 0 3 my $class = shift;
50              
51 1         3 my $self = {};
52              
53 1         2 bless $self, $class;
54              
55 1         4 $self->_init_V_or_H('V');
56 1         3 $self->_init_V_or_H('H');
57              
58 1         3 $self->{cells} = [];
59              
60 1         3 return $self;
61              
62             } #_}
63             sub _init_V_or_H { #_{
64             #_{ POD
65             =head2 _init_V_or_H
66              
67             $self->_init_V_or_H('V');
68             $self->_init_V_or_H('H');
69              
70             This method is called by L twice to initialize the vertical and the horizontal components of the layout.
71              
72             The parameter C<'V'> or C<'H'> indiciates which componenents to initialize.
73              
74             =cut
75             #_}
76              
77 2     2   3 my $self = shift;
78 2         3 my $V_or_H = shift;
79              
80 2         10 $self->{$V_or_H}{tracks} = [];
81 2         4 $self->{$V_or_H}{lines } = [];
82              
83             } #_}
84             sub add_vertical_track { #_{
85             #_{ POD
86             =head2 add_vertical_track
87              
88             =cut
89             #_}
90 8     8 0 4150 my $self = shift;
91              
92              
93 8         17 my $x = $self->size_x();
94 8         19 for my $y (0 .. $self->size_y() -1) {
95 60         103 $self->_add_cell($x, $y);
96             }
97              
98 8         20 return $self->_add_track('V');
99              
100             } #_}
101             sub add_horizontal_track { #_{
102             #_{ POD
103             =head2 add_horizontal_track
104              
105             =cut
106             #_}
107 10     10 0 5406 my $self = shift;
108              
109 10         26 my $y = $self->size_y;
110 10         22 for my $x (0 .. $self->size_x()-1) {
111 20         38 $self->_add_cell($x, $y);
112             }
113              
114 10         27 return $self->_add_track('H');
115              
116             } #_}
117             sub _add_track { #_{
118             #_{ POD
119             =head2 _add_track
120              
121             =cut
122             #_}
123              
124 18     18   25 my $self = shift;
125 18         23 my $V_or_H = shift;
126              
127 18         29 my $new_track = Grid::Layout::Track->new($self, $V_or_H, scalar @{$self->{$V_or_H}->{tracks}});
  18         65  
128              
129 18 100       24 $self->_add_line($V_or_H) unless @{$self->{$V_or_H}->{tracks}}; # An extra line (the first one) needs to be added for the first vertical and horizontal track.
  18         45  
130 18         51 $self->_add_line($V_or_H);
131              
132 18         23 push @{$self->{$V_or_H}{tracks}}, $new_track;
  18         28  
133              
134 18         42 return $new_track;
135              
136             } #_}
137             sub _add_line { #_{
138             #_{ POD
139             =head2 _add_line
140              
141             $self->_add_line($V_or_H);
142              
143             Internal function, called by L, to add a vertical or horizontal L<< Grid::Layout::Line >>.
144              
145             =cut
146             #_}
147              
148 20     20   27 my $self = shift;
149 20         26 my $V_or_H = shift;
150              
151 20         25 push @{$self->{$V_or_H}->{lines}}, Grid::Layout::Line->new($self);
  20         61  
152              
153             } #_}
154             sub area { #_{
155             #_{ POD
156             =head2 area
157              
158             my $vertical_track_from = $gl->add_vertical_track(…);
159             my $horizontal_track_from = $gl->add_vertical_track(…);
160              
161             my $vertical_track_to = $gl->add_vertical_track(…);
162             my $horizontal_track_to = $gl->add_vertical_track(…);
163              
164             my $area = $gl->area($vertical_track_from, $horizontal_track_from, $vertical_track_to, $vertical_track_to);
165              
166              
167             Define an L<< Area|Grid::Layout::Area >> bound by the four Tracks;
168              
169             =cut
170             #_}
171            
172 6     6 0 4328 my $self = shift;
173              
174 6         10 my $track_v_from = shift;
175 6         8 my $track_h_from = shift;
176 6         8 my $track_v_to = shift;
177 6         8 my $track_h_to = shift;
178              
179 6 50       26 croak 'track_v_from is not a Grid::Layout::Track' unless $track_v_from->isa('Grid::Layout::Track');
180 6 50       22 croak 'track_v_to is not a Grid::Layout::Track' unless $track_v_to ->isa('Grid::Layout::Track');
181 6 50       19 croak 'track_h_from is not a Grid::Layout::Track' unless $track_h_from->isa('Grid::Layout::Track');
182 6 50       15 croak 'track_h_to is not a Grid::Layout::Track' unless $track_h_to ->isa('Grid::Layout::Track');
183              
184 6 50       16 croak 'track_v_from is not a vertical' unless $track_v_from->{V_or_H} eq 'V';
185 6 50       15 croak 'track_v_to is not a vertical' unless $track_v_to ->{V_or_H} eq 'V';
186 6 50       16 croak 'track_h_from is not a vertical' unless $track_h_from->{V_or_H} eq 'H';
187 6 50       13 croak 'track_h_to is not a vertical' unless $track_h_to ->{V_or_H} eq 'H';
188              
189 6         19 for my $x ($track_v_from->{position} .. $track_v_to->{position}) {
190 15         32 for my $y ($track_h_from->{position} .. $track_h_to->{position}) {
191 29 100       51 if ($self->cell($x, $y)->{area}) {
192 1         23 croak "cell $x/$y already belongs to an area";
193             }
194             }}
195              
196 5         22 my $area = Grid::Layout::Area->new($track_v_from, $track_h_from, $track_v_to, $track_h_to);
197              
198 5         9 for my $x ($track_v_from->{position} .. $track_v_to->{position}) {
199 12         17 for my $y ($track_h_from->{position} .. $track_h_to->{position}) {
200 26         36 $self->cell($x, $y)->{area}= $area;
201             }}
202              
203 5         11 return $area;
204              
205             } #_}
206             sub size_x { #_{
207             #_{ POD
208             =head2 size_x
209              
210             my $x = $gl->size_x();
211              
212             Returns the horizontal size (x axis) in logical cell units.
213              
214             =cut
215             #_}
216 28     28 0 915 my $self = shift;
217 28         36 return scalar @{$self->{'V'}{tracks}};
  28         88  
218             } #_}
219             sub size_y { #_{
220             #_{ POD
221             =head2 size_y
222              
223             my $y = $gl->size_y();
224              
225             Returns the vertical size (y axis) in logical cell units.
226              
227             =cut
228             #_}
229 28     28 0 40 my $self = shift;
230 28         33 return scalar @{$self->{'H'}{tracks}};
  28         78  
231             } #_}
232             sub size { #_{
233             #_{ POD
234             =head2 size
235              
236             Returns size of grid (nof vertical tracks x nof horizontal tracks);
237              
238             my ($v, $h) = $gl -> size();
239              
240             =cut
241             #_}
242              
243 5     5 0 1950 my $self = shift;
244              
245 5         13 return ($self->size_x, $self->size_y);
246             } #_}
247             sub _size { #_{
248             #_{ POD
249             =head2 _size
250              
251             Internal use.
252              
253              
254             =cut
255             #_}
256              
257 12     12   21 my $self = shift;
258 12         21 my $V_or_H = shift;
259              
260 12         20 return scalar @{$self->{$V_or_H}{tracks}},
  12         55  
261              
262             } #_}
263             sub cell { #_{
264             #_{ POD
265             =head2 cell
266              
267             my $track_v = $gl->add_vertical_track(…);
268             my $track_h = $gl->add_horizontal_track(…);
269              
270             my $cell_1 = $gl->cell($x, $y);
271             my $cell_2 = $gl->cell($track_v, $track_h);
272              
273             Return the L<< Grid::Layout::Cell >> at horizontal position C<$x> and vertical position C<$y> or where C<$track_v> and C<$track_h> intersects.
274              
275             =cut
276             #_}
277              
278 203     203 0 7441 my $self = shift;
279 203         227 my $x = shift;
280 203         246 my $y = shift;
281              
282 203 100       615 unless ($x =~ /^\d+$/) {
283 16 50       58 if ($x->isa('Grid::Layout::Track')) {
284 16 50       44 croak '$x is not a vertical track' unless $x->{V_or_H} eq 'V';
285 16         25 $x = $x->{position};
286             }
287             else {
288 0         0 croak '$x neither number nor Grid::Layout::Track';
289             }
290             }
291 203 100       426 unless ($y =~ /^\d+$/) {
292 16 50       46 if ($y->isa('Grid::Layout::Track')) {
293 16 50       32 croak '$y is not a vertical track' unless $y->{V_or_H} eq 'H';
294 16         25 $y = $y->{position};
295             }
296             else {
297 0         0 croak '$y neither number nor Grid::Layout::Track';
298             }
299             }
300              
301 203         608 return $self->{cells}->[$x][$y];
302              
303             } #_}
304             sub _add_cell { #_{
305             #_{ POD
306             =head2 _add_cell
307              
308             Internal use.
309              
310             =cut
311             #_}
312              
313 80     80   96 my $self = shift;
314 80         85 my $x = shift;
315 80         90 my $y = shift;
316              
317 80         157 $self->{cells}->[$x][$y] = Grid::Layout::Cell->new($self, $x, $y);
318              
319             } #_}
320             sub line_x { #_{
321             #_{ POD
322             =head2 line_x
323              
324             my $line = $gl->line_x($postition);
325              
326             Returns the C<< $position >>th line in horizontal direction.
327              
328             =cut
329             #_}
330              
331 3     3 0 5 my $self = shift;
332 3         4 my $position = shift;
333 3         7 return $self->_line('V', $position);
334              
335             } #_}
336             sub line_y { #_{
337             #_{ POD
338             =head2 line_y
339              
340             my $line = $gl->line_y($postition);
341              
342             Returns the C<< $position >>th line in vertical direction.
343              
344             =cut
345             #_}
346              
347 3     3 0 8 my $self = shift;
348 3         33 my $position = shift;
349              
350 3         9 return $self->_line('H', $position);
351              
352             } #_}
353             sub _line { #_{
354             #_{ POD
355             =head2 _line
356              
357             my $line = $gl->_line($V_or_H, $position)
358              
359             Returns the C<< $position >>th line in vertical or horizontal direction.
360              
361             =cut
362             #_}
363              
364 6     6   10 my $self = shift;
365 6         9 my $V_or_H = shift;
366 6         9 my $position = shift;
367              
368 6         8 return ${$self->{$V_or_H}->{lines}}[$position];
  6         24  
369              
370             } #_}
371             sub VH_opposite { #_{
372             #_{ POD
373             =head2 VH_opposite
374              
375             my $o1 = Grid::Layout::VH_opposite('H');
376             my $02 = Grid::Layout::VH_opposite('V');
377              
378             Static method. Returns C<'V'> if passed C<'H'> and vice versa.
379              
380             =cut
381             #_}
382              
383 18     18 0 109 my $V_or_H = shift;
384              
385 18 100       64 return 'H' if $V_or_H eq 'V';
386 14 50       68 return 'V' if $V_or_H eq 'H';
387              
388 0           croak "$V_or_H is neither H nor V";
389              
390             } #_}
391             #_}
392             #_{ POD: Copyright
393              
394             =head1 Copyright
395             Copyright © 2017 René Nyffenegger, Switzerland. All rights reserved.
396             This program is free software; you can redistribute it and/or modify it
397             under the terms of the the Artistic License (2.0). You may obtain a
398             copy of the full license at: L
399             =cut
400              
401             #_}
402              
403             'tq84';