Author: hlship
Date: Tue Apr 15 16:59:10 2008
New Revision: 648462

URL: http://svn.apache.org/viewvc?rev=648462&view=rev
Log:
TAPESTRY-2359: Grid component should be able to update itself in place using an 
implicit Zone

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/InplaceGridDemo.tml
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/InplaceGridDemo.java
Modified:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Grid.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/GridColumns.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/event.apt
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Grid.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Grid.java?rev=648462&r1=648461&r2=648462&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Grid.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Grid.java
 Tue Apr 15 16:59:10 2008
@@ -23,11 +23,15 @@
 import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.internal.beaneditor.BeanModelUtils;
 import org.apache.tapestry.internal.bindings.AbstractBinding;
+import org.apache.tapestry.internal.services.ClientBehaviorSupport;
 import org.apache.tapestry.ioc.annotations.Inject;
 import org.apache.tapestry.ioc.internal.util.Defense;
 import org.apache.tapestry.services.BeanModelSource;
+import org.apache.tapestry.services.ComponentEventResultProcessor;
 import org.apache.tapestry.services.FormSupport;
+import org.apache.tapestry.services.Request;
 
+import java.io.IOException;
 import java.util.Collections;
 import java.util.List;
 
@@ -176,6 +180,21 @@
     @Property(write = false)
     private String _tableClass;
 
+    /**
+     * If true, then the Grid will be wrapped in an element that acts like a 
[EMAIL PROTECTED]
+     * org.apache.tapestry.corelib.components.Zone}; all the paging and 
sorting links will
+     */
+    @Parameter
+    private boolean _inPlace;
+
+    /**
+     * The name of the psuedo-zone that encloses the Grid.
+     */
+    @Property(write = false)
+    private String _zone;
+
+    private boolean _didRenderZoneDiv;
+
     @Persist
     private int _currentPage = 1;
 
@@ -191,10 +210,12 @@
     @Inject
     private BeanModelSource _modelSource;
 
+    @Environmental
+    private ClientBehaviorSupport _clientBehaviorSupport;
 
     @SuppressWarnings("unused")
     @Component(
-            parameters = { "lean=inherit:lean", "overrides=componentResources" 
})
+            parameters = { "lean=inherit:lean", 
"overrides=componentResources", "zone=zone" })
     private GridColumns _columns;
 
     @SuppressWarnings("unused")
@@ -202,7 +223,7 @@
             parameters = { "rowClass=rowClass", "rowsPerPage=rowsPerPage", 
"currentPage=currentPage", "row=row", "volatile=inherit:volatile", 
"lean=inherit:lean" })
     private GridRows _rows;
 
-    @Component(parameters = { "source=dataSource", "rowsPerPage=rowsPerPage", 
"currentPage=currentPage" })
+    @Component(parameters = { "source=dataSource", "rowsPerPage=rowsPerPage", 
"currentPage=currentPage", "zone=zone" })
     private GridPager _pager;
 
     @SuppressWarnings("unused")
@@ -220,6 +241,18 @@
     @Environmental(false)
     private FormSupport _formSupport;
 
+    @Inject
+    private Request _request;
+
+    @Environmental
+    private PageRenderSupport _pageRenderSupport;
+
+    /**
+     * Set up via the traditional or Ajax component event request handler
+     */
+    @Environmental
+    private ComponentEventResultProcessor _componentEventResultProcessor;
+
     /**
      * A version of GridDataSource that caches the availableRows property. 
This addresses TAPESTRY-2245.
      */
@@ -394,16 +427,36 @@
 
     }
 
-    Object beginRender()
+    Object beginRender(MarkupWriter writer)
     {
         // Skip rendering of component (template, body, etc.) when there's 
nothing to display.
         // The empty placeholder will already have rendered.
 
         if (_cachingSource.getAvailableRows() == 0) return false;
 
+        if (_inPlace && _zone == null)
+        {
+            _zone = _pageRenderSupport.allocateClientId(_resources);
+
+            writer.element("div", "id", _zone);
+
+            _clientBehaviorSupport.addZone(_zone, null, "show");
+
+            _didRenderZoneDiv = true;
+        }
+
         return null;
     }
 
+    void afterRender(MarkupWriter writer)
+    {
+        if (_didRenderZoneDiv)
+        {
+            writer.end(); // div
+            _didRenderZoneDiv = false;
+        }
+    }
+
     public BeanModel getDataModel()
     {
         return _model;
@@ -454,7 +507,6 @@
         _row = row;
     }
 
-
     /**
      * Resets the Grid to inital settings; this sets the current page to one, 
and [EMAIL PROTECTED]
      * org.apache.tapestry.grid.GridSortModel#clear() clears the sort model}.
@@ -463,5 +515,18 @@
     {
         _currentPage = 1;
         _sortModel.clear();
+    }
+
+    /**
+     * Event handler for inplaceupdate event triggered from nested components 
when an Ajax update occurs. The event
+     * context will carry the zone, which is recorded here, to allow the Grid 
and its sub-components to properly
+     * re-render themselves.  Invokes [EMAIL PROTECTED] 
org.apache.tapestry.services.ComponentEventResultProcessor#processResultValue(Object)}
+     * passing this (the Grid component) as the content provider for the 
update.
+     */
+    void onInPlaceUpdate(String zone) throws IOException
+    {
+        _zone = zone;
+
+        _componentEventResultProcessor.processResultValue(this);
     }
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/GridColumns.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/GridColumns.java?rev=648462&r1=648461&r2=648462&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/GridColumns.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/GridColumns.java
 Tue Apr 15 16:59:10 2008
@@ -23,6 +23,7 @@
 import org.apache.tapestry.grid.GridConstants;
 import org.apache.tapestry.grid.GridModel;
 import org.apache.tapestry.grid.GridSortModel;
+import org.apache.tapestry.internal.InternalConstants;
 import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.ioc.annotations.Inject;
@@ -58,8 +59,15 @@
     private ComponentResources _overrides;
 
 
+    /**
+     * If not null, then each link is output as a link to update the specified 
zone.
+     */
+    @Parameter
+    private String _zone;
+
     @SuppressWarnings("unused")
-    @Component(parameters = { "event=sort", "disabled=sortDisabled", 
"context=columnModel.id", "class=sortLinkClass" })
+    @Component(
+            parameters = { "event=sort", "disabled=sortDisabled", 
"context=columnContext", "class=sortLinkClass", "zone=inherit:zone" })
     private EventLink _sort, _sort2;
 
     @Inject
@@ -88,6 +96,9 @@
     @Property(write = false)
     private PropertyModel _columnModel;
 
+    @Inject
+    private ComponentResources _resources;
+
     void setupRender()
     {
         _lastColumnIndex = _gridModel.getDataModel().getPropertyNames().size() 
- 1;
@@ -144,11 +155,29 @@
         return getSortForColumn() != ColumnSort.UNSORTED;
     }
 
+    /**
+     * Normal, non-Ajax event handler.
+     */
+
     void onSort(String columnId)
     {
         _gridModel.getSortModel().updateSort(columnId);
     }
 
+    /**
+     * Ajax event handler, which carries the zone id.
+     */
+    boolean onSort(String columnId, String zone)
+    {
+        onSort(columnId);
+
+        _resources.triggerEvent(InternalConstants.GRID_INPLACE_UPDATE, new 
Object[] { zone }, null);
+
+        // Event is handled, don't trigger further event handler methods.
+
+        return true;
+    }
+
     public Asset getIcon()
     {
         switch (getSortForColumn())
@@ -162,6 +191,13 @@
             default:
                 return _sortableAsset;
         }
+    }
+
+    public Object getColumnContext()
+    {
+        if (_zone == null) return _columnModel.getId();
+
+        return new Object[] { _columnModel.getId(), _zone };
     }
 
     public String getIconLabel()

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/GridPager.java?rev=648462&r1=648461&r2=648462&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
 Tue Apr 15 16:59:10 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,12 +14,13 @@
 
 package org.apache.tapestry.corelib.components;
 
-import org.apache.tapestry.ComponentResources;
-import org.apache.tapestry.Link;
-import org.apache.tapestry.MarkupWriter;
-import org.apache.tapestry.TapestryConstants;
+import org.apache.tapestry.*;
+import org.apache.tapestry.annotations.Environmental;
 import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.dom.Element;
 import org.apache.tapestry.grid.GridDataSource;
+import org.apache.tapestry.internal.InternalConstants;
+import org.apache.tapestry.internal.services.ClientBehaviorSupport;
 import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.ioc.annotations.Inject;
 
@@ -54,6 +55,12 @@
     @Parameter("5")
     private int _range;
 
+    /**
+     * If not null, then each link is output as a link to update the specified 
zone.
+     */
+    @Parameter
+    private String _zone;
+
     private int _lastIndex;
 
     private int _maxPages;
@@ -64,6 +71,12 @@
     @Inject
     private Messages _messages;
 
+    @Environmental
+    private ClientBehaviorSupport _clientBehaviorSupport;
+
+    @Environmental
+    private PageRenderSupport _pageRenderSupport;
+
     void beginRender(MarkupWriter writer)
     {
         int availableRows = _source.getAvailableRows();
@@ -111,7 +124,7 @@
 
         if (pageIndex <= _lastIndex) return;
 
-        if (pageIndex != _lastIndex + 1) writer.write(" ... "); // &#8230; is 
ellipsis
+        if (pageIndex != _lastIndex + 1) writer.write(" ... ");
 
         _lastIndex = pageIndex;
 
@@ -123,19 +136,46 @@
             return;
         }
 
-        Link link = 
_resources.createActionLink(TapestryConstants.ACTION_EVENT, false, pageIndex);
+        Object[] context = _zone == null
+                           ? new Object[] { pageIndex }
+                           : new Object[] { pageIndex, _zone };
 
-        writer.element("a", "href", link, "title", 
_messages.format("goto-page", pageIndex));
+        Link link = 
_resources.createActionLink(TapestryConstants.ACTION_EVENT, false, context);
+
+        Element element = writer.element("a", "href", link, "title", 
_messages.format("goto-page", pageIndex));
 
         writer.write(Integer.toString(pageIndex));
         writer.end();
 
+        if (_zone != null)
+        {
+            String id = _pageRenderSupport.allocateClientId(_resources);
+
+            element.attribute("id", id);
+
+            _clientBehaviorSupport.linkZone(id, _zone);
+        }
     }
 
+    /**
+     * Normal, non-Ajax event handler.
+     */
     void onAction(int newPage)
     {
         // TODO: Validate newPage in range
 
         _currentPage = newPage;
+    }
+
+    /**
+     * Akjax event handler, passing the zone along.
+     */
+    boolean onAction(int newPage, String zone)
+    {
+        onAction(newPage);
+
+        _resources.triggerEvent(InternalConstants.GRID_INPLACE_UPDATE, new 
Object[] { zone }, null);
+
+        return true; // abort event
     }
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java?rev=648462&r1=648461&r2=648462&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java
 Tue Apr 15 16:59:10 2008
@@ -53,6 +53,11 @@
     public static final String PAGE_CONTEXT_NAME = "t:ac";
 
     /**
+     * Name of event triggered by Grid sub-components when an in-place Grid is 
updated.
+     */
+    public static final String GRID_INPLACE_UPDATE = "inplaceupdate";
+
+    /**
      * The name of a query parameter that stores the containing page (used in 
action links when the page containing the
      * component is not the same as the page that was rendering). The active 
page (the page which initiated the render)
      * is encoded into the URL, and the containing page is tacked on as this 
query parameter.

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/event.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/event.apt?rev=648462&r1=648461&r2=648462&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/event.apt 
(original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/event.apt Tue Apr 
15 16:59:10 2008
@@ -186,6 +186,12 @@
   The event will bubble up the hierarchy, until it is aborted. The event is 
aborted
   when an event handler method returns a non-null value.
 
+  Returning a boolean value from an event handler method is special.  
Returning true will abort the event
+  with no result; use this when the event is fully handled without a return 
value and no further event handlers
+  (in the same component, or in containing components) should be invoked.
+
+  Returning false is the same as returning null.
+
 Event Method Exceptions
 
   Event methods are allowed to throw any exception (not just runtime 
exceptions). If an event method does

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt?rev=648462&r1=648461&r2=648462&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt Tue Apr 15 
16:59:10 2008
@@ -10,6 +10,12 @@
 
 New And Of Note
 
+  * The {{{ref/org/apache/tapestry/corelib/components/Grid.html}Grid}} 
component can now update itself in place,
+    using Ajax, when paging or sorting links are clicked.
+
+  * Added a zone parameter to the  
{{{ref/org/apache/tapestry/corelib/components/BeanEditForm.;html}BeanEditForm}}
+    component, to support Ajax updates.
+
   * The @Cached annotation has been added to allowing the caching of method 
results.
 
   * Tapestry can now generate accessor methods for fields automatically via 
the @Property annotation.

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/InplaceGridDemo.tml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/InplaceGridDemo.tml?rev=648462&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/InplaceGridDemo.tml 
(added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/InplaceGridDemo.tml 
Tue Apr 15 16:59:10 2008
@@ -0,0 +1,23 @@
+<html t:type="Border" 
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
+
+    <h1>In-Place Grid Demo</h1>
+
+    <p>
+        Last full page refresh at:
+        <span id="lastupdate">${date}</span>
+    </p>
+
+    <table t:id="grid" source="tracks" row="track" inplace="true">
+        <t:parameter name="ratingheader">
+            <t:actionlink t:id="sortRating">Sort Rating</t:actionlink>
+        </t:parameter>
+        <t:parameter name="ratingcell">
+            <t:outputRating rating="track.rating"/>
+        </t:parameter>
+    </table>
+
+    <p>
+        [<t:actionlink t:id="reset">reset the Grid</t:actionlink>]
+    </p>
+
+</html>

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?rev=648462&r1=648461&r2=648462&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 Tue Apr 15 16:59:10 2008
@@ -1979,4 +1979,20 @@
                     "After update the nanoseconds time did not change, meaning 
@Cache was broken.");
 
     }
+
+    @Test
+    public void inplace_grid()
+    {
+        start("In-Place Grid Demo");
+
+        String timestamp = getText("lastupdate");
+
+        click("link=2");
+        sleep(100);
+        click("link=Album");
+        sleep(100);
+
+        assertEquals(getText("lastupdate"), timestamp,
+                     "Timestamp should not have changed because updates are 
in-place.");
+    }
 }

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/InplaceGridDemo.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/InplaceGridDemo.java?rev=648462&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/InplaceGridDemo.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/InplaceGridDemo.java
 Tue Apr 15 16:59:10 2008
@@ -0,0 +1,25 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.integration.app1.pages;
+
+import java.util.Date;
+
+public class InplaceGridDemo extends GridDemo
+{
+    public Date getDate()
+    {
+        return new Date();
+    }
+}

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java?rev=648462&r1=648461&r2=648462&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
 Tue Apr 15 16:59:10 2008
@@ -257,7 +257,9 @@
 
             new Item("cachedpage", "Cached Annotation", "Caching method return 
values"),
 
-            new Item("cachedpage2", "Cached Annotation2", "Caching method 
return values w/ inheritence")
+            new Item("cachedpage2", "Cached Annotation2", "Caching method 
return values w/ inheritence"),
+
+            new Item("inplacegriddemo", "In-Place Grid Demo", "Grid that 
updates in-place using Ajax")
     );
 
     static


Reply via email to