/*
* Copyright (C) 2015 thirdy
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package net.thirdy.blackmarket.fxcontrols.autocomplete;
import static net.thirdy.blackmarket.util.LangContants.STRING_EMPTY;
import static org.elasticsearch.common.lang3.StringUtils.trimToNull;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import org.controlsfx.control.textfield.CustomTextField;
import impl.org.controlsfx.autocompletion.AutoCompletionTextFieldBinding;
import impl.org.controlsfx.skin.AutoCompletePopupSkin;
import javafx.animation.FadeTransition;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.ObjectProperty;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.ListView;
import javafx.scene.control.Skin;
import javafx.scene.control.TextField;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.util.Callback;
import javafx.util.Duration;
/**
* @author thirdy
*
*/
public class BlackmarketTextField<T> extends CustomTextField {
private static final Duration FADE_DURATION = Duration.millis(350);
private Collection<T> items;
public BlackmarketTextField(T ... a) {
this(Arrays.asList(a));
}
public BlackmarketTextField(Collection<T> items) {
this(items, 10);
}
public BlackmarketTextField(Collection<T> items, int rowCount) {
super();
this.items = items;
setupClearButtonField(this, this.rightProperty());
// class CustomAutoCompletionTextFieldBinding extends AutoCompletionTextFieldBinding<T> {
// public CustomAutoCompletionTextFieldBinding(final TextField textField,
// Callback<ISuggestionRequest, Collection<T>> suggestionProvider) {
// super(textField, suggestionProvider);
// }
// public void setListViewMinWidth(double width) {
// Skin<?> skin = getSkin();
// if(skin instanceof AutoCompletePopupSkin){
// AutoCompletePopupSkin<?> au = (AutoCompletePopupSkin<?>)skin;
// ListView<?> li = (ListView<?>)au.getNode();
// li.setMinWidth(width);
// li.setPrefWidth(width);
// }
// }
// }
AutoCompletionTextFieldBinding actfb = new AutoCompletionTextFieldBinding(this,
BlackmarketSuggestionProvider.create(items));
actfb.setVisibleRowCount(rowCount);
// actfb.setAutoCompletionPopupMinWidth(400.0);
// tfName.setOnAction(e -> {
// String userText =
// Optional.ofNullable(trimToNull(tfName.getText())).orElse(STRING_EMPTY);
// System.out.println("Text: " + userText);
// actfb.setUserInput(userText);
// });
focusedProperty().addListener((observable, oldValue, newValue) -> {
if (newValue) {
String userText = Optional.ofNullable(trimToNull(getText())).orElse(STRING_EMPTY);
actfb.setUserInput(userText);
} else {
actfb.setUserInput(null);
}
});
// tfName.addEventFilter(MouseEvent.MOUSE_CLICKED,
// new EventHandler<MouseEvent>() {
//
// @Override
// public void handle(MouseEvent event) {
// String userText =
// Optional.ofNullable(trimToNull(tfName.getText())).orElse(STRING_EMPTY);
// System.out.println("Text: " + userText);
// actfb.setUserInput(userText);
// }
//
// });
}
/**
* Get the first matching item in the {@link #items}. Make sure to check if {@link #getText()} returns a valid value.
*/
public T item() {
return items.stream().filter(item -> item.toString().equalsIgnoreCase(getText())).findFirst().get();
}
private void setupClearButtonField(TextField inputField, ObjectProperty<Node> rightProperty) {
inputField.getStyleClass().add("clearable-field"); //$NON-NLS-1$
Region clearButton = new Region();
clearButton.getStyleClass().addAll("graphic"); //$NON-NLS-1$
StackPane clearButtonPane = new StackPane(clearButton);
clearButtonPane.getStyleClass().addAll("clear-button"); //$NON-NLS-1$
clearButtonPane.setOpacity(0.0);
clearButtonPane.setCursor(Cursor.DEFAULT);
clearButtonPane.setOnMouseReleased(e -> inputField.clear());
clearButtonPane.managedProperty().bind(inputField.editableProperty());
clearButtonPane.visibleProperty().bind(inputField.editableProperty());
rightProperty.set(clearButtonPane);
final FadeTransition fader = new FadeTransition(FADE_DURATION, clearButtonPane);
fader.setCycleCount(1);
inputField.textProperty().addListener(new InvalidationListener() {
@Override public void invalidated(Observable arg0) {
String text = inputField.getText();
boolean isTextEmpty = text == null || text.isEmpty();
boolean isButtonVisible = fader.getNode().getOpacity() > 0;
if (isTextEmpty && isButtonVisible) {
setButtonVisible(false);
} else if (!isTextEmpty && !isButtonVisible) {
setButtonVisible(true);
}
}
private void setButtonVisible( boolean visible ) {
fader.setFromValue(visible? 0.0: 1.0);
fader.setToValue(visible? 1.0: 0.0);
fader.play();
}
});
}
}