Skip to content
Browse files

simple layout rework

  • Loading branch information...
1 parent d1171af commit 7f435b2b206b3225731ba7ae58974072a1ac84e8 @phaylon committed May 15, 2011
View
33 lib/ReUI/Types/Common.pm
@@ -4,7 +4,7 @@ use strictures 1;
package ReUI::Types::Common;
-use ReUI::Util qw( human_join_with );
+use ReUI::Util qw( human_join_with load_class );
use Moose::Util qw( does_role );
use Moose::Util::TypeConstraints qw( register_type_constraint );
use MooseX::Types::Path::Class qw( :all );
@@ -38,6 +38,8 @@ use MooseX::Types -declare => [qw(
StrList
MessageType
CodeRefList
+ Container
+ Proto
)];
my $rxNamespaceStr = qr{
@@ -52,6 +54,14 @@ my $rxNamespaceStr = qr{
\Z
}x;
+fun load_proto ($proto) {
+ return $proto
+ if is_blessed $proto;
+ my %args = %$proto;
+ my $class = delete $args{class};
+ return load_class($class)->new(%args);
+}
+
subtype CodeRefList, as ArrayRef[ CodeRef ];
coerce CodeRefList, from CodeRef, via { [$_] };
@@ -156,6 +166,27 @@ coerce DirList,
subtype Renderable,
as Str | I18N | Does['ReUI::Widget::API'];
+subtype Proto, as Dict[ class => NonEmptySimpleStr, slurpy Any ];
+
+subtype Container, as class_type('ReUI::Widget::Container');
+
+coerce Container,
+ from ArrayRef[ Proto | Does['ReUI::Widget::API'] ], via {
+ return load_class('ReUI::Widget::Container')->new(
+ widgets => [ map { load_proto($_) } @$_ ],
+ );
+ },
+ from Proto, via {
+ return load_class('ReUI::Widget::Container')->new(
+ widgets => [ load_proto($_) ],
+ );
+ },
+ from Does['ReUI::Widget::API'], via {
+ return load_class('ReUI::Widget::Container')->new(
+ widgets => [ $_ ],
+ );
+ };
+
1;
__END__
View
1 lib/ReUI/Widget/Container.pm
@@ -24,6 +24,7 @@ has widgets => (
add => 'push',
is_empty => 'is_empty',
widget => 'get',
+ has_widgets => 'count',
},
);
View
90 lib/ReUI/Widget/Layout/Simple.pm
@@ -0,0 +1,90 @@
+use strictures 1;
+
+package ReUI::Widget::Layout::Simple;
+use Moose;
+
+use ReUI::Traits qw( Lazy RelatedClass );
+use ReUI::Types qw( Container );
+
+use syntax qw( function method );
+use namespace::autoclean;
+
+
+my @FixedSections = qw( header content footer );
+my @LooseSections = qw( left right );
+my @Sections = (@FixedSections, @LooseSections);
+
+
+for my $section (@Sections) {
+ has "${section}_class" => (
+ traits => [ RelatedClass ],
+ );
+ has $section => (
+ traits => [ Lazy ],
+ isa => Container,
+ coerce => 1,
+ handles => {
+ "add_to_${section}" => 'add',
+ "${section}_widgets" => 'widgets',
+ "has_${section}_widgets" => 'has_widgets',
+ "${section}_widget" => 'widget',
+ "${section}_is_empty" => 'is_empty',
+ "compile_${section}" => 'compile',
+ },
+ );
+ __PACKAGE__->meta->add_method("_build_${section}", method {
+ return $self->can("make_${section}")->($self);
+ });
+ __PACKAGE__->meta->add_method("_build_${section}_class", method {
+ return 'ReUI::Widget::Container';
+ });
+}
+
+method _compile_section ($state, $section) {
+ return $self->can("compile_${section}")->($self, $state);
+}
+
+method _has_widgets ($section) {
+ return $self->can("has_${section}_widgets")->($self);
+}
+
+
+method inner_content_populator ($state) {
+ return fun ($zoom, $section) {
+ return $zoom
+ ->select(".layout-${section}-inner")
+ ->replace_content($self->_compile_section($state, $section));
+ };
+}
+
+method compile ($state) {
+ my $replace_inner = $self->inner_content_populator($state);
+ my $remove_or_insert = fun ($zoom, $section) {
+ return $zoom->select(".layout-${section}")->replace([])
+ unless $self->_has_widgets($section);
+ return $zoom->$replace_inner($section);
+ };
+ return $state->markup_for($self)
+ ->apply($self->identity_populator_for('.layout-simple'))
+ ->apply(sub {
+ my $zoom = $_;
+ for my $section (@FixedSections) {
+ $zoom = $zoom->$replace_inner($section)->memoize;
+ }
+ for my $section (@LooseSections) {
+ $zoom = $zoom->$remove_or_insert($section)->memoize;
+ }
+ return $zoom;
+ });
+}
+
+
+with qw(
+ ReUI::Widget::API
+ ReUI::Widget::API::Styled
+ ReUI::Role::ElementClasses
+);
+
+__PACKAGE__->meta->make_immutable;
+
+1;
View
34 lib/ReUI/Widget/Page/Layout/Role/Header.pm
@@ -1,34 +0,0 @@
-use strictures 1;
-
-package ReUI::Widget::Page::Layout::Role::Header;
-use Moose::Role;
-
-use ReUI::Traits qw( Lazy RelatedClass );
-
-use aliased 'ReUI::Widget::Page::Header';
-
-use syntax qw( function method );
-use namespace::autoclean;
-
-
-has header_class => (
- traits => [ RelatedClass ],
-);
-
-method _build_header_class { Header }
-
-
-has header => (
- traits => [ Lazy ],
- is => 'ro',
- isa => Header,
-);
-
-method _build_header {
- return $self->make_header(
- content => $self->title,
- );
-}
-
-
-1;
View
43 lib/ReUI/Widget/Page/Layout/Simple.pm
@@ -1,43 +0,0 @@
-use strictures 1;
-
-package ReUI::Widget::Page::Layout::Simple;
-use Moose;
-
-use ReUI::Types qw( Bool );
-use ReUI::Traits qw( Lazy Resolvable );
-
-use syntax qw( function method );
-use namespace::autoclean;
-
-extends 'ReUI::Widget::Page';
-
-
-has show_header => (
- traits => [ Lazy, Resolvable ],
- is => 'rw',
- isa => Bool,
-);
-
-method _build_show_header { 1 }
-
-
-around compile_widgets => fun ($orig, $self, $state, @widgets) {
- my $show_header = $self->resolve_show_header($state);
- my $header = $self->header;
- return $self->$orig(
- $state,
- $show_header ? $header : (),
- @widgets,
- );
-};
-
-around event_propagation_targets => fun ($orig, $self, @args) {
- return $self->$orig(@args), $self->header;
-};
-
-
-with qw(
- ReUI::Widget::Page::Layout::Role::Header
-);
-
-1;
View
7 share/module/ReUI-Widget-Layout-Simple/base.html
@@ -0,0 +1,7 @@
+<div class="layout layout-simple">
+ <div class="layout-header layout-header-inner">Header</div>
+ <div class="layout-left layout-left-inner">Left</div>
+ <div class="layout-right layout-right-inner">Right</div>
+ <div class="layout-content layout-content-inner">Content</div>
+ <div class="layout-footer layout-footer-inner">Footer</div>
+</div>
View
71 t/widget-layout-simple.t
@@ -0,0 +1,71 @@
+use strictures 1;
+use Test::More;
+use Test::Fatal;
+use ReUI::Test;
+
+use aliased 'ReUI::Widget::Layout::Simple';
+
+use syntax qw( function );
+
+
+my %test_content = map {
+ ($_ => test_widget($_));
+} qw( header footer left right content );
+
+
+test_processing('empty',
+ { widget => Simple->new(id => 'my-layout', classes => [qw( foo bar )]) },
+ test_markup(fun ($markup) {
+ $markup->into('/div', fun ($layout) {
+ $layout->classes(qw( layout-simple layout foo bar ));
+ $layout->attr_is(id => 'my-layout');
+ $layout->into('./div',
+ fun ($header) {
+ $header->classes(qw(
+ layout-header
+ layout-header-inner
+ ));
+ $header->content_is('');
+ },
+ fun ($content) {
+ $content->classes(qw(
+ layout-content
+ layout-content-inner
+ ));
+ $content->content_is('');
+ },
+ fun ($footer) {
+ $footer->classes(qw(
+ layout-footer
+ layout-footer-inner
+ ));
+ $footer->content_is('');
+ },
+ );
+ });
+ }),
+);
+
+test_processing('filled',
+ { widget => Simple->new(
+ header => $test_content{header},
+ left => $test_content{left},
+ content => $test_content{content},
+ right => $test_content{right},
+ footer => $test_content{footer},
+ ),
+ },
+ test_markup(fun ($markup) {
+ $markup->into('/div', fun ($layout) {
+ $layout->classes(qw( layout-simple layout ));
+ $layout->into('./div', map {
+ my $name = $_;
+ fun ($section) {
+ $section->contains_test_value($name);
+ };
+ } qw( header left right content footer ));
+ });
+ }),
+);
+
+done_testing;
View
1 t/widget-navigation-trail.t
@@ -118,5 +118,4 @@ test_processing('limit by trailing',
),
);
-
done_testing;
View
49 t/widget-page-layout-simple.t
@@ -1,49 +0,0 @@
-use strictures 1;
-use Test::More;
-use ReUI::Test;
-use URI;
-
-use aliased 'ReUI::Widget::Page::Layout::Simple';
-
-use syntax qw( function );
-
-my $content = test_widget('page-content');
-my $logo_uri = 'http://example.com/logo.png';
-my $home_uri = 'http://example.com/';
-
-test_processing('complete and explicit',
- { widget => Simple->new(
- title => 'Test Title',
- header_arguments => {
- logo_link_uri => $home_uri,
- logo_image_uri => $logo_uri,
- },
- widgets => [
- $content,
- ],
- ),
- },
- test_markup(fun ($markup) {
- $markup->into('//html', fun ($page) {
- $page->into('./head', fun ($head) {
- $head->is('./title', 'Test Title', 'document title');
- });
- $page->into('./body', fun ($body) {
- $body->contains_test_value('page-content');
- $body->into('./div[@id="page-header"]', fun ($header) {
- $header->like('.', qr{Test Title}, 'page title');
- $header->into('./a', fun ($link) {
- $link->attr_is(href => $home_uri);
- $link->attr_is(id => 'page-header-logo-link');
- $link->into('./img', fun ($logo) {
- $link->attr_is(src => $logo_uri);
- $link->attr_is(id => 'page-header-logo');
- });
- });
- });
- });
- });
- }),
-);
-
-done_testing;

0 comments on commit 7f435b2

Please sign in to comment.
Something went wrong with that request. Please try again.