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 | |
349a57a4 |
17 | has 'widget_search_path' => (is => 'rw', isa => 'ArrayRef', lazy_fail => 1); |
18 | |
8a293e2e |
19 | has 'view' => ( |
20 | is => 'ro', required => 1, weak_ref => 1, |
f6b79841 |
21 | handles => [ qw(layout_set_class widget_class_for) ], |
8a293e2e |
22 | ); |
23 | |
24 | has 'super' => ( |
25 | is => 'rw', isa => Skin, required => 0, predicate => 'has_super', |
26 | ); |
27 | |
28 | sub BUILD { |
29 | my ($self) = @_; |
30 | $self->_load_skin_config; |
31 | } |
32 | |
33 | implements '_load_skin_config' => as { |
34 | my ($self) = @_; |
35 | my $base = $self->skin_base_path; |
36 | confess "No such skin base directory ${base}" |
37 | unless -d $base; |
349a57a4 |
38 | my $lst = sub { (ref $_[0] eq 'ARRAY') ? $_[0]: [$_[0]] }; |
39 | my @files = ( |
40 | $base->parent->file('defaults.conf'), $base->file('skin.conf') |
41 | ); |
42 | # we get [ { $file => $conf }, ... ] |
43 | my %cfg = (map { %{(values %{$_})[0]} } |
44 | @{Config::Any->load_files({ |
45 | files => [ grep { -e $_ } @files ], |
46 | use_ext => 1, |
47 | })} |
48 | ); |
49 | if (my $super_name = $cfg{extends}) { |
50 | my $super_dir = $base->parent->subdir($super_name); |
51 | my $super = $self->new( |
52 | view => $self->view, skin_base_path => $super_dir |
53 | ); |
54 | $self->super($super); |
55 | } |
56 | if (exists $cfg{widget_search_path}) { |
57 | $self->widget_search_path($lst->($cfg{widget_search_path})); |
58 | } else { |
59 | confess "No widget_search_path in defaults.conf or skin.conf"; |
7c2bcb55 |
60 | } |
8a293e2e |
61 | } |
62 | |
63 | implements 'create_layout_set' => as { |
64 | my ($self, $name) = @_; |
65 | if (my $path = $self->layout_path_for($name)) { |
66 | return $self->layout_set_class->new( |
67 | $self->layout_set_args_for($name), |
68 | source_file => $path, |
69 | ); |
70 | } |
71 | if ($self->has_super) { |
72 | return $self->super->create_layout_set($name); |
73 | } |
74 | confess "Couldn't find layout set file for ${name}"; |
75 | }; |
76 | |
77 | implements 'layout_set_args_for' => as { |
78 | my ($self, $name) = @_; |
79 | return ( |
80 | name => $name, |
8a293e2e |
81 | skin => $self, |
82 | ($self->has_super ? (next_skin => $self->super) : ()), |
83 | $self->view->layout_set_args_for($name), |
84 | ); |
85 | }; |
86 | |
87 | implements 'layout_path_for' => as { |
88 | my ($self, $layout) = @_; |
89 | my $file_name = join( |
349a57a4 |
90 | '.', $layout, $self->view->layout_set_file_extension |
8a293e2e |
91 | ); |
92 | my $path = $self->our_path_for_type('layout') |
93 | ->file($file_name); |
94 | return (-e $path ? $path : undef); |
95 | }; |
96 | |
97 | implements 'search_path_for_type' => as { |
98 | my ($self, $type) = @_; |
99 | return [ |
100 | $self->our_path_for_type($type), |
101 | ($self->has_super |
102 | ? @{$self->super->search_path_for_type($type)} |
103 | : () |
104 | ) |
105 | ]; |
106 | }; |
107 | |
108 | implements 'our_path_for_type' => as { |
109 | my ($self, $type) = @_; |
110 | return $self->skin_base_path->subdir($type) |
111 | }; |
112 | |
113 | }; |
114 | |
115 | 1; |