Filtered ObservableList of properties in JavaFX

Viewed 78

I do have a class:

class Person {
    private SimpleBooleanProperty graph = new SimpleBooleanProperty(false);
    private XYChart.Series<Date, Number> series = new XYChart.Series<>();

    public boolean isGraph() {
        return graph.get();
    }

    public XYChart.Series<Date, Number> getSeries() {
        return series;
    }
}

which has an extractor of a boolean graphProperty

private Callback<Person, Observable[]> extractor = person -> new Observable[] {
    person.graphProperty(),
};

For showing the series on a XYChart i now need an observable list of all series which have the graph property enabled like:

    ObservableList<XYChart.Series<Date, Number>> filteredSeries = persons
        .filtered(Person::isGraph)
        .stream()
        .map(Person::getSeries)
        .collect(Collectors.toCollection(FXCollections::observableArrayList));

Unfortunatly the FXCollections::observableArrayList is not backed by the person list. So the question is how do I create a correct ObservableList<XYChart.Series<Date, Number> of the person list?

Update:

I tried getting a filted list from persons by

FilteredList<Person> graphedPersons = new FilteredList<>(persons);
graphedPersons.setPredicate(Person::isGraph);

As @kleopatra suggested I then tried wrapping graphedPersons in a TranformationList:

ObservableList<XYChart.Series<Date, Number>> graphedSeries = new TransformationList<XYChart.Series<Date, Number>, Person>() {

    @Override
    public int size() {
        return getSource().size();
    }

    @Override
    public XYChart.Series<Date, Number> get(int index) {
       return getSource().get(index).getSeries();
    }

    @Override
    protected void sourceChanged(ListChangeListener.Change<? extends Person> c) {

    }

    @Override
    public int getSourceIndex(int index) {
        return index;
    }
};

The chart does not show anything.

1 Answers

The solution is as @klepatra suggested wrapping a filted listin a TransformationList

FilteredList<Person> graphedPersons = new FilteredList<>(persons);
graphedPersons.setPredicate(Person::isGraph);

Transformation List

ObservableList<XYChart.Series<Date, Number>> graphedSeries = new TransformationList<XYChart.Series<Date, Number>, Person>(graphedPersons) {

    @Override
    public int size() {
        return getSource().size();
    }

    @Override
    public XYChart.Series<Date, Number> get(int index) {
        return getSource().get(index).getSeries();
    }

    @Override
    protected void sourceChanged(ListChangeListener.Change<? extends Person> c) {
        beginChange();
        while (c.next()) {
            if (c.wasReplaced()) {
                nextReplace(c.getFrom(), c.getTo(), c.getRemoved().stream().map(Person::getSeries).collect(Collectors.toList()));
            } else if (c.wasRemoved()) {
                nextRemove(c.getFrom(), c.getRemoved().stream().map(Person::getSeries).collect(Collectors.toList()));
            } else if (c.wasAdded()) {
                nextAdd(c.getFrom(), c.getTo());
            }
        }
        endChange();
    }

    @Override
    public int getSourceIndex(int index) {
        return index;
    }
};
Related