You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2006/11/04 00:31:55 UTC

svn commit: r471051 - in /tapestry/tapestry5/tapestry-core/trunk/src: ./ main/java/org/apache/tapestry/annotations/ main/java/org/apache/tapestry/internal/structure/ main/java/org/apache/tapestry/runtime/ main/java/org/apache/tapestry/services/ site/ap...

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 {@link 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 {@link AfterRenderTemplate} or {@link AfterRender} phase (depending
+ * on whether the component does or does not have a template). Return true to return to the
+ * {@link BeforeRenderBody} phase.
+ */
+@Target(ElementType.METHOD)
+@Retention(RUNTIME)
+@Documented
+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 {@link BeforeRenderTemplate}, allowing additional markup after rendering the
+ * component's template. Returning false is the default, which progress to the {@link AfterRender}
+ * phase. Return true to return to the {@link BeforeRenderTemplate} phase.
+ */
+@Target(ElementType.METHOD)
+@Retention(RUNTIME)
+@Documented
+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
  * {@link 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 {@link 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
- * {@link org.apache.tapestry.annotations.AfterRender} phase will still execute after the template
- * finishes rendering.
+ * {@link 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 {@link AfterRenderTemplate} phase. Return false to skip the template and body, and jump
+ * directly to the {@link AfterRenderTemplate} phase.
+ */
+@Target(ElementType.METHOD)
+@Retention(RUNTIME)
+@Documented
+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
- * {@link 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 {@link org.apache.tapestry.annotations.BeforeRenderBody} phase will
- * execute. Either way, the {@link 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 {@link org.apache.tapestry.annotations.BeforeRenderBody} phase execute.
+ * This usually includes rendering of the component's start tag.
+ * <p>
+ * Such methods may optionally take a {@link 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
+ * {@link org.apache.tapestry.annotations.BeforeRenderBody} phase will execute. If a component has a
+ * template, the {@link BeforeRenderTemplate} phase will execute (and the render body will only
+ * occur if the template directs so).
+ * <p>
+ * Either way, the {@link 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 {@link org.apache.tapestry.annotations.BeforeRenderBody} phase execute.
  * <p>
  * Returning false will skip rendering of the template and/or body, and jump directly to the
  * {@link 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 {@link #renderTag(MarkupWriter)}, or false to skip to
-     * {@link #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
-     * {@link #beforeRenderBody(MarkupWriter)}, false to skip to
-     * {@link #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
-     * {@link #renderCloseTag(MarkupWriter)}, or false to skip the body and advance directly to
-     * {@link #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 {@link #renderTag(MarkupWriter)}, or false to advance
-     * to {@link #cleanupRender(MarkupWriter)}.
+     * Generally used to write the close tag matching any open tag written by
+     * {@link #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
-     * {@link #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
+     * {@link 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
+     * {@link 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
      * {@link 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
+     * {@link 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
+
+    }
 }