changeset 351:cfd7570c2af2

working on TTView: created TTView class for rendering models
author cin
date Tue, 08 Oct 2013 17:40:35 +0400
parents f356c4894d1b
children 675cd1829255
files Lib/IMPL/Web/View/TTContext.pm Lib/IMPL/Web/View/TTView.pm _test/Resources/view/layout/default.tt _test/Resources/view/layout/header.tt _test/Resources/view/packages/templates/ARRAY.tt _test/Resources/view/packages/templates/HASH.tt _test/Resources/view/packages/templates/plain.tt _test/Resources/view/site/product/view.tt _test/temp.pl
diffstat 9 files changed, 240 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- a/Lib/IMPL/Web/View/TTContext.pm	Mon Oct 07 17:35:54 2013 +0400
+++ b/Lib/IMPL/Web/View/TTContext.pm	Tue Oct 08 17:40:35 2013 +0400
@@ -31,6 +31,7 @@
 	   prefix
 	   cache
 	   includes
+	   modules
 	)) {
 		my $t = $prop;
 		
@@ -66,6 +67,7 @@
 	my ($this,$name) = @_;
 	
 	my $cache = $this->tt_cache;
+	
 	$this->tt_cache($cache = {}) unless $cache;
 	
 	if(my $tpl = $cache->{$name}) {
@@ -77,7 +79,7 @@
 	my $ext = $this->tt_ext || "";
 	
 	my $file;
-    
+	
 	foreach my $dir (@inc) {
 		$file = $dir ? "$dir/$name" : $name;
 		
@@ -85,15 +87,24 @@
 		
 		$file =  $ext ? "$file.$ext" : $file;
 		
-		warn "lookup: $file";
-		
-		my $tt = eval { $this->template($file) };
-		
-		return $cache->{$name} = {
-			base => $base,
-			labels => $this->load_labels($file),
-			template => $tt,
-		} if $tt;
+		if (exists($this->modules->{$file})) {
+			my $info = $this->modules->{$file};
+			return $cache->{$name} = $info
+                if $info;
+		} else {
+            if( my $tt = eval { $this->template($file) } ) {
+                my $info = {
+		            base => $base,
+		            labels => $this->load_labels($file),
+		            template => $tt,
+		            initialized => 0
+		        };
+		        $this->modules->{$file} = $info;
+		        return $cache->{$name} = $info;
+            } else {
+            	$this->modules->{$file} = undef;
+            }
+		}
 	}
 	
 	$this->throw(Template::Constants::ERROR_FILE, "$name: not found");
@@ -113,9 +124,7 @@
 	
 	my $prefix = $this->prefix;
 	
-	warn "no resolve" if $args and $args->{_no_resolve};
-	
-	if (not(($args and delete $args->{_no_resolve}) or ref $model)) {
+    if (not(($args and delete $args->{_no_resolve}) or ref $model)) {
 		$prefix = $prefix ? "${prefix}.${model}" : $model;
 		$model = $this->resolve_model($model);
 	} else {
@@ -136,6 +145,40 @@
     );
 }
 
+sub display_model {
+	my $this = shift;
+    my $model = shift;
+    my ($template, $args);
+    
+    if (ref $_[0] eq 'HASH') {
+        $args = shift;
+    } else {
+        $template = shift;
+        $args = shift;
+    }
+    
+    $args ||= {};
+    
+    my $prefix = delete $args->{prefix} || $this->prefix;
+    
+    if (my $rel = delete $args->{rel}) {
+    	$prefix = $prefix ? "${prefix}.${rel}" : $rel;
+    }
+    
+    $template = $template ? $this->find_template($template) : $this->find_template_for($model);
+    
+    return $this->render(
+        $template,
+        hashApply(
+            {
+                prefix => $prefix,
+                model => $model,
+            },
+            $args
+        )
+    );
+}
+
 sub invoke_environment {
 	my ($this,$code,$env) = @_;
 	
@@ -146,13 +189,18 @@
             hashApply(
 	            {
 					root => $this->root || $this,
+					modules => $this->modules || {},
 					cache => TypeKeyedCollection->new(),
 		            display => sub {
 		                $this->display(@_);
 		            },
 		            render => sub {
 		            	$this->render(@_);
-		            }
+		            },
+		            display_model => sub {
+		            	$this->display_model(@_);
+		            },
+		            tt_cache => {}
 				},
                 $env
             )
@@ -174,29 +222,38 @@
 	
 	$args ||= {};
 	
-	#TODO handle classes
-	
-	my ($base,$labels);
-	
-	$template = $this->find_template($template) unless ref $template;
+	my $info = ref $template ? $template : $this->find_template($template);
 	
-	if (ref $template eq 'HASH') {
-        $base = $template->{base};
-        $labels = $template->{labels};
-        $template = $template->{template};
-    } else {
-        carp "got an invalid template object: $template";
-        $base = $this->base;
+	if (ref($info) ne 'HASH') {
+		carp "got an invalid template object: $info (" . ref($info) . ")";
+    	$info = {
+    		template => $info,
+    		base => $this->base,
+    		initialized => 1
+    	};
     }
 	
-	return $this->invoke_environment(
-	   sub {
-	       return shift->include($template,$args);
+    return $this->invoke_environment(
+        sub {
+       	    my $ctx = shift;
+       	   
+       	    unless($info->{initialized}) {
+       	        if(my $init = $info->{template}->blocks->{INIT}) {
+       	        	$info->{initialized} = 1;
+       	            eval {
+       	                $ctx->visit($info->{template}->blocks);
+       	                $ctx->include($init);
+       	            };
+       	            $ctx->leave();
+       	        }
+       	    }
+       	   
+            return $ctx->include($info->{template},$args);
 	   },
 	   hashMerge(
-	       $labels || {},
+	       $info->{labels} || {},
 		   {
-		   	base => $base,
+		   	base => $info->{base},
 		   	parent => $this
 		   }
 	   )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lib/IMPL/Web/View/TTView.pm	Tue Oct 08 17:40:35 2013 +0400
@@ -0,0 +1,78 @@
+package IMPL::Web::View::TTView;
+use strict;
+
+use IMPL::Const qw(:prop);
+use IMPL::declare {
+	require => {
+		Context => 'IMPL::Web::View::TTContext'
+	},
+	base => [
+		'IMPL::Object' => undef,
+		'IMPL::Object::Autofill' => '@_',
+		'IMPL::Object::Serializable' => undef
+	],
+	props => [
+		options => PROP_RW,
+		view => PROP_RW,
+		layout => PROP_RW,
+		tt_ext => PROP_RW,
+		includes => PROP_RW | PROP_LIST
+	]
+};
+
+sub CTOR {
+	my ($this) = @_;
+	
+	$this->tt_ext('tt') unless defined $this->tt_ext;
+}
+
+sub display {
+	my ($this,$model,$template,$args) = @_;
+	
+	my $context = Context->new($this->options);
+	my $layout = delete $args->{layout};
+	
+	return $context->invoke_environment(
+		sub {
+			my $ctx = shift;
+			if ($layout) {
+				return $ctx->invoke_environment(
+					sub {
+						return $ctx->render($layout,$args);
+					},
+					{
+						base => $this->layout,
+						content => sub {
+							$ctx->invoke_environment(
+								sub {
+									return shift->display($model,$template,$args);
+								},
+								{
+									base => $this->view
+								}
+							)
+						}
+					}
+				);
+			} else {
+				return $ctx->invoke_environment(
+					sub {
+						return $ctx->display($model,$template,$args);
+					},
+					{
+						base => $this->view
+					}
+				);
+			}
+		},{
+			includes => scalar($this->includes),
+			tt_ext => 'tt',
+			document => {},
+			debug => sub {
+				warn @_;
+			}
+		}
+	);
+}
+
+1;
\ No newline at end of file
--- a/_test/Resources/view/layout/default.tt	Mon Oct 07 17:35:54 2013 +0400
+++ b/_test/Resources/view/layout/default.tt	Tue Oct 08 17:40:35 2013 +0400
@@ -1,5 +1,14 @@
-[% render('header') %]
-[% render('menu') %]
-[% render('nav') %]
-$content
-[% render('footer') %]
\ No newline at end of file
+[%
+    document.dojo.modules = [];
+%]
+[%~ WRAPPER DOC%]
+    $content
+[% END %]
+
+[% BLOCK DOC %]
+    [%~ render('header') %]
+    [% render('menu') %]
+    [% render('nav') %]
+    $content
+    [% render('footer') %]
+[% END %]
\ No newline at end of file
--- a/_test/Resources/view/layout/header.tt	Mon Oct 07 17:35:54 2013 +0400
+++ b/_test/Resources/view/layout/header.tt	Tue Oct 08 17:40:35 2013 +0400
@@ -2,5 +2,18 @@
 <html>
 <head>
 <title>$document.title</title>
+<script>
+    [%
+        IF document.dojo.modules.size;
+            modules = [];
+            FOREACH module IN document.dojo.modules.unique;
+                modules.push('"' _ module _ '"');
+            END;
+    %]
+            require([ [% modules.join(', ') %] ]);
+    [%
+        END;
+    %]
+</script>
 </head>
 <body>
\ No newline at end of file
--- a/_test/Resources/view/packages/templates/ARRAY.tt	Mon Oct 07 17:35:54 2013 +0400
+++ b/_test/Resources/view/packages/templates/ARRAY.tt	Tue Oct 08 17:40:35 2013 +0400
@@ -1,3 +1,3 @@
 [% FOR item IN model %]
-    * ${loop.index}. [% display(item, { _no_resolve => 1, prefix => "$prefix[$loop.index]"}) %]
+    * ${loop.index}. [% display_model(item, prefix = "$prefix[$loop.index]") %]
 [% END %]
\ No newline at end of file
--- a/_test/Resources/view/packages/templates/HASH.tt	Mon Oct 07 17:35:54 2013 +0400
+++ b/_test/Resources/view/packages/templates/HASH.tt	Tue Oct 08 17:40:35 2013 +0400
@@ -1,3 +1,3 @@
 [% FOR item IN model %]
-    <div>$item.key : [% display(item.key) %]</div>
+    <div>$item.key : [% display_model(item.value, rel = item.key) %]</div>
 [% END %]
\ No newline at end of file
--- a/_test/Resources/view/packages/templates/plain.tt	Mon Oct 07 17:35:54 2013 +0400
+++ b/_test/Resources/view/packages/templates/plain.tt	Tue Oct 08 17:40:35 2013 +0400
@@ -1,1 +1,6 @@
+[%
+    BLOCK INIT;
+        document.dojo.modules.push('diji/form/Textbox');
+    END
+%]
 <input name="$prefix">$model</input>
\ No newline at end of file
--- a/_test/Resources/view/site/product/view.tt	Mon Oct 07 17:35:54 2013 +0400
+++ b/_test/Resources/view/site/product/view.tt	Tue Oct 08 17:40:35 2013 +0400
@@ -1,3 +1,4 @@
+[% document.title = PageTitle %]
 <h1> $PageTitle </h1>
 <div>name: [% display('name') %]</div>
 <div>description: [% display(model) %]</div>
\ No newline at end of file
--- a/_test/temp.pl	Mon Oct 07 17:35:54 2013 +0400
+++ b/_test/temp.pl	Tue Oct 08 17:40:35 2013 +0400
@@ -2,59 +2,46 @@
 use strict;
 
 use IMPL::require {
-	TTContext => 'IMPL::Web::View::TTContext'
+	TTView => 'IMPL::Web::View::TTView'
 };
 
-my $ctx = TTContext->new({
-	INCLUDE_PATH => './Resources/view',
-	INTERPOLATE => 1,
-	RECURSION => 1000
-});
+use Time::HiRes qw(gettimeofday tv_interval);
+
+my $t = [gettimeofday];
+
+my $view = TTView->new(
+	options => {
+		INCLUDE_PATH => './Resources/view',
+		INTERPOLATE => 1,
+		RECURSION => 1000
+	},
+	view => 'site',
+	layout => 'layout',
+	includes => [
+		'packages'
+	]
+);
 
-print $ctx->invoke_environment(sub {
-	my ($this) = @_;
-	return $this->render(
-	    'default',
-	    {
-	    	content => sub {
-	    		return $this->invoke_environment(
-	    		    sub {
-		    			shift->render(
-			                'product/view',
-			                {
-					            model => {
-								    name => 'debugger',
-								    manufature => {
-										name => 'DEBUGGERS INC',
-										address => [
-										     {
-										     	coutry => 'Russuia',
-										     	city => 'Moscow'
-										     },
-										     {
-										     	country => 'GB',
-										     	city => 'Essex'
-										     }
-										]
-								    }
-					            }				            
-						    }
-						);
-		    		}, {
-		    			base => 'site'
-		    		}
-                );
-		    }
-	    }
-    );
-}, {
-	base => 'layout',
-	includes => [
-	   'packages'
-	],
-	tt_ext => 'tt',
-	document => {
-		title => 'Test document'
-	}
-});
+print $view->display(
+	{
+		name => 'debugger',
+		manufacture => {
+			name => 'DEBUGGERS INC',
+			address => [
+				{
+					coutry => 'Russuia',
+					city => 'Moscow'
+				},
+				{
+					country => 'GB',
+					city => 'Essex'
+				}
+			]
+		}
+	},
+	'product/view',
+	{ layout => 'default' }
+), "\n";
+
+print "render page: ",tv_interval($t,[gettimeofday]),"ms\n";