view Lib/IMPL/Web/View/TTControl.pm @ 192:a9faf883cdce

IMPL::Web::View refactoring
author cin
date Fri, 06 Apr 2012 16:22:38 +0400
parents 78a18a2b6266
children 4d0e1962161c
line wrap: on
line source

package IMPL::Web::View::TTControl;
use strict;

use IMPL::DOM::Property qw(_dom);
use IMPL::lang qw(:declare :constants);

use Template::Context();
use Scalar::Util qw(weaken);

use parent qw(
	IMPL::DOM::Node
);

{
	my $nextId = 1;
	sub _GetNextId {
		return $nextId++;
	}
}


BEGIN {
	public _dom property id => PROP_ALL;
	
	public property context => PROP_GET | PROP_OWNERSET;
	public property template => PROP_ALL;
}


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;
	
	weaken($this); # prevent cyclic references produces by the code below
	
	$context->stash->set('append', sub { $this->appendChild(@_); undef; } );
	$context->stash->set('select', sub { $this->selectNodes(@_); } );
	
}

our %CTOR = (
	'IMPL::DOM::Node' => sub {
		nodeName => $_[0],
		%{ $_[3] || {} }
	}
);

sub InitInstance {
	my ($this,$args) = @_;
	
	$args ||= {};
	
	if ( my $ctor = $this->template->blocks->{CTOR} ) {
		$this->context->process($ctor, { %$args, this => $this } );
		$this->context->stash->set('this',undef);
	}
}

sub renderBlock {
	$_[0]->template->blocks->{RENDER} || $_[0]->template;
}

sub Render {
	my ($this,$args) = @_;
	
	$args = {} unless ref $args eq 'HASH';
	
	if(my $body = $this->renderBlock ) {
		return $this->context->include( $body, { %$args, this => $this, template => $this->template, document => $this->document } );
	} else {
		return "";
	}	
}

sub AUTOLOAD {
	our $AUTOLOAD;
	
	my $method = ($AUTOLOAD =~ m/(\w+)$/)[0];
	
	return if $method eq 'DESTROY';
	
	my $this = shift;
	
	$this->nodeProperty($method,@_);
}

1;

__END__

=pod

=head1 NAME

C<IMPL::Web::View::TTControl>

=head1 SYNPOSIS

=head1 DESCRIPTION

=head2 BLOCKS

При загрузке шаблона, создается фабрика, с собственным контекстом в которой выполняется шаблон элемента управления

=head3 INIT

Данный блок шаблона управления выполняется один раз при создании первого экземпляра элемента управления

=head3 CTOR

данный блок выполняется каждый раз при создании нового экземпляра элемента управления, при этом переменная C<this>
указывает на эземпляр элемента упарвления

=head3 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