`
dengyin2000
  • 浏览: 1228358 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

扔掉T5复杂的Grid组件,打造自己灵活的支持分页排序组件。

阅读更多
Grid算是比较T5中较复杂的一个组件,我也有篇介绍Grid怎么使用的文章。http://www.iteye.com/topic/114754   但是如果我们平时需要些比较灵活的布局。 Grid组件用起来就比较别扭了。 

下面我介绍下使用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.iteye.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.iteye.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.iteye.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.iteye.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.iteye.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>&nbsp;</td>
	  <td class="navigation">
	  	<span t:type="If" t:test="notUnderAllStatus">
	  		<a t:type="ActionLink" t:id="first" t:context="first" t:disabled="firstDisabled">|&lt;&lt;</a>
	  		&nbsp;
	  		<a t:type="ActionLink" t:id="previous" t:context="previous" t:disabled="previousDisabled">&lt;&lt;</a>
	  		&nbsp;
	  		Page ${currentPage} Of ${pageCount}
	  		<a t:type="ActionLink" t:id="next" t:context="next" t:disabled="nextDisabled">&gt;&gt;</a>
	  		&nbsp;
	  		<a t:type="ActionLink" t:id="last" t:context="last" t:disabled="lastDisabled">&gt;&gt;|</a>
	  		&nbsp;
	  		<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.iteye.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.iteye.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中就行了。

分享到:
评论
4 楼 hitalang 2008-06-16  
这个可以吗???请指点??
3 楼 Linuxboy 2008-05-31  
出错的地方在这儿:
引用
private int maxResults = ROWS_PER_PAGE;

然后dengyin的代码中没有对maxResults < ROWS_PER_PAGE(15)的情况进行判断处理。
2 楼 iorigod123 2008-01-09  
我跑了一下,好像下面的导航显示有问题,数字不对。而且点到最后一页会报错,溢出了吧。。。
1 楼 hongyuzhe 2008-01-04  
太厉害了.

相关推荐

    SUN T5-4 固件包 SUN T5-4 固件包

    总的来说,"SUN T5-4 固件包"是保证SUN T5-4服务器持续高效运行的关键要素,通过定期检查和应用最新的固件更新,用户可以确保其服务器始终保持在最佳状态,以应对日益复杂的企业级计算需求。对于任何拥有SUN T5-4...

    光伏组件压块有限元受力计算书

    光伏组件作为可再生能源领域的重要组成部分,其稳定性和安全性对于长期运行至关重要。特别是在面对恶劣气候条件,如强风作用时,光伏组件的固定装置能否承受相应的风荷载,是确保整个系统安全运行的关键问题。本计算...

    友价T5最新版商城免签约支付插件免费下载个人也可签约使用

    在这个场景中,我们关注的是"友价T5最新版商城免签约支付插件",这是一款允许个人商家无需经过传统金融机构的复杂签约流程就能接入支付功能的软件组件。 在电商领域,支付接口的签约通常涉及到繁琐的手续,包括企业...

    插入排序 冒泡法排序 快速排序 直接选择排序 堆排序 归并排序 希尔排序 7种排序算法及时间比较

    printf("\t5: 堆排序\n"); printf("\t6: 归并排序\n"); printf("\t7: 希尔排序\n"); printf("\t***************************\n"); scanf("%d",&i); //输入整数1-7,选择排序方式 switch (i){ case 1: ...

    T5UIC2 开发指南_V20.pdf

    T5UIC2软件平台以其精简的指令集和灵活的配置选项,为开发者提供了一个高效的人机界面解决方案。 首先,T5UIC2支持多种尺寸的串口屏硬件型号,从2.8寸到12.1寸不等,提供了丰富的分辨率选项,满足不同应用场景下的...

    T5导入导出软件v2.3.398免费绿色版

    T5导入导出工具是一款...T5导入导出工具是一款专业的数据导入导出工具,适用于T5标准版无线盘点机,支持导入数据监测,支持导入导出商品信息,支持导出直接盘点信息等等。软件界面简洁功能强大而且全面,有需要的朋友

    T5LCFG汇总(仅参考)20200219_DWIN迪文T5L配置文件CFG_源码

    在IT行业中,尤其是在嵌入式显示系统开发领域,DWIN迪文T5L系列显示屏是一款广泛应用的产品。这个标题“T5LCFG汇总(仅参考)20200219_DWIN迪文T5L配置文件CFG_源码”指的是一个关于DWIN迪文T5L显示屏的配置文件集合...

    基于T5-small的问答模型 它实际上是QuestEval指标的一个组成部分,但可以按原样独立使用,仅用于 QA

    - **灵活性**:T5-Small可以适应各种问题类型和领域,只需要适当的训练数据。 - **生成性质**:由于T5是基于生成的模型,它能生成连贯且完整的答案,而不仅仅是选择最佳选项。 - **效率**:尽管模型较小,但T5-Small...

    爱威T5+ 效果器 调试软件

    爱威T5+ 效果器调试软件是一个专为音乐制作和音频工程设计的专业工具,主要针对爱威T5+这一型号的音频处理器。这款软件提供了详细的参数调整和控制功能,使得用户能够根据不同的应用场景和声音需求,精细地优化T5+的...

    迪文T5L Keil C51项目模板.rar

    迪文T5L是一款基于8051内核的微控制器,由迪文科技公司设计生产,常用于工业控制、智能家居、消费电子等领域。Keil C51是针对8051系列微控制器的集成开发环境,它集成了编译器、调试器和IDE,使得C语言编程变得简单...

    迪文屏幕T5L DGUSII应用开发指南

    迪文屏幕T5L DGUSII应用开发指南是北京迪文科技有限公司提供的一份详尽的文档,旨在帮助开发者高效地进行串口屏的开发工作。迪文串口屏是一款基于DGUS II系统的智能显示屏,它结合了硬件与软件的优势,提供了一种...

    T5L开发手册及开发平台.zip

    迪文T5L屏是一款专为人机交互设计的串口屏,它提供了高效且灵活的显示解决方案。在“T5L开发手册及开发平台.zip”压缩包中,包含了两个主要的资源,即“T5L DGUSII 应用开发指南20200710.pdf”和“DGUS_V7618.rar”...

    spart T5-2 solaris

    通过深入学习和掌握Sparc T5-2 服务器与Solaris操作系统结合的特性和实践操作,用户不仅可以提升工作效率,还能确保系统稳定运行,应对各种复杂的企业级挑战。在压缩包文件" SparcT5-2 "中,可能包含了详细的安装...

    T5 前级 控制软件 调试工具

    这样的工具对于系统集成商、开发人员以及技术支持团队来说至关重要,因为他们需要对T5设备进行精确的配置、故障排查和性能优化。 首先,我们来了解一下"前级"在技术领域中的含义。在音频或信号处理系统中,"前级...

    友价T5免签约支付接口插件

    这款插件的亮点在于其灵活性和便捷性,允许用户根据自己的需求自主配置支付渠道,适应不同商家的支付习惯和业务场景。 在支付接口方面,友价T5插件对接的是易支付系统,而非传统的码支付服务。易支付是一个集成了...

    【苹果cms模板】苹果cms仿T5资源站模板、支持在线播放.zip

    在给定的压缩包文件“【苹果cms模板】苹果cms仿T5资源站模板、支持在线播放.zip”中,包含了一个专门为苹果CMS设计的模板,其目标是模仿T5资源站的风格,并且支持视频资源的在线播放。 模板设计通常包括网站的不同...

    迪文串口屏T5UIC1开发资料.rar

    - 示例工程:提供已实现的简单或复杂应用实例,帮助开发者理解如何使用T5UIC1。 - GUI设计工具:可能有一个图形用户界面设计工具,用于创建屏幕布局和动画。 7. **开发流程**:使用这些资料,开发者首先需要了解...

    T5写频软件

    "特易通T5写频软件"是一款专为特易通T5系列对讲机设计的频率编程工具,主要用于设置和管理对讲机的工作频率、信道、编码方式等通信参数。这款软件使得用户无需专业知识就能轻松进行对讲机的个性化配置,极大地提高了...

Global site tag (gtag.js) - Google Analytics