Mercurial > pub > Impl
view Lib/IMPL/Web/View/TTControl.pm @ 260:2879cdb6b8cd
sync
author | sergey |
---|---|
date | Tue, 25 Dec 2012 02:18:59 +0400 |
parents | f48a1a9f4fa2 |
children | 6b6d4b2275a1 |
line wrap: on
line source
package IMPL::Web::View::TTControl; use strict; use IMPL::Const qw(:prop); use IMPL::lang qw(:hash); use Scalar::Util qw(blessed); use IMPL::declare { require => { TTContext => 'Template::Context', Exception => 'IMPL::Exception', ArgumentException => '-IMPL::InvalidArgumentException', OperationException => '-IMPL::InvalidOperationException' }, base => [ 'IMPL::Object' => undef ], props => [ id => PROP_RO, attributes => PROP_RW, name => PROP_RO, context => PROP_RO, template => PROP_RO ] }; { my $nextId = 1; sub _GetNextId { return $nextId++; } } our $AutoloadRegex = qr/^[a-z]/; our @REFLECT_META = qw(title layout); sub CTOR { my ($this,$name,$template,$context,$refProps) = @_; $name ||= "control"; $this->template( $template ) or die new IMPL::ArgumentException("A template is required"); $this->context( $context ) or die new IMPL::ArgumentException("A context is required"); $this->id($name . "-" . _GetNextId()) unless $this->id; $this->name($name); $this->attributes({}); my %attrs; foreach my $meta ( @REFLECT_META ) { next if $meta =~ /^_/; if( my $value = $template->$meta() ) { $attrs{$meta} = $value; } } hashApply(\%attrs,$refProps) if ref $refProps eq 'HASH'; while (my($key,$value) = each %attrs) { $this->SetAttribute($key,$value); } } sub InitInstance { my ($this,$args) = @_; $args ||= {}; if ( my $ctor = $this->template->blocks->{CTOR} ) { $this->context->include($ctor, { %$args, this => $this, template => $this->template } ); } } sub GetAttribute { my ($this,$name) = (shift,shift); if (my $method = $this->can($name)) { unshift @_,$this; goto &$method; } else { return $this->attributes->{$name}; } } sub SetAttribute { my $this = shift; my $name = shift; if (my $method = $this->can($name)) { unshift @_, $this; goto &$method; } else { return $this->attributes->{$name} = shift; } } sub GetRenderBlock { $_[0]->template->blocks->{RENDER} || $_[0]->template; } sub Render { my ($this,$args) = @_; $args = {} unless ref $args eq 'HASH'; if(my $body = $this->GetRenderBlock ) { return $this->context->include( $body, { %$args, this => $this, template => $this->template } ); } else { return ""; } } sub AUTOLOAD { our $AUTOLOAD; my $method = ($AUTOLOAD =~ m/(\w+)$/)[0]; return if $method eq 'DESTROY'; if ($method =~ /$AutoloadRegex/) { my $this = shift; die OperationException->new("can't invoke method '$method' on an unblessed reference") unless blessed $this; return @_ ? $this->SetAttribute($method,@_) : $this->GetAttribute($method); } else { die OperationException->new("The specified method '$method' doesn't exists"); } } 1; __END__ =pod =head1 NAME C<IMPL::Web::View::TTControl> =head1 SYNPOSIS =head1 DESCRIPTION =head2 BLOCKS =head3 INIT Данный блок шаблона управления выполняется один раз при создании первого экземпляра элемента управления, может использоваться для формирования заголовочной части документа, скрипта подключающего ajax модули при необходимости и т.п. =head3 CTOR данный блок выполняется каждый раз при создании нового экземпляра элемента управления, при этом переменная C<this> указывает на эземпляр элемента упарвления. Данный блок можно использовать для инициализации свойств элемента управления. =head3 RENDER Данный блок выполняется при вызове метода C<Render()>, вывод данного блока и есть результат отображения элемента управления. Если в шаблоне нет блока C<RENDER>, то сам шаблон считается таковым. =head2 TEMPLATE VARS Каждый шаблон имеет собственное пространство имен, унаследованное от пространства имен фабрики элементов (которая в свою очередь наследует контекст документа). В шаблоне могут определяться новые переменные, которые разделяются между блоками. Также доступны стандартные переменные =over =item * C<this> ссылка на объект элемента управления =item * C<component> ссылка на текущий шаблон, устанавливается автоматически в методе C<Template::Context::process>. =item * C<template> ссылка на шаблон элемента управления, для совместимости с C<TT> =back =head1 MEMBERS =over =item * C<[get]context> Контекст элемента управления, хранит пременные шаблона. Наследуется от контекста фабрики элементов управления, который наследуется от контекста документа. =item * C<[get,set]template> C<Template::Document> Шаблон элемента управления. =item * C<AUTOLOAD> Для удобства работы с шаблоном, элементы управления предоставляю доступ к своим свойствам через метод C<AUTOLOAD>. =back C<lang ru> =cut