Commit | Line | Data |
7adfd53f |
1 | package Reaction::UI::LayoutSet; |
2 | |
3 | use Reaction::Class; |
4 | use File::Spec; |
5 | |
6 | class LayoutSet which { |
7 | |
f2fef590 |
8 | has 'layouts' => (is => 'ro', default => sub { {} }); |
7adfd53f |
9 | |
10 | has 'name' => (is => 'ro', required => 1); |
11 | |
12 | has 'source_file' => (is => 'rw', lazy_fail => 1); |
1c41e332 |
13 | |
e22de101 |
14 | has 'file_extension'=> (isa => 'Str', is => 'rw', lazy_build => 1); |
15 | |
aa8c0c90 |
16 | has 'widget_class' => ( |
17 | is => 'rw', lazy_fail => 1, predicate => 'has_widget_class' |
18 | ); |
19 | |
1c41e332 |
20 | has 'widget_type' => (is => 'rw', lazy_build => 1); |
21 | |
aa8c0c90 |
22 | has 'super' => (is => 'rw', predicate => 'has_super'); |
f2fef590 |
23 | |
89939ff9 |
24 | implements _build_file_extension => as { 'html' }; |
7adfd53f |
25 | |
26 | implements 'BUILD' => as { |
27 | my ($self, $args) = @_; |
28 | my @path = @{$args->{search_path}||[]}; |
29 | confess "No search_path provided" unless @path; |
aa8c0c90 |
30 | confess "No view object provided" unless $args->{view}; |
7adfd53f |
31 | my $found; |
e22de101 |
32 | my $ext = $self->file_extension; |
7adfd53f |
33 | SEARCH: foreach my $path (@path) { |
e22de101 |
34 | my $cand = $path->file($self->name . ".${ext}"); |
35 | #print STDERR $cand,"\n"; |
7adfd53f |
36 | if ($cand->stat) { |
aa8c0c90 |
37 | $self->_load_file($cand, $args); |
7adfd53f |
38 | $found = 1; |
39 | last SEARCH; |
40 | } |
41 | } |
42 | confess "Unable to load file for LayoutSet ".$self->name unless $found; |
aa8c0c90 |
43 | unless ($self->has_widget_class) { |
44 | $self->widget_class($args->{view}->widget_class_for($self)); |
45 | } |
f2fef590 |
46 | }; |
47 | |
48 | implements 'widget_order_for' => as { |
49 | my ($self, $name) = @_; |
aa8c0c90 |
50 | return ( |
51 | ($self->has_layout($name) |
52 | ? ([ $self->widget_class, $self ]) #; |
53 | : ()), |
54 | ($self->has_super |
55 | ? ($self->super->widget_order_for($name)) |
56 | : ()), |
57 | ); |
7adfd53f |
58 | }; |
59 | |
aa8c0c90 |
60 | implements 'layout_names' => as { |
61 | my ($self) = @_; |
62 | my %seen; |
63 | return [ |
64 | grep { !$seen{$_}++ } |
65 | keys %{shift->layouts}, |
66 | ($self->has_super |
67 | ? (@{$self->super->layout_names}) |
68 | : ()) |
69 | ]; |
70 | }; |
f2fef590 |
71 | |
72 | implements 'has_layout' => as { exists $_[0]->layouts->{$_[1]} }; |
73 | |
7adfd53f |
74 | implements '_load_file' => as { |
aa8c0c90 |
75 | my ($self, $file, $build_args) = @_; |
7adfd53f |
76 | my $data = $file->slurp; |
f2fef590 |
77 | my $layouts = $self->layouts; |
78 | # cheesy match for "=for layout name ... =something" |
7adfd53f |
79 | # final split group also handles last in file, (?==) is lookahead |
f2fef590 |
80 | # assertion for '=' so "=for layout name1 ... =for layout name2" |
81 | # doesn't have the match pos go past the latter = and lose name2 |
aa8c0c90 |
82 | while ($data =~ m/=(.*?)\n(.*?)(?:\n(?==)|$)/sg) { |
83 | my ($data, $text) = ($1, $2); |
aa8c0c90 |
84 | if ($data =~ /^for layout (\S+)/) { |
85 | my $fname = $1; |
cf272446 |
86 | $text =~ s/^(?:\s*\r?\n)+//; #remove leading empty lines |
87 | $text =~ s/[\s\r\n]+$//; #remove trailing whitespace |
88 | $layouts->{$fname} = $text; |
aa8c0c90 |
89 | } elsif ($data =~ /^extends (\S+)/) { |
90 | my $super_name = $1; |
91 | $self->super($build_args->{view}->create_layout_set($super_name)) |
1c41e332 |
92 | } elsif ($data =~ /^widget (\S+)/) { |
93 | my $widget_type = $1; |
94 | $self->widget_type($1); |
aa8c0c90 |
95 | } elsif ($data =~ /^cut/) { |
96 | # no-op |
97 | } else { |
98 | confess "Unparseable directive ${data}"; |
99 | } |
7adfd53f |
100 | } |
101 | $self->source_file($file); |
102 | }; |
103 | |
1c41e332 |
104 | implements '_build_widget_type' => as { |
7adfd53f |
105 | my ($self) = @_; |
6ab43711 |
106 | my $widget = join('', map { ucfirst($_) } split('_', $self->name)); |
107 | $widget = join('::', map { ucfirst($_) } split('/', $widget)); |
108 | |
e22de101 |
109 | #print STDERR "--- ", $self->name, " maps to widget $widget \n"; |
6ab43711 |
110 | |
111 | return $widget; |
7adfd53f |
112 | }; |
7b78a39d |
113 | |
7adfd53f |
114 | }; |
115 | |
116 | 1; |