edu.kit.dama.ui.repo.components.PaginationPanel.java Source code

Java tutorial

Introduction

Here is the source code for edu.kit.dama.ui.repo.components.PaginationPanel.java

Source

/*
 * Copyright 2014 Karlsruhe Institute of Technology.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.kit.dama.ui.repo.components;

import com.vaadin.event.LayoutEvents;
import com.vaadin.server.ThemeResource;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Link;
import com.vaadin.ui.NativeButton;
import com.vaadin.ui.VerticalLayout;
import edu.kit.dama.authorization.entities.IAuthorizationContext;
import edu.kit.dama.commons.types.DigitalObjectId;
import edu.kit.dama.mdm.base.DigitalObject;
import edu.kit.dama.ui.repo.MyVaadinUI;
import edu.kit.dama.ui.repo.util.DigitalObjectPersistenceHelper;
import java.util.LinkedList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Pagination panel component used to render and navigate through search
 * results.
 *
 * @author mf6319
 */
public class PaginationPanel extends CustomComponent {

    private static final Logger LOGGER = LoggerFactory.getLogger(PaginationPanel.class);

    private VerticalLayout mainLayout;
    private final VerticalLayout pageLayout = new VerticalLayout();
    private HorizontalLayout navigation = new HorizontalLayout();
    private final ShareObjectComponent shareComponent = new ShareObjectComponent();

    //special mode where only the entries that are not ingested yet are listed. In this mode, editing is not possible.
    private int currentPage = 0;
    private int overallPages = 0;
    //could be customizable
    private final int entriesPerPage = 10;
    private final MyVaadinUI parent;
    private final List<DigitalObjectId> allEntries = new LinkedList<>();

    /**
     * Default constructor.
     *
     * @param pParent The parent used to obtain the authorization context.
     */
    public PaginationPanel(MyVaadinUI pParent) {
        parent = pParent;
        buildMainLayout();
        setCompositionRoot(mainLayout);
    }

    /**
     * Set the list of all elements which can be rendered.
     *
     * @param pObjects All digital object ids.
     */
    public final void setAllEntries(List<DigitalObjectId> pObjects) {
        allEntries.clear();
        allEntries.addAll(pObjects);
        overallPages = allEntries.size() / entriesPerPage;
        overallPages += (allEntries.size() % entriesPerPage > 0) ? 1 : 0;
        currentPage = 0;
        updatePage();
    }

    /**
     * Get the parent UI.
     *
     * @return The parent UI.
     */
    public final MyVaadinUI getParentUI() {
        return parent;
    }

    @Override
    protected final void setCompositionRoot(Component compositionRoot) {
        super.setCompositionRoot(compositionRoot);
    }

    /**
     * Open the popup used to share access to the provided object.
     *
     * @param pObject The object to share.
     */
    protected final void showSharingPopup(DigitalObject pObject) {
        shareComponent.setup(pObject);
        shareComponent.getPopupView().setPopupVisible(true);
    }

    /**
     * Build the main layout.
     */
    private void buildMainLayout() {
        mainLayout = new VerticalLayout();
        mainLayout.setSizeFull();
        pageLayout.setSizeFull();
        pageLayout.setSpacing(true);
        mainLayout.addComponent(pageLayout);
        mainLayout.addComponent(navigation);
        mainLayout.setComponentAlignment(pageLayout, Alignment.MIDDLE_CENTER);
        mainLayout.setComponentAlignment(navigation, Alignment.BOTTOM_CENTER);
        mainLayout.setExpandRatio(pageLayout, 1.0f);
        mainLayout.setExpandRatio(navigation, .1f);
        mainLayout.addComponent(shareComponent.getPopupView());
        mainLayout.setComponentAlignment(shareComponent.getPopupView(), Alignment.MIDDLE_CENTER);
    }

    /**
     * Update the currently rendered page.
     */
    private void updatePage() {
        pageLayout.removeAllComponents();
        List<DigitalObjectId> objectsOnPage = allEntries.subList(currentPage * entriesPerPage,
                Math.min(currentPage * entriesPerPage + entriesPerPage, allEntries.size()));
        int cnt = 0;
        IAuthorizationContext ctx = parent.getAuthorizationContext();
        while (cnt < entriesPerPage) {
            if (objectsOnPage.size() > cnt) {
                DigitalObject entry = null;
                String entryId = null;
                try {
                    entryId = objectsOnPage.get(cnt).getStringRepresentation().trim();
                    entry = DigitalObjectPersistenceHelper.getDigitalObjectByIdentifier(entryId, ctx);
                } catch (Exception ex) {
                    //do nothing, entry stays null
                    LOGGER.warn("Failed to get object by id '" + entryId + "'. Adding error placeholder component.",
                            ex);
                }
                if (entry == null) {
                    entry = new DigitalObject();
                    entry.setDigitalObjectId(new DigitalObjectId(entryId));
                    entry.setLabel(EntryRenderPanel.ERROR_PLACEHOLDER);
                }
                pageLayout.addComponent(new EntryRenderPanel(this, entry, ctx));
            }
            cnt++;
        }

        //update navigation
        if (!objectsOnPage.isEmpty()) {
            HorizontalLayout newNavigation = buildNavigationComponent();
            mainLayout.replaceComponent(navigation, newNavigation);
            navigation = newNavigation;
        } else {
            String noResultsMessage = "<h2>No objects found for the provided search criteria.</h2>";
            HorizontalLayout newNavigation = new HorizontalLayout(new Label(noResultsMessage, ContentMode.HTML));
            mainLayout.replaceComponent(navigation, newNavigation);
            navigation = newNavigation;
        }
    }

    /**
     * Build the navigation layout including the appropriate buttons to navigate
     * through the pagination pages.
     *
     * @return The navigation layout component.
     */
    private HorizontalLayout buildNavigationComponent() {
        HorizontalLayout result = new HorizontalLayout();
        //add "JumpToFirstPage" button
        final NativeButton first = new NativeButton();
        first.setIcon(new ThemeResource("img/16x16/beginning.png"));
        first.setDescription("First Page");
        first.addClickListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                currentPage = 0;
                updatePage();
            }
        });
        //add "PreviousPage" button
        final NativeButton prev = new NativeButton();
        prev.setIcon(new ThemeResource("img/16x16/prev.png"));
        prev.setDescription("Previous Page");
        prev.addClickListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                if (currentPage > 0) {
                    currentPage--;
                    updatePage();
                }
            }
        });
        //add "NextPage" button
        final NativeButton next = new NativeButton();
        next.setDescription("Next Page");
        next.setIcon(new ThemeResource("img/16x16/next.png"));
        next.addClickListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                if (currentPage + 1 < overallPages) {
                    currentPage++;
                    updatePage();
                }
            }
        });
        //add "JumpToLastPage" button
        final NativeButton last = new NativeButton();
        last.setDescription("Last Page");
        last.setIcon(new ThemeResource("img/16x16/end.png"));
        last.addClickListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                currentPage = overallPages - 1;
                updatePage();
            }
        });

        //enable/disable buttons depending on the current page
        if (overallPages == 0) {
            first.setEnabled(false);
            prev.setEnabled(false);
            next.setEnabled(false);
            last.setEnabled(false);
        } else {
            first.setEnabled(!(currentPage == 0) || !(overallPages < 2));
            prev.setEnabled(!(currentPage == 0) || !(overallPages < 2));
            next.setEnabled(!(currentPage == overallPages - 1) || !(overallPages < 2));
            last.setEnabled(!(currentPage == overallPages - 1) || !(overallPages < 2));
        }

        Label leftFiller = new Label();
        result.addComponent(leftFiller);
        result.setExpandRatio(leftFiller, 1.0f);
        result.addComponent(first);
        result.addComponent(prev);
        int start = currentPage - 5;
        start = (start < 0) ? 0 : start;
        int end = start + 10;
        end = (end > overallPages) ? overallPages : end;

        if (end - start < 10 && overallPages > 10) {
            start = end - 10;
        }

        if (overallPages == 0) {
            Label noEntryLabel = new Label("<i>No entries</i>", ContentMode.HTML);
            //noEntryLabel.setWidth("80px");
            noEntryLabel.setSizeUndefined();
            result.addComponent(noEntryLabel);
            result.setComponentAlignment(noEntryLabel, Alignment.MIDDLE_CENTER);
        }
        //build the actual page entries
        for (int i = start; i < end; i++) {
            if (i == currentPage) {
                //the current page is marked with a special style
                Label pageLink = new Label("<b>" + Integer.toString(i + 1) + "</b>", ContentMode.HTML);
                pageLink.setStyleName("currentpage");
                pageLink.setWidth("15px");
                result.addComponent(pageLink);
                result.setComponentAlignment(pageLink, Alignment.MIDDLE_CENTER);
            } else {
                //otherwise normal links are added, click-events are handled via LayoutClickListener 
                Link pageLink = new Link(Integer.toString(i + 1), null);
                result.addComponent(pageLink);
                result.setComponentAlignment(pageLink, Alignment.MIDDLE_CENTER);
            }
        }
        //add right navigation buttons
        result.addComponent(next);
        result.addComponent(last);
        //...and fill the remaining space 
        Label rightFiller = new Label();
        result.addComponent(rightFiller);
        result.setExpandRatio(rightFiller, 1.0f);
        result.setSpacing(true);

        //put everything ot the middle
        result.setComponentAlignment(first, Alignment.MIDDLE_CENTER);
        result.setComponentAlignment(prev, Alignment.MIDDLE_CENTER);
        result.setComponentAlignment(next, Alignment.MIDDLE_CENTER);
        result.setComponentAlignment(last, Alignment.MIDDLE_CENTER);

        //add layout click listener to be able to navigate by clicking the single pages
        result.addLayoutClickListener(new LayoutEvents.LayoutClickListener() {
            @Override
            public void layoutClick(LayoutEvents.LayoutClickEvent event) {

                // Get the child component which was clicked
                Component child = event.getChildComponent();

                if (child == null) {
                    // Not over any child component
                } else // Over a child component
                {
                    if (child instanceof Link) {
                    }
                }
            }
        });

        //finalize
        result.setWidth("100%");
        result.setHeight("25px");
        return result;
    }
}