X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FReaction%2FUI%2FWidget%2FContainer.pm;h=bd00c6285f1009db5eb52adc0f311304d1a5baa9;hb=37fd1e93572648a630a614cfa223c943c48a8fa0;hp=3b11afbfb0ab2e481f6c188d3b5128754bcd6a5a;hpb=1c41e332e495bee30ba8c31d44023fddb7e2602b;p=catagits%2FReaction.git diff --git a/lib/Reaction/UI/Widget/Container.pm b/lib/Reaction/UI/Widget/Container.pm index 3b11afb..bd00c62 100644 --- a/lib/Reaction/UI/Widget/Container.pm +++ b/lib/Reaction/UI/Widget/Container.pm @@ -4,56 +4,88 @@ use Reaction::UI::WidgetClass; use aliased 'Reaction::UI::ViewPort'; -class Container which { - - our $child_name; - - # somewhat evil. fragment returns ($name, $code) to pass to implements - # or a method modifier name, so [1] will get us just the code - - # This is convenient to do here but DO NOT duplicate this code outside of - # the same dist as WidgetClass since it's internals-dependent. - - my $child_fragment_method - = (fragment container_child { - arg '_' => $_{viewport}->$child_name; - render 'viewport'; - })[1]; - - around _method_for_fragment_name => sub { - my $orig = shift; - my $self = shift; - my ($fragment_name) = @_; - if (defined($child_name) - && $fragment_name eq $child_name) { - return $self->$orig(@_) || $child_fragment_method; - } - return $self->$orig(@_); - }; - - before _fragment_widget => sub { - my ($self, $do_render, $args, $new_args) = @_; - my @contained_names = $self->_contained_names($args->{viewport}); - foreach my $name (@contained_names) { - $new_args->{$name} ||= sub { - local $child_name = $name; - $self->render($name, @_); - }; - } - }; - - implements _contained_names => sub { - my ($self, $vp) = @_; - my @names; - foreach my $attr ($vp->meta->compute_all_applicable_attributes) { - next unless eval { $attr->type_constraint->name->isa(ViewPort) }; - my $name = $attr->name; - next if ($name eq 'outer'); - push(@names, $name); - } - return @names; - }; +use namespace::clean -except => [ qw(meta) ]; + +our $child_name; + +# somewhat evil. fragment returns ($name, $code) to pass to implements +# or a method modifier name, so [1] will get us just the code + +# This is convenient to do here but DO NOT duplicate this code outside of +# the same dist as WidgetClass since it's internals-dependent. + +my $child_fragment_method + = (fragment container_child { + arg '_' => $_{viewport}->$child_name; + render 'viewport'; + })[1]; + +around _method_for_fragment_name => sub { + my $orig = shift; + my $self = shift; + my ($fragment_name) = @_; + if (defined($child_name) + && $fragment_name eq $child_name) { + return $self->$orig(@_) || $child_fragment_method; + } + return $self->$orig(@_); +}; + +before _fragment_widget => sub { + my ($self, $do_render, $args, $new_args) = @_; + my @contained_names = $self->_contained_names($args->{viewport}); + foreach my $name (@contained_names) { + $new_args->{$name} ||= sub { + local $child_name = $name; + $self->render($name, @_); + }; + } }; +implements _contained_names => sub { + my ($self, $vp) = @_; + my @names; + foreach my $attr ($vp->meta->get_all_attributes) { + next unless eval { $attr->type_constraint->name->isa(ViewPort) }; + my $name = $attr->name; + next if ($name eq 'outer'); + push(@names, $name); + } + return @names; +}; + +__PACKAGE__->meta->make_immutable; + 1; + +__END__ + +=head1 NAME + +Reaction::UI::Widget::Container - Provide viewport attibutes in the current viewport + +=head1 DESCRIPTION + +This widget base class (with no corresponding layout set) will search the viewports +attributes for those that contain L classes or subclasses. + +These attributes will then be provided as arguments to the C fragment and +can be rendered by their attribute name. + +=head1 FRAGMENTS + +=head2 widget + +Provides rendering callbacks to those attributes of the viewport that can contain +viewport objects as arguments to the C layout. + +=head1 AUTHORS + +See L for authors. + +=head1 LICENSE + +See L for the license. + +=cut