diff options
author | matthewt <matthewt@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7> | 2008-01-30 16:33:10 +0000 |
---|---|---|
committer | matthewt <matthewt@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7> | 2008-01-30 16:33:10 +0000 |
commit | 8a293e2eee23938229a7dbfb617faee579914dfc (patch) | |
tree | f1626e9facac38a6b323c92e7d31585e5902cbba /lib/Reaction | |
parent | 46937531eb2d28950b21c8b0982539e28b277b60 (diff) | |
download | reaction-8a293e2eee23938229a7dbfb617faee579914dfc.tar.gz reaction-8a293e2eee23938229a7dbfb617faee579914dfc.zip |
first cut of Reaction::UI::Skin and SiteLayout VP+widget
Diffstat (limited to 'lib/Reaction')
-rw-r--r-- | lib/Reaction/UI/LayoutSet.pm | 21 | ||||
-rw-r--r-- | lib/Reaction/UI/LayoutSet/TT.pm | 2 | ||||
-rw-r--r-- | lib/Reaction/UI/RenderingContext/TT.pm | 45 | ||||
-rw-r--r-- | lib/Reaction/UI/Skin.pm | 91 | ||||
-rw-r--r-- | lib/Reaction/UI/View.pm | 102 | ||||
-rw-r--r-- | lib/Reaction/UI/ViewPort/SiteLayout.pm | 14 | ||||
-rw-r--r-- | lib/Reaction/UI/Widget/SiteLayout.pm | 15 |
7 files changed, 171 insertions, 119 deletions
diff --git a/lib/Reaction/UI/LayoutSet.pm b/lib/Reaction/UI/LayoutSet.pm index de00c7c..9de03eb 100644 --- a/lib/Reaction/UI/LayoutSet.pm +++ b/lib/Reaction/UI/LayoutSet.pm @@ -9,9 +9,7 @@ class LayoutSet which { 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 'source_file' => (is => 'ro', required => 1); has 'widget_class' => ( is => 'rw', lazy_fail => 1, predicate => 'has_widget_class' @@ -21,25 +19,11 @@ class LayoutSet which { has 'super' => (is => 'rw', predicate => 'has_super'); - implements _build_file_extension => as { 'html' }; - implements 'BUILD' => as { my ($self, $args) = @_; my @path = @{$args->{search_path}||[]}; - confess "No search_path provided" unless @path; confess "No view object provided" unless $args->{view}; - my $found; - my $ext = $self->file_extension; - SEARCH: foreach my $path (@path) { - my $cand = $path->file($self->name . ".${ext}"); - #print STDERR $cand,"\n"; - if ($cand->stat) { - $self->_load_file($cand, $args); - $found = 1; - last SEARCH; - } - } - confess "Unable to load file for LayoutSet ".$self->name unless $found; + $self->_load_file($self->source_file, $args); unless ($self->has_widget_class) { $self->widget_class($args->{view}->widget_class_for($self)); } @@ -98,7 +82,6 @@ class LayoutSet which { confess "Unparseable directive ${data}"; } } - $self->source_file($file); }; implements '_build_widget_type' => as { diff --git a/lib/Reaction/UI/LayoutSet/TT.pm b/lib/Reaction/UI/LayoutSet/TT.pm index c131bdb..7f9e2df 100644 --- a/lib/Reaction/UI/LayoutSet/TT.pm +++ b/lib/Reaction/UI/LayoutSet/TT.pm @@ -8,7 +8,7 @@ class TT is LayoutSet, which { has 'tt_view' => (is => 'rw', isa => View, lazy_fail => 1); - implements _build_file_extension => as { 'tt' }; + implements file_extension => as { 'tt' }; implements 'BUILD' => as { my ($self, $args) = @_; diff --git a/lib/Reaction/UI/RenderingContext/TT.pm b/lib/Reaction/UI/RenderingContext/TT.pm index 8308c0c..b359747 100644 --- a/lib/Reaction/UI/RenderingContext/TT.pm +++ b/lib/Reaction/UI/RenderingContext/TT.pm @@ -6,11 +6,6 @@ use aliased 'Template::View'; class TT is RenderingContext, which { - has 'iter_class' => ( - is => 'ro', required => 1, - default => sub { 'Reaction::UI::Renderer::TT::Iter'; }, - ); - our $body; implements 'dispatch' => as { @@ -67,45 +62,5 @@ class TT is RenderingContext, which { }; }; - -package Reaction::UI::Renderer::TT::Iter; - -use overload ( - q{""} => 'stringify', - fallback => 1 -); - -sub pos { shift->{pos} } - -sub new { - my ($class, $cr, $rctx) = @_; - bless({ rctx => $rctx, cr => $cr, pos => 0 }, $class); -} - -sub next { - my $self = shift; - $self->{pos}++; - my $next = $self->{cr}->(); - return unless $next; - return sub { $next->($self->{rctx}) }; -} - -sub all { - my $self = shift; - my @all; - while (my $e = $self->next) { - push(@all, $e); - } - \@all; -} - -sub stringify { - my $self = shift; - my $res = ''; - foreach my $e (@{$self->all}) { - $res .= $e->(); - } - $res; -} 1; diff --git a/lib/Reaction/UI/Skin.pm b/lib/Reaction/UI/Skin.pm new file mode 100644 index 0000000..ff31a3a --- /dev/null +++ b/lib/Reaction/UI/Skin.pm @@ -0,0 +1,91 @@ +package Reaction::UI::Skin; + +use Reaction::Class; + +# declaring dependencies +use Reaction::UI::LayoutSet; +use Reaction::UI::RenderingContext; + +use aliased 'Path::Class::Dir'; + +class Skin which { + + has '_layout_set_cache' => (is => 'ro', default => sub { {} }); + + has 'skin_base_path' => (is => 'ro', isa => Dir, required => 1); + + has 'view' => ( + is => 'ro', required => 1, weak_ref => 1, + handles => [ qw(layout_set_class) ], + ); + + has 'super' => ( + is => 'rw', isa => Skin, required => 0, predicate => 'has_super', + ); + + sub BUILD { + my ($self) = @_; + $self->_load_skin_config; + } + + implements '_load_skin_config' => as { + my ($self) = @_; + my $base = $self->skin_base_path; + confess "No such skin base directory ${base}" + unless -d $base; + } + + implements 'create_layout_set' => as { + my ($self, $name) = @_; + if (my $path = $self->layout_path_for($name)) { + return $self->layout_set_class->new( + $self->layout_set_args_for($name), + source_file => $path, + ); + } + if ($self->has_super) { + return $self->super->create_layout_set($name); + } + confess "Couldn't find layout set file for ${name}"; + }; + + implements 'layout_set_args_for' => as { + my ($self, $name) = @_; + return ( + name => $name, + view => $self->view, + skin => $self, + ($self->has_super ? (next_skin => $self->super) : ()), + $self->view->layout_set_args_for($name), + ); + }; + + implements 'layout_path_for' => as { + my ($self, $layout) = @_; + my $file_name = join( + '.', $layout, $self->layout_set_class->file_extension + ); + my $path = $self->our_path_for_type('layout') + ->file($file_name); + return (-e $path ? $path : undef); + }; + + implements 'search_path_for_type' => as { + my ($self, $type) = @_; + return [ + $self->our_path_for_type($type), + ($self->has_super + ? @{$self->super->search_path_for_type($type)} + : () + ) + ]; + }; + + implements 'our_path_for_type' => as { + my ($self, $type) = @_; + return $self->skin_base_path->subdir($type) + }; + +}; + +1; diff --git a/lib/Reaction/UI/View.pm b/lib/Reaction/UI/View.pm index 5fb9056..7a1ebc5 100644 --- a/lib/Reaction/UI/View.pm +++ b/lib/Reaction/UI/View.pm @@ -5,17 +5,25 @@ use Reaction::Class; # declaring dependencies use Reaction::UI::LayoutSet; use Reaction::UI::RenderingContext; +use aliased 'Reaction::UI::Skin'; +use aliased 'Path::Class::Dir'; class View which { - has '_layout_set_cache' => (is => 'ro', default => sub { {} }); has '_widget_class_cache' => (is => 'ro', default => sub { {} }); has '_widget_cache' => (is => 'ro', default => sub { {} }); + has '_layout_set_cache' => (is => 'ro', default => sub { {} }); + has 'app' => (is => 'ro', required => 1); has 'skin_name' => (is => 'ro', required => 1); + has 'skin' => ( + is => 'ro', lazy_build => 1, + handles => [ qw(create_layout_set search_path_for_type) ] + ); + has 'layout_set_class' => (is => 'ro', lazy_build => 1); has 'rendering_context_class' => (is => 'ro', lazy_build => 1); @@ -30,20 +38,20 @@ class View which { return $self->find_related_class('RenderingContext'); }; + implements '_build_skin' => as { + my ($self) = @_; + Skin->new( + name => $self->skin_name, view => $self, + skin_base_path => # returns a File, not a Dir. Thanks, Catalyst. + Dir->new($self->app->path_to('share', 'skin', $self->skin_name)), + ); + }; + implements 'COMPONENT' => as { my ($class, $app, $args) = @_; return $class->new(%{$args||{}}, app => $app); }; - sub BUILD{ - my $self = shift; - my $skin_name = $self->skin_name; - #XXX i guess we will add the path to installed reaction templates here - my $skin_path = $self->app->path_to('share','skin',$skin_name); - confess("'${skin_path}' is not a valid path for skin '${skin_name}'") - unless -d $skin_path; - } - implements 'render_window' => as { my ($self, $window) = @_; my $root_vp = $window->focus_stack->vp_head; @@ -72,25 +80,33 @@ class View which { implements 'widget_class_for' => as { my ($self, $layout_set) = @_; my $base = $self->blessed; - my $tail = $layout_set->widget_type; - my $lset_name = $layout_set->name; - # eventually more stuff will go here i guess? + my $widget_type = $layout_set->widget_type; my $app_name = ref $self->app || $self->app; - my $cache = $self->_widget_class_cache; - return $cache->{ $lset_name } if exists $cache->{ $lset_name }; - - my @search_path = ($base, $app_name, 'Reaction::UI'); - my @haystack = map { join '::', $_, 'Widget', $tail } @search_path; - for my $class (@haystack){ - #here we should throw if exits and error instead of eating the error - #only next when !exists - eval { Class::MOP::load_class($class) }; - #$@ ? next : return $class; - #warn "Loaded ${class}" unless $@; - $@ ? next : return $cache->{ $lset_name } = $class; - } - confess "Couldn't load widget '$tail' for layout '$lset_name': tried: " . - join(", ", @haystack); + return $self->_widget_class_cache->{$widget_type} ||= do { + + my @search_path = ($base, $app_name, 'Reaction::UI'); + my @haystack = map { join('::', $_, 'Widget', $widget_type) } + @search_path; + my $found; + foreach my $class (@haystack) { + #here we should throw if exits and error instead of eating the error + #only next when !exists + eval { Class::MOP::load_class($class) }; + #$@ ? next : return $class; + #warn "Loaded ${class}" unless $@; + #warn "Boom loading ${class}: $@" if $@; + unless ($@) { + $found = $class; + last; + } + } + unless ($found) { + confess "Couldn't load widget '${widget_type}'" + ." for layout '${\$layout_set->name}':" + ." tried: ".join(", ", @haystack); + } + $found; + }; }; implements 'layout_set_for' => as { @@ -110,13 +126,6 @@ class View which { return $cache->{$lset_name} ||= $self->create_layout_set($lset_name); }; - implements 'create_layout_set' => as { - my ($self, $name) = @_; - return $self->layout_set_class->new( - $self->layout_set_args_for($name), - ); - }; - implements 'find_related_class' => as { my ($self, $rel) = @_; my $own_class = ref($self) || $self; @@ -133,25 +142,6 @@ class View which { confess "Unable to find related ${rel} class for ${own_class}"; }; - implements 'layout_set_args_for' => as { - my ($self, $name) = @_; - return ( - name => $name, - search_path => $self->layout_search_path, - view => $self, - ); - }; - - implements 'layout_search_path' => as { - my ($self) = @_; - return $self->search_path_for_type('layout'); - }; - - implements 'search_path_for_type' => as { - my ($self, $type) = @_; - return [ $self->app->path_to('share','skin',$self->skin_name,$type) ]; - }; - implements 'create_rendering_context' => as { my ($self, @args) = @_; return $self->rendering_context_class->new( @@ -164,6 +154,10 @@ class View which { return (); }; + implements 'layout_set_args_for' => as { + return (); + }; + }; 1; diff --git a/lib/Reaction/UI/ViewPort/SiteLayout.pm b/lib/Reaction/UI/ViewPort/SiteLayout.pm new file mode 100644 index 0000000..4560dc6 --- /dev/null +++ b/lib/Reaction/UI/ViewPort/SiteLayout.pm @@ -0,0 +1,14 @@ +package Reaction::UI::ViewPort::SiteLayout; + +use Reaction::Class; +use aliased 'Reaction::UI::ViewPort'; + +class SiteLayout is ViewPort, which { + + has 'title' => (isa => 'Str', is => 'rw', lazy_fail => 1); + + has 'static_base_uri' => (isa => 'Str', is => 'rw', lazy_fail => 1); + +}; + +1; diff --git a/lib/Reaction/UI/Widget/SiteLayout.pm b/lib/Reaction/UI/Widget/SiteLayout.pm new file mode 100644 index 0000000..73406a9 --- /dev/null +++ b/lib/Reaction/UI/Widget/SiteLayout.pm @@ -0,0 +1,15 @@ +package Reaction::UI::Widget::SiteLayout; + +use Reaction::UI::WidgetClass; +use aliased 'Reaction::UI::Widget::Container'; + +class SiteLayout is Container, which { + + after fragment widget { + arg static_base => $_{viewport}->static_base_uri; + arg title => $_{viewport}->title; + }; + +}; + +1; |