+++ /dev/null
-package ComponentUI::View::Site::Widget::Layout;
-
-use Reaction::UI::WidgetClass;
-
-class Layout, which {
-
- implements fragment main_content {
- if (my $inner = $_{viewport}->inner) {
- arg '_' => $inner;
- render 'viewport';
- }
- };
-
-};
-
-1;
has 'name' => (is => 'ro', required => 1);
has 'source_file' => (is => 'rw', lazy_fail => 1);
+
has 'file_extension'=> (isa => 'Str', is => 'rw', lazy_build => 1);
has 'widget_class' => (
is => 'rw', lazy_fail => 1, predicate => 'has_widget_class'
);
+ has 'widget_type' => (is => 'rw', lazy_build => 1);
+
has 'super' => (is => 'rw', predicate => 'has_super');
implements _build_file_extension => as { 'html' };
} elsif ($data =~ /^extends (\S+)/) {
my $super_name = $1;
$self->super($build_args->{view}->create_layout_set($super_name))
+ } elsif ($data =~ /^widget (\S+)/) {
+ my $widget_type = $1;
+ $self->widget_type($1);
} elsif ($data =~ /^cut/) {
# no-op
} else {
$self->source_file($file);
};
- implements 'widget_type' => as {
+ implements '_build_widget_type' => as {
my ($self) = @_;
my $widget = join('', map { ucfirst($_) } split('_', $self->name));
$widget = join('::', map { ucfirst($_) } split('/', $widget));
$rctx->dispatch($render_tree, $new_args);
};
+ implements '_method_for_fragment_name' => as {
+ my ($self, $fragment_name) = @_;
+ return $self->can("_fragment_${fragment_name}");
+ };
+
implements '_render_dispatch_order' => as {
my ($self, $fragment_name, $args, $new_args) = @_;
my @render_stack = (my $render_deep = (my $render_curr = []));
my @layout_order = $self->layout_set->widget_order_for($fragment_name);
- if (my $f_meth = $self->can("_fragment_${fragment_name}")) {
+ if (my $f_meth = $self->_method_for_fragment_name($fragment_name)) {
my @wclass_stack;
my $do_render = sub {
my $package = shift;
--- /dev/null
+package Reaction::UI::Widget::Container;
+
+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;
+ };
+
+};
+
+1;
+=widget Container
+
=for layout widget
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<div id="contents">
<div id="wrapper">
[% sidebar %]
- [% main_content %]
+ [% inner %]
</div>
<div class="spacer"></div>
</div>
</html>
-=for layout main_content
+=for layout inner
<!-- main content start -->
[% call_next %]
<!-- main content end -->