001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ui.dataview;
029
030import org.opencms.ui.CmsVaadinUtils;
031import org.opencms.ui.Messages;
032
033import java.util.List;
034
035import com.google.common.collect.Lists;
036import com.vaadin.server.FontAwesome;
037import com.vaadin.ui.Alignment;
038import com.vaadin.ui.Button;
039import com.vaadin.ui.Button.ClickEvent;
040import com.vaadin.ui.Button.ClickListener;
041import com.vaadin.v7.ui.HorizontalLayout;
042import com.vaadin.v7.ui.Label;
043
044/**
045 * Set of buttons allowing the user to navigate between pages in a paged list.<p>
046 */
047public class CmsPagingControls extends HorizontalLayout {
048
049    /**
050     * Callback which is called when the user changes the page.<p>
051     */
052    public static interface I_PagingCallback {
053
054        /**
055         * Method which is called when the user changes the page.<p>
056         *
057         * @param page the page number
058         */
059        void pageChanged(int page);
060    }
061
062    /** Serial version id. */
063    private static final long serialVersionUID = 1L;
064
065    /** The registered callback. */
066    private List<I_PagingCallback> m_callbacks = Lists.newArrayList();
067
068    /** The page number. */
069    private int m_page;
070
071    /** Button to go to the next page. */
072    private Button m_forward = new Button(FontAwesome.FORWARD);
073
074    /** Button to go to the last page. */
075    private Button m_fastForward = new Button(FontAwesome.FAST_FORWARD);
076
077    /** Button to go to the previous page. */
078    private Button m_back = new Button(FontAwesome.BACKWARD);
079
080    /** Button to go the first page. */
081    private Button m_fastBack = new Button(FontAwesome.FAST_BACKWARD);
082
083    /** Label to show the current page number. */
084    private Label m_label = new Label();
085
086    /** The results label. */
087    private Label m_resultsLabel = new Label();
088
089    /** The index of the last page. */
090    private int m_lastPage;
091
092    /** The page size. */
093    private int m_pageSize;
094
095    /** The result count. */
096    private int m_resultCount;
097
098    /**
099     * Creates a new instance.<p>
100     */
101    public CmsPagingControls() {
102
103        setMargin(true);
104        addComponent(m_label);
105        addComponent(m_fastBack);
106        addComponent(m_back);
107        addComponent(m_forward);
108        addComponent(m_fastForward);
109        addComponent(m_resultsLabel);
110        m_resultsLabel.setWidthUndefined();
111        m_label.setWidthUndefined();
112        setExpandRatio(m_resultsLabel, 1.0f);
113        setComponentAlignment(m_resultsLabel, Alignment.TOP_RIGHT);
114        setSpacing(true);
115
116        m_forward.addClickListener(new ClickListener() {
117
118            private static final long serialVersionUID = 1L;
119
120            @SuppressWarnings("synthetic-access")
121            public void buttonClick(ClickEvent event) {
122
123                setPage(Math.min(m_lastPage, m_page + 1), true);
124                updateButtons();
125            }
126        });
127
128        m_fastForward.addClickListener(new ClickListener() {
129
130            private static final long serialVersionUID = 1L;
131
132            @SuppressWarnings("synthetic-access")
133            public void buttonClick(ClickEvent event) {
134
135                setPage(m_lastPage, true);
136                updateButtons();
137
138            }
139        });
140        m_back.addClickListener(new ClickListener() {
141
142            private static final long serialVersionUID = 1L;
143
144            @SuppressWarnings("synthetic-access")
145            public void buttonClick(ClickEvent event) {
146
147                setPage(Math.max(0, m_page - 1), true);
148                updateButtons();
149
150            }
151
152        });
153
154        m_fastBack.addClickListener(new ClickListener() {
155
156            private static final long serialVersionUID = 1L;
157
158            public void buttonClick(ClickEvent event) {
159
160                setPage(0, true);
161                updateButtons();
162
163            }
164        });
165    }
166
167    /**
168     * Adds a new page change callback.<p>
169     *
170     * @param callback the callback
171     */
172    public void addCallback(I_PagingCallback callback) {
173
174        m_callbacks.add(callback);
175    }
176
177    /**
178     * Notifies the registered listeners of a page change.<p>
179     *
180     * @param pageNum the page index
181     */
182    public void firePageChanged(int pageNum) {
183
184        for (I_PagingCallback callback : m_callbacks) {
185            callback.pageChanged(pageNum);
186        }
187    }
188
189    /**
190     * Gets the current page number.<p>
191     *
192     * @return the current page number
193     */
194    public int getPage() {
195
196        return m_page;
197    }
198
199    /**
200     * Removes a registered callback.<p>
201     *
202     * @param callback the callback to remove
203     */
204    public void removeCallback(I_PagingCallback callback) {
205
206        m_callbacks.remove(callback);
207    }
208
209    /**
210     * Resets the paging controls (used when the size of the underlying list changes).<p>
211     *
212     * @param resultCount total number of results
213     * @param pageSize size of a page
214     * @param fireChanged true if the listeners should be notified
215     */
216    public void reset(int resultCount, int pageSize, boolean fireChanged) {
217
218        m_lastPage = resultCount == 0 ? 0 : (resultCount - 1) / pageSize;
219        m_resultCount = resultCount;
220        m_pageSize = pageSize;
221        setPage(0, false);
222        updateButtons();
223        if (fireChanged) {
224            firePageChanged(0);
225        }
226    }
227
228    /**
229     * Sets the page index.<p>
230     *
231     * @param page the page index
232     * @param fireChanged true if the registered listeners should be notified
233     */
234    public void setPage(int page, boolean fireChanged) {
235
236        m_page = page;
237        m_label.setValue("( " + (1 + m_page) + " / " + (m_lastPage + 1) + " )");
238        int start = (m_page * m_pageSize) + 1;
239        int end = Math.min((start + m_pageSize) - 1, m_resultCount);
240        String resultsMsg = CmsVaadinUtils.getMessageText(
241            Messages.GUI_DATAVIEW_RESULTS_3,
242            "" + start,
243            "" + end,
244            "" + m_resultCount);
245        m_resultsLabel.setValue(start <= end ? resultsMsg : "");
246        if (fireChanged) {
247            firePageChanged(page);
248        }
249    }
250
251    /**
252     * Updates the button state, i.e. enables/disables the buttons depending on whether we are on the first or last page or not.<p>
253     */
254    public void updateButtons() {
255
256        for (Button button : new Button[] {m_forward, m_fastForward}) {
257            button.setEnabled(m_page < m_lastPage);
258        }
259        for (Button button : new Button[] {m_back, m_fastBack}) {
260            button.setEnabled(m_page > 0);
261        }
262    }
263
264}