aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Reaction
diff options
context:
space:
mode:
authormatthewt <matthewt@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7>2008-01-30 16:33:10 +0000
committermatthewt <matthewt@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7>2008-01-30 16:33:10 +0000
commit8a293e2eee23938229a7dbfb617faee579914dfc (patch)
treef1626e9facac38a6b323c92e7d31585e5902cbba /lib/Reaction
parent46937531eb2d28950b21c8b0982539e28b277b60 (diff)
downloadreaction-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.pm21
-rw-r--r--lib/Reaction/UI/LayoutSet/TT.pm2
-rw-r--r--lib/Reaction/UI/RenderingContext/TT.pm45
-rw-r--r--lib/Reaction/UI/Skin.pm91
-rw-r--r--lib/Reaction/UI/View.pm102
-rw-r--r--lib/Reaction/UI/ViewPort/SiteLayout.pm14
-rw-r--r--lib/Reaction/UI/Widget/SiteLayout.pm15
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;