Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,14 @@
import org.controlsfx.control.textfield.AutoCompletionBinding;

/**
* Represents a binding between a text input control and an auto-completion popup
* Represents a binding between a text input control and an auto-completion popup.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great fix!

* This class is a slightly modified version of {@link impl.org.controlsfx.autocompletion.AutoCompletionTextFieldBinding}
* that works with general text input controls instead of just text fields.
* <p>
* Use the {@link Builder} to create instances of this class.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

* </p>
*
* @param <T> the type of the suggestions
*/
public class AutoCompletionTextInputBinding<T> extends AutoCompletionBinding<T> {

Expand All @@ -66,37 +71,28 @@ public class AutoCompletionTextInputBinding<T> extends AutoCompletionBinding<T>
};

/**
* Private constructor to enforce the use of Builder.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you now know, no javadoc for private members.

* Creates a new auto-completion binding between the given textInputControl
* and the given suggestion provider.
*
* @param builder the builder containing all configuration parameters
*/
private AutoCompletionTextInputBinding(final TextInputControl textInputControl,
Callback<ISuggestionRequest, Collection<T>> suggestionProvider) {

this(textInputControl,
suggestionProvider,
AutoCompletionTextInputBinding.defaultStringConverter(),
new ReplaceStrategy());
}

private AutoCompletionTextInputBinding(final TextInputControl textInputControl,
final Callback<ISuggestionRequest, Collection<T>> suggestionProvider,
final StringConverter<T> converter) {
this(textInputControl, suggestionProvider, converter, new ReplaceStrategy());
}

private AutoCompletionTextInputBinding(final TextInputControl textInputControl,
final Callback<ISuggestionRequest, Collection<T>> suggestionProvider,
final StringConverter<T> converter,
final AutoCompletionStrategy inputAnalyzer) {

super(textInputControl, suggestionProvider, converter);
this.converter = converter;
this.inputAnalyzer = inputAnalyzer;
private AutoCompletionTextInputBinding(Builder<T> builder) {
super(builder.textInputControl, builder.suggestionProvider, builder.converter);
this.converter = builder.converter;
this.inputAnalyzer = builder.inputAnalyzer;
this.showOnFocus = builder.showOnFocus;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip: The Problems pane has suggestions of further improvements.

image


getCompletionTarget().textProperty().addListener(textChangeListener);
getCompletionTarget().focusedProperty().addListener(focusChangedListener);
}

/**
* Returns the default string converter that uses toString() for conversion.
*
* @param <T> the type of the suggestions
* @return a default string converter
*/
private static <T> StringConverter<T> defaultStringConverter() {
return new StringConverter<>() {
@Override
Expand All @@ -112,20 +108,86 @@ public T fromString(String string) {
};
}

public static <T> void autoComplete(TextInputControl textArea, Callback<ISuggestionRequest, Collection<T>> suggestionProvider) {
new AutoCompletionTextInputBinding<>(textArea, suggestionProvider);
/**
* Creates a new Builder for constructing AutoCompletionTextInputBinding instances.
*
* @param <T> the type of the suggestions
* @param textInputControl the text input control to bind auto-completion to
* @param suggestionProvider the callback to provide suggestions based on user input
* @return a new Builder instance
*/
public static <T> Builder<T> builder(TextInputControl textInputControl,
Callback<ISuggestionRequest, Collection<T>> suggestionProvider) {
return new Builder<>(textInputControl, suggestionProvider);
}

public static <T> void autoComplete(TextInputControl textArea, Callback<ISuggestionRequest, Collection<T>> suggestionProvider, StringConverter<T> converter) {
new AutoCompletionTextInputBinding<>(textArea, suggestionProvider, converter);
/**
* Convenience method for simple auto-completion setup.
* Equivalent to: {@code builder(textArea, suggestionProvider).build()}
*
* @param <T> the type of the suggestions
* @param textArea the text input control to bind auto-completion to
* @param suggestionProvider the callback to provide suggestions based on user input
* @return a new AutoCompletionTextInputBinding instance
*/
public static <T> AutoCompletionTextInputBinding<T> autoComplete(TextInputControl textArea,
Callback<ISuggestionRequest, Collection<T>> suggestionProvider) {
return builder(textArea, suggestionProvider).build();
}

/**
* Convenience method for auto-completion with custom converter.
* Equivalent to: {@code builder(textArea, suggestionProvider).converter(converter).build()}
*
* @param <T> the type of the suggestions
* @param textArea the text input control to bind auto-completion to
* @param suggestionProvider the callback to provide suggestions based on user input
* @param converter the string converter for suggestion display
* @return a new AutoCompletionTextInputBinding instance
*/
public static <T> AutoCompletionTextInputBinding<T> autoComplete(TextInputControl textArea,
Callback<ISuggestionRequest, Collection<T>> suggestionProvider,
StringConverter<T> converter) {
return builder(textArea, suggestionProvider).converter(converter).build();
}

public static <T> AutoCompletionTextInputBinding<T> autoComplete(TextInputControl textArea, Callback<ISuggestionRequest, Collection<T>> suggestionProvider, StringConverter<T> converter, AutoCompletionStrategy inputAnalyzer) {
return new AutoCompletionTextInputBinding<>(textArea, suggestionProvider, converter, inputAnalyzer);
/**
* Convenience method for auto-completion with custom converter and input analyzer.
* Equivalent to: {@code builder(textArea, suggestionProvider).converter(converter).inputAnalyzer(inputAnalyzer).build()}
*
* @param <T> the type of the suggestions
* @param textArea the text input control to bind auto-completion to
* @param suggestionProvider the callback to provide suggestions based on user input
* @param converter the string converter for suggestion display
* @param inputAnalyzer the strategy for analyzing user input
* @return a new AutoCompletionTextInputBinding instance
*/
public static <T> AutoCompletionTextInputBinding<T> autoComplete(TextInputControl textArea,
Callback<ISuggestionRequest, Collection<T>> suggestionProvider,
StringConverter<T> converter,
AutoCompletionStrategy inputAnalyzer) {
return builder(textArea, suggestionProvider)
.converter(converter)
.inputAnalyzer(inputAnalyzer)
.build();
}

public static <T> AutoCompletionTextInputBinding<T> autoComplete(TextInputControl textArea, Callback<ISuggestionRequest, Collection<T>> suggestionProvider, AutoCompletionStrategy inputAnalyzer) {
return autoComplete(textArea, suggestionProvider, AutoCompletionTextInputBinding.defaultStringConverter(), inputAnalyzer);
/**
* Convenience method for auto-completion with custom input analyzer.
* Equivalent to: {@code builder(textArea, suggestionProvider).inputAnalyzer(inputAnalyzer).build()}
*
* @param <T> the type of the suggestions
* @param textArea the text input control to bind auto-completion to
* @param suggestionProvider the callback to provide suggestions based on user input
* @param inputAnalyzer the strategy for analyzing user input
* @return a new AutoCompletionTextInputBinding instance
*/
public static <T> AutoCompletionTextInputBinding<T> autoComplete(TextInputControl textArea,
Callback<ISuggestionRequest, Collection<T>> suggestionProvider,
AutoCompletionStrategy inputAnalyzer) {
return builder(textArea, suggestionProvider)
.inputAnalyzer(inputAnalyzer)
.build();
}

private void setUserInputText(String newText) {
Expand Down Expand Up @@ -157,10 +219,108 @@ protected void completeUserInput(T completion) {
AutoCompletionInput input = inputAnalyzer.analyze(inputText);
String newText = input.getPrefix() + completionText;
getCompletionTarget().setText(newText);
getCompletionTarget().positionCaret(newText.length());
}

/**
* Sets whether the auto-completion popup should be shown when the control gains focus.
*
* @param showOnFocus true to show popup on focus, false otherwise
*/
public void setShowOnFocus(boolean showOnFocus) {
this.showOnFocus = showOnFocus;
}

/**
* Builder for creating {@link AutoCompletionTextInputBinding} instances.
* This builder allows flexible configuration of auto-completion behavior with a fluent API.
*
* <p>Example usage:</p>
* <pre>{@code
* AutoCompletionTextInputBinding<String> binding =
* AutoCompletionTextInputBinding.<String>builder(textField, suggestionProvider)
* .converter(customConverter)
* .inputAnalyzer(new CustomStrategy())
* .showOnFocus(true)
* .build();
* }</pre>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice

*
* @param <T> the type of the suggestions
*/
public static class Builder<T> {
// Required parameters
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good comments

private final TextInputControl textInputControl;
private final Callback<ISuggestionRequest, Collection<T>> suggestionProvider;

// Optional parameters with default values
private StringConverter<T> converter = defaultStringConverter();
private AutoCompletionStrategy inputAnalyzer = new ReplaceStrategy();
private boolean showOnFocus = false;

/**
* Constructs a new Builder with required parameters.
*
* @param textInputControl the text input control to bind auto-completion to (must not be null)
* @param suggestionProvider the callback to provide suggestions based on user input (must not be null)
*/
public Builder(TextInputControl textInputControl,
Callback<ISuggestionRequest, Collection<T>> suggestionProvider) {
if (textInputControl == null) {
throw new IllegalArgumentException("textInputControl cannot be null");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good checks. Document them in the @throws clause of the javadoc. You can then remove "(must not be null)" from the @param tags.

}
if (suggestionProvider == null) {
throw new IllegalArgumentException("suggestionProvider cannot be null");
}
this.textInputControl = textInputControl;
this.suggestionProvider = suggestionProvider;
}

/**
* Sets the string converter for displaying suggestions.
*
* @param converter the string converter (must not be null)
* @return this Builder instance for method chaining
*/
public Builder<T> converter(StringConverter<T> converter) {
if (converter == null) {
throw new IllegalArgumentException("converter cannot be null");
}
this.converter = converter;
return this;
}

/**
* Sets the input analyzer strategy for processing user input.
*
* @param inputAnalyzer the auto-completion strategy (must not be null)
* @return this Builder instance for method chaining
*/
public Builder<T> inputAnalyzer(AutoCompletionStrategy inputAnalyzer) {
if (inputAnalyzer == null) {
throw new IllegalArgumentException("inputAnalyzer cannot be null");
}
this.inputAnalyzer = inputAnalyzer;
return this;
}

/**
* Sets whether the auto-completion popup should be shown when the control gains focus.
*
* @param showOnFocus true to show popup on focus, false otherwise
* @return this Builder instance for method chaining
*/
public Builder<T> showOnFocus(boolean showOnFocus) {
this.showOnFocus = showOnFocus;
return this;
}

/**
* Builds and returns a new {@link AutoCompletionTextInputBinding} instance
* with the configured parameters.
*
* @return a new AutoCompletionTextInputBinding instance
*/
public AutoCompletionTextInputBinding<T> build() {
return new AutoCompletionTextInputBinding<>(this);
}
}
}
Loading