X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FReaction%2FUI%2FLayoutSet.pm;h=1ebc64639ba9bc229de0d5291a5745b38c61a59b;hb=4edebf11a6eb893a7dea6aedd7565497b8907b6b;hp=77a0dac663c38ad922b0a733d9ac4dd6a9cac0bf;hpb=f6b79841f315129d8e1261614efaa8253d286dee;p=catagits%2FReaction.git diff --git a/lib/Reaction/UI/LayoutSet.pm b/lib/Reaction/UI/LayoutSet.pm index 77a0dac..1ebc646 100644 --- a/lib/Reaction/UI/LayoutSet.pm +++ b/lib/Reaction/UI/LayoutSet.pm @@ -3,106 +3,105 @@ package Reaction::UI::LayoutSet; 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 skin object provided" unless $args->{skin}; - $self->_load_file($self->source_file, $args); - unless ($self->has_widget_class) { - $self->widget_class($args->{skin}->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;