Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.scene.control;
027
028import java.util.ArrayList;
029import java.util.Collections;
030import java.util.List;
031import javafx.beans.DefaultProperty;
032import javafx.beans.property.IntegerProperty;
033import javafx.beans.property.ObjectProperty;
034import javafx.beans.property.SimpleIntegerProperty;
035import javafx.beans.property.SimpleObjectProperty;
036import javafx.css.CssMetaData;
037import javafx.css.StyleOrigin;
038import javafx.css.StyleableIntegerProperty;
039import javafx.css.Styleable;
040import javafx.css.StyleableProperty;
041import javafx.scene.Node;
042import javafx.util.Callback;
043import com.sun.javafx.css.converters.SizeConverter;
044import com.sun.javafx.scene.control.skin.PaginationSkin;
045
046/**
047 * <p>
048 * A Pagination control is used for navigation between pages of a single content,
049 * which has been divided into smaller parts.
050 * </p>
051 *
052 * <h3>Styling the page indicators</h3>
053 * <p>
054 * The control can be customized to display numeric page indicators or bullet style indicators by
055 * setting the style class {@link #STYLE_CLASS_BULLET}.  The
056 * {@link #maxPageIndicatorCountProperty() maxPageIndicatorCountProperty} can be used to change
057 * the maximum number of page indicators.  The property value can also be changed
058 * via CSS using -fx-max-page-indicator-count.
059 *</p>
060 *
061 * <h3>Page count</h3>
062 * <p>
063 * The {@link #pageCountProperty() pageCountProperty} controls the number of
064 * pages this pagination control has.  If the page count is
065 * not known {@link #INDETERMINATE} should be used as the page count.
066 * </p>
067 *
068 * <h3>Page factory</h3>
069 * <p>
070 * The {@link #pageFactoryProperty() pageFactoryProperty} is a callback function
071 * that is called when a page has been selected by the application or
072 * the user.  The function is required for the functionality of the pagination
073 * control.  The callback function should load and return the contents of the selected page.
074 * Null should be returned if the selected page index does not exist.
075 * </p>
076 *
077 * <h3>Creating a Pagination control:</h3>
078 * <p>
079 * A simple example of how to create a pagination control with ten pages and
080 * each page containing ten hyperlinks.
081 * </p>
082 *
083 * <pre>
084 * {@code
085 *   Pagination pagination = new Pagination(10, 0);
086 *   pagination.setPageFactory(new Callback<Integer, Node>() {
087 *       public Node call(Integer pageIndex) {
088 *           VBox box = new VBox(5);
089 *           for (int i = 0; i < pageIndex + 10; i++) {
090 *               Hyperlink link = new Hyperlink(myurls[i]);
091 *               box.getChildren().add(link);
092 *           }
093 *           return box;
094 *       }
095 *   });
096 * }</pre>
097 * @since 2.2
098 */
099@DefaultProperty("pages")
100public class Pagination extends Control {
101
102    private static final int DEFAULT_MAX_PAGE_INDICATOR_COUNT = 10;
103
104    /**
105     * The style class to change the numeric page indicators to
106     * bullet indicators.
107     */
108    public static final String STYLE_CLASS_BULLET = "bullet";
109
110    /**
111     * Value for indicating that the page count is indeterminate.
112     *
113     * @see #setPageCount
114     */
115    public static final int INDETERMINATE = Integer.MAX_VALUE;
116
117    /**
118     * Constructs a new Pagination control with the specified page count
119     * and page index.
120     *
121     * @param pageCount the number of pages for the pagination control
122     * @param pageIndex the index of the first page.
123     *
124     */
125    public Pagination(int pageCount, int pageIndex) {
126        getStyleClass().setAll(DEFAULT_STYLE_CLASS);
127        setPageCount(pageCount);
128        setCurrentPageIndex(pageIndex);
129    }
130
131    /**
132     * Constructs a new Pagination control with the specified page count.
133     *
134     * @param pageCount the number of pages for the pagination control
135     *
136     */
137    public Pagination(int pageCount) {
138        this(pageCount, 0);
139    }
140
141    /**
142     * Constructs a Pagination control with an {@link #INDETERMINATE} page count
143     * and a page index equal to zero.
144     */
145    public Pagination() {
146        this(INDETERMINATE, 0);
147    }
148
149    /***************************************************************************
150     *                                                                         *
151     * Properties                                                              *
152     *                                                                         *
153     **************************************************************************/
154
155    private int oldMaxPageIndicatorCount = DEFAULT_MAX_PAGE_INDICATOR_COUNT;
156    private IntegerProperty maxPageIndicatorCount;
157
158    /**
159     * Sets the maximum number of page indicators.
160     *
161     * @param value the number of page indicators.  The default is 10.
162     */
163    public final void setMaxPageIndicatorCount(int value) { maxPageIndicatorCountProperty().set(value); }
164
165    /**
166     * Returns the maximum number of page indicators.
167     */
168    public final int getMaxPageIndicatorCount() {
169        return maxPageIndicatorCount == null ? DEFAULT_MAX_PAGE_INDICATOR_COUNT : maxPageIndicatorCount.get();
170    }
171
172    /**
173     * The maximum number of page indicators to use for this pagination control.
174     * The maximum number of pages indicators will remain unchanged if the value is less than 1
175     * or greater than the {@link #pageCount}.  The number of page indicators will be
176     * reduced to fit the control if the {@code maxPageIndicatorCount} cannot fit.
177     *
178     * The default is 10 page indicators.
179     */
180    public final IntegerProperty maxPageIndicatorCountProperty() {
181        if (maxPageIndicatorCount == null) {
182            maxPageIndicatorCount = new StyleableIntegerProperty(DEFAULT_MAX_PAGE_INDICATOR_COUNT) {
183
184                @Override protected void invalidated() {
185                    if (!maxPageIndicatorCount.isBound()) {
186                        if (getMaxPageIndicatorCount() < 1 || getMaxPageIndicatorCount() > getPageCount()) {
187                            setMaxPageIndicatorCount(oldMaxPageIndicatorCount);
188                        }
189                        oldMaxPageIndicatorCount = getMaxPageIndicatorCount();
190                    }
191                }
192
193                @Override
194                public CssMetaData<Pagination,Number> getCssMetaData() {
195                    return StyleableProperties.MAX_PAGE_INDICATOR_COUNT;
196                }
197
198                @Override
199                public Object getBean() {
200                    return Pagination.this;
201                }
202
203                @Override
204                public String getName() {
205                    return "maxPageIndicatorCount";
206                }
207            };
208        }
209        return maxPageIndicatorCount;
210    }
211
212    private int oldPageCount = INDETERMINATE;
213    private IntegerProperty pageCount = new SimpleIntegerProperty(this, "pageCount", INDETERMINATE) {
214        @Override protected void invalidated() {
215            if (!pageCount.isBound()) {
216                if (getPageCount() < 1) {
217                    setPageCount(oldPageCount);
218                }
219                oldPageCount = getPageCount();
220            }
221        }
222    };
223
224    /**
225     * Sets the number of pages.
226     *
227     * @param value the number of pages
228     */
229    public final void setPageCount(int value) { pageCount.set(value); }
230
231    /**
232     * Returns the number of pages.
233     */
234    public final int getPageCount() { return pageCount.get(); }
235
236    /**
237     * The number of pages for this pagination control.  This
238     * value must be greater than or equal to 1. {@link #INDETERMINATE}
239     * should be used as the page count if the total number of pages is unknown.
240     *
241     * The default is an {@link #INDETERMINATE} number of pages.
242     */
243    public final IntegerProperty pageCountProperty() { return pageCount; }
244
245    private final IntegerProperty currentPageIndex = new SimpleIntegerProperty(this, "currentPageIndex", 0) {
246        @Override protected void invalidated() {
247            if (!currentPageIndex.isBound()) {
248                if (getCurrentPageIndex() < 0) {
249                    setCurrentPageIndex(0);
250                } else if (getCurrentPageIndex() > getPageCount() - 1) {
251                    setCurrentPageIndex(getPageCount() - 1);
252                }
253            }
254        }
255    };
256
257    /**
258     * Sets the current page index.
259     * @param value the current page index.
260     */
261    public final void setCurrentPageIndex(int value) { currentPageIndex.set(value); }
262
263    /**
264     * Returns the current page index.
265     */
266    public final int getCurrentPageIndex() { return currentPageIndex.get(); }
267
268    /**
269     * The current page index to display for this pagination control.  The first page will be
270     * the current page if the value is less than 0.  Similarly the last page
271     * will be the current page if the value is greater than the {@link #pageCount}
272     *
273     * The default is 0 for the first page.
274     */
275    public final IntegerProperty currentPageIndexProperty() { return currentPageIndex; }
276
277    private ObjectProperty<Callback<Integer, Node>> pageFactory =
278            new SimpleObjectProperty<Callback<Integer, Node>>(this, "pageFactory");
279
280    /**
281     * Sets the page factory callback function.
282     */
283    public final void setPageFactory(Callback<Integer, Node> value) { pageFactory.set(value); }
284
285    /**
286     * Returns the page factory callback function.
287     */
288    public final Callback<Integer, Node> getPageFactory() {return pageFactory.get(); }
289
290    /**
291     * The pageFactory callback function that is called when a page has been
292     * selected by the application or the user.
293     *
294     * This function is required for the functionality of the pagination
295     * control.  The callback function should load and return the contents the page index.
296     * Null should be returned if the page index does not exist.  The currentPageIndex
297     * will not change when null is returned.
298     *
299     * The default is null if there is no page factory set.
300     */
301    public final ObjectProperty<Callback<Integer, Node>> pageFactoryProperty() { return pageFactory; }
302
303
304    /***************************************************************************
305     *                                                                         *
306     * Methods                                                                 *
307     *                                                                         *
308     **************************************************************************/
309
310    /** {@inheritDoc} */
311    @Override protected Skin<?> createDefaultSkin() {
312        return new PaginationSkin(this);
313    }
314
315    /***************************************************************************
316     *                                                                         *
317     *                         Stylesheet Handling                             *
318     *                                                                         *
319     **************************************************************************/
320
321    private static final String DEFAULT_STYLE_CLASS = "pagination";
322
323    private static class StyleableProperties {
324        private static final CssMetaData<Pagination,Number> MAX_PAGE_INDICATOR_COUNT =
325            new CssMetaData<Pagination,Number>("-fx-max-page-indicator-count",
326                SizeConverter.getInstance(), DEFAULT_MAX_PAGE_INDICATOR_COUNT) {
327
328            @Override
329            public boolean isSettable(Pagination n) {
330                return n.maxPageIndicatorCount == null || !n.maxPageIndicatorCount.isBound();
331            }
332
333            @Override
334            public StyleableProperty<Number> getStyleableProperty(Pagination n) {
335                return (StyleableProperty<Number>)n.maxPageIndicatorCountProperty();
336            }
337        };
338        private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
339        static {
340            final List<CssMetaData<? extends Styleable, ?>> styleables =
341                new ArrayList<CssMetaData<? extends Styleable, ?>>(Control.getClassCssMetaData());
342            styleables.add(MAX_PAGE_INDICATOR_COUNT);
343            STYLEABLES = Collections.unmodifiableList(styleables);
344        }
345    }
346
347    /**
348     * @return The CssMetaData associated with this class, which may include the
349     * CssMetaData of its super classes.
350     */
351    public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
352        return StyleableProperties.STYLEABLES;
353    }
354
355    /**
356     * {@inheritDoc}
357     */
358    @Override
359    public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() {
360        return getClassCssMetaData();
361    }
362
363}