package Reaction::UI::Widget::Container; use Reaction::UI::WidgetClass; use aliased 'Reaction::UI::ViewPort'; 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