2008-01-03
扔掉T5复杂的Grid组件,打造自己灵活的支持分页排序组件。
关键字: tapestry
Grid算是比较T5中较复杂的一个组件,我也有篇介绍Grid怎么使用的文章。http://www.javaeye.com/topic/114754 但是如果我们平时需要些比较灵活的布局。 Grid组件用起来就比较别扭了。
下面我介绍下使用Loop组件实现一个灵活但是又不缺乏分页,排序功能的Grid组件的实现。
首先我们全局看下页面上是要怎样写的。
是不是比较简单。 你可以单独输出Table的头部和body部分。 这里使用了2个组件一个OrderColumn,一个是PageNavigation。 这两个组件公用了一个paging对象, 这个paging对象其实提供了对分页,和当前排序字段的支持。 下面看看page class的内容。
这里我们把paging对象保存在了session里。 然后绑定到OrderColumn和PageNavigation组件中。 请注意getItems方法。 这个是获得你要显示的数据。 这里你要先得到所有的数据的总数然后调用setItemCount方法, 然后你要通过paging中的firstResult maxResult orderProperty order(desc,ase)去获取你要显示的数据。 下面看看paging对象。
ok, 下面贴下OrderColumn, PageNavigation的代码
OrderColumn.tml
OrderColumn.java
PageNavigation.tml
PageNavigation.java
package
Ok,这个对于T4, T3也是一样的。 你只要把OrderColumn 和 PageNavigation 组件改成相应版本下面的组件就行了。 还有就是如果觉得PageNavigation看起来不是很好的话, 你也可以自己做各式各样的PageNavigation,他就只需要Paging这个类。
我把这个打包成了一个Maven项目。 如果你装了WTP的话。
运行mvn eclipse:eclipse -Dwtpversion=1.0 -DdownloadSources=true 然后再import项目到eclipse中就行了。
下面我介绍下使用Loop组件实现一个灵活但是又不缺乏分页,排序功能的Grid组件的实现。
首先我们全局看下页面上是要怎样写的。
<table>
<tr>
<td><a t:type="OrderColumn" orderProperty="country" paging="paging">Country</a> </td>
<td><a t:type="OrderColumn" orderProperty="language" paging="paging">Language</a> </td>
</tr>
<tr t:type="Loop" source="items" value="item">
<td>${item.country}</td>
<td>${item.language}</td>
</tr>
<tr>
<td colspan="2"><div t:type="PageNavigation" paging="paging" useAll="false"></div></td>
</tr>
</table>
是不是比较简单。 你可以单独输出Table的头部和body部分。 这里使用了2个组件一个OrderColumn,一个是PageNavigation。 这两个组件公用了一个paging对象, 这个paging对象其实提供了对分页,和当前排序字段的支持。 下面看看page class的内容。
package com.javaeye.com.dengyin000.tapestry.quickstart.pages;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import org.apache.tapestry.annotations.Persist;
import com.javaeye.com.dengyin000.tapestry.quickstart.utils.Paging;
/**
* Start page of application quickstart.
*/
public class Start
{
@Persist("session")
private Paging paging;
private Locale item;
public Locale getItem() {
return item;
}
public Date getCurrentTime()
{
return new Date();
}
public Locale[] getAvailableLocales(){
return Locale.getAvailableLocales();
}
public void pageLoaded(){
if (paging == null){
paging = new Paging("country");
}
}
public List<Locale> getItems(){
Locale[] availableLocales = Locale.getAvailableLocales();
List<Locale> list = Arrays.asList(availableLocales);
paging.setItemCount(list.size());
return list.subList(paging.getFirstResult(), paging.getFirstResult() + paging.getMaxResults());
}
public Paging getPaging() {
return paging;
}
public void setPaging(Paging paging) {
this.paging = paging;
}
public void setItem(Locale item) {
this.item = item;
}
}
这里我们把paging对象保存在了session里。 然后绑定到OrderColumn和PageNavigation组件中。 请注意getItems方法。 这个是获得你要显示的数据。 这里你要先得到所有的数据的总数然后调用setItemCount方法, 然后你要通过paging中的firstResult maxResult orderProperty order(desc,ase)去获取你要显示的数据。 下面看看paging对象。
package com.javaeye.com.dengyin000.tapestry.quickstart.utils;
import java.io.Serializable;
import java.util.List;
public class Paging implements Serializable {
private static final long serialVersionUID = 4260574632101852340L;
public static int ROWS_PER_PAGE = 15;
public static int ALL = -1;
private int firstResult = 0;
private int maxResults = ROWS_PER_PAGE;
/**
* One or more property names separated by comma (,). They are later used in
* ORDER BY clause.
*/
private String orderProperties;
private boolean orderDescending = false;
private int pageNo = 0;
private long itemCount = 0;
private String alias = null;
protected boolean recalculateFirst = false; // enabled by setPageNo or
// setItemCount
private transient List results;
public Paging(String orderColumn) {
setOrderProperties(orderColumn);
}
public Paging(String orderColumn, boolean orderDescending) {
setOrderProperties(orderColumn);
setOrderDescending(orderDescending);
}
public Paging(String orderColumn, int pageNo) {
setOrderProperties(orderColumn);
setPageNo(pageNo);
}
public Paging(int firstResult, int maxResults, String orderColumn,
boolean orderDescending) {
this(firstResult, maxResults, orderColumn, null, orderDescending);
}
public Paging(int firstResult, int maxResults, String orderColumn,
String alias, boolean orderDescending) {
setFirstResult(firstResult);
setMaxResults(maxResults);
setOrderProperties(orderColumn);
setOrderDescending(orderDescending);
setAlias(alias);
}
public boolean isAll() {
return pageNo == ALL;
}
public int getFirstResult() {
if (this.recalculateFirst == true) {
if (pageNo != ALL) {
if (pageNo < 0) {
pageNo = 0;
}
firstResult = pageNo * maxResults;
if (firstResult >= itemCount) {
firstResult = pageNo = 0;
}
} else {
firstResult = 0;
}
this.recalculateFirst = false;
}
return firstResult;
}
public void changeSortColumn(String sortColumn) {
if (sortColumn != null && sortColumn.equals(getOrderProperties())) {
setOrderDescending(isOrderDescending() == true ? false : true); // change
// order
// desc
} else {
setOrderDescending(false); // set ascending order
setOrderProperties(sortColumn);
}
}
public void setFirstResult(int firstResult) {
this.firstResult = firstResult;
}
public int getMaxResults() {
return maxResults;
}
public void setMaxResults(int maxResults) {
this.maxResults = maxResults;
}
public String getOrderProperties() {
return orderProperties;
}
public void setOrderProperties(String sortColumn) {
this.orderProperties = sortColumn;
}
public boolean isOrderDescending() {
return orderDescending;
}
public void setOrderDescending(boolean sortOrder) {
this.orderDescending = sortOrder;
}
public long getItemCount() {
return itemCount;
}
public void setItemCount(long itemCount) {
this.itemCount = itemCount;
this.recalculateFirst = true;
}
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
this.recalculateFirst = true;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public void setResults(List results) {
this.results = results;
}
public List getResults() {
return results;
}
/**
* apply order properties to the query string.
* @param query
* @param pas
* @return
*/
public static String buildOrderBy(String query, Paging pas) {
//FIXME
if (pas != null && pas.getOrderProperties() != null) {
StringBuffer orderBy = new StringBuffer();
/** Oracle
int groupindex = query.toLowerCase().indexOf(" group ");
if(groupindex>0){
int i = query.toLowerCase().indexOf(" by ",groupindex+1);
if(i>groupindex && (i-groupindex)<12)return query;
}
**/
int posOrder = query.toLowerCase().indexOf(" order ");
if (posOrder > 0) {
int posBy = query.toLowerCase().indexOf(" by ", posOrder - 1);
if (posBy >= 0) {
orderBy.append(query.substring(0, posOrder));
} else
orderBy.append(new String(query));
} else {
orderBy.append(new String(query));
}
orderBy.append(" order by ");
String[] orderCols = pas.getOrderProperties().split(",");
for (int i = 0; i < orderCols.length; i++) {
if (i > 0) {
orderBy.append(", ");
}
if (pas.getAlias() != null) {
orderBy.append(pas.getAlias() + ".");
}
orderBy.append(orderCols[i]);
if (pas.isOrderDescending()) {
orderBy.append(" desc");
}
}
return orderBy.toString();
}
return query;
}
/**
* 'from User' or 'select name from User' will be changed to
* 'select count(*) from User'
* replace select fields with count(*)
* @param queryString
* @return
*/
public static String buildItemCount(String queryString) {
int posOfFrom = queryString.toLowerCase().indexOf("from ");
return "select count(*) " + queryString.substring(posOfFrom);
}
}
ok, 下面贴下OrderColumn, PageNavigation的代码
OrderColumn.tml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<span xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<a t:type="ActionLink" t:id="changeOrderLink" t:context="orderProperty">
<t:body/><img src="${icon}" class="t-sort-icon" alt="${iconLabel}"/>
</a>
</span>
OrderColumn.java
package com.javaeye.com.dengyin000.tapestry.quickstart.components;
import org.apache.tapestry.Asset;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.annotations.Path;
import org.apache.tapestry.ioc.annotations.Inject;
import com.javaeye.com.dengyin000.tapestry.quickstart.utils.Paging;
public class OrderColumn {
@Parameter(required=true, defaultPrefix="literal")
private String orderProperty;
@Parameter(required=true)
private Paging paging;
@Inject
@Path("sort-asc.png")
private Asset _ascendingAsset;
@Inject
@Path("sort-desc.png")
private Asset _descendingAsset;
@Inject
@Path("sortable.png")
private Asset _sortableAsset;
public String getOrderProperty() {
return orderProperty;
}
public void setOrderProperty(String orderProperty) {
this.orderProperty = orderProperty;
}
public Paging getPaging() {
return paging;
}
public void setPaging(Paging paging) {
this.paging = paging;
}
public void onActionFromChangeOrderLink(String orderProperty){
paging.changeSortColumn(orderProperty);
}
public Asset getIcon(){
if (isActiveSortColumn()) {
return getPaging().isOrderDescending() ? _descendingAsset : _ascendingAsset;
}
return _sortableAsset;
}
private boolean isActiveSortColumn() {
return orderProperty.equals(getPaging().getOrderProperties());
}
public String getIconLabel(){
String key = isActiveSortColumn() ? ( getPaging().isOrderDescending() ? "descending": "ascending")
: "sortable";
return key;
}
}
PageNavigation.tml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<span t:type="If" t:test="navigationDisplayed" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<table border="0">
<tr>
<td> </td>
<td class="navigation">
<span t:type="If" t:test="notUnderAllStatus">
<a t:type="ActionLink" t:id="first" t:context="first" t:disabled="firstDisabled">|<<</a>
<a t:type="ActionLink" t:id="previous" t:context="previous" t:disabled="previousDisabled"><<</a>
Page ${currentPage} Of ${pageCount}
<a t:type="ActionLink" t:id="next" t:context="next" t:disabled="nextDisabled">>></a>
<a t:type="ActionLink" t:id="last" t:context="last" t:disabled="lastDisabled">>>|</a>
<span t:type="If" t:test="useAll">
<a t:type="ActionLink" t:context="all" t:disabled="allDisabled">All</a>
<t:parameter name="else">
<a t:type="ActionLink" t:id="pageStatus" t:disabled="prop:notUnderAllStatus">View Paginated</a>
</t:parameter>
</span>
</span>
</td>
</tr>
</table>
</span>
PageNavigation.java
package
com.javaeye.com.dengyin000.tapestry.quickstart.components;
import org.apache.tapestry.annotations.OnEvent;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.annotations.Persist;
import com.javaeye.com.dengyin000.tapestry.quickstart.utils.Paging;
public class PageNavigation {
@Persist
private boolean underAllStatus;
@Parameter(required=true)
private Paging paging;
private Integer num;
@Parameter
private boolean useAll;
public boolean isUseAll() {
return useAll;
}
public void setUseAll(boolean useAll) {
this.useAll = useAll;
}
public boolean isUnderAllStatus() {
return underAllStatus;
}
public boolean getNotUnderAllStatus(){
return !underAllStatus;
}
public void setUnderAllStatus(boolean underAllStatus) {
this.underAllStatus = underAllStatus;
}
public Paging getPaging() {
return paging;
}
public void setPaging(Paging paging) {
this.paging = paging;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
public void onActionFromFirst(Integer newPageNo){
changePageNo(newPageNo);
}
public void onActionFromPrevious(Integer newPageNo){
changePageNo(newPageNo);
}
public void onActionFromNext(Integer newPageNo){
changePageNo(newPageNo);
}
public void onActionFromLast(Integer newPageNo){
changePageNo(newPageNo);
}
public void changePageNo(Integer newPageNo) {
getPaging().setPageNo(newPageNo == null ? Paging.ALL : newPageNo.intValue());
// setPaging(getPaging()); // persist!
if (newPageNo == null)
setUnderAllStatus(true);
}
public Integer[] getAllPageNumbers() {
int size = getLast().intValue() + 1;
Integer[] allPages = new Integer[size];
for (int i = 0; i < size; i++) {
allPages[i] = new Integer(i);
}
return allPages;
}
public String getPageLabel() {
return "" + (getNum().intValue() + 1);
}
public Integer getFirst() {
return new Integer(0);
}
public Integer getPrevious() {
return new Integer(getPaging().getPageNo() - 1);
}
public Integer getNext() {
return new Integer(getPaging().getPageNo() + 1);
}
public Integer getLast() {
int last = (int)Math.ceil((double)getPaging().getItemCount() / getPaging().getMaxResults()) - 1;
return new Integer(last);
}
public Integer getAll() {
return null;
}
public boolean isFirstDisabled() {
return getPaging().getPageNo() == 0;
}
public boolean isPreviousDisabled() {
return isFirstDisabled() || getPaging().getPageNo() == Paging.ALL;
}
public boolean isSelectedPage() {
return getPaging().getPageNo() == getNum().intValue();
}
public boolean isNextDisabled() {
return isLastDisabled() || getPaging().getPageNo() == Paging.ALL;
}
public boolean isLastDisabled() {
return getPaging().getPageNo() == getLast().intValue();
}
public boolean isAllDisabled() {
return getPaging().getPageNo() == Paging.ALL || getLast().intValue() == 0;
}
public boolean isNavigationDisplayed() {
return getLast().intValue() > 0;
}
@OnEvent(component="pageStatus")
public void enterPagingStatus(){
setUnderAllStatus(false);
getPaging().setPageNo(0);
// setPaging(getPaging());
}
public int getCurrentPage(){
return paging.getPageNo() + 1;
}
public int getPageCount(){
return getLast() + 1;
}
}
Ok,这个对于T4, T3也是一样的。 你只要把OrderColumn 和 PageNavigation 组件改成相应版本下面的组件就行了。 还有就是如果觉得PageNavigation看起来不是很好的话, 你也可以自己做各式各样的PageNavigation,他就只需要Paging这个类。
我把这个打包成了一个Maven项目。 如果你装了WTP的话。
运行mvn eclipse:eclipse -Dwtpversion=1.0 -DdownloadSources=true 然后再import项目到eclipse中就行了。
评论
Linuxboy
2008-05-31
出错的地方在这儿:
然后dengyin的代码中没有对maxResults < ROWS_PER_PAGE(15)的情况进行判断处理。
引用
private int maxResults = ROWS_PER_PAGE;
然后dengyin的代码中没有对maxResults < ROWS_PER_PAGE(15)的情况进行判断处理。
iorigod123
2008-01-09
我跑了一下,好像下面的导航显示有问题,数字不对。而且点到最后一页会报错,溢出了吧。。。
发表评论
提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则
- 浏览: 215196 次
- 性别:

- 来自: 广州

- 详细资料
搜索本博客
我的相册
VB-seamless
共 13 张
共 13 张
最近加入圈子
最新评论
-
使用Terracotta和Tomcat建 ...
"运行start.bat 9081 这样我们就启动了目录9081中的tomcat ...
-- by renavatior -
广州3年多经验 5500的 ...
fucku 写道广州的软件厂家可比深圳多多了,不过比起北京上海来,还是少了很多, ...
-- by yongfan_420 -
广州3年多经验 5500的 ...
广州的软件厂家可比深圳多多了,不过比起北京上海来,还是少了很多,导致机会也没有这 ...
-- by fucku -
广州3年多经验 5500的 ...
想高工资就去厂家咯,老在集成商里面混能有多大个奔头
-- by fucku -
广州3年多经验 5500的 ...
active1001 写道eddie404956 写道active1001 写道 ...
-- by mayu






评论排行榜