diff options
Diffstat (limited to 'lib/Reaction/UI/LayoutSet.pm')
-rw-r--r-- | lib/Reaction/UI/LayoutSet.pm | 58 |
1 files changed, 44 insertions, 14 deletions
diff --git a/lib/Reaction/UI/LayoutSet.pm b/lib/Reaction/UI/LayoutSet.pm index 68d23d1..4a9c533 100644 --- a/lib/Reaction/UI/LayoutSet.pm +++ b/lib/Reaction/UI/LayoutSet.pm @@ -12,7 +12,11 @@ class LayoutSet which { has 'source_file' => (is => 'rw', lazy_fail => 1); has 'file_extension'=> (isa => 'Str', is => 'rw', lazy_build => 1); - has 'widget_class' => (is => 'rw', lazy_fail => 1); + has 'widget_class' => ( + is => 'rw', lazy_fail => 1, predicate => 'has_widget_class' + ); + + has 'super' => (is => 'rw', predicate => 'has_super'); implements _build_file_extension => as { 'html' }; @@ -20,46 +24,72 @@ class LayoutSet which { my ($self, $args) = @_; my @path = @{$args->{search_path}||[]}; confess "No search_path provided" unless @path; + confess "No view object provided" unless $args->{view}; my $found; my $ext = $self->file_extension; SEARCH: foreach my $path (@path) { my $cand = $path->file($self->name . ".${ext}"); #print STDERR $cand,"\n"; if ($cand->stat) { - $self->_load_file($cand); + $self->_load_file($cand, $args); $found = 1; last SEARCH; } } confess "Unable to load file for LayoutSet ".$self->name unless $found; - confess "No view object provided" unless $args->{view}; - $self->widget_class($args->{view}->widget_class_for($self)); + unless ($self->has_widget_class) { + $self->widget_class($args->{view}->widget_class_for($self)); + } }; implements 'widget_order_for' => as { my ($self, $name) = @_; - if ($self->has_layout($name)) { - return ([ $self->widget_class, $self ]); - } else { - return (); - } + return ( + ($self->has_layout($name) + ? ([ $self->widget_class, $self ]) #; + : ()), + ($self->has_super + ? ($self->super->widget_order_for($name)) + : ()), + ); }; - implements 'layout_names' => as { [ keys %{shift->layouts} ] }; + implements 'layout_names' => as { + my ($self) = @_; + my %seen; + return [ + grep { !$seen{$_}++ } + keys %{shift->layouts}, + ($self->has_super + ? (@{$self->super->layout_names}) + : ()) + ]; + }; implements 'has_layout' => as { exists $_[0]->layouts->{$_[1]} }; implements '_load_file' => as { - my ($self, $file) = @_; + my ($self, $file, $build_args) = @_; my $data = $file->slurp; my $layouts = $self->layouts; # cheesy match for "=for layout name ... =something" # final split group also handles last in file, (?==) is lookahead # assertion for '=' so "=for layout name1 ... =for layout name2" # doesn't have the match pos go past the latter = and lose name2 - while ($data =~ m/=for layout (.*?)\n(.+?)(?:\n(?==)|$)/sg) { - my ($fname, $text) = ($1, $2); - $layouts->{$fname} = $text; + while ($data =~ m/=(.*?)\n(.*?)(?:\n(?==)|$)/sg) { + my ($data, $text) = ($1, $2); + + if ($data =~ /^for layout (\S+)/) { + my $fname = $1; + $layouts->{$fname} = $text; + } elsif ($data =~ /^extends (\S+)/) { + my $super_name = $1; + $self->super($build_args->{view}->create_layout_set($super_name)) + } elsif ($data =~ /^cut/) { + # no-op + } else { + confess "Unparseable directive ${data}"; + } } $self->source_file($file); }; |