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