Filter In Javafx
package com.ibadmin.control.tablefilter;
import java.util.Optional;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
/**
* Applies a filtering control to a provided {@link TableView} instance. The filter will be applied immediately on construction, and can be
* made visible by right-clicking the desired column to filter on. <br>
* <br>
* <b>Features</b><br>
* -Convenient filter control holds a checklist of distinct items to include/exclude, much like an Excel filter.<br>
* -New/removed records will be captured by the filter control and reflect new or removed values from checklist. -Filters on more than one
* column are combined to only display mutually inclusive records on the client's TableView.
*
* @param <T>
*/
public final class TableFilter<T> {
private final TableView<T> tableView;
/**
* TODO Please rename this to some understandable name!!!
*/
private final ObservableList<T> backingList;
private final FilteredList<T> filteredList;
private final SortedList<T> sortedControlList;
private boolean parentSearchEnable = false;
BooleanProperty clearButtonDisabledProperty = new SimpleBooleanProperty(true);
private final ObservableList<ColumnFilter<T, ?>> columnFilters = FXCollections.observableArrayList();
/**
* Constructor applies a filtering control to the provided {@link TableView} instance.
*
* @param tableView
*/
public TableFilter(TableView<T> tableView, ObservableList<T> sourceList) {
this.tableView = tableView;
// sourceList passed here is the FilteredList from the Repository Controller. FilteredList has its source as the originalReferenceList
backingList = sourceList;
filteredList = new FilteredList<>(backingList);
sortedControlList = new SortedList<>(filteredList);
// initially display full list without filters
filteredList.setPredicate(v -> true);
sortedControlList.comparatorProperty().bind(tableView.comparatorProperty());
tableView.setItems(sortedControlList);
applyForAllColumns();
columnFilters.forEach(ColumnFilter::initialize);
}
/**
* Allows specifying a different behavior for the search box on the TableFilter. By default, the contains() method on a String is used to
* evaluate the search box input to qualify the distinct filter values. But you can specify a different behavior by providing a simple
* BiPredicate argument to this method. The BiPredicate argument allows you take the input value and target value and use a lambda to
* evaluate a boolean. For instance, you can implement a comparison by assuming the input value is a regular expression, and call
* matches() on the target value to see if it aligns to the pattern.
*
* @param searchStrategy
*/
public void setSearchStrategy(BiPredicate<String, String> searchStrategy) {
columnFilters.forEach(cf -> cf.setSearchStrategy(searchStrategy));
}
/**
* Returns the backing {@link ObservableList} originally provided to the constructor.
*
* @return ObservableList
*/
public ObservableList<T> getBackingList() {
return backingList;
}
/**
* Returns the {@link FilteredList} used by this TableFilter and is backing the {@link TableView}.
*
* @return FilteredList
*/
public FilteredList<T> getFilteredList() {
return filteredList;
}
/**
* @treatAsPrivate
*/
private void applyForAllColumns() {
columnFilters.setAll(this.tableView.getColumns().stream().map(c -> new ColumnFilter<>(this, c)).collect(Collectors.toList()));
}
public void executeFilter() {
if (columnFilters.stream().filter(ColumnFilter::isFiltered).findAny().isPresent()) {
filteredList.setPredicate(item -> !columnFilters.stream().filter(cf -> !cf.evaluate(item)).findAny().isPresent());
clearButtonDisabledProperty.setValue(filteredList.equals(backingList));
} else {
resetFilter();
}
}
public void resetFilter() {
filteredList.setPredicate(item -> true);
}
/**
* @treatAsPrivate
*/
public TableView<T> getTableView() {
return tableView;
}
/**
* @treatAsPrivate
*/
public ObservableList<ColumnFilter<T, ?>> getColumnFilters() {
return columnFilters;
}
/**
* @treatAsPrivate
*/
public Optional<ColumnFilter<T, ?>> getColumnFilter(TableColumn<T, ?> tableColumn) {
return columnFilters.stream().filter(f -> f.getTableColumn().equals(tableColumn)).findAny();
}
public boolean isDirty() {
return columnFilters.stream().filter(ColumnFilter::isFiltered).findAny().isPresent();
}
public boolean containsIgnoreCase(final String str, final String searchStr) {
if (str == null || searchStr == null) {
return false;
}
final int len = searchStr.length();
final int max = str.length() - len;
for (int i = 0; i <= max; i++) {
if (str.regionMatches(true, i, searchStr, 0, len)) {
return true;
}
}
return false;
}
public void clearAllFilters() {
columnFilters.stream().forEach(cf -> cf.resetAllFilters());
columnFilters.stream().forEach(cf -> {
if (!(cf.getTableColumn().getGraphic() != null && cf.getTableColumn().getGraphic() instanceof CheckBox))
cf.getTableColumn().setGraphic(null);
});
clearButtonDisabledProperty.setValue(true);
}
public boolean isParentSearchEnable() {
return parentSearchEnable;
}
public void setParentSearchEnable(boolean parentSearchEnable) {
this.parentSearchEnable = parentSearchEnable;
}
//DEV-5207 New IBAdmin:Issues in Search in Repo UI in New Admin
public BooleanProperty getClearButtonDisabledProperty() {
return clearButtonDisabledProperty;
}
// DEV-5207 END
}
import java.util.Optional;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
/**
* Applies a filtering control to a provided {@link TableView} instance. The filter will be applied immediately on construction, and can be
* made visible by right-clicking the desired column to filter on. <br>
* <br>
* <b>Features</b><br>
* -Convenient filter control holds a checklist of distinct items to include/exclude, much like an Excel filter.<br>
* -New/removed records will be captured by the filter control and reflect new or removed values from checklist. -Filters on more than one
* column are combined to only display mutually inclusive records on the client's TableView.
*
* @param <T>
*/
public final class TableFilter<T> {
private final TableView<T> tableView;
/**
* TODO Please rename this to some understandable name!!!
*/
private final ObservableList<T> backingList;
private final FilteredList<T> filteredList;
private final SortedList<T> sortedControlList;
private boolean parentSearchEnable = false;
BooleanProperty clearButtonDisabledProperty = new SimpleBooleanProperty(true);
private final ObservableList<ColumnFilter<T, ?>> columnFilters = FXCollections.observableArrayList();
/**
* Constructor applies a filtering control to the provided {@link TableView} instance.
*
* @param tableView
*/
public TableFilter(TableView<T> tableView, ObservableList<T> sourceList) {
this.tableView = tableView;
// sourceList passed here is the FilteredList from the Repository Controller. FilteredList has its source as the originalReferenceList
backingList = sourceList;
filteredList = new FilteredList<>(backingList);
sortedControlList = new SortedList<>(filteredList);
// initially display full list without filters
filteredList.setPredicate(v -> true);
sortedControlList.comparatorProperty().bind(tableView.comparatorProperty());
tableView.setItems(sortedControlList);
applyForAllColumns();
columnFilters.forEach(ColumnFilter::initialize);
}
/**
* Allows specifying a different behavior for the search box on the TableFilter. By default, the contains() method on a String is used to
* evaluate the search box input to qualify the distinct filter values. But you can specify a different behavior by providing a simple
* BiPredicate argument to this method. The BiPredicate argument allows you take the input value and target value and use a lambda to
* evaluate a boolean. For instance, you can implement a comparison by assuming the input value is a regular expression, and call
* matches() on the target value to see if it aligns to the pattern.
*
* @param searchStrategy
*/
public void setSearchStrategy(BiPredicate<String, String> searchStrategy) {
columnFilters.forEach(cf -> cf.setSearchStrategy(searchStrategy));
}
/**
* Returns the backing {@link ObservableList} originally provided to the constructor.
*
* @return ObservableList
*/
public ObservableList<T> getBackingList() {
return backingList;
}
/**
* Returns the {@link FilteredList} used by this TableFilter and is backing the {@link TableView}.
*
* @return FilteredList
*/
public FilteredList<T> getFilteredList() {
return filteredList;
}
/**
* @treatAsPrivate
*/
private void applyForAllColumns() {
columnFilters.setAll(this.tableView.getColumns().stream().map(c -> new ColumnFilter<>(this, c)).collect(Collectors.toList()));
}
public void executeFilter() {
if (columnFilters.stream().filter(ColumnFilter::isFiltered).findAny().isPresent()) {
filteredList.setPredicate(item -> !columnFilters.stream().filter(cf -> !cf.evaluate(item)).findAny().isPresent());
clearButtonDisabledProperty.setValue(filteredList.equals(backingList));
} else {
resetFilter();
}
}
public void resetFilter() {
filteredList.setPredicate(item -> true);
}
/**
* @treatAsPrivate
*/
public TableView<T> getTableView() {
return tableView;
}
/**
* @treatAsPrivate
*/
public ObservableList<ColumnFilter<T, ?>> getColumnFilters() {
return columnFilters;
}
/**
* @treatAsPrivate
*/
public Optional<ColumnFilter<T, ?>> getColumnFilter(TableColumn<T, ?> tableColumn) {
return columnFilters.stream().filter(f -> f.getTableColumn().equals(tableColumn)).findAny();
}
public boolean isDirty() {
return columnFilters.stream().filter(ColumnFilter::isFiltered).findAny().isPresent();
}
public boolean containsIgnoreCase(final String str, final String searchStr) {
if (str == null || searchStr == null) {
return false;
}
final int len = searchStr.length();
final int max = str.length() - len;
for (int i = 0; i <= max; i++) {
if (str.regionMatches(true, i, searchStr, 0, len)) {
return true;
}
}
return false;
}
public void clearAllFilters() {
columnFilters.stream().forEach(cf -> cf.resetAllFilters());
columnFilters.stream().forEach(cf -> {
if (!(cf.getTableColumn().getGraphic() != null && cf.getTableColumn().getGraphic() instanceof CheckBox))
cf.getTableColumn().setGraphic(null);
});
clearButtonDisabledProperty.setValue(true);
}
public boolean isParentSearchEnable() {
return parentSearchEnable;
}
public void setParentSearchEnable(boolean parentSearchEnable) {
this.parentSearchEnable = parentSearchEnable;
}
//DEV-5207 New IBAdmin:Issues in Search in Repo UI in New Admin
public BooleanProperty getClearButtonDisabledProperty() {
return clearButtonDisabledProperty;
}
// DEV-5207 END
}
USE :
Platform.runLater(new Runnable() {
@Override
public void run() {
repositoryTableFilter = new TableFilter<GenerationForRepoProperty>(repositoryTableView, filteredGenerationForRepoList);
clearAllFiltersButton.disableProperty().bind(repositoryTableFilter.getClearButtonDisabledProperty());
repositoryTableFilter.setSearchStrategy((input, target) -> {
try {
return repositoryTableFilter.containsIgnoreCase(target, input);
} catch (Exception e) {
return false;
}
});
}
});
This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDelete