skin inheritnace within a single search path
[catagits/Reaction.git] / lib / Reaction / UI / Skin.pm
CommitLineData
8a293e2e 1package Reaction::UI::Skin;
2
3use Reaction::Class;
4
5# declaring dependencies
6use Reaction::UI::LayoutSet;
7use Reaction::UI::RenderingContext;
8
9use aliased 'Path::Class::Dir';
10
11class Skin which {
12
13 has '_layout_set_cache' => (is => 'ro', default => sub { {} });
14
15 has 'skin_base_path' => (is => 'ro', isa => Dir, required => 1);
16
17 has 'view' => (
18 is => 'ro', required => 1, weak_ref => 1,
19 handles => [ qw(layout_set_class) ],
20 );
21
22 has 'super' => (
23 is => 'rw', isa => Skin, required => 0, predicate => 'has_super',
24 );
25
26 sub BUILD {
27 my ($self) = @_;
28 $self->_load_skin_config;
29 }
30
31 implements '_load_skin_config' => as {
32 my ($self) = @_;
33 my $base = $self->skin_base_path;
34 confess "No such skin base directory ${base}"
35 unless -d $base;
7c2bcb55 36 if (-e (my $conf_file = $base->file('skin.conf'))) {
37 # we get [ { $file => $conf } ]
38 my ($cfg) = values %{
39 Config::Any->load_files({
40 files => [ $conf_file ], use_ext => 1
41 })->[0]
42 };
43 if (my $super_name = $cfg->{extends}) {
44 my $super_dir = $base->parent->subdir($super_name);
45 my $super = $self->new(
46 view => $self->view, skin_base_path => $super_dir
47 );
48 $self->super($super);
49 }
50 }
8a293e2e 51 }
52
53 implements 'create_layout_set' => as {
54 my ($self, $name) = @_;
55 if (my $path = $self->layout_path_for($name)) {
56 return $self->layout_set_class->new(
57 $self->layout_set_args_for($name),
58 source_file => $path,
59 );
60 }
61 if ($self->has_super) {
62 return $self->super->create_layout_set($name);
63 }
64 confess "Couldn't find layout set file for ${name}";
65 };
66
67 implements 'layout_set_args_for' => as {
68 my ($self, $name) = @_;
69 return (
70 name => $name,
71 view => $self->view,
72 skin => $self,
73 ($self->has_super ? (next_skin => $self->super) : ()),
74 $self->view->layout_set_args_for($name),
75 );
76 };
77
78 implements 'layout_path_for' => as {
79 my ($self, $layout) = @_;
80 my $file_name = join(
81 '.', $layout, $self->layout_set_class->file_extension
82 );
83 my $path = $self->our_path_for_type('layout')
84 ->file($file_name);
85 return (-e $path ? $path : undef);
86 };
87
88 implements 'search_path_for_type' => as {
89 my ($self, $type) = @_;
90 return [
91 $self->our_path_for_type($type),
92 ($self->has_super
93 ? @{$self->super->search_path_for_type($type)}
94 : ()
95 )
96 ];
97 };
98
99 implements 'our_path_for_type' => as {
100 my ($self, $type) = @_;
101 return $self->skin_base_path->subdir($type)
102 };
103
104};
105
1061;