javafx.scene.control.FocusModel Maven / Gradle / Ivy
/*
* Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javafx.scene.control;
import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
/**
* The abstract base class for FocusModel implementations.
*
* @param the type of the focused item
* @since JavaFX 2.0
*/
public abstract class FocusModel {
/* *********************************************************************
* *
* Constructors *
* *
**********************************************************************/
/**
* Creates a default FocusModel instance.
*/
public FocusModel() {
focusedIndexProperty().addListener(valueModel -> {
// we used to lazily retrieve the focused item, but now we just
// do it when the focused index changes.
setFocusedItem(getModelItem(getFocusedIndex()));
});
}
/* *************************************************************************
* *
* Focus Properties *
* *
**************************************************************************/
/**
* The index of the current item in the FocusModel which has the focus. It
* is possible that this will be -1, but only if the control is empty.
* If the control is not itself focused, this property will still
* reference the row index that would receive the keyboard focus if the control
* itself were focused.
*/
private ReadOnlyIntegerWrapper focusedIndex = new ReadOnlyIntegerWrapper(this, "focusedIndex", -1);
public final ReadOnlyIntegerProperty focusedIndexProperty() { return focusedIndex.getReadOnlyProperty(); }
public final int getFocusedIndex() { return focusedIndex.get(); }
final void setFocusedIndex(int value) { focusedIndex.set(value); }
/**
* The current item in the FocusModel which has the focus. It
* is possible that this will be null, but only if the control is empty.
* If the control is not itself focused, this property will still
* reference the item that would receive the keyboard focus if the control
* itself were focused.
*/
private ReadOnlyObjectWrapper focusedItem = new ReadOnlyObjectWrapper<>(this, "focusedItem");
public final ReadOnlyObjectProperty focusedItemProperty() { return focusedItem.getReadOnlyProperty(); }
public final T getFocusedItem() { return focusedItemProperty().get(); }
final void setFocusedItem(T value) { focusedItem.set(value); }
/* *********************************************************************
* *
* Public Focus API *
* *
**********************************************************************/
/**
* Returns the number of items in the data model that underpins the control.
* An example would be that a ListView focus model would likely return
* listView.getItems().size()
. The valid range of focusable
* indices is between 0 and whatever is returned by this method.
* @return the number of items in the data model that underpins the control
*/
protected abstract int getItemCount();
/**
* Returns the item at the given index. An example using ListView would be
* listView.getItems().get(index)
.
*
* @param index The index of the item that is requested from the underlying
* data model.
* @return Returns null if the index is out of bounds, or an element of type
* T that is related to the given index.
*/
protected abstract T getModelItem(int index);
/**
* Convenience method to inform if the given index is currently focused
* in this SelectionModel. Is functionally equivalent to calling
*
getFocusedIndex() == index
.
*
* @param index The index to check as to whether it is currently focused
* or not.
* @return True if the given index is focused, false otherwise.
*/
public boolean isFocused(int index) {
if (index < 0 || index >= getItemCount()) return false;
return getFocusedIndex() == index;
}
/**
* Causes the item at the given index to receive the focus. This does not
* cause the current selection to change. Updates the focusedItem and
* focusedIndex properties such that focusedIndex = -1
unless
* 0 <= index < model size
.
*
* @param index The index of the item to get focus.
*/
public void focus(int index) {
if (index < 0 || index >= getItemCount()) {
setFocusedIndex(-1);
} else {
int oldFocusIndex = getFocusedIndex();
setFocusedIndex(index);
if (oldFocusIndex == index) {
// manually update the focus item to ensure consistency
setFocusedItem(getModelItem(index));
}
}
}
/**
* Attempts to give focus to the row previous to the currently focused row.
* If the current focus owner is the first row, or is -1 (representing that
* there is no current focus owner), calling this method will have no result.
*/
public void focusPrevious() {
if (getFocusedIndex() == -1) {
focus(0);
} else if (getFocusedIndex() > 0) {
focus(getFocusedIndex() - 1);
}
}
/**
* Attempts to give focus to the row after to the currently focused row.
* If the current focus owner is the last row, calling this method will have
* no result.
*/
public void focusNext() {
if (getFocusedIndex() == -1) {
focus(0);
} else if (getFocusedIndex() != getItemCount() -1) {
focus(getFocusedIndex() + 1);
}
}
}