Author: hlship
Date: Fri Nov  3 15:31:53 2006
New Revision: 471051

URL: http://svn.apache.org/viewvc?view=rev&rev=471051
Log:
Add several more render phases to the component rendering state machine

Added:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/AfterRenderBody.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/AfterRenderTemplate.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeforeRenderTemplate.java
Modified:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeforeRenderBody.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeginRender.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/ComponentLifecycle.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java
    tapestry/tapestry5/tapestry-core/trunk/src/render-states.ygf
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt
    
tapestry/tapestry5/tapestry-core/trunk/src/site/resources/images/component-render-states.png
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/AfterRenderBody.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/AfterRenderBody.java?view=auto&rev=471051
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/AfterRenderBody.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/AfterRenderBody.java
 Fri Nov  3 15:31:53 2006
@@ -0,0 +1,22 @@
+package org.apache.tapestry.annotations;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Corresponds to [EMAIL PROTECTED] BeforeRenderBody}, allowing additional 
markup after rendering the body of
+ * a component, but before rendering the rest of the component's template. 
Return false (the
+ * default) to progress to the [EMAIL PROTECTED] AfterRenderTemplate} or 
[EMAIL PROTECTED] AfterRender} phase (depending
+ * on whether the component does or does not have a template). Return true to 
return to the
+ * [EMAIL PROTECTED] BeforeRenderBody} phase.
+ */
[EMAIL PROTECTED](ElementType.METHOD)
[EMAIL PROTECTED](RUNTIME)
[EMAIL PROTECTED]
+public @interface AfterRenderBody {
+
+}

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/AfterRenderTemplate.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/AfterRenderTemplate.java?view=auto&rev=471051
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/AfterRenderTemplate.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/AfterRenderTemplate.java
 Fri Nov  3 15:31:53 2006
@@ -0,0 +1,20 @@
+package org.apache.tapestry.annotations;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Corresponds to [EMAIL PROTECTED] BeforeRenderTemplate}, allowing additional 
markup after rendering the
+ * component's template. Returning false is the default, which progress to the 
[EMAIL PROTECTED] AfterRender}
+ * phase. Return true to return to the [EMAIL PROTECTED] BeforeRenderTemplate} 
phase.
+ */
[EMAIL PROTECTED](ElementType.METHOD)
[EMAIL PROTECTED](RUNTIME)
[EMAIL PROTECTED]
+public @interface AfterRenderTemplate {
+
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeforeRenderBody.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeforeRenderBody.java?view=diff&rev=471051&r1=471050&r2=471051
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeforeRenderBody.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeforeRenderBody.java
 Fri Nov  3 15:31:53 2006
@@ -26,17 +26,13 @@
  * component's template where the body element occurs. Such methods may 
optionally take a
  * [EMAIL PROTECTED] org.apache.tapestry.MarkupWriter} parameter, and may 
return void or boolean.
  * <p>
- * Returning true (or void) will queue up the component's body for rendering. 
Once the body and the
- * rest of the component's template renders, the [EMAIL PROTECTED] 
org.apache.tapestry.annotations.AfterRender}
- * phase will execute.
+ * Returning true (or void) will queue up the component's body for rendering.
  * <p>
  * Returning false will skip the component's body, but continue rendering the 
template. The
- * [EMAIL PROTECTED] org.apache.tapestry.annotations.AfterRender} phase will 
still execute after the template
- * finishes rendering.
+ * [EMAIL PROTECTED] org.apache.tapestry.annotations.AfterRenderBody} phase 
will still execute after the
+ * template finishes rendering.
  * <p>
  * This phase is skipped for components which do not have a body.
- * 
- * 
  */
 @Target(ElementType.METHOD)
 @Retention(RUNTIME)

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeforeRenderTemplate.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeforeRenderTemplate.java?view=auto&rev=471051
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeforeRenderTemplate.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeforeRenderTemplate.java
 Fri Nov  3 15:31:53 2006
@@ -0,0 +1,22 @@
+package org.apache.tapestry.annotations;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Associated with components that have a template, this phase is invoked to 
allow the component to
+ * decorate its template with additional markup. Returning true will cause the 
component's template
+ * to render (possibly including additional components, or this component's 
body), and eventually
+ * reach the [EMAIL PROTECTED] AfterRenderTemplate} phase. Return false to 
skip the template and body, and jump
+ * directly to the [EMAIL PROTECTED] AfterRenderTemplate} phase.
+ */
[EMAIL PROTECTED](ElementType.METHOD)
[EMAIL PROTECTED](RUNTIME)
[EMAIL PROTECTED]
+public @interface BeforeRenderTemplate {
+
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeginRender.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeginRender.java?view=diff&rev=471051&r1=471050&r2=471051
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeginRender.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/BeginRender.java
 Fri Nov  3 15:31:53 2006
@@ -23,18 +23,21 @@
 
 /**
  * Marker annotation for methods that should be executed at the start of 
rendering the component.
- * This usually includes rendering of the component's start tag. Such methods 
may optionally take a
- * [EMAIL PROTECTED] org.apache.tapestry.MarkupWriter} parameter, and may 
return void or boolean. Returning
- * true or void will allow the component to advance into the render template / 
render body phase. If
- * a body is present, the [EMAIL PROTECTED] 
org.apache.tapestry.annotations.BeforeRenderBody} phase will
- * execute. Either way, the [EMAIL PROTECTED] 
org.apache.tapestry.annotations.AfterRender} phase will execute
- * after the template and/or body have rendered. A component with a body but 
without a template will
- * still see the [EMAIL PROTECTED] 
org.apache.tapestry.annotations.BeforeRenderBody} phase execute.
+ * This usually includes rendering of the component's start tag.
+ * <p>
+ * Such methods may optionally take a [EMAIL PROTECTED] 
org.apache.tapestry.MarkupWriter} parameter, and may
+ * return void or boolean. Returning true or void will allow the component to 
advance into the
+ * render template / render body phase. If a body is present, the
+ * [EMAIL PROTECTED] org.apache.tapestry.annotations.BeforeRenderBody} phase 
will execute. If a component has a
+ * template, the [EMAIL PROTECTED] BeforeRenderTemplate} phase will execute 
(and the render body will only
+ * occur if the template directs so).
+ * <p>
+ * Either way, the [EMAIL PROTECTED] 
org.apache.tapestry.annotations.AfterRender} phase will execute after the
+ * template and/or body have rendered. A component with a body but without a 
template will still see
+ * the [EMAIL PROTECTED] org.apache.tapestry.annotations.BeforeRenderBody} 
phase execute.
  * <p>
  * Returning false will skip rendering of the template and/or body, and jump 
directly to the
  * [EMAIL PROTECTED] org.apache.tapestry.annotations.CleanupRender} phase.
- * 
- * 
  */
 @Target(ElementType.METHOD)
 @Retention(RUNTIME)

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java?view=diff&rev=471051&r1=471050&r2=471051
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
 Fri Nov  3 15:31:53 2006
@@ -281,9 +281,8 @@
 
     // This is the state machine for rendering an individual component.
 
-    private RenderCommand _setupRender = new RenderCommand()
+    private final RenderCommand _setupRender = new RenderCommand()
     {
-
         public void render(MarkupWriter writer, RenderQueue queue)
         {
             _rendering = true;
@@ -293,6 +292,16 @@
             for (ComponentLifecycle component : _components)
                 component.setupRender(writer, event);
 
+            // Here's the problem: if an exception gets thrown during 
rendering, then
+            // some components may never see their CleanupRender phase cleanup 
occur, leaving
+            // the page as a whole in an undesirable state. I suppose
+            // that the pageDidDetach() would be another place to clean things 
up, but perhaps
+            // RenderQueue needs to catch exceptions and invoke commands that 
related to cleanup?
+            // Or have a way to determine if the page is "dirty" and should 
not go back into the
+            // pool?
+
+            queue.push(_cleanupRender);
+
             if (event.getResult())
                 queue.push(_beginRender);
         }
@@ -304,9 +313,8 @@
         }
     };
 
-    private RenderCommand _beginRender = new RenderCommand()
+    private final RenderCommand _beginRender = new RenderCommand()
     {
-
         public void render(MarkupWriter writer, RenderQueue queue)
         {
             LifecycleEvent<Boolean> event = newEvent(true);
@@ -314,8 +322,15 @@
             for (ComponentLifecycle component : _components)
                 component.beginRender(writer, event);
 
+            // If the component has no template whatsoever, then a
+            // renderBody element is added as the lone element of the 
component's template.
+            // So every component will have a non-empty template.
+
             if (event.getResult())
-                enqueueTemplate(queue);
+            {
+                queue.push(_afterRender);
+                queue.push(_beforeRenderTemplate);
+            }
         }
 
         @Override
@@ -323,10 +338,53 @@
         {
             return String.format("BeginRender[%s]", _completeId);
         }
+    };
+
+    private final RenderCommand _beforeRenderTemplate = new RenderCommand()
+    {
+        public void render(MarkupWriter writer, RenderQueue queue)
+        {
+            LifecycleEvent<Boolean> event = newEvent(true);
+
+            for (ComponentLifecycle component : _components)
+                component.beforeRenderTemplate(writer, event);
+
+            queue.push(_afterRenderTemplate);
+
+            if (event.getResult())
+                pushElements(queue, _template);
+        }
 
+        @Override
+        public String toString()
+        {
+            return String.format("BeforeRenderTemplate[%s]", _completeId);
+        }
     };
 
-    private RenderCommand _beforeRenderBody = new RenderCommand()
+    private final RenderCommand _afterRenderTemplate = new RenderCommand()
+    {
+        public void render(MarkupWriter writer, RenderQueue queue)
+        {
+            LifecycleEvent<Boolean> event = newEvent(false);
+
+            Iterator<ComponentLifecycle> i = 
InternalUtils.reverseIterator(_components);
+
+            while (i.hasNext())
+                i.next().afterRenderTemplate(writer, event);
+
+            if (event.getResult())
+                queue.push(_beforeRenderTemplate);
+        }
+
+        @Override
+        public String toString()
+        {
+            return String.format("BeforeRenderTemplate[%s]", _completeId);
+        }
+    };
+
+    private final RenderCommand _beforeRenderBody = new RenderCommand()
     {
 
         public void render(MarkupWriter writer, RenderQueue queue)
@@ -334,10 +392,12 @@
             LifecycleEvent<Boolean> event = newEvent(true);
 
             for (ComponentLifecycle component : _components)
-                _component.beforeRenderBody(writer, event);
+                component.beforeRenderBody(writer, event);
+
+            queue.push(_afterRenderBody);
 
             if (event.getResult())
-                enqueueBody(queue);
+                pushElements(queue, _body);
         }
 
         @Override
@@ -348,9 +408,30 @@
 
     };
 
-    private RenderCommand _afterRender = new RenderCommand()
+    private final RenderCommand _afterRenderBody = new RenderCommand()
     {
+        public void render(MarkupWriter writer, RenderQueue queue)
+        {
+            LifecycleEvent<Boolean> event = newEvent(false);
+
+            Iterator<ComponentLifecycle> i = 
InternalUtils.reverseIterator(_components);
+
+            while (i.hasNext())
+                i.next().afterRenderBody(writer, event);
+
+            if (event.getResult())
+                queue.push(_beforeRenderBody);
+        }
+
+        @Override
+        public String toString()
+        {
+            return String.format("AfterRenderBody[%s]", _completeId);
+        }
+    };
 
+    private final RenderCommand _afterRender = new RenderCommand()
+    {
         public void render(MarkupWriter writer, RenderQueue queue)
         {
             LifecycleEvent<Boolean> event = newEvent(false);
@@ -369,12 +450,10 @@
         {
             return String.format("AfterRender[%s]", _completeId);
         }
-
     };
 
-    private RenderCommand _cleanupRender = new RenderCommand()
+    private final RenderCommand _cleanupRender = new RenderCommand()
     {
-
         public void render(MarkupWriter writer, RenderQueue queue)
         {
             LifecycleEvent<Boolean> event = newEvent(false);
@@ -386,7 +465,6 @@
 
             if (event.getResult())
             {
-                queue.push(this);
                 queue.push(_setupRender);
             }
             else
@@ -405,48 +483,19 @@
         {
             return String.format("CleanupRender[%s]", _completeId);
         }
-
     };
 
-    /** Pushes CleanupRender and SetupRender phase commands onto the queue. */
-    public void render(MarkupWriter writer, RenderQueue queue)
+    /** Pushes the SetupRender phase state onto the queue. */
+    public final void render(MarkupWriter writer, RenderQueue queue)
     {
-        // Here's the problem: if an exception gets thrown during rendering, 
then
-        // some components may never see their CleanupRender phase cleanup 
occur, leaving
-        // the page as a whole in an undesirable state. I suppose
-        // that the pageDidDetach() would be another place to clean things up, 
but perhaps
-        // RenderQueue needs to catch exceptions and invoke commands that 
related to cleanup?
-        // Or have a way to determine if the page is "dirty" and should not go 
back into the
-        // pool?
-
-        queue.push(_cleanupRender);
         queue.push(_setupRender);
     }
 
-    private void enqueueBody(RenderQueue queue)
-    {
-        pushElements(queue, _body);
-    }
-
     private int size(List<?> list)
     {
         return list == null ? 0 : list.size();
     }
 
-    private void enqueueTemplate(RenderQueue queue)
-    {
-        // Push this deepest: after rendering the template
-        // (including the render body directive), we want to
-        // give the component a chance to render its close tag.
-
-        queue.push(_afterRender);
-
-        // Push them in reverse order, so that the first template item
-        // it at the head of the queue.
-
-        pushElements(queue, _template);
-    }
-
     private void pushElements(RenderQueue queue, List<PageElement> list)
     {
         int count = size(list);
@@ -456,6 +505,8 @@
 
     public void enqueueBeforeRenderBody(RenderQueue queue)
     {
+        // If no body, then no beforeRenderBody or afterRenderBody
+
         if (_body != null)
             queue.push(_beforeRenderBody);
     }

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/ComponentLifecycle.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/ComponentLifecycle.java?view=diff&rev=471051&r1=471050&r2=471051
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/ComponentLifecycle.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/ComponentLifecycle.java
 Fri Nov  3 15:31:53 2006
@@ -23,6 +23,9 @@
  * but is <em>not</em> expected to be directly implemented by component 
classes; it should only be
  * implemented as part of the component class transformation process.
  * <p>
+ * Most of the methods are related to render phases; see the corresponding 
annotations and component
+ * rendering documentation to see how they relate to each other.
+ * <p>
  * This interface is likely to change without notice.
  */
 public interface ComponentLifecycle extends ComponentResourcesAware, 
PageLifecycleListener
@@ -38,45 +41,38 @@
 
     /**
      * Invoked before rendering a component (or its template).
-     * <p>
-     * Set event result to true to procede to [EMAIL PROTECTED] 
#renderTag(MarkupWriter)}, or false to skip to
-     * [EMAIL PROTECTED] #cleanupRender(MarkupWriter)}.
      */
     void setupRender(MarkupWriter writer, LifecycleEvent<Boolean> event);
 
     /**
      * Invoked to allow a component to render its tag (start tag and 
attributes).
-     * <p>
-     * Set event result to true to render the component's template (eventually 
invoking
-     * [EMAIL PROTECTED] #beforeRenderBody(MarkupWriter)}, false to skip to
-     * [EMAIL PROTECTED] #cleanupRender(MarkupWriter)}.
      */
     void beginRender(MarkupWriter writer, LifecycleEvent<Boolean> event);
 
     /**
+     * This phase is only invoked for components with templates.
+     */
+    void beforeRenderTemplate(MarkupWriter writer, LifecycleEvent<Boolean> 
event);
+
+    /** Invoked after rendering the template for a component (only for 
components with a template). */
+    void afterRenderTemplate(MarkupWriter writer, LifecycleEvent<Boolean> 
event);
+
+    /**
      * Invoked just before rendering the body of component.
-     * <p>
-     * Set event result to true to render the body before advancing to
-     * [EMAIL PROTECTED] #renderCloseTag(MarkupWriter)}, or false to skip the 
body and advance directly to
-     * [EMAIL PROTECTED] #renderCloseTag(MarkupWriter)}.
      */
     void beforeRenderBody(MarkupWriter writer, LifecycleEvent<Boolean> event);
 
+    /** Invoked just after rendering the body of the component. */
+    void afterRenderBody(MarkupWriter writer, LifecycleEvent<Boolean> event);
+
     /**
-     * Renders the close tag. Decides whether to render the the tag (and its 
template and/or body)
-     * again.
-     * <p>
-     * Set event result to true to return to [EMAIL PROTECTED] 
#renderTag(MarkupWriter)}, or false to advance
-     * to [EMAIL PROTECTED] #cleanupRender(MarkupWriter)}.
+     * Generally used to write the close tag matching any open tag written by
+     * [EMAIL PROTECTED] #beginRender(MarkupWriter, LifecycleEvent)}.
      */
     void afterRender(MarkupWriter writer, LifecycleEvent<Boolean> event);
 
     /**
      * Generally used to perform final cleanup of the component after 
rendering.
-     * <p>
-     * Set event result to true to re-render the component, returning to
-     * [EMAIL PROTECTED] #beforeRender(MarkupWriter)}, or false to indicate 
that rendering of the component is
-     * complete.
      */
     void cleanupRender(MarkupWriter writer, LifecycleEvent<Boolean> event);
 

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=471051&r1=471050&r2=471051
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
 Fri Nov  3 15:31:53 2006
@@ -27,7 +27,10 @@
 import org.apache.commons.logging.Log;
 import org.apache.tapestry.MarkupWriter;
 import org.apache.tapestry.annotations.AfterRender;
+import org.apache.tapestry.annotations.AfterRenderBody;
+import org.apache.tapestry.annotations.AfterRenderTemplate;
 import org.apache.tapestry.annotations.BeforeRenderBody;
+import org.apache.tapestry.annotations.BeforeRenderTemplate;
 import org.apache.tapestry.annotations.BeginRender;
 import org.apache.tapestry.annotations.CleanupRender;
 import org.apache.tapestry.annotations.SetupRender;
@@ -514,12 +517,27 @@
         add(configuration, TransformConstants.BEGIN_RENDER_SIGNATURE, 
BeginRender.class, false);
         add(
                 configuration,
+                TransformConstants.BEFORE_RENDER_TEMPLATE_SIGNATURE,
+                BeforeRenderTemplate.class,
+                false);
+        add(
+                configuration,
                 TransformConstants.BEFORE_RENDER_BODY_SIGNATURE,
                 BeforeRenderBody.class,
                 false);
 
         // These phases operate in reverse order.
 
+        add(
+                configuration,
+                TransformConstants.AFTER_RENDER_BODY_SIGNATURE,
+                AfterRenderBody.class,
+                true);
+        add(
+                configuration,
+                TransformConstants.AFTER_RENDER_TEMPLATE_SIGNATURE,
+                AfterRenderTemplate.class,
+                true);
         add(configuration, TransformConstants.AFTER_RENDER_SIGNATURE, 
AfterRender.class, true);
         add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, 
CleanupRender.class, true);
 

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java?view=diff&rev=471051&r1=471050&r2=471051
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java
 Fri Nov  3 15:31:53 2006
@@ -84,11 +84,35 @@
 
     /**
      * Signature for
+     * [EMAIL PROTECTED] 
org.apache.tapestry.runtime.ComponentLifecycle#beforeRenderTemplate(MarkupWriter,
 LifecycleEvent)}.
+     * 
+     * @see org.apache.tapestry.annotations.BeforeRenderTemplate
+     */
+    public static MethodSignature BEFORE_RENDER_TEMPLATE_SIGNATURE = 
newLifecycleMethodSignature("beforeRenderTemplate");
+
+    /**
+     * Signature for
+     * [EMAIL PROTECTED] 
org.apache.tapestry.runtime.ComponentLifecycle#afterRenderTemplate(MarkupWriter,
 LifecycleEvent)}.
+     * 
+     * @see org.apache.tapestry.annotations.BeforeRenderTemplate
+     */
+    public static MethodSignature AFTER_RENDER_TEMPLATE_SIGNATURE = 
newLifecycleMethodSignature("afterRenderTemplate");
+
+    /**
+     * Signature for
      * [EMAIL PROTECTED] 
org.apache.tapestry.runtime.ComponentLifecycle#beforeRenderBody(MarkupWriter, 
LifecycleEvent)}.
      * 
      * @see org.apache.tapestry.annotations.BeforeRenderBody
      */
     public static final MethodSignature BEFORE_RENDER_BODY_SIGNATURE = 
newLifecycleMethodSignature("beforeRenderBody");
+
+    /**
+     * Signature for
+     * [EMAIL PROTECTED] 
org.apache.tapestry.runtime.ComponentLifecycle#afterRenderBody(MarkupWriter, 
LifecycleEvent)}.
+     * 
+     * @see org.apache.tapestry.annotations.AfterRenderBody
+     */
+    public static final MethodSignature AFTER_RENDER_BODY_SIGNATURE = 
newLifecycleMethodSignature("afterRenderBody");
 
     /**
      * Signature for

Modified: tapestry/tapestry5/tapestry-core/trunk/src/render-states.ygf
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/render-states.ygf?view=diff&rev=471051&r1=471050&r2=471051
==============================================================================
Binary files - no diff available.

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt?view=diff&rev=471051&r1=471050&r2=471051
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/rendering.apt Fri 
Nov  3 15:31:53 2006
@@ -30,15 +30,15 @@
  
 [../images/component-render-states.png] Component Render States
 
-  Each of the orange phases (SetupRender, BeginRender, BeforeRenderBody,
-  AfterRender and CleanupRender) corresponds to an annotation you
+  Each of the orange phases (SetupRender, BeginRender, BeforeRenderBody, etc.) 
+  corresponds to an annotation you
   may place on one or more methods of your class.  The annotation directs
   Tapestry to invoke your method as part of that phase.
   
   Methods marked with these annotations are called <<render phase methods>>.
   
   Your methods may be void, or return a boolean value. Returning a value can 
force
-  phases to be skipped, or re-visited.
+  phases to be skipped, or even be re-visited.
   
   Render phase methods may take no parameters, or may take
   a parameter of type {{{dom.html}MarkupWriter}}.  The methods can have any 
visibility
@@ -49,6 +49,13 @@
   
   These methods are <<optional>>, a default behavior is associated with each 
phase.
  
+  The large number of phases reflects the use of {{{mixin.html}component 
mixins}} which
+  also plug into the render phases. Several of the phases (such as 
PreBeginRender and PostBeginRender)
+  exist almost exclusively for mixins.
+  
+  Generally, your code will use the SetupRender, BeginRender, AfterRender and 
CleanupRender
+  phases ... often just one or two of those.
+ 
   Here's the source for a looping component that counts up or down between two 
values,
   renders its body a number of times,
   and stores the current index value in a parameter:
@@ -123,9 +130,7 @@
   What's really mind blowing is that the template and body of a component will
   often contain ... more components! That means that many different components 
will
   be in different phases of their own state machine.
-  
-  <TODO: Add more phases as needed.  Could phases be extensible?>
-  
+    
 * {{{../apidocs/org/apache/tapestry/annotations/SetupRender.html}SetupRender}}
 
   This is where you can perform any one-time per-render setup for your 
component.
@@ -151,19 +156,29 @@
   this phase, but the template (if present) or body (if no template is 
present, but
   the component has a body) will be rendered.
   
+  <<PreBeginRender and PostBeginRender are not yet implemented.>>
+  
+* 
{{{../apidocs/org/apache/tapestry/annotations/BeforeRenderTemplate.html}BeforeRenderTemplate}}
+
+  Invoked only for components that have a template. This phase exists to allow 
a component to decorate
+  its template (creating markup around the template generated markup), or to 
allow a component
+  to skip its template.
+  
 * 
{{{../apidocs/org/apache/tapestry/annotations/BeforeRenderBody.html}BeforeRenderBody}}
 
   Phase associated with a component's body (the portion of its container's 
template that
   the component occupies).  The BeforeRenderBody phase allows the component 
the ability
   to skip the body, while still rendering the rest of the component's template 
(if any).
   
-  If not methods are annotated with BeforeRenderBody, then the body will be 
rendered by
+  If no methods are annotated with BeforeRenderBody, then the body will be 
rendered by
   default. Again, this occurs when the \<render-body\> element of the 
component's template
   is reached, or automatically if the component has no template (but the 
component does
   have a body).
-  
-  <TODO: At some point in the future, we may add an AfterRenderBody phase, 
which would allow
-  the component to wrap the body in additional markup, as desired.>
+
+* 
{{{../apidocs/org/apache/tapestry/annotations/AfterRenderBody.html}AfterRenderBody}}
+
+  Phase that is executed after the body is rendered; this only occurs for 
components with a 
+  body.
   
 * {{{../apidocs/org/apache/tapestry/annotations/AfterRender.html}AfterRender}}
   
@@ -198,11 +213,11 @@
   Ordering is always parent-first.  Methods defined in the parent class are 
always invoked
   before methods defined in the child class.
   
-* Reverse Ordering for AfterRender and CleanupRender
+* Reverse Ordering for AfterXXX and CleanupRender
 
-  The AfterRender phase exists to balance the BeginRender phase.  Often 
elements will
-  be started inside the BeginRender phase and then the elements will be ended 
(closed)
-  inside the AfterRender support (with the body and template of the component 
rendering
+  The After<XXX> phases exists to balance the Begin<XXX> and Before<XXX> 
phases.  Often elements will
+  be started inside an earlier phase and then the elements will be ended 
(closed)
+  inside the correspopnding After<XXX> phase (with the body and template of 
the component rendering
   between).
   
   In order to ensure that operations occur in the correct, and natural order, 
the

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/site/resources/images/component-render-states.png
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/resources/images/component-render-states.png?view=diff&rev=471051&r1=471050&r2=471051
==============================================================================
Binary files - no diff available.

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java?view=diff&rev=471051&r1=471050&r2=471051
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java
 Fri Nov  3 15:31:53 2006
@@ -71,4 +71,22 @@
     {
         return false;
     }
+
+    public void afterRenderBody(MarkupWriter writer, LifecycleEvent<Boolean> 
event)
+    {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void afterRenderTemplate(MarkupWriter writer, 
LifecycleEvent<Boolean> event)
+    {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void beforeRenderTemplate(MarkupWriter writer, 
LifecycleEvent<Boolean> event)
+    {
+        // TODO Auto-generated method stub
+
+    }
 }


Reply via email to