Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce SUGGESTION_SELECTED event and fix multiple commit calls #82

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ and actually inherits a lot of styling attributes from it.

![YearMonthPicker](gemsfx/docs/year-month-picker.png)

## Spacer

Spacer extends Region and is designed to create flexible spaces in container layouts, especially in HBox and VBox. Within an HBox, the Spacer grows horizontally. Within a VBox, it grows vertically. When the activeProperty is set to false, the Spacer will not grow.

![Spacer](gemsfx/docs/spacer.png)

## StripView

A view for horizontally positioning a number of nodes, one for each item added to the view's model. Scroll buttons will
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public void start(Stage primaryStage) throws Exception {

CountriesSearchField field = new CountriesSearchField();
field.getEditor().setPrefColumnCount(30);
field.addEventHandler(SearchField.SearchEvent.SUGGESTION_SELECTED, event -> {
System.out.println("A suggestion was selected! => " + event.getSelectedSuggestion());
});

Region regionLeft = new Region();
regionLeft.setPrefWidth(30);
Expand Down
Binary file added gemsfx/docs/spacer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 42 additions & 18 deletions gemsfx/src/main/java/com/dlsc/gemsfx/SearchField.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ public class SearchField<T> extends Control {

private final SearchFieldPopup<T> popup;

private BooleanProperty shouldCommitProperty = new SimpleBooleanProperty(this, "shouldCommit", false);

/**
* Constructs a new spotlight field. The field will set defaults for the
* matcher, the converter, the cell factory, and the comparator. It will
Expand All @@ -78,7 +80,7 @@ public class SearchField<T> extends Control {
public SearchField() {
getStyleClass().add(DEFAULT_STYLE_CLASS);

popup = new SearchFieldPopup<>(this);
popup = new SearchFieldPopup<>(this, shouldCommitProperty);

editor.textProperty().bindBidirectional(textProperty());
editor.promptTextProperty().bindBidirectional(promptTextProperty());
Expand Down Expand Up @@ -211,11 +213,11 @@ public T fromString(String s) {
}
});

searchService.setOnRunning(evt -> fireEvent(new SearchEvent(SearchEvent.SEARCH_STARTED, searchService.getText())));
searchService.setOnRunning(evt -> fireEvent(SearchEvent.createEventForText(SearchEvent.SEARCH_STARTED, searchService.getText())));

searchService.setOnSucceeded(evt -> {
update(searchService.getValue());
fireEvent(new SearchEvent(SearchEvent.SEARCH_FINISHED, searchService.getText()));
fireEvent(SearchEvent.createEventForText(SearchEvent.SEARCH_FINISHED, searchService.getText()));
});

searching.bind(searchService.runningProperty());
Expand All @@ -229,22 +231,25 @@ public T fromString(String s) {
* item.
*/
public void commit() {
committing = true;
try {
T selectedItem = getSelectedItem();
if (selectedItem != null) {
String text = getConverter().toString(selectedItem);
if (text != null) {
editor.setText(text);
editor.positionCaret(text.length());
if (shouldCommitProperty.get()) {
committing = true;
try {
T selectedItem = getSelectedItem();
if (selectedItem != null) {
String text = getConverter().toString(selectedItem);
if (text != null) {
editor.setText(text);
editor.positionCaret(text.length());
} else {
clear();
}
} else {
clear();
}
} else {
clear();
} finally {
committing = false;
}
} finally {
committing = false;
shouldCommitProperty.set(false);
}
}

Expand Down Expand Up @@ -290,7 +295,6 @@ public final EventHandler<SearchEvent> getOnSearchStarted() {

private SearchEventHandlerProperty onSearchFinished;


/**
* An event handler that can be used to get informed whenever the field finishes a search.
*
Expand Down Expand Up @@ -850,24 +854,44 @@ public static class SearchEvent extends Event {
*/
public static final EventType<SearchEvent> SEARCH_FINISHED = new EventType<>(Event.ANY, "SEARCH_FINISHED");

private String text;
/**
* An event that gets fired when the user selects a suggestion.
*/
public static final EventType<SearchEvent> SUGGESTION_SELECTED = new EventType<>(Event.ANY, "SUGGESTION_SELECTED");

private final Object selectedSuggestion;
private final String text;

public static SearchEvent createEventForText(EventType<? extends SearchEvent> eventType, String text) {
return new SearchEvent(eventType, text, null);
}

public SearchEvent(EventType<? extends SearchEvent> eventType, String text) {
public static SearchEvent createEventForSuggestion(Object suggestion) {
return new SearchEvent(SUGGESTION_SELECTED, null, suggestion);
}

private SearchEvent(EventType<? extends SearchEvent> eventType, String text, Object suggestion) {
super(eventType);
this.text = text;
this.selectedSuggestion = suggestion;
}

public String getText() {
return text;
}

public Object getSelectedSuggestion() {
return selectedSuggestion;
}

@Override
public String toString() {
return new ToStringBuilder(this)
.append("eventType", eventType)
.append("target", target)
.append("consumed", consumed)
.append("text", text)
.append("selectedSuggestion", selectedSuggestion)
.toString();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package com.dlsc.gemsfx.skins;

import com.dlsc.gemsfx.SearchField;
import javafx.beans.property.BooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.NodeOrientation;
Expand All @@ -25,8 +26,11 @@ public class SearchFieldPopup<T> extends PopupControl {

public static final String DEFAULT_STYLE_CLASS = "search-field-popup";

public SearchFieldPopup(SearchField<T> searchField) {
private final BooleanProperty shouldCommitProperty;

public SearchFieldPopup(SearchField<T> searchField, BooleanProperty shouldCommitProperty) {
this.searchField = Objects.requireNonNull(searchField);
this.shouldCommitProperty = shouldCommitProperty;

minWidthProperty().bind(searchField.widthProperty());

Expand Down Expand Up @@ -104,6 +108,6 @@ private void selectFirstSuggestion() {
}

protected Skin<?> createDefaultSkin() {
return new SearchFieldPopupSkin(this);
return new SearchFieldPopupSkin(this, shouldCommitProperty);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
package com.dlsc.gemsfx.skins;

import com.dlsc.gemsfx.SearchField;
import javafx.beans.property.BooleanProperty;
import javafx.collections.transformation.SortedList;
import javafx.scene.Node;
import javafx.scene.control.ListView;
import javafx.scene.control.Skin;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.util.StringConverter;

Expand All @@ -20,9 +23,10 @@ public class SearchFieldPopupSkin<T> implements Skin<SearchFieldPopup<T>> {
private final SearchFieldPopup<T> control;
private final ListView<T> suggestionList;
private final SearchField<T> searchField;

public SearchFieldPopupSkin(SearchFieldPopup<T> control) {
private BooleanProperty shouldCommit;
public SearchFieldPopupSkin(SearchFieldPopup<T> control, BooleanProperty shouldCommit) {
this.control = control;
this.shouldCommit = shouldCommit;

searchField = control.getSearchField();

Expand Down Expand Up @@ -88,9 +92,23 @@ private Comparator<T> createInnerComparator() {
}

private void registerEventListener() {
suggestionList.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
shouldCommit.set(true);
if (event.getCode() == KeyCode.ENTER || event.getCode() == KeyCode.TAB) {
fireSuggestionSelected();
}
});

suggestionList.setOnMouseClicked((me) -> {
if (me.getButton() == MouseButton.PRIMARY) {
selectItem();
if (me.getClickCount() == 2) {
// hide the popup on double click
control.hide();
} else if (me.getClickCount() == 1) {
shouldCommit.set(true);
selectItem();
fireSuggestionSelected();
}
}
});

Expand All @@ -116,6 +134,14 @@ private void registerEventListener() {

}

private void fireSuggestionSelected() {
Object selectedSuggestion = suggestionList.getSelectionModel().getSelectedItem();
if (selectedSuggestion != null) {
SearchField.SearchEvent searchEvent = SearchField.SearchEvent.createEventForSuggestion(selectedSuggestion);
searchField.fireEvent(searchEvent);
}
}

private void selectItem() {
T selectedItem = suggestionList.getSelectionModel().getSelectedItem();
if (selectedItem != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.dlsc.gemsfx.skins;

import com.dlsc.gemsfx.SearchField;
import com.dlsc.gemsfx.SearchField.SearchFieldListCell;
import javafx.scene.control.SkinBase;

public class SearchFieldSkin<T> extends SkinBase<SearchField<T>> {
Expand Down
Loading