diff Lib/IMPL/Web/View/TTControl.pm @ 352:675cd1829255

working on TTView: added control classes support
author cin
date Thu, 10 Oct 2013 19:51:19 +0400
parents f05634287ac7
children feeb3bc4a818
line wrap: on
line diff
--- a/Lib/IMPL/Web/View/TTControl.pm	Tue Oct 08 17:40:35 2013 +0400
+++ b/Lib/IMPL/Web/View/TTControl.pm	Thu Oct 10 19:51:19 2013 +0400
@@ -3,24 +3,22 @@
 
 use IMPL::Const qw(:prop);
 use IMPL::lang qw(:hash :base);
-use Scalar::Util qw(blessed reftype);
 use IMPL::declare {
 	require => {
-	    TemplateDocument => 'Template::Document',
-        TTContext => 'IMPL::Web::View::TTContext',
-        Exception => 'IMPL::Exception',
-        ArgumentException => '-IMPL::InvalidArgumentException',
-        OperationException => '-IMPL::InvalidOperationException'
+		Exception => 'IMPL::Exception',
+		ArgException => '-IMPL::InvalidArgumentException'
 	},
 	base => [
 	   'IMPL::Object' => undef
 	],
 	props => [
-	   id => PROP_RO,
-	   attributes => PROP_RW,
-	   context => PROP_RO,
-	   template => PROP_RO,
-	   parents => PROP_RO
+		context => PROP_RO,
+		template => PROP_RO,
+		_stash => PROP_RO,
+		id => {
+	   		get => sub { shift->_stash->get('id') },
+	   		set => sub { shift->_stash->set('id',shift) }
+		}
 	]
 };
 
@@ -34,128 +32,45 @@
 
 our $AUTOLOAD_REGEX = qr/^[a-z]/;
 
-my %mapSkipAttributes = map { $_, 1 } qw(attributes context);
-
 sub CTOR {
-    my ($this,$template,$context,$attrs) = @_;
-    
-   
-    $this->template( $template ) or die new IMPL::ArgumentException("A template is required");
-    
-    die IMPL::ArgumentException->new(context => "A context is required, supplied: $context")
-        unless is($context,TTContext);
-    
-    $this->context( $context );
-    
-    $this->attributes({});
-    
-    if(ref($attrs) eq 'HASH') {
-	    while (my($key,$value) = each %$attrs) {
-	        next if $mapSkipAttributes{$key};
-	        $this->SetAttribute($key,$value);
-	    }
-    }    
+    my ($this,$context,$template) = @_;
     
-    $this->id(_GetNextId()) unless $this->id;
-}
-
-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;
-    }
+    $this->context($context)
+    	or die ArgException->new(context => 'A context is required');
+    $this->template($template)
+    	or die ArgException->new(template => 'A template is required');
+    	
+    $this->_stash($context->stash);
 }
 
 sub Render {
-    my ($this,$args) = @_;
-    
-    $args = {} unless ref $args eq 'HASH';
-    
-    return $this->context->include(
-        $this->template->block,
-        {
-            %$args,
-            this => $this,
-            template => $this->template
-        }
-    );
-}
-
-sub GetTemplate {
-    my ($this,$name) = @_;
-    
-    return eval { $this->context->template($name) }; 
-}
-
-sub Include {
-    my ($this,$template, $args) = @_;
-    
-    my $tpl = $this->GetTemplate($template)
-        or die OperationException->new("The specified template isn't found", $template);
-        
-    return $this->context->include(
-        $tpl,
-        $args
-    );
+	my ($this,$args) = @_;
+	return $this->context->include($this->template,$args);
 }
 
-sub HasBlock {
-    my ($this,$block) = @_;
-    
-    $this->GetTemplate ? 1 : 0;
+our $AUTOLOAD;
+sub AUTOLOAD {
+	my ($prop) = ($AUTOLOAD =~ m/(\w+)$/);
+	
+	die Exception->new("Control doesn't have method '$prop'") unless $prop=~/$AUTOLOAD_REGEX/;
+	
+	no strict 'refs';
+	
+	my $method = sub {
+		if (@_ == 1) {
+			return shift->_stash->get($prop);
+		} elsif (@_ == 2) {
+			return shift->_stash->set($prop,shift);
+		} else {
+			return shift->_stash->get([$prop,[@_]]);
+		}
+	};
+	
+	*{$AUTOLOAD} = $method;
+	
+	goto &$method;
 }
 
-sub AUTOLOAD {
-    our $AUTOLOAD;
-    
-    my $method = ($AUTOLOAD =~ m/(\w+)$/)[0];
-    
-    return if $method eq 'DESTROY';
-    
-    if ($method =~ /$AUTOLOAD_REGEX/) {
-        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");
-    }
-}
-
-sub CreateControlFromTemplate {
-    my ($this,$template,$args) = @_;
-    
-    if (not ref($template)) {
-        return $this->context->stash->get([
-            require => [
-                $template
-            ]
-        ])->new($args);
-    } else {
-        return $this->new(
-            $template,
-            $this->context->clone(),
-            $args
-        );
-    }
-}
 
 1;
 
@@ -165,117 +80,32 @@
 
 =head1 NAME
 
-C<IMPL::Web::View::TTControl>
+C<IMPL::Web::View::TTControl> расширяет функциональность шаблонов
 
 =head1 SYNPOSIS
 
-=begin text
+=begin code
+
+package My::View::Menu;
+use IMPL::declare {
+	base => [
+		'IMPL::Web::View::TTControl' => '@_'
+	]
+};
 
-[%
-    META version = 1;
-    BLOCK INIT;
-        # this is a document scope
-        dojo.modules.push( 'dijit/form/Input' );
-    END;
-    
-    # local to this block
-    TPreview = require('My/Org/TextPreview');
-        
-    # init control props 
-    visualClass = this.visualClass || 'classic';
-%]    
-<div id="$id" class="$visualClass" data-dojo-type="dijit/form/Input">
-    [% FOREACH item IN model %]
-        <div class="itemContainer">
-        [% Display(item) %]
-        </div>
-    [% END %]
-</div>
+sub Render {
+	my ($this,$args) = @_;
+	
+	$this->PrepareItems($args);
+	
+	return $this->next::method($args);
+}
 
-=end text
+sub PrepareItems
+
+=end code
 
 =head1 DESCRIPTION
 
-Легкая обертка вокруг шаблона, позволяет изолировать пространство имен шаблона,
-а также реализовать собственные методы по представлению данных (в случае если
-это проще сделать в виде методов класса). 
-
-=head2 BLOCKS
-
-=head3 META
-
-Атрибуты C<META> C<layout>, C<title> будут перенесены в свойства элемента
-управления. 
-
-=head3 INIT
-
-Данный блок шаблона управления выполняется один раз при создании первого
-экземпляра элемента управления, в пространстве имен документа. Может
-использоваться для формирования заголовочной части документа, скрипта
-подключающего C<js> модули и т.п.
-
-Выполнение данного блока производится фабрикой элементов управления.
-
-=head2 TEMPLATE VARS
-
-Каждый шаблон имеет собственное пространство имен, вложенное в пространство имен
-фабрики элементов (которая разделяет пространство имен документа). В шаблоне
-могут определяться новые переменные, однако они останутся локальными для блоков.
-
-Чтобы передать данные между блоками следует использовать ссылку на элемент
-управления C<this>.
-
-=begin text
-
-[%
-    BLOCK CTOR;
-        this.extraCssClass = 'active';
-        text = "this text will gone";
-    END;
-%]
-
-<div class="$this.extraCssClass">some text $text</div>
-
-=end text
-
-В примере выше переменная C<$text> установленная в конструкторе шаблона, при
-отображении элемента управления будет неопределена.
-
-=over
-
-=item * C<this>
-
-ссылка на объект элемента управления
-
-=item * C<component>
-
-ссылка на текущий шаблон, устанавливается автоматически в методе
-C<Template::Context::process>.
-
-=item * C<template>
-
-ссылка на шаблон элемента управления, для совместимости с C<TT>
-
-=back
-
-=head1 MEMBERS
-
-=head2 C<[get]context>
-
-Контекст элемента управления, хранит пременные шаблона. Фабрика элементов
-управления создает новый контекст пространство имен которого вложено в
-пространство имен документа.
-
-Контекст следует использовать только при рендеринге документа.
-
-=head2 C<[get,set]template>
-
-C<Template::Document> Шаблон элемента управления.
-
-=head2 C<AUTOLOAD>
-
-Для удобства работы с шаблоном, элементы управления предоставляю доступ к своим
-свойствам через метод C<AUTOLOAD>. Имена свойств должны начинаться со строчной
-буквы.
 
 =cut
\ No newline at end of file