I have been trying to use make AbstractTableCell and AbstractTableController.
The goal is to move the highlight functionality to my AbstractTableController instead of repeating it in every TableController. Introduce a new functionality: move the next cell if tab is pressed and save the data of the previous cell. This is what i have done so far. The highlight method is throwing error.
public class AbstractTableCell<S, T> extends TableCell<S, T> {
protected final TextField textField = new TextField();
// Define the states
private final BooleanProperty activeState = new SimpleBooleanProperty(false);
private final BooleanProperty inactiveState = new SimpleBooleanProperty(false);
private final BooleanProperty highlightedState = new SimpleBooleanProperty(false);
private final BooleanProperty errorState = new SimpleBooleanProperty(false);
// Define the styles
private final String activeStyle = "-fx-background-color: #f0f0f5;" +
"-fx-text-fill: #456482;" +
"-fx-font-family: 'Lexend Deca Medium';" +
"-fx-font-size: 14px;" +
"-fx-alignment: CENTER;" +
"-fx-table-cell-border-color: #a2a2a2;";
private final String inactiveStyle = "-fx-background-color: #d3d3d3;" +
"-fx-text-fill: #878787;" +
"-fx-font-family: 'Lexend Deca Medium';" +
"-fx-font-size: 14px;" +
"-fx-alignment: CENTER;" +
"-fx-table-cell-border-color: #a2a2a2;";
private final String highlightedStyle = "-fx-background-color: yellow;" +
"-fx-text-fill: #000000;" +
"-fx-font-family: 'Lexend Deca Medium';" +
"-fx-font-size: 14px;" +
"-fx-alignment: CENTER;" +
"-fx-table-cell-border-color: #a2a2a2;";
private final String errorStyle = "-fx-background-color: red;" +
"-fx-text-fill: #ffffff;" +
"-fx-font-family: 'Lexend Deca Medium';" +
"-fx-font-size: 14px;" +
"-fx-alignment: CENTER;" +
"-fx-table-cell-border-color: #a2a2a2;";
public AbstractTableCell() {
itemProperty().addListener((obx, oldItem, newItem) -> {
if (newItem == null) {
setText(null);
} else {
setText(newItem.toString());
}
});
setGraphic(textField);
setContentDisplay(ContentDisplay.TEXT_ONLY);
textField.setOnAction(evt -> {
commitEdit((T) textField.getText());
});
textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (!isNowFocused) {
commitEdit((T) textField.getText());
}
});
textField.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (event.getCode() == KeyCode.ESCAPE) {
textField.setText(getItem().toString());
cancelEdit();
event.consume();
}
});
}
@Override
public void startEdit() {
super.startEdit();
textField.setText(getItem().toString());
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
textField.requestFocus();
}
@Override
public void cancelEdit() {
super.cancelEdit();
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
@Override
public void commitEdit(T item) {
if (!isEditing() && !item.equals(getItem())) {
commitEdit(item);
}
super.commitEdit(item);
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
private void applyStyleBasedOnState() {
if (activeState.get()) {
setStyle(activeStyle);
inactiveState.set(false);
highlightedState.set(false);
errorState.set(false);
} else if (inactiveState.get()) {
setStyle(inactiveStyle);
activeState.set(false);
highlightedState.set(false);
errorState.set(false);
} else if (highlightedState.get()) {
setStyle(highlightedStyle);
activeState.set(false);
inactiveState.set(false);
errorState.set(false);
} else if (errorState.get()) {
setStyle(errorStyle);
activeState.set(false);
inactiveState.set(false);
highlightedState.set(false);
}
}
// Add methods to set the state
public void setActiveState(boolean isActive) {
activeState.set(isActive);
applyStyleBasedOnState();
}
public void setInactiveState(boolean isInactive) {
inactiveState.set(isInactive);
applyStyleBasedOnState();
}
public void setHighlightedState(boolean isHighlighted) {
highlightedState.set(isHighlighted);
applyStyleBasedOnState();
}
public void setErrorState(boolean isError) {
errorState.set(isError);
applyStyleBasedOnState();
}
}
public class AbstractTableController2<S, T> {
@FXML protected AnchorPane _backgroundPane = new AnchorPane();
@FXML protected TableView<S> _tableView = new TableView<>();
protected TableColumn<S, Number> _indexColumn = new TableColumn<>("#");
protected final Map<String, TableColumn<S, ?>> _columnMap = new LinkedHashMap<>();
protected final List<TableColumn<S, ?>> _columns = new ArrayList<>();
private int _selectedIndex = -1;
protected final Label _label = new Label();
protected ObservableList<S> _data = FXCollections.observableArrayList();
public AbstractTableController2(final double tableWidth, final double tableHeight) {
Platform.runLater(() -> {
DropShadow dropshadow = GuiUtil.createDropShadow(5.0,
5.0,
2.0,
2.0,
CustomColor.SHADOW_BLACK,
0.0,
10.0);
dropshadow.setBlurType(BlurType.GAUSSIAN);
_backgroundPane.setEffect(dropshadow);
_backgroundPane.setPrefWidth(tableWidth);
_tableView.setPrefWidth(tableWidth);
_backgroundPane.setPrefHeight(tableHeight);
_tableView.setPrefHeight(tableHeight);
// Setup _indexColumn programmatically
_indexColumn.setMaxWidth(200.0);
_indexColumn.setMinWidth(60.0);
_indexColumn.setPrefWidth(140.0);
_tableView.getColumns().add(_indexColumn);
// _indexColumn.setStyle("-fx-background-color: #f0f0f5; -fx-text-fill: #456482; -fx-font-size: 14; -fx-table-cell-border-color: #a2a2a2; -fx-alignment: CENTER;");
_indexColumn.setCellValueFactory(col -> new ReadOnlyObjectWrapper<>(_tableView.getItems().indexOf(col.getValue()) + 1));
_tableView.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
if (newSelection != null) {
highlightRow(_tableView.getItems().indexOf(newSelection));
}
});
_tableView.setOnKeyPressed(event -> {
TablePosition<S, ?> pos = _tableView.getFocusModel().getFocusedCell();
if (pos != null && event.getCode().isLetterKey()) {
_tableView.edit(pos.getRow(), pos.getTableColumn());
}
});
_tableView.getColumns().forEach(column -> ((TableColumn<S, String>) column).setSortable(false));
_tableView.refresh();
_tableView.setOnMouseClicked(event -> {
if (!_tableView.getItems().isEmpty()) {
_selectedIndex = _tableView.getSelectionModel().getSelectedIndex();
if (event.getClickCount() == 1) {
highlightRow(_selectedIndex);
} else if (event.getClickCount() == 2 && event.getButton() == MouseButton.PRIMARY) {
TablePosition<S, ?> pos = _tableView.getSelectionModel().getSelectedCells().get(0);
int row = pos.getRow();
int col = pos.getColumn();
TableColumn<S, ?> column = pos.getTableColumn();
if (column.isEditable()) {
_tableView.edit(_selectedIndex, _tableView.getColumns().get(_tableView.getSelectionModel().getSelectedCells().get(0).getColumn()));
}
}
_tableView.getSelectionModel().clearSelection();
}
});
});
}
private void highlightRow(int rowIndex) {
_tableView.getItems().forEach(item -> {
TableRow<S> tableRow = new TableRow<>();
if (_tableView.getItems().indexOf(item) == rowIndex) {
((AbstractTableCell<S, ?>) tableRow.getChildrenUnmodifiable().get(_tableView.getColumns().indexOf(_indexColumn))).setHighlightedState(true);
} else {
tableRow.setStyle("");
((AbstractTableCell<S, ?>) tableRow.getChildrenUnmodifiable().get(_tableView.getColumns().indexOf(_indexColumn))).setHighlightedState(false);
}
});
}
public void clearHighlightRow(int rowIndex) {
_tableView.getItems().forEach(item -> {
TableRow<S> tableRow = new TableRow<>();
if (_tableView.getItems().indexOf(item) == rowIndex) {
tableRow.setStyle("");
((AbstractTableCell<S, ?>) tableRow.getChildrenUnmodifiable().get(_tableView.getColumns().indexOf(_indexColumn))).setInactiveState(true);
}
});
}
public void setData(String name) {
TableColumn<S, String> column = new TableColumn<>(_label.getText());
column.setCellValueFactory(new PropertyValueFactory<>(name));
column.setEditable(true);
_columnMap.put(_label.getText(), column);
_columns.add(column);
column.setStyle("-fx-alignment: CENTER;");
_tableView.getColumns().addAll(column);
}
public boolean checkItem(String item) {
return containOnlyDigitsAndDecimalPoint(item);
}
public String checkInput(double item) {
DecimalFormat decimalFormat = new DecimalFormat("#,###.#########");
return decimalFormat.format(item);
}
public boolean checkInputRange(double data, double min, double max) {
return data >= min && data <= max;
}
public boolean containCharacters(String input) {
return input.matches(".*[a-zA-Z].*");
}
public boolean containOnlyDigitsAndDecimalPoint(String input) {
return input.matches("\d+(\.\d+)?");
}
public void clearData(ObservableList<S> dataList) {
_data.removeAll(dataList);
}
public void showData(ObservableList<S> dataList) {
_data.addAll(dataList);
}
public void setColumnName(String str) {
_label.setText(str);
}
public String getColumnName() {
return _label.getText();
}
public TableView<S> getTable() {
return _tableView;
}
public Pane getBackgroundPane() {
return _backgroundPane;
}
public List<TableColumn<S, ?>> getColumnList() {
return _columns;
}
}