Commit | Line | Data |
1c41e332 |
1 | package Reaction::UI::Widget::Container; |
2 | |
3 | use Reaction::UI::WidgetClass; |
4 | |
5 | use aliased 'Reaction::UI::ViewPort'; |
6 | |
bae75bee |
7 | use namespace::clean -except => [ qw(meta) ]; |
1c41e332 |
8 | |
bae75bee |
9 | |
10 | our $child_name; |
11 | |
12 | # somewhat evil. fragment returns ($name, $code) to pass to implements |
13 | # or a method modifier name, so [1] will get us just the code |
14 | |
15 | # This is convenient to do here but DO NOT duplicate this code outside of |
16 | # the same dist as WidgetClass since it's internals-dependent. |
17 | |
18 | my $child_fragment_method |
19 | = (fragment container_child { |
20 | arg '_' => $_{viewport}->$child_name; |
21 | render 'viewport'; |
22 | })[1]; |
23 | |
24 | around _method_for_fragment_name => sub { |
25 | my $orig = shift; |
26 | my $self = shift; |
27 | my ($fragment_name) = @_; |
28 | if (defined($child_name) |
29 | && $fragment_name eq $child_name) { |
30 | return $self->$orig(@_) || $child_fragment_method; |
31 | } |
32 | return $self->$orig(@_); |
1c41e332 |
33 | }; |
bae75bee |
34 | |
35 | before _fragment_widget => sub { |
36 | my ($self, $do_render, $args, $new_args) = @_; |
37 | my @contained_names = $self->_contained_names($args->{viewport}); |
38 | foreach my $name (@contained_names) { |
39 | $new_args->{$name} ||= sub { |
40 | local $child_name = $name; |
41 | $self->render($name, @_); |
42 | }; |
43 | } |
44 | }; |
45 | |
46 | implements _contained_names => sub { |
47 | my ($self, $vp) = @_; |
48 | my @names; |
4d0bacd2 |
49 | foreach my $attr ($vp->meta->get_all_attributes) { |
bae75bee |
50 | next unless eval { $attr->type_constraint->name->isa(ViewPort) }; |
51 | my $name = $attr->name; |
52 | next if ($name eq 'outer'); |
53 | push(@names, $name); |
54 | } |
55 | return @names; |
56 | }; |
57 | |
58 | __PACKAGE__->meta->make_immutable; |
59 | |
1c41e332 |
60 | 1; |
f9b32c83 |
61 | |
62 | __END__ |
63 | |
64 | =head1 NAME |
65 | |
66 | Reaction::UI::Widget::Container - Provide viewport attibutes in the current viewport |
67 | |
68 | =head1 DESCRIPTION |
69 | |
70 | This widget base class (with no corresponding layout set) will search the viewports |
71 | attributes for those that contain L<Reaction::UI::ViewPort> classes or subclasses. |
72 | |
73 | These attributes will then be provided as arguments to the C<widget> fragment and |
74 | can be rendered by their attribute name. |
75 | |
76 | =head1 FRAGMENTS |
77 | |
78 | =head2 widget |
79 | |
80 | Provides rendering callbacks to those attributes of the viewport that can contain |
81 | viewport objects as arguments to the C<widget> layout. |
82 | |
83 | =head1 AUTHORS |
84 | |
85 | See L<Reaction::Class> for authors. |
86 | |
87 | =head1 LICENSE |
88 | |
89 | See L<Reaction::Class> for the license. |
90 | |
91 | =cut |