use Reaction::Class;
use File::Spec;
-class LayoutSet which {
+use namespace::clean -except => [ qw(meta) ];
- has 'layouts' => (is => 'ro', default => sub { {} });
- has 'name' => (is => 'ro', required => 1);
+has 'layouts' => (is => 'ro', default => sub { {} });
- has 'source_file' => (is => 'ro', required => 1);
+has 'name' => (is => 'ro', required => 1);
- has 'widget_class' => (
- is => 'rw', lazy_fail => 1, predicate => 'has_widget_class'
- );
-
- has 'widget_type' => (is => 'rw', lazy_build => 1);
+has 'source_file' => (is => 'ro', required => 1);
- has 'super' => (is => 'rw', predicate => 'has_super');
+has 'widget_class' => (
+ is => 'rw', lazy_fail => 1, predicate => 'has_widget_class'
+);
- implements 'BUILD' => as {
- my ($self, $args) = @_;
- my @path = @{$args->{search_path}||[]};
- confess "No view object provided" unless $args->{view};
- confess "No skin object provided" unless $args->{skin};
- $self->_load_file($self->source_file, $args);
- unless ($self->has_widget_class) {
- $self->widget_class($args->{view}->widget_class_for($self));
- }
- };
+has 'widget_type' => (is => 'rw', lazy_build => 1);
- implements 'widget_order_for' => as {
- my ($self, $name) = @_;
- return (
- ($self->has_layout($name)
- ? ([ $self->widget_class, $self ]) #;
- : ()),
+has 'super' => (is => 'rw', predicate => 'has_super');
+sub BUILD {
+ my ($self, $args) = @_;
+ my @path = @{$args->{search_path}||[]};
+ confess "No skin object provided" unless $args->{skin};
+ confess "No top skin object provided" unless $args->{top_skin};
+ $self->_load_file($self->source_file, $args);
+ unless ($self->has_widget_class) {
+ $self->widget_class($args->{skin}->widget_class_for($self));
+ }
+};
+sub widget_order_for {
+ my ($self, $name) = @_;
+ return (
+ ($self->has_layout($name)
+ ? ([ $self->widget_class, $self ]) #;
+ : ()),
+ ($self->has_super
+ ? ($self->super->widget_order_for($name))
+ : ()),
+ );
+};
+sub layout_names {
+ my ($self) = @_;
+ my %seen;
+ return [
+ grep { !$seen{$_}++ }
+ keys %{shift->layouts},
($self->has_super
- ? ($self->super->widget_order_for($name))
- : ()),
- );
- };
-
- 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, $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/=(.*?)\n(.*?)(?:\n(?==)|$)/sg) {
- my ($data, $text) = ($1, $2);
- if ($data =~ /^for layout (\S+)/) {
- my $fname = $1;
- $text =~ s/^(?:\s*\r?\n)+//; #remove leading empty lines
- $text =~ s/[\s\r\n]+$//; #remove trailing whitespace
- $layouts->{$fname} = $text;
- } elsif ($data =~ /^extends (\S+)/) {
- my $super_name = $1;
- my $skin;
- if ($super_name eq 'NEXT') {
- confess "No next skin and layout extends NEXT"
- unless $build_args->{next_skin};
- $skin = $build_args->{next_skin};
- $super_name = $self->name;
- } else {
- $skin = $build_args->{skin};
- }
- $self->super($skin->create_layout_set($super_name));
- } elsif ($data =~ /^widget (\S+)/) {
- my $widget_type = $1;
- $self->widget_type($1);
- } elsif ($data =~ /^cut/) {
- # no-op
+ ? (@{$self->super->layout_names})
+ : ())
+ ];
+};
+sub has_layout { exists $_[0]->layouts->{$_[1]} };
+sub _load_file {
+ my ($self, $file, $build_args) = @_;
+ my $data = $file->slurp;
+ utf8::decode($data)
+ unless utf8::is_utf8($data);
+ 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/=(.*?)\n(.*?)(?:\n(?==)|$)/sg) {
+ my ($data, $text) = ($1, $2);
+ if ($data =~ /^for layout (\S+)/) {
+ my $fname = $1;
+ $text =~ s/^(?:\s*\r?\n)+//; #remove leading empty lines
+ $text =~ s/[\s\r\n]+$//; #remove trailing whitespace
+ $layouts->{$fname} = $text;
+ } elsif ($data =~ /^extends (\S+)/) {
+ my $super_name = $1;
+ my $skin;
+ if ($super_name eq 'NEXT') {
+ confess "No next skin and layout extends NEXT"
+ unless $build_args->{next_skin};
+ $skin = $build_args->{next_skin};
+ $super_name = $self->name;
} else {
- confess "Unparseable directive ${data}";
+ $skin = $build_args->{top_skin};
}
+ $self->super($skin->create_layout_set($super_name));
+ } elsif ($data =~ /^widget (\S+)/) {
+ my $widget_type = $1;
+ $self->widget_type($1);
+ } elsif ($data =~ /^cut/) {
+ # no-op
+ } else {
+ confess "Unparseable directive ${data} in ${file}";
}
- };
+ }
+};
+sub _build_widget_type {
+ my ($self) = @_;
+ my $widget = join('', map { ucfirst($_) } split('_', $self->name));
+ $widget = join('::', map { ucfirst($_) } split('/', $widget));
- implements '_build_widget_type' => as {
- my ($self) = @_;
- my $widget = join('', map { ucfirst($_) } split('_', $self->name));
- $widget = join('::', map { ucfirst($_) } split('/', $widget));
+ #print STDERR "--- ", $self->name, " maps to widget $widget \n";
- #print STDERR "--- ", $self->name, " maps to widget $widget \n";
+ return $widget;
+};
- return $widget;
- };
+__PACKAGE__->meta->make_immutable;
-};
1;