/*
* Copyright (c) 2002-2015, JIDE Software Inc. 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.
*/
package jidefx.scene.control.searchable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.control.ChoiceBox;
import javafx.util.StringConverter;
/**
* {@code ChoiceBoxSearchable} is an concrete implementation of {@link Searchable} that enables the search function on
* non-editable ChoiceBox. <p>It's very simple to use it. Assuming you have a ChoiceBox, all you need to do is to call
* <pre>{@code
* ChoiceBox choiceBox = ....;
* ChoiceBoxSearchable searchable = new ChoiceBoxSearchable(choiceBox);
* }</pre>
* Now the ChoiceBox will have the search function.
* <p/>
* There is very little customization you need to do to ChoiceBoxSearchable. The only thing you might need is when the
* element in the ChoiceBox needs a special conversion to convert to string. If so, you can override
* convertElementToString() to provide you own algorithm to do the conversion.
* <pre>{@code
* ChoiceBox choiceBox = ....;
* ChoiceBoxSearchable searchable = new ChoiceBoxSearchable(choiceBox) {
* protected String convertElementToString(Object object) {
* ...
* }
* };
* }</pre>
* <p/>
*
* @param <T> the element type in the ChoiceBox.
*/
@SuppressWarnings({"Convert2Lambda", "unchecked"})
public class ChoiceBoxSearchable<T> extends Searchable<T> {
private ListChangeListener<T> _listChangeListener;
private ChangeListener<ObservableList<T>> _itemsChangeListener;
public ChoiceBoxSearchable(ChoiceBox<T> choiceBox) {
super(choiceBox);
}
@Override
public void installListeners() {
super.installListeners();
if (_listChangeListener == null) {
_listChangeListener = new ListChangeListener<T>() {
@Override
public void onChanged(Change<? extends T> c) {
hidePopup();
}
};
}
((ChoiceBox<T>) _node).getItems().addListener(_listChangeListener);
if (_itemsChangeListener == null) {
_itemsChangeListener = new ChangeListener<ObservableList<T>>() {
@Override
public void changed(ObservableValue<? extends ObservableList<T>> observable, ObservableList<T> oldValue, ObservableList<T> newValue) {
hidePopup();
}
};
}
((ChoiceBox<T>) _node).itemsProperty().addListener(_itemsChangeListener);
}
@Override
public void uninstallListeners() {
if (_listChangeListener != null) {
((ChoiceBox<T>) _node).getItems().removeListener(_listChangeListener);
_listChangeListener = null;
}
if (_itemsChangeListener != null) {
((ChoiceBox<T>) _node).itemsProperty().removeListener(_itemsChangeListener);
_itemsChangeListener = null;
}
super.uninstallListeners();
}
private BooleanProperty _showPopupProperty;
public BooleanProperty showPopupProperty() {
if (_showPopupProperty == null) {
_showPopupProperty = new SimpleBooleanProperty(false);
}
return _showPopupProperty;
}
public boolean isShowPopup() {
return showPopupProperty().get();
}
public void setShowPopup(boolean showPopup) {
showPopupProperty().set(showPopup);
}
@Override
protected int getSelectedIndex() {
return ((ChoiceBox<T>) _node).getSelectionModel().getSelectedIndex();
}
@Override
protected void setSelectedIndex(int index, boolean incremental) {
ChoiceBox<T> choiceBox = (ChoiceBox<T>) _node;
choiceBox.getSelectionModel().select(index);
if (isShowPopup() && !choiceBox.isShowing()) {
choiceBox.show();
}
}
@Override
protected int getElementCount() {
return ((ChoiceBox<T>) _node).getItems().size();
}
@Override
protected T getElementAt(int index) {
return ((ChoiceBox<T>) _node).getItems().get(index);
}
@Override
protected String convertElementToString(T element) {
ChoiceBox<T> choiceBox = (ChoiceBox<T>) _node;
StringConverter<T> converter = choiceBox.getConverter();
return converter != null ? converter.toString(element) : (element != null ? element.toString() : "");
}
}