Mercurial > pub > Impl
annotate Lib/IMPL/Web/View/TTControl.pm @ 298:78f767765706
TT view refactoring
author | cin |
---|---|
date | Tue, 19 Mar 2013 02:02:37 +0400 |
parents | 86ff93b34f2a |
children | bd79145657e5 |
rev | line source |
---|---|
181 | 1 package IMPL::Web::View::TTControl; |
2 use strict; | |
3 | |
234 | 4 use IMPL::Const qw(:prop); |
241
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
5 use IMPL::lang qw(:hash); |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
6 use Scalar::Util qw(blessed); |
234 | 7 use IMPL::declare { |
8 require => { | |
296 | 9 TemplateDocument => 'Template::Document', |
234 | 10 TTContext => 'Template::Context', |
11 Exception => 'IMPL::Exception', | |
238 | 12 ArgumentException => '-IMPL::InvalidArgumentException', |
13 OperationException => '-IMPL::InvalidOperationException' | |
234 | 14 }, |
15 base => [ | |
241
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
16 'IMPL::Object' => undef |
234 | 17 ], |
18 props => [ | |
19 id => PROP_RO, | |
238 | 20 attributes => PROP_RW, |
21 name => PROP_RO, | |
234 | 22 context => PROP_RO, |
23 template => PROP_RO | |
24 ] | |
25 }; | |
26 | |
181 | 27 |
187 | 28 { |
194 | 29 my $nextId = 1; |
30 sub _GetNextId { | |
31 return $nextId++; | |
32 } | |
187 | 33 } |
181 | 34 |
238 | 35 our $AutoloadRegex = qr/^[a-z]/; |
241
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
36 our @REFLECT_META = qw(title layout); |
238 | 37 |
181 | 38 sub CTOR { |
194 | 39 my ($this,$name,$template,$context,$refProps) = @_; |
40 | |
41 $name ||= "control"; | |
42 | |
43 $this->template( $template ) or die new IMPL::ArgumentException("A template is required"); | |
44 $this->context( $context ) or die new IMPL::ArgumentException("A context is required"); | |
45 | |
46 $this->id($name . "-" . _GetNextId()) unless $this->id; | |
47 | |
238 | 48 $this->name($name); |
49 $this->attributes({}); | |
194 | 50 |
241
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
51 my %attrs; |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
52 |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
53 foreach my $meta ( @REFLECT_META ) { |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
54 next if $meta =~ /^_/; |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
55 if( my $value = $template->$meta() ) { |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
56 $attrs{$meta} = $value; |
238 | 57 } |
58 } | |
241
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
59 |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
60 hashApply(\%attrs,$refProps) if ref $refProps eq 'HASH'; |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
61 |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
62 while (my($key,$value) = each %attrs) { |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
63 $this->SetAttribute($key,$value); |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
64 } |
181 | 65 } |
66 | |
191 | 67 sub InitInstance { |
194 | 68 my ($this,$args) = @_; |
69 | |
70 $args ||= {}; | |
71 | |
72 if ( my $ctor = $this->template->blocks->{CTOR} ) { | |
212 | 73 $this->context->include($ctor, { %$args, this => $this, template => $this->template } ); |
194 | 74 } |
191 | 75 } |
76 | |
238 | 77 sub GetAttribute { |
78 my ($this,$name) = (shift,shift); | |
79 | |
80 if (my $method = $this->can($name)) { | |
81 unshift @_,$this; | |
82 goto &$method; | |
83 } else { | |
84 return $this->attributes->{$name}; | |
85 } | |
86 } | |
87 | |
88 sub SetAttribute { | |
89 my $this = shift; | |
90 my $name = shift; | |
91 | |
92 if (my $method = $this->can($name)) { | |
93 unshift @_, $this; | |
94 goto &$method; | |
95 } else { | |
96 return $this->attributes->{$name} = shift; | |
97 } | |
98 } | |
99 | |
267 | 100 sub GetMainBlock { |
194 | 101 $_[0]->template->blocks->{RENDER} || $_[0]->template; |
187 | 102 } |
103 | |
104 sub Render { | |
194 | 105 my ($this,$args) = @_; |
106 | |
107 $args = {} unless ref $args eq 'HASH'; | |
108 | |
267 | 109 if(my $body = $this->GetMainBlock ) { |
241
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
110 return $this->context->include( $body, { %$args, this => $this, template => $this->template } ); |
194 | 111 } else { |
112 return ""; | |
113 } | |
185 | 114 } |
115 | |
267 | 116 sub RenderBlock { |
296 | 117 my ($this, $block, $args) = @_; |
267 | 118 |
119 $args = {} unless ref $args eq 'HASH'; | |
120 | |
296 | 121 return $block ? $this->context->include( $block, { %$args, this => $this, template => $this->template } ) : undef; |
122 } | |
123 | |
124 sub ExportBlock { | |
125 my ($this,$block) = @_; | |
126 | |
127 return TemplateDocument->new({ | |
128 BLOCK => $this->template->blocks->{$block}, | |
129 DEFBLOCKS => $this->template->blocks | |
130 }); | |
267 | 131 } |
132 | |
185 | 133 sub AUTOLOAD { |
194 | 134 our $AUTOLOAD; |
135 | |
136 my $method = ($AUTOLOAD =~ m/(\w+)$/)[0]; | |
137 | |
138 return if $method eq 'DESTROY'; | |
139 | |
238 | 140 if ($method =~ /$AutoloadRegex/) { |
141 my $this = shift; | |
241
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
142 |
f48a1a9f4fa2
+Added ViewResult to allow implementation of the view environment.
sergey
parents:
238
diff
changeset
|
143 die OperationException->new("can't invoke method '$method' on an unblessed reference") unless blessed $this; |
238 | 144 |
145 return @_ ? $this->SetAttribute($method,@_) : $this->GetAttribute($method); | |
146 } else { | |
147 die OperationException->new("The specified method '$method' doesn't exists"); | |
148 } | |
181 | 149 } |
150 | |
151 1; | |
152 | |
153 __END__ | |
154 | |
155 =pod | |
156 | |
157 =head1 NAME | |
158 | |
159 C<IMPL::Web::View::TTControl> | |
160 | |
161 =head1 SYNPOSIS | |
162 | |
265 | 163 =begin text |
164 | |
165 [% | |
166 META version = 1; | |
167 BLOCK INIT; | |
168 # this is a document scope | |
169 dojo.require.push( 'dijit/form/Input' ); | |
170 END; | |
171 BLOCK CTOR; | |
172 # local to this block | |
173 TPreview = require('My/Org/TextPreview'); | |
174 | |
175 # init control props | |
176 this.dojoClass = this.dojoClass || 'dijit.form.Input'; | |
177 this.visualClass = this.visualClass || 'classic'; | |
178 this.childNodes = []; | |
179 | |
180 # init content | |
181 FOREACH text IN this.data; | |
182 this.childNodes.push( TPreview.new('preview', nodeValue = text ) ); | |
183 END; | |
184 | |
185 END; | |
186 %] | |
187 | |
188 <div class="$this.visualClass" data-dojo-type="$this.dojoClass"> | |
189 [% FOREACH node IN this.childNodes %] | |
190 [% node.Render() %] | |
191 <hr /> | |
192 [% END %] | |
193 </div> | |
194 | |
195 =end text | |
196 | |
181 | 197 =head1 DESCRIPTION |
198 | |
265 | 199 Представляет собой фрагмент документа, который имеет шаблон для отображения, |
200 набор свойств и т.п. | |
201 | |
181 | 202 =head2 BLOCKS |
203 | |
265 | 204 =head3 META |
205 | |
206 Атрибуты C<META> C<layout>, C<title> будут перенесены в свойства элемента | |
207 управления. | |
208 | |
181 | 209 =head3 INIT |
210 | |
265 | 211 Данный блок шаблона управления выполняется один раз при создании первого |
212 экземпляра элемента управления, в пространстве имен документа. Может | |
213 использоваться для формирования заголовочной части документа, скрипта | |
214 подключающего C<js> модули и т.п. | |
215 | |
216 Выполнение данного блока производится фабрикой элементов управления. | |
181 | 217 |
218 =head3 CTOR | |
219 | |
265 | 220 данный блок выполняется каждый раз при создании нового экземпляра элемента |
221 управления, при этом переменная C<this> указывает на эземпляр элемента | |
222 упарвления. Данный блок можно использовать для инициализации свойств элемента | |
213 | 223 управления. |
181 | 224 |
225 =head3 RENDER | |
226 | |
265 | 227 Данный блок выполняется при вызове метода C<Render()>, вывод данного блока и |
228 есть результат отображения элемента управления. Если в шаблоне нет блока | |
229 C<RENDER>, то сам шаблон считается таковым. | |
187 | 230 |
231 =head2 TEMPLATE VARS | |
232 | |
265 | 233 Каждый шаблон имеет собственное пространство имен, вложенное в пространство имен |
234 фабрики элементов (которая разделяет пространство имен документа). В шаблоне | |
235 могут определяться новые переменные, однако они останутся локальными для блоков. | |
236 | |
237 Чтобы передать данные между блоками следует использовать ссылку на элемент | |
238 управления C<this>. | |
239 | |
240 =begin text | |
241 | |
242 [% | |
243 BLOCK CTOR; | |
244 this.extraCssClass = 'active'; | |
245 text = "this text will gone"; | |
246 END; | |
247 %] | |
248 | |
249 <div class="$this.extraCssClass">some text $text</div> | |
250 | |
251 =end text | |
252 | |
253 В примере выше переменная C<$text> установленная в конструкторе шаблона, при | |
254 отображении элемента управления будет неопределена. | |
187 | 255 |
256 =over | |
257 | |
265 | 258 =item * C<this> |
259 | |
260 ссылка на объект элемента управления | |
261 | |
262 =item * C<component> | |
187 | 263 |
265 | 264 ссылка на текущий шаблон, устанавливается автоматически в методе |
265 C<Template::Context::process>. | |
187 | 266 |
265 | 267 =item * C<template> |
268 | |
269 ссылка на шаблон элемента управления, для совместимости с C<TT> | |
187 | 270 |
271 =back | |
272 | |
273 =head1 MEMBERS | |
274 | |
275 =over | |
276 | |
277 =item * C<[get]context> | |
278 | |
265 | 279 Контекст элемента управления, хранит пременные шаблона. Передается в |
280 конструкторе. Фабрика элементов управления создает новый контекст пространство | |
281 имен которого вложено в пространство имен документа. | |
187 | 282 |
283 =item * C<[get,set]template> | |
284 | |
285 C<Template::Document> Шаблон элемента управления. | |
286 | |
287 =item * C<AUTOLOAD> | |
288 | |
265 | 289 Для удобства работы с шаблоном, элементы управления предоставляю доступ к своим |
290 свойствам через метод C<AUTOLOAD>. Имена свойств должны начинаться со строчной | |
291 буквы. | |
187 | 292 |
293 =back | |
181 | 294 |
295 =cut |