package org.phoenicis.javafx.views.common;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.transformation.TransformationList;
import java.util.stream.IntStream;
/**
* This class combines an {@link ObservableList} and a number of non exchangeable objects called <code>others</code> to a single {@link ObservableList}.
* These <code>others</code> are prepended to the given {@link ObservableList}.
*
* @author marc
* @since 26.04.17
*/
public class AdhocList<E> extends TransformationList<E, E> {
/**
* An array containing a number of objects that are prepended to the {@link ObservableList} <code>source</code>
*/
private E[] others;
/**
* Constructor
*
* @param source An observable list which should be part of this list
* @param others A number of objects of the same type as <code>source</code> that should be prepended to <code>source</code>
*/
public AdhocList(ObservableList<? extends E> source, E... others) {
super(source);
this.others = others;
}
@Override
public int getSourceIndex(int index) {
return index - others.length;
}
@Override
public E get(int index) {
if (index < others.length) {
return others[index];
} else {
return getSource().get(index - others.length);
}
}
@Override
public int size() {
return others.length + getSource().size();
}
@Override
protected void sourceChanged(ListChangeListener.Change<? extends E> c) {
beginChange();
while (c.next()) {
if (c.wasPermutated()) {
permutate(c);
} else if (c.wasUpdated()) {
update(c);
} else {
addRemove(c);
}
}
endChange();
}
private void permutate(ListChangeListener.Change<? extends E> c) {
int from = c.getFrom();
int to = c.getTo();
if (to > from) {
int[] perm = IntStream.range(0, size()).toArray();
for (int i = from; i < to; ++i) {
perm[i + others.length] = c.getPermutation(i) + others.length;
}
nextPermutation(from, to, perm);
}
}
private void update(ListChangeListener.Change<? extends E> c) {
int from = c.getFrom();
int to = c.getTo();
if (to > from) {
for (int i = from; i < to; ++i) {
nextUpdate(i + others.length);
}
}
}
private void addRemove(ListChangeListener.Change<? extends E> c) {
int from = c.getFrom();
int to = c.getTo();
nextRemove(from + others.length, c.getRemoved());
nextAdd(from + others.length, from + c.getAddedSize() + others.length);
}
}