package bluej.utility.javafx;
import java.util.ArrayList;
import java.util.List;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import threadchecker.OnThread;
import threadchecker.Tag;
| Created by neil on 11/06/2016.
|
@OnThread(Tag.FXPlatform)
public class GrowableList<T extends Node>{
private final FXPlatformSupplier<T> newNodeFactory;
private final List<T> items = new ArrayList<T>();
private final ObservableList<Node> inclButtons = FXCollections.observableArrayList();
public GrowableList(FXPlatformSupplier<T> newNodeFactory)
{
this.newNodeFactory = newNodeFactory;
inclButtons.setAll(makePlusButton());
addNewItem(0);
}
private Node makeCrossButton()
{
Button button = JavaFXUtil.withStyleClass(new Button(), "growable-remove");
button.setGraphic(JavaFXUtil.withStyleClass(new Region(), "growable-remove-graphic"));
button.setOnAction(e -> {
int index = inclButtons.indexOf(button);
removeItem((index - 2) / 3);
});
button.addEventFilter(MouseEvent.MOUSE_ENTERED, e -> {
setRemoveHighlight(button, true
/*Always turn on
;
});
button.addEventFilter(MouseEvent.MOUSE_EXITED, e -> {
setRemoveHighlight(button, button.isFocused()
| Keep only if focused
|
;
});
JavaFXUtil.addFocusListener(button, focus -> setRemoveHighlight(button, focus));
HangingFlowPane.setBreakBefore(button, false);
return button;
}
private void setRemoveHighlight(Button button, boolean on)
{
int index = inclButtons.indexOf(button);
if (index != -1)
JavaFXUtil.setPseudoclass("bj-growable-remove-highlight", on, inclButtons.get(index - 1));
}
private void removeItem(int index)
{
items.remove(index);
inclButtons.remove(index * 3 + 3);
inclButtons.remove(index * 3 + 2);
inclButtons.remove(index * 3 + 1);
}
private Node makePlusButton()
{
Button button = JavaFXUtil.withStyleClass(new Button(), "growable-add");
button.setGraphic(JavaFXUtil.withStyleClass(new Region(), "growable-add-graphic"));
button.setOnAction(e -> {
int index = inclButtons.indexOf(button);
addNewItem(index / 3);
});
HangingFlowPane.setBreakBefore(button, true);
HangingFlowPane.setMargin(button, new Insets(0, 0, 0, 8));
return button;
}
private void addNewItem(int itemIndex)
{
T newItem = newNodeFactory.get();
HangingFlowPane.setBreakBefore(newItem, false);
items.add(itemIndex, newItem);
inclButtons.add(itemIndex * 3 + 1, newItem);
inclButtons.add(itemIndex * 3 + 2, makeCrossButton());
inclButtons.add(itemIndex * 3 + 3, makePlusButton());
}
public T getItem(int index)
{
return items.get(index);
}
public ObservableList extends Node> getNodes()
{
return inclButtons;
}
public int size()
{
return items.size();
}
}
. GrowableList
. makeCrossButton
. setRemoveHighlight
. removeItem
. makePlusButton
. addNewItem
. getItem
. getNodes
. size
129 neLoCode
+ 3 LoComm