1package Data::Page::Pageset;
2use Carp;
3use strict;
4use Data::Page::Pageset::Chunk;
5use POSIX;
6
7use base 'Class::Accessor::Fast';
8__PACKAGE__->mk_accessors( qw(
9	total_pages
10	first_pageset
11	last_pageset
12	current_pageset
13	previous_pageset
14	next_pageset
15 ) );
16# add this for make more version to be 1.02
17our $VERSION = sprintf "%d.%02d", q$Revision: 1.2 $ =~ /: (\d+)\.(\d+)/;
18
19sub new {
20	my $class = shift;
21	my $page = shift;
22	my $param = shift;
23
24	croak("The first is not a Data::Page object!")
25		unless $page->UNIVERSAL::isa('Data::Page');
26
27	my $self = bless {}, $class;
28	$self->{_page} = $page;
29	$self->{_total_pagesets} = [];
30	$self->{_MAX_PAGESETS} = 1;
31	$self->{_PAGE_PER_SET} = 2;
32
33	if ( not defined $param or ref $param eq '' ){
34		$self->pages_per_set( $param || 10 );
35
36	}elsif ( defined $param->{max_pagesets} ){
37		$self->max_pagesets( $param->{max_pagesets} );
38
39	}elsif ( defined $param->{pages_per_set} ){
40		$self->pages_per_set( $param->{pages_per_set} );
41	}
42
43	return $self;
44}
45
46sub total_pagesets {
47	my $self = shift;
48	if ( $_[0] ){
49		$self->{_total_pagesets} = $_[0];
50	}
51	return ( wantarray ) ? @{$self->{_total_pagesets}} : $self->{_total_pagesets};
52}
53
54sub max_pagesets {
55	my ( $self, $number ) = @_;
56	if ( defined $number ){
57		$number = int $number;
58		croak("Fewer than one pagesets!") if $number < 1;
59		return $self->{_MAX_PAGESETS} if $number == $self->{_MAX_PAGESETS};
60		$self->{_MAX_PAGESETS} = $number;
61		$self->pages_per_set( POSIX::ceil( $self->{_page}->last_page / $number ) );
62	}
63	return $self->{_MAX_PAGESETS};
64}
65
66sub pages_per_set {
67	my ( $self, $number ) = @_;
68	if ( defined $number ){
69		$number = int $number;
70		croak("Fewer than two pages per set!") if $number < 2;
71		return $self->{_PAGE_PER_SET} if $number == $self->{_PAGE_PER_SET};
72		$self->{_PAGE_PER_SET} = $number;
73		$self->_refresh;
74	}
75	return $self->{_PAGE_PER_SET};
76}
77
78sub _refresh {
79	my $self = shift;
80	my $number = $self->pages_per_set;
81	my $page = $self->{_page};
82
83	my $current_page = $page->current_page;
84	my @total_pages = ( $page->first_page .. $page->last_page );
85	$self->total_pages( scalar @total_pages );
86
87	my @pageset;
88	while ( @total_pages ){
89		my @array = splice( @total_pages, 0, $number );
90		my $chunk = Data::Page::Pageset::Chunk->new( @array );
91		push @pageset, $chunk;
92		if ( $current_page >= $chunk->first and $current_page <= $chunk->last ){
93			$chunk->is_current(1);
94			$self->current_pageset( $chunk );
95			$self->previous_pageset( $pageset[-2] ) if $#pageset;
96		}
97		$self->next_pageset( $chunk ) if ( $#pageset and $pageset[-2]->is_current );
98	}
99	$self->first_pageset( $pageset[0] );
100	$self->last_pageset( $pageset[-1] ) if $#pageset;
101	$self->total_pagesets( \@pageset );
102}
103
1041;
105
106=head1 NAME
107
108Data::Page::Pageset - change long page list to be shorter and well navigate
109
110=head1 DESCRIPTION
111
112Pages number can be very high, and it is not comfortable to show user from the first page to the last page list. Sometimes we need split the page list into some sets to shorten the page list, the form is like:
113
114 1-6 7-12 13 14 15 16 17 18 19-24 25-30 31-36 37-41
115
116the first two part indicats the two pagesets, and in current pageset, we provide the normal page list from the first one to the last one, and provide the rest pagesets to indicate the pages scope.
117
118In this module, you can specify the pages_per_set or max_pagesets for fine showing.
119
120=head1 SYNOPSIS
121
122 use Data::Page::Pageset;
123 # we use Data::Page object, so do prepare
124 my $page = Data::Page->new($total_entries, $entries_per_page, $current_page);
125 # create the pageset object
126 my $pageset = Data::Page::Pageset->new( $page );
127 my $pageset = Data::Page::Pageset->new( $page, 12 );
128 my $pageset = Data::Page::Pageset->new( $page, { max_pagesets => $max_pagesets } );
129 my $pageset = Data::Page::Pageset->new( $page, { pages_per_set => $pages_per_set } );
130
131 # for using
132 foreach my $chunk ( $pageset->total_pagesets ){
133 	if ( $chunk->is_current ){
134 		map { print "$_ " } ( $chunk->first .. $chunk->last );
135 	}else{
136 		print "$chunk ";
137 	}
138 }
139
140=head1 METHODS
141
142=over
143
144=item new()
145
146 # default page_per_set is 10
147 my $pageset = Data::Page::Pageset->new( $page );
148
149 # set the page_per_set to be 12
150 my $pageset = Data::Page::Pageset->new( $page, 12 );
151 # another the same by passing hashref
152 my $pageset = Data::Page::Pageset->new( $page, { pages_per_set => $pages_per_set } );
153
154 # set the max_pagesets value, default is 1
155 my $pageset = Data::Page::Pageset->new( $page,	{ max_pagesets => $max_pagesets } );
156 # if max_pagesets supplies, the pages_per_set setting will be ignore
157 my $pageset = Data::Page::Pageset->new( $page,
158 	{ max_pagesets => $max_pagesets, pages_per_set => $pages_per_set } );
159
160We must need $page(isa Data::Page) object.
161
162=item max_pagesets( $number )
163
164 # set the max_pagesets value, and the $pageset's info will changed immediately
165 $pageset->max_pagesets( $number );
166
167=item pages_per_set( $number )
168
169 # set the pages_per_set value, and the $pageset's info will changed immediately
170 $pageset->pages_per_set( $number );
171 my $present_setting = $pageset->pages_per_set();
172
173=item $pageset->total_pages
174
175return total pages' number.
176
177=item $pageset->total_pagesets
178
179return the actual pagesets number.
180
181=item $pageset->first_pageset
182
183 my $chunk = $pageset->first_pageset;
184
185return the first pageset, it's Data::Page::Pageset::Chunk object
186
187=item $pageset->last_pageset
188
189 my $chunk = $pageset->last_pageset;
190
191return the last pageset, it's Data::Page::Pageset::Chunk object
192
193=item $pageset->current_pageset
194
195 my $chunk = $pageset->current_pageset;
196
197return the current pageset which current page is in this pageset, it's Data::Page::Pageset::Chunk object
198
199=item $pageset->previous_pageset
200
201 my $chunk = $pageset->previous_pageset;
202
203return the previous pageset, it's Data::Page::Pageset::Chunk object
204
205=item $pageset->next_pageset
206
207 my $chunk = $pageset->next_pageset;
208
209return the next pageset, it's Data::Page::Pageset::Chunk object
210
211=back
212
213=head1 Data::Page::Pageset::Chunk object
214
215a $pageset gives you some $chunk to do more stuff as you see above. Here gives the $chunk methods
216
217=over
218
219=item first
220
221 # return the first page number in this chunk
222 $chunk->first;
223
224=item last
225
226 # return the last page number in this chunk
227 $chunk->last;
228
229=item middle
230
231 # return the middle page number in this chunk
232 $chunk->middle;
233
234=item pages
235
236 # return the pages number in this chunk
237 $chunk->pages;
238
239=item is_current
240
241 # return true if this $chunk contains the current_page
242 $chunk->is_current;
243
244=item as_string
245
246 # if this chunk is from page 3 to 7, then print '3-7'
247 print $chunk;
248 print $chunk->as_string;
249 print $chunk->as_string('-');
250
251 # you can change default '-' as:
252 print $chunk->as_string('~');
253
254if the $chunk only contains one page, it will only return the page number.
255
256=back
257
258=head1 SEE ALSO
259
260L<Data::Page|Data::Page> is what we need, L<Data::Pageset|Data::Pageset> is the similar one, L<Template::Plugin::Pageset|Template::Plugin::Pageset> is the wrapper for this to using it more converiently in TT2 tempale.
261
262=head1 BUGS
263
264just mail me to <me@chunzi.org>
265
266=head1 COPYRIGHT AND LICENSE
267
268Copyright 2004 by Chun Sheng.
269
270This library is free software; you can redistribute it and/or modify
271it under the same terms as Perl itself.
272
273=head1 AUTHOR
274
275Chun Sheng, <me@chunzi.org>
276
277=cut
278