Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2010, 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 javafx.beans.InvalidationListener;
029import javafx.beans.Observable;
030import javafx.beans.property.ReadOnlyIntegerProperty;
031import javafx.beans.property.ReadOnlyIntegerWrapper;
032import javafx.beans.property.ReadOnlyObjectProperty;
033import javafx.beans.property.ReadOnlyObjectWrapper;
034
035/**
036 * The abstract base class for FocusModel implementations.
037 */
038public abstract class FocusModel<T> {
039
040    /***********************************************************************
041     *                                                                     *
042     * Constructors                                                        *
043     *                                                                     *
044     **********************************************************************/
045
046    /**
047     * Creates a default FocusModel instance.
048     */
049    public FocusModel() {
050        focusedIndexProperty().addListener(new InvalidationListener() {
051            @Override public void invalidated(Observable valueModel) {
052                // we used to lazily retrieve the focused item, but now we just
053                // do it when the focused index changes.
054                setFocusedItem(getModelItem(getFocusedIndex()));
055            }
056        });
057    }
058
059
060
061    /***************************************************************************
062     *                                                                         *
063     * Focus Properties                                                        *
064     *                                                                         *
065     **************************************************************************/
066
067    /**
068     * The index of the current item in the FocusModel which has the focus. It
069     * is possible that this will be -1, but only if the control is empty.
070     * If the control is not itself focused, this property will still
071     * reference the row index that would receive the keyboard focus if the control
072     * itself were focused.
073     */
074    private ReadOnlyIntegerWrapper focusedIndex = new ReadOnlyIntegerWrapper(this, "focusedIndex", -1);
075    public final ReadOnlyIntegerProperty focusedIndexProperty() { return focusedIndex.getReadOnlyProperty();  }
076    public final int getFocusedIndex() { return focusedIndex.get(); }
077    final void setFocusedIndex(int value) { focusedIndex.set(value); }
078
079
080
081    /**
082     * The current item in the FocusModel which has the focus. It
083     * is possible that this will be null, but only if the control is empty.
084     * If the control is not itself focused, this property will still
085     * reference the item that would receive the keyboard focus if the control
086     * itself were focused.
087     */
088    private ReadOnlyObjectWrapper<T> focusedItem = new ReadOnlyObjectWrapper<T>(this, "focusedItem");
089    public final ReadOnlyObjectProperty<T> focusedItemProperty() { return focusedItem.getReadOnlyProperty(); }
090    public final T getFocusedItem() { return focusedItemProperty().get(); }
091    final void setFocusedItem(T value) { focusedItem.set(value); }
092
093
094            
095    /***********************************************************************
096     *                                                                     *
097     * Public Focus API                                                    *
098     *                                                                     *
099     **********************************************************************/
100
101    
102    /**
103     * Returns the number of items in the data model that underpins the control.
104     * An example would be that a ListView focus model would likely return
105     * <code>listView.getItems().size()</code>. The valid range of focusable
106     * indices is between 0 and whatever is returned by this method.
107     */
108    protected abstract int getItemCount();
109    
110    /**
111     * Returns the item at the given index. An example using ListView would be
112     * <code>listView.getItems().get(index)</code>.
113     * 
114     * @param index The index of the item that is requested from the underlying
115     *      data model.
116     * @return Returns null if the index is out of bounds, or an element of type
117     *      T that is related to the given index.
118     */
119    protected abstract T getModelItem(int index);
120
121    /**
122     * <p>Convenience method to inform if the given index is currently focused
123     * in this SelectionModel. Is functionally equivalent to calling
124     * <pre><code>getFocusedIndex() == index</code></pre>.
125     *
126     * @param index The index to check as to whether it is currently focused
127     *      or not.
128     * @return True if the given index is focused, false otherwise.
129     */
130    public boolean isFocused(int index) {
131        if (index < 0 || index >= getItemCount()) return false;
132
133        return getFocusedIndex() == index;
134    }
135
136    /**
137     * Causes the item at the given index to receive the focus. This does not
138     * cause the current selection to change. Updates the focusedItem and
139     * focusedIndex properties such that <code>focusedIndex = -1</code> unless
140     * <code>0 <= index < model size</code>.
141     *
142     * @param index The index of the item to get focus.
143     */
144    public void focus(int index) {
145        if (index < 0 || index >= getItemCount()) {
146            setFocusedIndex(-1);
147        } else {
148            setFocusedIndex(index);
149        }
150    }
151
152    /**
153     * Attempts to give focus to the row previous to the currently focused row.
154     * If the current focus owner is the first row, or is -1 (representing that
155     * there is no current focus owner), calling this method will have no result.
156     */
157    public void focusPrevious() {
158        if (getFocusedIndex() == -1) {
159            focus(0);
160        } else if (getFocusedIndex() > 0) {
161            focus(getFocusedIndex() - 1);
162        }
163    }
164
165    /**
166     * Attempts to give focus to the row after to the currently focused row.
167     * If the current focus owner is the last row, calling this method will have
168     * no result.
169     */
170    public void focusNext() {
171        if (getFocusedIndex() == -1) {
172            focus(0);
173        } else if (getFocusedIndex() != getItemCount() -1) {
174            focus(getFocusedIndex() + 1);
175        }
176    }
177}