🐛 Fix inconsistent filters (#313)

Signed-off-by: palexdev <alessandro.parisi406@gmail.com>
This commit is contained in:
palexdev 2023-11-13 12:54:42 +01:00
parent 6a6b5b5675
commit 7aa2c5330f
4 changed files with 39 additions and 40 deletions

View File

@ -2,9 +2,9 @@ import io.github.palexdev.materialfx.controls.MFXButton;
import io.github.palexdev.materialfx.controls.MFXContextMenu;
import io.github.palexdev.materialfx.controls.MFXContextMenuItem;
import io.github.palexdev.materialfx.factories.InsetsFactory;
import io.github.palexdev.mfxresources.fonts.MFXFontIcon;
import io.github.palexdev.materialfx.utils.ColorUtils;
import io.github.palexdev.materialfx.utils.StringUtils;
import io.github.palexdev.mfxresources.fonts.fontawesome.FontAwesomeSolid;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
@ -24,10 +24,10 @@ public class ContextTest extends Application {
Label labelSeparator = new Label("Separator");
labelSeparator.setPadding(InsetsFactory.of(5, 3, 5, 0));
menu.addSeparator(labelSeparator);
menu.addItem(new MFXContextMenuItem("Separated Item", MFXFontIcon.getRandomIcon(12, ColorUtils.getRandomColor())));
menu.addItem(new MFXContextMenuItem("Separated Item", FontAwesomeSolid.random(ColorUtils.getRandomColor(), 12)));
menu.addLineSeparator(MFXContextMenu.Builder.getLineSeparator());
menu.addItem(new MFXContextMenuItem("LSeparated Item", MFXFontIcon.getRandomIcon(12, ColorUtils.getRandomColor())));
menu.addItem(new MFXContextMenuItem("LSeparated Item", FontAwesomeSolid.random(ColorUtils.getRandomColor(), 12)));
menu.install();
@ -40,7 +40,7 @@ public class ContextTest extends Application {
private void populateMenu(MFXContextMenu menu, int num) {
MFXContextMenuItem[] items = new MFXContextMenuItem[num];
for (int i = 0; i < num; i++) {
MFXContextMenuItem item = new MFXContextMenuItem("Menu Item " + (i + 1), MFXFontIcon.getRandomIcon(12, ColorUtils.getRandomColor()));
MFXContextMenuItem item = new MFXContextMenuItem("Menu Item " + (i + 1), FontAwesomeSolid.random(ColorUtils.getRandomColor(), 12));
item.setAccelerator("Alt + " + StringUtils.randAlphabetic(1).toUpperCase());
items[i] = item;
}

View File

@ -1,35 +1,26 @@
import io.github.palexdev.materialfx.controls.MFXComboBox;
import io.github.palexdev.materialfx.controls.MFXTableColumn;
import io.github.palexdev.materialfx.controls.MFXTableView;
import io.github.palexdev.materialfx.controls.cell.MFXTableRowCell;
import io.github.palexdev.materialfx.demo.model.Model;
import io.github.palexdev.materialfx.demo.model.Person;
import io.github.palexdev.materialfx.filter.IntegerFilter;
import io.github.palexdev.materialfx.filter.StringFilter;
import io.github.palexdev.materialfx.theming.CSSFragment;
import io.github.palexdev.materialfx.theming.JavaFXThemes;
import io.github.palexdev.materialfx.theming.MaterialFXStylesheets;
import io.github.palexdev.materialfx.theming.UserAgentBuilder;
import io.github.palexdev.mfxcore.builders.InsetsBuilder;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Reproducer extends Application {
@Override
public void start(Stage stage) throws Exception {
VBox box = new VBox(20);
box.setAlignment(Pos.TOP_CENTER);
box.setPadding(new Insets(20));
UserAgentBuilder.builder()
.themes(JavaFXThemes.MODENA)
.themes(MaterialFXStylesheets.forAssemble(true))
.setResolveAssets(true)
.setDeploy(true)
.build()
.setGlobal();
StackPane pane = new StackPane();
pane.setPadding(InsetsBuilder.all(10));
MFXTableView<Person> table = new MFXTableView<>(Model.people);
MFXTableColumn<Person> name = new MFXTableColumn<>("Name");
@ -39,7 +30,14 @@ public class Reproducer extends Application {
MFXTableColumn<Person> age = new MFXTableColumn<>("Age");
age.setRowCellFactory(p -> new MFXTableRowCell<>(Person::getAge));
table.getTableColumns().addAll(name, surname, age);
box.getChildren().add(table);
pane.getChildren().add(table);
table.setMinSize(400.0, 400.0);
table.getFilters().addAll(
new StringFilter<>("Name", Person::getName),
new StringFilter<>("Surname", Person::getSurname),
new IntegerFilter<>("Age", Person::getAge)
);
CSSFragment.Builder.build()
.addSelector(".mfx-filter-pane")
@ -47,15 +45,14 @@ public class Reproducer extends Application {
.closeSelector()
.applyOn(table);
MFXComboBox<String> combo = new MFXComboBox<>(Model.strings);
box.getChildren().add(combo);
CSSFragment.Builder.build()
.addSelector(".mfx-combo-box .combo-popup .virtual-flow")
.addStyle("-fx-background-color: gold")
.closeSelector()
.applyOn(combo);
Scene scene = new Scene(box, 400, 400);
UserAgentBuilder.builder()
.themes(JavaFXThemes.MODENA)
.themes(MaterialFXStylesheets.forAssemble(false))
.setResolveAssets(true)
.setDeploy(true)
.build()
.setGlobal();
Scene scene = new Scene(pane, 600, 600);
stage.setScene(scene);
stage.show();
}

View File

@ -31,7 +31,7 @@ import java.util.function.Predicate;
* It wraps the following data:
* <p> - A String which is the query
* <p> - An object of type {@link AbstractFilter}, which is effectively responsible for producing the {@link Predicate}
* <p> - A {@link BiPredicateBean}, which is used by {@link AbstractFilter}, see {@link AbstractFilter#predicateFor(String)} or {@link AbstractFilter#predicateFor(String, BiPredicate)}
* <p> - A {@link BiPredicateBean}, which is used by {@link AbstractFilter}, see {@link AbstractFilter#predicateFor(String, FilterBean)}
* <p> - A {@link ChainMode} enumeration to specify how this filter should be combined with other filters
*
* @param <T> the type of objects to filter
@ -65,10 +65,10 @@ public class FilterBean<T, U> {
//================================================================================
/**
* Calls {@link AbstractFilter#predicateFor(String)} with the query specified by this bean.
* Calls {@link AbstractFilter#predicateFor(String, FilterBean)} with the query specified by this bean.
*/
public Predicate<T> predicate() {
return filter.predicateFor(query);
return filter.predicateFor(query, this);
}
/**

View File

@ -43,7 +43,7 @@ import java.util.function.Predicate;
* To make the filter system flexible and yet highly specialized, every implementation must specify a
* {@link StringConverter} which is used to convert the query to an object of type U.
* <p></p>
* At this point we have all the basic elements to describe how the {@link Predicate} is predicate is produced.
* At this point we have all the basic elements to describe how the {@link Predicate} is produced.
* Every implementation of this base class has some predefined {@link BiPredicate} which operate on U objects.
* The query is converted to an object of type U, and the extractor gets the U field from a T object, both U
* objects are fed to the {@link BiPredicate}. In code:
@ -131,6 +131,12 @@ public abstract class AbstractFilter<T, U> {
* return t -> biPredicate.test(extractor.apply(t), convertedQuery);
* }
* </pre>
* <p></p>
* <b>WARN:</b> this method should not be used to convert {@link FilterBean}s to {@link Predicate}.
* A {@link FilterBean} already has a {@link BiPredicate} that specifies its filter behavior. This method instead
* selects a {@link BiPredicate} according to the value of {@link #selectedPredicateIndexProperty()}, which may have
* changed since the creation of the {@link FilterBean}, leading to another filter being used instead.
* For this reason, use {@link #predicateFor(String, FilterBean)} instead.
*/
public Predicate<T> predicateFor(String input) {
checkIndex();
@ -153,15 +159,11 @@ public abstract class AbstractFilter<T, U> {
* }
* </pre>
* <p></p>
* <b>WARN:</b> to be honest this method should have been removed but I wanted to keep it
* since it adds some flexibility to the filter system. Note that using this method may lead
* to inconsistencies in UI controls since the given argument is not a {@link BiPredicateBean},
* which means that it won't be added to the predicates list of this filter, and the selected predicate index
* property won't be updated. This also means that any other method that relies on that index will fail.
* This is used by {@link FilterBean}s to convert themselves into a {@link Predicate}.
*/
public Predicate<T> predicateFor(String input, BiPredicate<U, U> biPredicate) {
public Predicate<T> predicateFor(String input, FilterBean<T, U> bean) {
U convertedInput = getValue(input);
return t -> biPredicate.test(extractor.apply(t), convertedInput);
return t -> bean.getPredicateBean().predicate().test(extractor.apply(t), convertedInput);
}
/**