001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://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: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://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        setMargin(true);
103        addComponent(m_label);
104        addComponent(m_fastBack);
105        addComponent(m_back);
106        addComponent(m_forward);
107        addComponent(m_fastForward);
108        addComponent(m_resultsLabel);
109        m_resultsLabel.setWidthUndefined();
110        m_label.setWidthUndefined();
111        setExpandRatio(m_resultsLabel, 1.0f);
112        setComponentAlignment(m_resultsLabel, Alignment.TOP_RIGHT);
113        setSpacing(true);
114
115        m_forward.addClickListener(new ClickListener() {
116
117            private static final long serialVersionUID = 1L;
118
119            @SuppressWarnings("synthetic-access")
120            public void buttonClick(ClickEvent event) {
121
122                setPage(Math.min(m_lastPage, m_page + 1), true);
123                updateButtons();
124            }
125        });
126
127        m_fastForward.addClickListener(new ClickListener() {
128
129            private static final long serialVersionUID = 1L;
130
131            @SuppressWarnings("synthetic-access")
132            public void buttonClick(ClickEvent event) {
133
134                setPage(m_lastPage, true);
135                updateButtons();
136
137            }
138        });
139        m_back.addClickListener(new ClickListener() {
140
141            private static final long serialVersionUID = 1L;
142
143            @SuppressWarnings("synthetic-access")
144            public void buttonClick(ClickEvent event) {
145
146                setPage(Math.max(0, m_page - 1), true);
147                updateButtons();
148
149            }
150
151        });
152
153        m_fastBack.addClickListener(new ClickListener() {
154
155            private static final long serialVersionUID = 1L;
156
157            public void buttonClick(ClickEvent event) {
158
159                setPage(0, true);
160                updateButtons();
161
162            }
163        });
164    }
165
166    /**
167     * Adds a new page change callback.<p>
168     *
169     * @param callback the callback
170     */
171    public void addCallback(I_PagingCallback callback) {
172
173        m_callbacks.add(callback);
174    }
175
176    /**
177     * Notifies the registered listeners of a page change.<p>
178     *
179     * @param pageNum the page index
180     */
181    public void firePageChanged(int pageNum) {
182
183        for (I_PagingCallback callback : m_callbacks) {
184            callback.pageChanged(pageNum);
185        }
186    }
187
188    /**
189     * Gets the current page number.<p>
190     *
191     * @return the current page number
192     */
193    public int getPage() {
194
195        return m_page;
196    }
197
198    /**
199     * Removes a registered callback.<p>
200     *
201     * @param callback the callback to remove
202     */
203    public void removeCallback(I_PagingCallback callback) {
204
205        m_callbacks.remove(callback);
206    }
207
208    /**
209     * Resets the paging controls (used when the size of the underlying list changes).<p>
210     *
211     * @param resultCount total number of results
212     * @param pageSize size of a page
213     * @param fireChanged true if the listeners should be notified
214     */
215    public void reset(int resultCount, int pageSize, boolean fireChanged) {
216
217        m_lastPage = resultCount == 0 ? 0 : (resultCount - 1) / pageSize;
218        m_resultCount = resultCount;
219        m_pageSize = pageSize;
220        setPage(0, false);
221        updateButtons();
222        if (fireChanged) {
223            firePageChanged(0);
224        }
225    }
226
227    /**
228     * Sets the page index.<p>
229     *
230     * @param page the page index
231     * @param fireChanged true if the registered listeners should be notified
232     */
233    public void setPage(int page, boolean fireChanged) {
234
235        m_page = page;
236        m_label.setValue("( " + (1 + m_page) + " / " + (m_lastPage + 1) + " )");
237        int start = (m_page * m_pageSize) + 1;
238        int end = Math.min((start + m_pageSize) - 1, m_resultCount);
239        String resultsMsg = CmsVaadinUtils.getMessageText(
240            Messages.GUI_DATAVIEW_RESULTS_3,
241            "" + start,
242            "" + end,
243            "" + m_resultCount);
244        m_resultsLabel.setValue(start <= end ? resultsMsg : "");
245        if (fireChanged) {
246            firePageChanged(page);
247        }
248    }
249
250    /**
251     * Updates the button state, i.e. enables/disables the buttons depending on whether we are on the first or last page or not.<p>
252     */
253    public void updateButtons() {
254
255        for (Button button : new Button[] {m_forward, m_fastForward}) {
256            button.setEnabled(m_page < m_lastPage);
257        }
258        for (Button button : new Button[] {m_back, m_fastBack}) {
259            button.setEnabled(m_page > 0);
260        }
261    }
262
263}