@SuppressWarnings("unchecked")
public <T> HBox beanTF(String path, String selectionPath, String itemPath,
final Class<?> itemType, final int maxChars,
Class<? extends Control> controlType, final String restictTo,
T... choices) {
HBox box = new HBox();
Control ctrl;
if (controlType == CheckBox.class) {
CheckBox cb = new CheckBox();
// POJO binding magic...
personPA.bindBidirectional(path, cb.selectedProperty());
ctrl = cb;
} else if (controlType == ComboBox.class) {
ComboBox<T> cb = new ComboBox<>(
FXCollections.observableArrayList(choices));
cb.setPromptText("Select");
cb.setPrefWidth(100d);
// POJO binding magic (due to erasure of T in
// ObjectProperty<T> of cb.valueProperty() we need
// to also pass in the choice class)
personPA.bindBidirectional(path, cb.valueProperty(),
(Class<T>) choices[0].getClass());
ctrl = cb;
} else if (controlType == ListView.class) {
ListView<T> lv = new ListView<>(
FXCollections.observableArrayList(choices));
lv.setEditable(true);
lv.setMaxHeight(100d);
lv.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
// POJO binding magic (due to erasure of T in
// ObservableList<T> of lv.getItems() we need
// to also pass in the choice class)
personPA.bindContentBidirectional(path, itemPath, itemType,
lv.getItems(), (Class<T>) choices[0].getClass(), null, null);
if (selectionPath != null && !selectionPath.isEmpty()) {
// POJO binding magic (due to erasure of T in
// ReadOnlyUnbackedObservableList<T> of
// lv.getSelectionModel().getSelectedItems() we need
// to also pass in the choice class as well as the
// SelectionModel<T> of lv.getSelectionModel() so that updates
// to the ReadOnlyUnbackedObservableList<T> can be updated)
personPA.bindContentBidirectional(selectionPath, itemPath,
itemType, lv.getSelectionModel().getSelectedItems(),
(Class<T>) choices[0].getClass(),
lv.getSelectionModel(), path);
}
// personPA.bindBidirectional(path, lv.itemsProperty(),
// (Class<T>) choices[0].getClass());
ctrl = lv;
} else if (controlType == Slider.class) {
Slider sl = new Slider();
sl.setShowTickLabels(true);
sl.setShowTickMarks(true);
sl.setMajorTickUnit(maxChars / 2);
sl.setMinorTickCount(7);
sl.setBlockIncrement(1);
sl.setMax(maxChars + 1);
sl.setSnapToTicks(true);
// POJO binding magic...
personPA.bindBidirectional(path, sl.valueProperty());
ctrl = sl;
} else if (controlType == PasswordField.class) {
final PasswordField tf = new PasswordField() {
@Override
public void replaceText(int start, int end, String text) {
if (matchTest(text)) {
super.replaceText(start, end, text);
}
}
@Override
public void replaceSelection(String text) {
if (matchTest(text)) {
super.replaceSelection(text);
}
}
private boolean matchTest(String text) {
return text.isEmpty()
|| (text.matches(restictTo) && (getText() == null || getText()
.length() < maxChars));
}
};
// POJO binding magic...
personPA.bindBidirectional(path, tf.textProperty());
ctrl = tf;
} else {
final TextField tf = controlType == PasswordField.class ? new PasswordField() {
@Override
public void replaceText(int start, int end, String text) {
if (matchTest(text)) {
super.replaceText(start, end, text);
}
}
@Override
public void replaceSelection(String text) {
if (matchTest(text)) {
super.replaceSelection(text);
}
}
private boolean matchTest(String text) {
return text.isEmpty()
|| (text.matches(restictTo) && (getText() == null || getText()
.length() < maxChars));
}
}
: new TextField() {
@Override
public void replaceText(int start, int end, String text) {
if (matchTest(text)) {
super.replaceText(start, end, text);
}
}
@Override
public void replaceSelection(String text) {
if (matchTest(text)) {
super.replaceSelection(text);
}
}
private boolean matchTest(String text) {
return text.isEmpty()
|| (text.matches(restictTo) && (getText() == null || getText()
.length() < maxChars));
}
};
// POJO binding magic...
personPA.bindBidirectional(path, tf.textProperty());
ctrl = tf;
}
box.getChildren()
.addAll(new Label(
path
+ (selectionPath != null
&& !selectionPath.isEmpty() ? " (items) = \n"
+ selectionPath + " (selected) = "