package examples; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.time.temporal.ChronoUnit; import java.util.Random; import javafx.application.Application; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.TableCell; import javafx.stage.Stage; import syntheticafx.base.RootPane; import syntheticafx.base.SyntheticaFX; import syntheticafx.xtableview.ComparableColumnFilter; import syntheticafx.xtableview.DateColumnFilter; import syntheticafx.xtableview.PatternColumnFilter; import syntheticafx.xtableview.TextFormatterFactory; import syntheticafx.xtableview.XTableColumn; import syntheticafx.xtableview.XTableView; import syntheticafx.xtableview.filter.Boundaries; import syntheticafx.xtableview.filter.ComparableFilterModel; import syntheticafx.xtableview.filter.ComparisonType; import syntheticafx.xtableview.filter.PredicateProvider; import syntheticafx.xtableview.filter.PredicateProvider.SimplePredicateProvider; import syntheticafx.xtableview.filter.RangeType; @SuppressWarnings({ "rawtypes", "unchecked" }) public class XTableCustomMatchRuleDemo extends Application { private PredicateProvider under20 = new SimplePredicateProvider<>((value, matchValue) -> value != null ? value.intValue() < 20 : false, "under 20", true); private PredicateProvider over50 = new SimplePredicateProvider<>((value, matchValue) -> value != null ? value.intValue() > 50 : false, "over 50", true); private Parent createContent() { XTableView table = createTableView(); table.setTableMenuButtonVisible(true); return table; } private XTableView createTableView() { XTableView table = new XTableView<>(Person.persons()); table.setAutoCreateTransformedItems(true); XTableColumn firstNameCol = new XTableColumn<>("First Name"); table.getColumns().addAll(firstNameCol); firstNameCol.setCellValueFactory(c -> c.getValue().firstNameProperty()); firstNameCol.setColumnFilter(new PatternColumnFilter<>()); firstNameCol.setPrefWidth(120); XTableColumn lastNameCol = new XTableColumn<>("Last Name"); table.getColumns().addAll(lastNameCol); lastNameCol.setCellValueFactory(c -> c.getValue().lastNameProperty()); lastNameCol.setColumnFilter(new PatternColumnFilter<>()); lastNameCol.setPrefWidth(120); XTableColumn dateCol = new XTableColumn<>("Birthday"); table.getColumns().addAll(dateCol); // custom rendering for date values dateCol.setCellFactory((column) -> new TableCell(){ @Override protected void updateItem(LocalDate value, boolean empty){ super.updateItem(value, empty); setText(empty || value == null ? "" : value.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM))); } }); dateCol.setCellValueFactory(c -> c.getValue().birthdayProperty()); dateCol.setPrefWidth(150); /* // regular date filter dateCol.setColumnFilter(new DateColumnFilter<>()); // set match rule EQUAL as default dateCol.getColumnFilter().getFilterModel().setMatchRule(ComparisonType.EQUAL); */ // date filter with custom match rules PredicateProvider bornOnSunday = new SimplePredicateProvider<>((value, matchValue) -> value != null ? value.getDayOfWeek() == DayOfWeek.SUNDAY : false, "born on sunday", true); dateCol.setColumnFilter(new DateColumnFilter(new ComparableFilterModel(FXCollections.observableArrayList(ComparisonType.BEFORE, ComparisonType.AFTER, bornOnSunday)))); PredicateProvider daysAroundRule = createDaysAroundRule(10); dateCol.getColumnFilter().getFilterModel().getMatchRules().add(daysAroundRule); // set 'days around' match rule as default dateCol.getColumnFilter().getFilterModel().setMatchRule(daysAroundRule); XTableColumn ageCol = new XTableColumn<>("Age"); table.getColumns().addAll(ageCol); // create calculated data column ageCol.setCellValueFactory(c -> { LocalDate birthday = c.getValue().getBirthday(); return new SimpleObjectProperty(birthday != null ? (int) ChronoUnit.YEARS.between(birthday, LocalDate.now()) : null); }); ObservableList rules = FXCollections.observableArrayList(ComparisonType.values()); rules.addAll(under20, over50); ageCol.setColumnFilter(new ComparableColumnFilter(new ComparableFilterModel(rules), TextFormatterFactory.INTEGER_TEXTFORMATTER_FACTORY)); // set 'greater than' match rule as default ageCol.getColumnFilter().getFilterModel().setMatchRule(ComparisonType.AFTER); ageCol.setPrefWidth(120); return table; } private PredicateProvider createDaysAroundRule(int yearsAround) { return new SimplePredicateProvider<>((value, matchValue) -> { LocalDate lower = matchValue.minusYears(yearsAround); LocalDate upper = matchValue.plusYears(yearsAround); return RangeType.ALL_INCLUSIVE.asBiPredicate().test(value, new Boundaries<>(lower, upper)); }, "+/- " + yearsAround + " years"); } @Override public void start(Stage primaryStage) throws Exception { SyntheticaFX.init("syntheticafx.theme.modena.SyntheticaFXModena"); //SyntheticaFX.init("syntheticafx.theme.standard.SyntheticaFXStandard"); primaryStage.setScene(new Scene(new RootPane(primaryStage, createContent()), 800, 400)); primaryStage.setTitle(getClass().getSimpleName()); primaryStage.show(); } public static void main(String[] args) { launch(args); } /**************************************************************************** * * Data Class * /**************************************************************************/ public static class Person { private final SimpleStringProperty firstName; private final SimpleStringProperty lastName; private final SimpleStringProperty email; private final SimpleStringProperty secondaryMail; private final SimpleObjectProperty birthday; public Person(String fName, String lName, String email, LocalDate birthday) { this.firstName = new SimpleStringProperty(fName); this.lastName = new SimpleStringProperty(lName); this.email = new SimpleStringProperty(email); this.secondaryMail = new SimpleStringProperty("xx" + email); this.birthday = new SimpleObjectProperty<>(birthday); } public Person(String fName, String lName, String email) { this(fName, lName, email, null); } public String getFirstName() { return firstName.get(); } public void setFirstName(String fName) { firstName.set(fName); } public StringProperty firstNameProperty() { return firstName; } public String getLastName() { return lastName.get(); } public void setLastName(String fName) { lastName.set(fName); } public StringProperty lastNameProperty() { return lastName; } public String getEmail() { return email.get(); } public void setEmail(String fName) { email.set(fName); } public StringProperty emailProperty() { return email; } public String getSecondaryMail() { return secondaryMailProperty().get(); } public void setSecondaryMail(String mail) { secondaryMailProperty().set(mail); } public StringProperty secondaryMailProperty() { return secondaryMail; } public ObjectProperty birthdayProperty() { return birthday; } public LocalDate getBirthday() { return birthdayProperty().get(); } public void setBirthday(LocalDate birthday) { birthdayProperty().set(birthday); } @Override public String toString() { return getLastName() + ", " + getFirstName(); } public static ObservableList persons() { return FXCollections.observableArrayList( new Person("Antony", "Jacobs", "antony.jacobs@example.com", createRandomDate(36500)), new Person("Joe", "Bell", "joe.bell@example.com", createRandomDate(36500)), new Person("Jacob", "Smith", "jacob.smith@example.com", createRandomDate(36500)), new Person("Isabella", "Johnson", "isabella.johnson@example.com", createRandomDate(36500)), new Person("Ethan", "Williams", "ethan.williams@example.com", createRandomDate(36500)), new Person("Emma", "Jones", "emma.jones@example.com", createRandomDate(36500)), new Person("Lucinda", "Micheals", "lucinda.micheals@example.com", createRandomDate(36500)), new Person("Michael", "Brown", "michael.brown@example.com", createRandomDate(36500)), new Person("Barbara", "Pope", "barbara.pope@example.com", createRandomDate(36500)), new Person("Penelope", "Rooster", "penelope.rooster@example.com", createRandomDate(36500)), new Person("Raphael", "Adamson", "raphael.adamson@example.com", createRandomDate(36500))); } private static LocalDate createRandomDate(int dayRangeFromNow) { LocalDate date = LocalDate.now(); int daysBefore = new Random().nextInt(dayRangeFromNow); return date.minusDays(daysBefore); } } }