/**
* Copyright [2015] [Christian Loehnert]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.ks.idnadrev.cost.bookingview;
import de.ks.BaseController;
import de.ks.i18n.Localized;
import de.ks.idnadrev.entity.cost.Booking;
import de.ks.persistence.PersistentWork;
import de.ks.validation.cell.ValidatingTableCell;
import de.ks.validation.validators.DoubleValidator;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.input.KeyCode;
import javafx.util.converter.DoubleStringConverter;
import java.net.URL;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
public class BookingViewTableController extends BaseController<BookingViewModel> {
@FXML
protected TableView<Booking> bookingTable;
@FXML
protected TableColumn<Booking, Boolean> markedColumn;
@FXML
protected TableColumn<Booking, String> timeColumn;
@FXML
protected TableColumn<Booking, String> descriptionColumn;
@FXML
protected TableColumn<Booking, String> categoryColumn;
@FXML
protected TableColumn<Booking, Double> amountColumn;
protected DateTimeFormatter dateTimeFormatter;
protected final Map<Booking, SimpleBooleanProperty> marked = new HashMap<>();
@Override
public void initialize(URL location, ResourceBundle resources) {
String pattern = Localized.get("fullDate");
dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
bookingTable.setEditable(true);
timeColumn.setCellValueFactory(c -> new SimpleStringProperty(dateTimeFormatter.format(c.getValue().getBookingTime())));
descriptionColumn.setCellValueFactory(c -> new SimpleStringProperty(c.getValue().getDescription()));
descriptionColumn.setCellFactory(TextFieldTableCell.forTableColumn());
descriptionColumn.setOnEditCommit(e -> {
String newCat = e.getNewValue();
Booking booking = e.getRowValue();
PersistentWork.wrap(() -> {
PersistentWork.reload(booking).setDescription(newCat);
});
});
categoryColumn.setCellValueFactory(c -> new SimpleStringProperty(c.getValue().getCategory()));
categoryColumn.setCellFactory(TextFieldTableCell.forTableColumn());
categoryColumn.setOnEditCommit(e -> {
String newCat = e.getNewValue();
Booking booking = e.getRowValue();
PersistentWork.wrap(() -> {
PersistentWork.reload(booking).setCategory(newCat);
});
});
amountColumn.setCellValueFactory(c -> (ObservableValue) new SimpleDoubleProperty(c.getValue().getAmount()));
amountColumn.setCellFactory(b -> new ValidatingTableCell<Booking, Double>(new DoubleStringConverter(), new DoubleValidator()) {
@Override
public void updateItem(Double item, boolean empty) {
super.updateItem(item, empty);
getStyleClass().clear();
if (item != null && item.doubleValue() < 0) {
getStyleClass().add("bookingNegative");
} else if (item != null && item.doubleValue() > 0) {
getStyleClass().add("bookingPositive");
}
}
});
amountColumn.setOnEditCommit(e -> {
Double newValue = e.getNewValue();
Double oldValue = e.getOldValue();
Booking booking = e.getRowValue();
if (!newValue.equals(oldValue)) {
PersistentWork.wrap(() -> {
PersistentWork.reload(booking).setAmount(newValue);
});
controller.reload();
}
});
markedColumn.setCellFactory(column -> {
if (column == null) {
return null;
} else {
CheckBoxTableCell cell = new CheckBoxTableCell();
cell.setSelectedStateCallback(i -> {
Booking booking = bookingTable.getItems().get((int) i);
SimpleBooleanProperty property = marked.get(booking);
return property;
});
MenuItem selectItem = new MenuItem(Localized.get("select.all"));
selectItem.setOnAction(e -> {
marked.values().forEach(property -> property.set(true));
});
MenuItem deselectItem = new MenuItem(Localized.get("deselect.all"));
deselectItem.setOnAction(e -> {
marked.values().forEach(property -> property.set(false));
});
ContextMenu contextMenu = new ContextMenu(selectItem, deselectItem);
cell.setContextMenu(contextMenu);
return cell;
}
});
bookingTable.setOnKeyPressed(e -> {
TablePosition focusedCell = bookingTable.getFocusModel().getFocusedCell();
int beginOfEditableColumns = 2;
if (focusedCell.getColumn() < beginOfEditableColumns && !e.isControlDown() && !e.isAltDown()) {
Booking item = bookingTable.getSelectionModel().getSelectedItem();
if (e.getCode() == KeyCode.SPACE) {
if (item != null) {
SimpleBooleanProperty property = marked.get(item);
property.set(!property.get());
e.consume();
}
}
if (e.getCode() == KeyCode.D) {
e.consume();
bookingTable.edit(bookingTable.getSelectionModel().getSelectedIndex(), descriptionColumn);
}
if (e.getCode() == KeyCode.C) {
e.consume();
bookingTable.edit(bookingTable.getSelectionModel().getSelectedIndex(), categoryColumn);
}
}
});
}
@Override
protected void onRefresh(BookingViewModel model) {
ObservableList<Booking> bookings = FXCollections.observableArrayList(model.getBookings());
bookingTable.getItems().clear();
bookingTable.getItems().addAll(bookings);
marked.clear();
for (Booking booking : bookings) {
marked.put(booking, new SimpleBooleanProperty(false));
}
}
public Map<Booking, SimpleBooleanProperty> getMarked() {
return marked;
}
public TableColumn<Booking, Boolean> getMarkedColumn() {
return markedColumn;
}
public TableView<Booking> getBookingTable() {
return bookingTable;
}
}