Commit | Line | Data |
8a293e2e |
1 | package Reaction::UI::Skin; |
2 | |
3 | use Reaction::Class; |
4 | |
5 | # declaring dependencies |
6 | use Reaction::UI::LayoutSet; |
7 | use Reaction::UI::RenderingContext; |
8 | |
9 | use aliased 'Path::Class::Dir'; |
10 | |
11 | class 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 | |
106 | 1; |