Mercurial > pub > Impl
comparison Lib/IMPL/Web/View/TTDocument.pm @ 194:4d0e1962161c
Replaced tabs with spaces
IMPL::Web::View - fixed document model, new features (control classes, document constructor parameters)
author | cin |
---|---|
date | Tue, 10 Apr 2012 20:08:29 +0400 |
parents | 8e8401c0aea4 |
children | 7a920771fd8e |
comparison
equal
deleted
inserted
replaced
193:8e8401c0aea4 | 194:4d0e1962161c |
---|---|
8 | 8 |
9 use Scalar::Util qw(weaken); | 9 use Scalar::Util qw(weaken); |
10 | 10 |
11 | 11 |
12 use parent qw( | 12 use parent qw( |
13 IMPL::DOM::Document | 13 IMPL::DOM::Document |
14 IMPL::Web::View::TTControl | 14 IMPL::Web::View::TTControl |
15 ); | 15 ); |
16 | 16 |
17 BEGIN { | 17 BEGIN { |
18 public _dom property layout => PROP_ALL; | 18 public _dom property layout => PROP_ALL; |
19 public property opts => PROP_GET | PROP_OWNERSET; | 19 public property opts => PROP_GET | PROP_OWNERSET; |
20 public property loader => PROP_GET | PROP_OWNERSET; | 20 public property loader => PROP_ALL; |
21 public property controls => PROP_GET | PROP_OWNERSET; | 21 public property controls => PROP_GET | PROP_OWNERSET; |
22 | 22 |
23 # store the stash separately to make require() method to work correctly | 23 # store the stash separately to make require() method to work correctly |
24 # even when a stash of the context is modified during the processing | 24 # even when a stash of the context is modified during the processing |
25 public property stash => PROP_GET | PROP_OWNERSET; | 25 public property stash => PROP_GET | PROP_OWNERSET; |
26 } | 26 } |
27 | 27 |
28 sub CTOR { | 28 sub CTOR { |
29 my ($this,$template,$refOpts,%args) = @_; | 29 my ($this,$template,$refOpts,$loader,$vars) = @_; |
30 | 30 |
31 $this->controls({}); | 31 $this->controls({}); |
32 $this->loader($args{loader}) if $args{loader}; | 32 $this->loader($loader) if $loader; |
33 | 33 |
34 $this->layout( $template->layout ) unless $this->layout; | 34 $this->layout( $template->layout ) unless $this->layout; |
35 | 35 |
36 $this->opts($refOpts); | 36 $this->opts($refOpts); |
37 $this->stash($this->context->stash); | 37 $this->stash($this->context->stash); |
38 | 38 |
39 my $self = $this; | 39 my $self = $this; |
40 weaken($self); | 40 weaken($self); |
41 | 41 |
42 $this->templateVars('require', sub { | 42 $this->templateVars('require', sub { |
43 my $doc = $self; | 43 my $doc = $self; |
44 die new IMPL::Exception("A document is destroyed or invalid") unless $doc; | 44 die new IMPL::Exception("A document is destroyed or invalid") unless $doc; |
45 $doc->require(@_); | 45 $doc->require(@_); |
46 }); | 46 }); |
47 | 47 |
48 $this->templateVars('document', sub { $self } ); | 48 $this->templateVars('document', sub { $self } ); |
49 $this->InitInstance(); | 49 $this->InitInstance($vars); |
50 } | 50 } |
51 | 51 |
52 our %CTOR = ( | 52 our %CTOR = ( |
53 'IMPL::Web::View::TTControl' => sub { | 53 'IMPL::Web::View::TTControl' => sub { |
54 'document', | 54 my ($template,$contextOpts) = @_; |
55 $_[0], # template | 55 'document', |
56 new Template::Context($_[1]) # context | 56 $_[0], # template |
57 }, | 57 new Template::Context($_[1]) # context |
58 'IMPL::DOM::Document' => sub { | 58 }, |
59 nodeName => 'document' | 59 'IMPL::DOM::Document' => sub { |
60 } | 60 nodeName => 'document' |
61 } | |
61 ); | 62 ); |
62 | 63 |
63 sub templateVars { | 64 sub templateVars { |
64 my $this = shift; | 65 my $this = shift; |
65 my $name = shift; | 66 my $name = shift; |
66 | 67 |
67 if (@_) { | 68 if (@_) { |
68 return $this->stash->set($name, shift); | 69 return $this->stash->set($name, shift); |
69 } else { | 70 } else { |
70 return $this->stash->get($name); | 71 return $this->stash->get($name); |
71 } | 72 } |
72 } | 73 } |
73 | 74 |
74 sub require { | 75 sub require { |
75 my ($this, $control, $nodeProps) = @_; | 76 my ($this, $control, $nodeProps) = @_; |
76 | 77 |
77 $nodeProps ||= {}; | 78 $nodeProps ||= {}; |
78 $nodeProps->{document} = $this; | 79 $nodeProps->{document} = $this; |
79 | 80 |
80 if (my $factory = $this->controls->{$control}) { | 81 if (my $factory = $this->controls->{$control}) { |
81 return $factory; | 82 return $factory; |
82 } else { | 83 } else { |
83 | 84 |
84 my $path = $control; | 85 my $path = $control; |
85 if ( my $template = $this->loader->template($path) ) { | 86 if ( my $template = $this->loader->template($path) ) { |
86 | 87 my $opts = { %{$this->opts} }; |
87 my $opts = { %{$this->opts} }; | 88 |
88 $opts->{STASH} = $this->context->stash->clone(); | 89 # avoid propagation of local variables |
90 $opts->{STASH} = $this->stash->clone(); | |
89 | 91 |
90 my $ctx = new Template::Context($opts); | 92 my $ctx = new Template::Context($opts); |
91 | 93 |
92 $factory = new IMPL::Web::View::TTFactory( | 94 $factory = new IMPL::Web::View::TTFactory( |
93 typeof IMPL::Web::View::TTControl, | 95 $template->class || typeof IMPL::Web::View::TTControl, |
94 $template, | 96 $template, |
95 $ctx, | 97 $ctx, |
96 $opts, | 98 $opts |
97 { document => $this } | 99 ); |
98 ); | 100 |
99 | 101 my @parts = split(/\/+/,$control); |
100 my @parts = split(/\/+/,$control); | 102 |
101 | 103 $this->controls->{$control} = $factory; |
102 $this->controls->{$control} = $factory; | 104 |
103 | 105 return $factory; |
104 return $factory; | 106 |
105 | 107 } else { |
106 } else { | 108 die new IMPL::KeyNotFoundException($control); |
107 die new IMPL::KeyNotFoundException($control); | 109 } |
108 } | 110 } |
109 } | |
110 } | 111 } |
111 | 112 |
112 sub Render { | 113 sub Render { |
113 my ($this,$args) = @_; | 114 my ($this,$args) = @_; |
114 | 115 |
115 my $output; | 116 my $output; |
116 | 117 |
117 if ($this->layout) { | 118 if ($this->layout) { |
118 $output = $this->context->include( | 119 $output = $this->context->include( |
119 $this->loader->template($this->layout), | 120 $this->loader->template($this->layout), |
120 { | 121 { |
121 content => sub { $output ||= $this->RenderContent($args); } | 122 content => sub { $output ||= $this->RenderContent($args); }, |
122 } | 123 this => $this, |
123 ); | 124 template => $this->template |
124 } else { | 125 } |
125 return $this->RenderContent($args); | 126 ); |
126 } | 127 } else { |
127 | 128 return $this->RenderContent($args); |
128 return $output; | 129 } |
130 | |
131 return $output; | |
129 } | 132 } |
130 | 133 |
131 sub RenderContent { | 134 sub RenderContent { |
132 my $this = shift; | 135 my $this = shift; |
133 return $this->SUPER::Render(@_); | 136 return $this->SUPER::Render(@_); |
134 } | 137 } |
135 | 138 |
136 | 139 |
137 1; | 140 1; |
138 | 141 |
213 | 216 |
214 =head2 Загрузка элемента управления | 217 =head2 Загрузка элемента управления |
215 | 218 |
216 =over | 219 =over |
217 | 220 |
218 =item 1 C<require('my/org/input')> | 221 =item 1 C<TInput = require('my/org/input')> |
219 | 222 |
220 =item 1 Загружает шаблон C<my/org/input.tt> | 223 =item 1 Загружает шаблон C<my/org/input.tt> |
221 | 224 |
222 =item 1 Создает фабрику элементов управления с собственным контекстом, унаследованным от контекст документа. | 225 =item 1 Создает фабрику элементов управления с собственным контекстом, унаследованным от контекст документа. |
223 | 226 |
227 | 230 |
228 =head2 Создание элемента управления | 231 =head2 Создание элемента управления |
229 | 232 |
230 =over | 233 =over |
231 | 234 |
232 =item 1 C<< my.org.input.new('login') >> | 235 =item 1 C<< TInput.new('login') >> |
233 | 236 |
234 =item 1 Если это первый элемент управления, то выполняетя статический конструктор в контексте фабрики | 237 =item 1 Если это первый элемент управления, то выполняетя статический конструктор в контексте фабрики |
235 | 238 |
236 =item 1 Создается новый дочерний контекст к контексту фабрики | 239 =item 1 Создается новый дочерний контекст к контексту фабрики |
237 | 240 |