Paginate things a bit differently
[Sone.git] / src / main / kotlin / net / pterodactylus / sone / utils / Pagination.kt
1 package net.pterodactylus.sone.utils
2
3 /**
4  * Helper class for lists that need pagination. Setting the page or the page
5  * size will automatically recalculate all other parameters, and the next call
6  * to [Pagination.items] retrieves all items on the current page.
7  * <p>
8  * A pagination object can be used as an [Iterable]. When the [Iterator]
9  * from [Pagination.iterator] is requested, the iterator over
10  * [Pagination.items] is returned.
11  *
12  * @param <T>
13  *            The type of the list elements
14  */
15 class Pagination<out T>(private val originalItems: List<T>, pageSize: Int): Iterable<T> {
16
17         var page: Int = 0
18                 set(value) {
19                         field = maxOf(0, minOf(value, lastPage))
20                 }
21
22         var pageSize = pageSize
23                 set(value) {
24                         val oldFirstIndex = page * field
25                         field = maxOf(1, value)
26                         page = oldFirstIndex / field
27                 }
28
29         val pageNumber get() = page + 1
30         val pageCount get() = maxOf((originalItems.size - 1) / pageSize + 1, 1)
31         val itemCount get() = minOf(originalItems.size - page * pageSize, pageSize)
32         val items get() = originalItems.subList(page * pageSize, minOf(originalItems.size, (page + 1) * pageSize))
33         val isFirst get() = page == 0
34         val isLast get() = page == lastPage
35         val isNecessary get() = pageCount > 1
36         val previousPage get() = page - 1
37         val nextPage get() = page + 1
38         val lastPage get() = pageCount - 1
39
40         override fun iterator() = items.iterator()
41
42         fun turnTo(page: Int) = apply { this.page = page }
43
44 }
45
46 fun <T> Iterable<T>.paginate(pageSize: Int) = Pagination<T>(toList(), pageSize)