I am working on a project where we use a SpreadSheetView component in the controlsfx library and we display a SearchableComboBox inside a SpreadSheetCell.
Everything is working well expect when we go from a the previous cell to the next that contains a SearchableComboBox using the tab key and press some keys to search the searchablebox (Which should show an editable TextBox), that doesn't work unless we mouse click the component which is very time consuming especially when we want to enter multiple data/rows.
Here are the classes and samples code we use:
- The Interface
- Instantiate the SpreadSheet
var sheet = new RowDetailsSpreadSheetView();
**- Creating a cell with SearchableComboBox **
var types = new DetailsType(names);
cell = types.createCell(i, 1,
1, 1, "rabe");
randomRow.add(
cell
);
- class DetailsType
public class DetailsType extends SpreadsheetCellType<String> {
protected final List<String> items;
public DetailsType(final List<String> items) {
super(new DefaultStringConverter() {
@Override
public String fromString(String str) {
if (str != null && items.contains(str)) {
return str;
} else {
return null;
}
}
});
this.items = items;
}
@Override
public String toString() {
return "list"; //$NON-NLS-1$
}
public SpreadsheetCell createCell(final int row, final int column, final int rowSpan, final int columnSpan,
String value) {
SpreadsheetCell cell = new SpreadsheetCellBase(row, column, rowSpan, columnSpan, this);
if (items != null && items.size() > 0) {
if (value != null && items.contains(value)) {
cell.setItem(value);
} else {
cell.setItem(items.get(0));
}
}
return cell;
}
@Override
public SpreadsheetCellEditor createEditor(SpreadsheetView view) {
return new ComboboxSphreadSheetEditor<>(view, items);
}
@Override
public boolean match(Object value, Object... options) {
if (value instanceof String && items.contains(value.toString()))
return true;
else
return items.contains(value == null ? null : value.toString());
}
@Override
public String convertValue(Object value) {
return converter.fromString(value == null ? null : value.toString());
}
@Override
public String toString(String item) {
return converter.toString(item);
}
}
- Class ComboboxSphreadSheetEditor
public class ComboboxSphreadSheetEditor<R> extends SpreadsheetCellEditor {
private final List<String> itemList;
private final SearchableComboBox<String> cb;
private String originalValue;
public ComboboxSphreadSheetEditor(SpreadsheetView view, final List<String> itemList) {
super(view);
this.itemList = itemList;
cb = new SearchableComboBox<>();
cb.setVisibleRowCount(5);
cb.show();
}
@Override
public void startEdit(Object value, String format, Object... os) {
if (value instanceof String) {
originalValue = value.toString();
} else {
originalValue = null;
}
ObservableList<String> items = FXCollections.observableList(itemList);
cb.setItems(items);
cb.setValue(originalValue);
cb.getEditor().requestFocus();
}
@Override
public void end() {
cb.setOnKeyPressed(null);
}
@Override
public SearchableComboBox<String> getEditor() {
return cb;
}
@Override
public String getControlValue() {
return cb.getSelectionModel().getSelectedItem();
}
}
At this point, we think the way to go is to catch some sort of KEY EVENT in the SpreadsheetCell but we are a bit clueless how to do it.
Also we think we should catch a KEY EVENT in the SearchableComboBox direclty but we are stuck there also.
This seems to be a minor bug but very important for user experience since users are going to enter a lot of data.