001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019package org.apache.wiki.tags; 020 021import java.io.IOException; 022 023import javax.servlet.jsp.jstl.fmt.LocaleSupport; 024 025import org.apache.wiki.util.TextUtil; 026 027 028/** 029 * Calculate pagination string. Used for page-info and search results 030 * 031 * <P><B>Attributes</B></P> 032 * <UL> 033 * <LI> start - start item of the page to be highlighted 034 * <LI> total - total number of items 035 * <LI> pagesize - total number of items per page 036 * <LI> maxlinks - number of page links to be generated 037 * <LI> fmtkey - pagination prefix of the i18n resource keys. Following keys are used: 038 * <br>fmtkey="info.pagination" 039 * <UL> 040 * <LI> info.pagination.first=<span class="first">First</span> 041 * <LI> info.pagination.last=<span class="last">Last</span> 042 * <LI> info.pagination.previous=<span class="prev">Previous</span> 043 * <LI> info.pagination.next=<span class="next">Next</span> 044 * <LI> info.pagination.all=<span class="all">all</span> 045 * <LI> info.pagination.total= (Total items: {0} ) 046 * <LI> info.pagination.show.title=Show items from {0} to {1} 047 * <LI> info.pagination.showall.title=Show all items 048 * </UL> 049 * </UL> 050 * <P>Following optional attributes can be parameterized with '%s' (item count)</P> 051 * <UL> 052 * <LI> href - href of each page link. (optional) 053 * <LI> onclick - onclick of each page link. (optional) 054 * </UL> 055 * 056 * @since 2.5.109 057 */ 058public class SetPaginationTag 059 extends WikiTagBase 060{ 061 private static final long serialVersionUID = 0L; 062 private static final int ALLITEMS = -1; 063 064 private int m_start; 065 private int m_total; 066 private int m_pagesize; 067 private int m_maxlinks; 068 private String m_fmtkey; 069 private String m_href; 070 private String m_onclick; 071 072 public void initTag() 073 { 074 super.initTag(); 075 m_start = 0; 076 m_total = 0; 077 m_pagesize = 20; 078 m_maxlinks = 9; 079 m_fmtkey = null; 080 m_href = null; 081 m_onclick = null; 082 } 083 084 public void setStart(final int arg) 085 { 086 m_start = arg; 087 } 088 089 public void setTotal(final int arg) 090 { 091 m_total = arg; 092 } 093 094 public void setPagesize(final int arg) 095 { 096 m_pagesize = arg; 097 } 098 099 public void setMaxlinks(final int arg) 100 { 101 m_maxlinks = arg; 102 if( m_maxlinks % 2 == 0 ) m_maxlinks--; /* must be odd */ 103 } 104 105 public void setFmtkey(final String arg) 106 { 107 m_fmtkey = arg; 108 } 109 110 public void setHref(final String arg) 111 { 112 m_href = arg; 113 } 114 115 public void setOnclick(final String arg) 116 { 117 m_onclick = arg; 118 } 119 120 121 // 0 20 40 60 122 // 0 20 40 60 80 next last 123 // first previous 20 40 *60* 80 100 next last 124 // fist previous 40 60 80 100 120 125 public int doWikiStartTag() 126 throws IOException 127 { 128 if( m_total <= m_pagesize ) return SKIP_BODY; 129 130 final StringBuilder pagination = new StringBuilder(); 131 132 if( m_start > m_total ) m_start = m_total; 133 if( m_start < ALLITEMS ) m_start = 0; 134 135 final int maxs = m_pagesize * m_maxlinks; 136 final int mids = m_pagesize * ( m_maxlinks / 2 ); 137 138 pagination.append( "<div class='pagination'>"); 139 140 pagination.append( LocaleSupport.getLocalizedMessage( pageContext, m_fmtkey ) ).append( " " ); 141 142 int cursor = 0; 143 int cursormax = m_total; 144 145 if( m_total > maxs ) //need to calculate real window ends 146 { 147 if( m_start > mids ) cursor = m_start - mids; 148 if( (cursor + maxs) > m_total ) 149 cursor = ( ( 1 + m_total/m_pagesize ) * m_pagesize ) - maxs ; 150 151 cursormax = cursor + maxs; 152 } 153 154 155 if( ( m_start == ALLITEMS ) || (cursor > 0) ) 156 { 157 appendLink ( pagination, 0, m_fmtkey + ".first" ); 158 } 159 160 161 if( (m_start != ALLITEMS ) && (m_start-m_pagesize >= 0) ) 162 { 163 appendLink( pagination, m_start-m_pagesize, m_fmtkey + ".previous" ); 164 } 165 166 if( m_start != ALLITEMS ) 167 { 168 while( cursor < cursormax ) 169 { 170 if( cursor == m_start ) 171 { 172 pagination.append( "<span class='cursor'>" ); 173 pagination.append( 1 + cursor/m_pagesize ); 174 pagination.append( "</span>" ); 175 } 176 else 177 { 178 appendLink( pagination, cursor, 1+cursor/m_pagesize ); 179 } 180 cursor += m_pagesize; 181 } 182 } 183 184 185 if( (m_start != ALLITEMS ) && (m_start + m_pagesize < m_total) ) 186 { 187 appendLink( pagination, m_start+m_pagesize, m_fmtkey + ".next" ); 188 189 if( (m_start == ALLITEMS ) || (cursormax < m_total) ) 190 appendLink ( pagination, ( (m_total/m_pagesize) * m_pagesize ), m_fmtkey + ".last" ); 191 } 192 193 if( m_start == ALLITEMS ) 194 { 195 pagination.append( "<span class='cursor'>" ); 196 pagination.append( LocaleSupport.getLocalizedMessage(pageContext, m_fmtkey + ".all" ) ); 197 pagination.append( "</span> " ); 198 } 199 else 200 { 201 appendLink ( pagination, ALLITEMS, m_fmtkey + ".all" ); 202 } 203 204 //(Total items: " + m_total + ")" ); 205 pagination.append( LocaleSupport.getLocalizedMessage(pageContext, m_fmtkey + ".total", 206 new Object[]{ m_total } ) ); 207 208 pagination.append( "</div>" ); 209 210 211 /* +++ processing done +++ */ 212 213 final String p = pagination.toString(); 214 215 pageContext.getOut().println( p ); 216 217 pageContext.setAttribute( "pagination", p ); /* and cache for later use in page context */ 218 219 return SKIP_BODY; 220 } 221 222 223 /** 224 * Generate pagination links <a href='' title='' onclick=''>text</a> 225 * for pagination blocks starting a page. 226 * Uses m_href and m_onclick as attribute patterns 227 * '%s' in the patterns are replaced with page offset 228 * 229 * @param sb : stringbuilder to write output to 230 * @param page : start of page block 231 * 232 **/ 233 private void appendLink(final StringBuilder sb, final int page, final String fmttextkey ) 234 { 235 appendLink2( sb, page, LocaleSupport.getLocalizedMessage( pageContext, fmttextkey ) ); 236 } 237 private void appendLink(final StringBuilder sb, final int page, final int paginationblock ) 238 { 239 appendLink2( sb, page, Integer.toString( paginationblock ) ); 240 } 241 private void appendLink2(final StringBuilder sb, final int page, final String text ) 242 { 243 sb.append( "<a title=\"" ); 244 if( page == ALLITEMS ) 245 { 246 sb.append( LocaleSupport.getLocalizedMessage( pageContext, m_fmtkey + ".showall.title" ) ); 247 } 248 else 249 { 250 sb.append( LocaleSupport.getLocalizedMessage( pageContext, m_fmtkey + ".show.title", 251 new Object[]{ page + 1, page + m_pagesize } ) ); 252 } 253 sb.append( "\" " ); 254 255 if( m_href != null ) 256 { 257 sb.append( "href=\"" ); 258 sb.append( TextUtil.replaceString( m_href, "%s", Integer.toString( page ) ) ); 259 sb.append( "\" " ); 260 } 261 262 if( m_onclick != null ) 263 { 264 sb.append( "onclick=\"" ); 265 sb.append( TextUtil.replaceString( m_onclick, "%s", Integer.toString( page ) ) ); 266 sb.append( "\" " ); 267 } 268 269 sb.append( ">" ); 270 sb.append( text ); 271 sb.append( "</a>" ); 272 } 273 274}