org.bklab.flow.components.pagination.Pagination Maven / Gradle / Ivy
package org.bklab.flow.components.pagination;
import org.bklab.flow.layout.ToolBar;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Pagination extends ToolBar {
private final PaginationTotalLabel totalLabel = new PaginationTotalLabel();
private final PaginationPageSize pageSize = new PaginationPageSize();
private final PaginationJumpField jumpField = new PaginationJumpField();
private final PaginationButtonContainer pagesContainer = new PaginationButtonContainer();
private final GeneratePagesContainer generatePagesContainer = new GeneratePagesContainer();
private PageSwitchEvent pageSwitchEvent;
private ICustomPaginationLayout ICustomPaginationLayout;
private Consumer paginationButtonConsumer;
private boolean tinyMode = false;
private boolean compactMode = false;
private int total = 1;
private int totalData;
private int limit = 5;
private int currentPage = 1;
private boolean hasInit = false;
public Pagination() {
}
/**
* 无边框模式
*
* @param tinyMode true 无边框 false 有边框
* @return this
*/
public Pagination tinyMode(boolean tinyMode) {
this.tinyMode = tinyMode;
return this;
}
/**
* 无边框模式
*
* @return this
*/
public Pagination tinyMode() {
this.tinyMode = true;
return this;
}
/**
* 紧凑模式 默认false
*
* @param compactMode true 全部居左,
* false 左:total 中:页码+跳转 右:单页数量
* @return this
*/
public Pagination compactMode(boolean compactMode) {
this.compactMode = compactMode;
return this;
}
/**
* 自定义翻页组件布局
*
* @param ICustomPaginationLayout CustomPaginationLayout
* @return this
* @see ICustomPaginationLayout
*/
public Pagination customLayout(ICustomPaginationLayout ICustomPaginationLayout) {
if (this.ICustomPaginationLayout != null) throw new RuntimeException("禁止重复调用");
ICustomPaginationLayout.apply(this, totalLabel, pagesContainer, jumpField, pageSize);
this.ICustomPaginationLayout = ICustomPaginationLayout;
return this;
}
/**
* @param total 全部数量 默认0
* @return this;
*/
public Pagination totalData(int total) {
this.totalLabel.setTotal(total);
this.totalData = total;
return this;
}
/**
* @param limit 最大拥有翻页按钮数量,默认5,例如选择 5:
* 精简模式:< 1 2 3 4 5 >
* 普通模式:< 1 << 5 6 7 8 9 >> 100 >
* @return this;
*/
public Pagination limit(int limit) {
this.limit = limit;
return this;
}
/**
* @param onePageSize 单页数量,推荐 10 20 50 100 默认20
* @return this;
*/
public Pagination onePageSize(int onePageSize) {
this.pageSize.setValue(onePageSize);
return this;
}
public Pagination onePageSize(int defaultOnePageSize, int... pageSizes) {
List p = Arrays.stream(pageSizes).boxed()
.collect(Collectors.toCollection(() -> new ArrayList<>(defaultOnePageSize)));
this.pageSize.setItems(p.stream().distinct().sorted(Comparator.comparingInt(Integer::intValue)).collect(Collectors.toList()));
this.pageSize.setValue(defaultOnePageSize);
return this;
}
/**
* @param currentPage 当前页
* @return this;
*/
public Pagination setCurrentPage(int currentPage) {
this.currentPage = currentPage;
return this;
}
public Pagination peekTotalLabel(Consumer totalLabelConsumer) {
totalLabelConsumer.accept(totalLabel);
return this;
}
public Pagination peekPageSize(Consumer pageSizeConsumer) {
pageSizeConsumer.accept(pageSize);
return this;
}
public Pagination peekJumpField(Consumer jumpFieldConsumer) {
jumpFieldConsumer.accept(jumpField);
return this;
}
public int getPageSize() {
return pageSize.getValue();
}
public int getCurrentPage() {
return currentPage;
}
/**
* 初始化组件
*
* @return this;
*/
public Pagination init() {
if (hasInit) return this;
if (tinyMode) initTiny();
else initNormal();
if (ICustomPaginationLayout == null) {
if (compactMode) {
left(totalLabel, pagesContainer, pageSize, jumpField);
} else {
left(totalLabel);
middle(pagesContainer, jumpField);
right(pageSize);
}
}
pageSize.addValueChangeListener(e -> build());
jumpField.addValueChangeConsumer(generatePagesContainer::go);
this.hasInit = true;
return this;
}
private void initTiny() {
pageSize.tinySize();
paginationButtonConsumer = p -> p.border(false);
jumpField.tinySize();
}
private void initNormal() {
pageSize.normalSize();
paginationButtonConsumer = p -> p.border(true);
jumpField.normalSize();
}
public Pagination refresh() {
generatePagesContainer.go(false, currentPage);
return this;
}
public Pagination build() {
if (!hasInit) init();
this.total = (int) Math.ceil(1d * totalData / pageSize.getValue());
if (this.currentPage > total) this.currentPage = 1;
jumpField.setMax(total);
generatePagesContainer.bind();
return this;
}
public Pagination pageSwitchEvent(PageSwitchEvent pageSwitchEvent) {
this.pageSwitchEvent = pageSwitchEvent;
return this;
}
private class GeneratePagesContainer {
private final Map pageMap = new LinkedHashMap<>();
private final List allButtons = new ArrayList<>();
private PaginationButton prev;
private PaginationButton prevJump;
private PaginationButton nextJump;
private PaginationButton next;
private int lastPage = currentPage;
public void bind() {
pagesContainer.setLimit(limit);
pageMap.clear();
allButtons.clear();
prev = apply(new PaginationButton(false, e -> goPrev(e.isFromClient())));
next = apply(new PaginationButton(true, e -> goNext(e.isFromClient())));
prevJump = apply(new PaginationButton(e -> goPrevJump(e.isFromClient()), false)).setDescription("向前 " + (limit / 2) + "页");
nextJump = apply(new PaginationButton(e -> goNextJump(e.isFromClient()), true)).setDescription("向后 " + (limit / 2) + "页");
IntStream.rangeClosed(1, Math.max(total, 1)).forEachOrdered(current ->
pageMap.put(current, apply(new PaginationButton(current, e -> go(e.isFromClient(), current)))));
addToContainer();
checkAbilities(false);
go(true, currentPage);
}
private void addToContainer() {
pagesContainer.setPrev(prev).setFirstPage(pageMap.get(1)).setPrevJump(prevJump)
.setNextJump(nextJump).setLastPage(pageMap.get(Math.max(total, 1))).setNext(next).init();
int start = (int) (currentPage - (limit / 2.0d));
if (start < 0) {
start = 0;
}
for (int i = 1; i <= limit && i < total; i++) {
Optional.ofNullable(pageMap.get(i + start)).ifPresent(pagesContainer::addLast);
}
}
private PaginationButton apply(PaginationButton button) {
paginationButtonConsumer.accept(button);
allButtons.add(button);
return button;
}
private void checkAbilities(boolean isFromClient) {
prev.enable(currentPage > 1);
next.enable(currentPage < total);
prevJump.setVisible(pagesContainer.getContainerFirst() > 2);
nextJump.setVisible(pagesContainer.getContainerLast() < total - 1);
}
private void go(boolean isFromClient, int i) {
deselectAll();
lastPage = currentPage;
currentPage = i;
int a = currentPage - (limit / 2);
if (a + limit > total) a = total - limit;
if (a < limit / 2) a = 2;
pagesContainer.clearContainer();
IntStream.range(a, Math.min(a + limit, total)).boxed()
.map(pageMap::get).forEachOrdered(pagesContainer::addLast);
select(isFromClient);
checkAbilities(isFromClient);
}
private void goPrev(boolean isFromClient) {
deselectAll();
lastPage = currentPage;
currentPage = Math.max(1, --currentPage);
select(isFromClient);
Optional.ofNullable(pageMap.get(pagesContainer.getContainerFirst() - 1)).ifPresent(pagesContainer::addFirst);
checkAbilities(isFromClient);
}
private void goNext(boolean isFromClient) {
deselectAll();
lastPage = currentPage;
currentPage = Math.min(total, ++currentPage);
select(isFromClient);
Optional.ofNullable(pageMap.get(pagesContainer.getContainerLast() + 1)).ifPresent(pagesContainer::addLast);
checkAbilities(isFromClient);
}
private void goPrevJump(boolean isFromClient) {
go(isFromClient, Math.max(1, currentPage -= limit));
}
private void goNextJump(boolean isFromClient) {
go(isFromClient, Math.min(total, currentPage += limit));
}
private void select(boolean isFromClient) {
Optional.ofNullable(pageMap.get(currentPage)).ifPresent(PaginationButton::select);
if (pageSwitchEvent != null)
pageSwitchEvent.accept(currentPage, pageSize.getValue(), lastPage, isFromClient);
}
private void deselectAll() {
allButtons.forEach(PaginationButton::deselect);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy