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(" ... "); // … 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