package org.jabref.gui.journals; import javax.inject.Inject; import javafx.concurrent.Task; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.control.ProgressIndicator; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.TextField; import javafx.scene.input.KeyCode; import javafx.stage.Stage; import org.jabref.gui.AbstractController; import org.jabref.gui.DialogService; import org.jabref.gui.IconTheme; import org.jabref.gui.util.TaskExecutor; import org.jabref.gui.util.ValueTableCellFactory; import org.jabref.logic.journals.JournalAbbreviationLoader; import org.jabref.preferences.PreferencesService; public class ManageJournalAbbreviationsController extends AbstractController<ManageJournalAbbreviationsViewModel> { @FXML public Label loadingLabel; @FXML public ProgressIndicator progressIndicator; @FXML private TableView<AbbreviationViewModel> journalAbbreviationsTable; @FXML private TableColumn<AbbreviationViewModel, String> journalTableNameColumn; @FXML private TableColumn<AbbreviationViewModel, String> journalTableAbbreviationColumn; @FXML private TableColumn<AbbreviationViewModel, Boolean> journalTableEditColumn; @FXML private TableColumn<AbbreviationViewModel, Boolean> journalTableDeleteColumn; @FXML private Button cancelButton; @FXML private ComboBox<AbbreviationsFileViewModel> journalFilesBox; @FXML private Button addJournalFileButton; @FXML private Button addNewJournalFileButton; @FXML private Button removeJournalAbbreviationsButton; @Inject private PreferencesService preferences; @Inject private DialogService dialogService; @Inject private TaskExecutor taskExecutor; @Inject private JournalAbbreviationLoader journalAbbreviationLoader; @FXML private void initialize() { viewModel = new ManageJournalAbbreviationsViewModel(preferences, dialogService, taskExecutor, journalAbbreviationLoader); setUpTable(); setBindings(); setButtonStyles(); viewModel.init(); } private void setButtonStyles() { addJournalFileButton.setGraphic(IconTheme.JabRefIcon.OPEN.getGraphicNode()); addNewJournalFileButton.setGraphic(IconTheme.JabRefIcon.NEW.getGraphicNode()); removeJournalAbbreviationsButton.setGraphic(IconTheme.JabRefIcon.CLOSE.getGraphicNode()); } private void setUpTable() { journalAbbreviationsTable.setOnKeyPressed(event -> { if (event.getCode() == KeyCode.DELETE) { viewModel.deleteAbbreviation(); } }); journalTableNameColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty()); journalTableNameColumn.setCellFactory(cell -> new JournalAbbreviationsNameTableEditingCell()); journalTableAbbreviationColumn.setCellValueFactory(cellData -> cellData.getValue().abbreviationProperty()); journalTableAbbreviationColumn.setCellFactory(cell -> new JournalAbbreviationsAbbreviationTableEditingCell()); journalTableEditColumn.setCellValueFactory(cellData -> cellData.getValue().isPseudoAbbreviationProperty()); journalTableDeleteColumn.setCellValueFactory(cellData -> cellData.getValue().isPseudoAbbreviationProperty()); journalTableEditColumn.setCellFactory(new ValueTableCellFactory<AbbreviationViewModel, Boolean>(). withGraphic(isPseudoAbbreviation -> { if (isPseudoAbbreviation) { return IconTheme.JabRefIcon.ADD.getGraphicNode(); } else { return viewModel.isAbbreviationEditableAndRemovable() ? IconTheme.JabRefIcon.EDIT.getGraphicNode() : null; } }). withOnMouseClickedEvent(isPseudoAbbreviation -> { if (isPseudoAbbreviation) { return evt -> addAbbreviation(); } else { return viewModel.isAbbreviationEditableAndRemovable() ? evt -> editAbbreviation() : evt -> { }; } }) ); journalTableDeleteColumn.setCellFactory(new ValueTableCellFactory<AbbreviationViewModel, Boolean>(). withGraphic(isPseudoAbbreviation -> { if (!isPseudoAbbreviation && viewModel.isAbbreviationEditableAndRemovable()) { return IconTheme.JabRefIcon.DELETE_ENTRY.getGraphicNode(); } else { return null; } }). withOnMouseClickedEvent(isPseudoAbbreviation -> { if (!isPseudoAbbreviation && viewModel.isAbbreviationEditableAndRemovable()) { return evt -> removeAbbreviation(); } else { return evt -> { }; } }) ); } private void setBindings() { journalAbbreviationsTable.itemsProperty().bindBidirectional(viewModel.abbreviationsProperty()); journalFilesBox.itemsProperty().bindBidirectional(viewModel.journalFilesProperty()); viewModel.currentFileProperty().addListener((observable, oldvalue, newvalue) -> journalFilesBox.getSelectionModel().select(newvalue)); journalFilesBox.getSelectionModel().selectedItemProperty() .addListener((observable, oldvalue, newvalue) -> viewModel.currentFileProperty().set(newvalue)); viewModel.currentAbbreviationProperty().addListener((observable, oldvalue, newvalue) -> journalAbbreviationsTable.getSelectionModel().select(newvalue)); journalAbbreviationsTable.getSelectionModel().selectedItemProperty() .addListener((observable, oldvalue, newvalue) -> viewModel.currentAbbreviationProperty().set(newvalue)); removeJournalAbbreviationsButton.disableProperty().bind(viewModel.isFileRemovableProperty().not()); loadingLabel.visibleProperty().bind(viewModel.isLoadingProperty()); progressIndicator.visibleProperty().bind(viewModel.isLoadingProperty()); } @FXML private void addNewFile() { viewModel.addNewFile(); } @FXML private void openFile() { viewModel.openFile(); } @FXML private void removeList() { viewModel.removeCurrentFile(); } @FXML private void addAbbreviation() { viewModel.addAbbreviation(); selectNewAbbreviation(); } @FXML private void editAbbreviation() { journalAbbreviationsTable.edit(journalAbbreviationsTable.getSelectionModel().getSelectedIndex(), journalTableNameColumn); } private void selectNewAbbreviation() { int lastRow = viewModel.abbreviationsCountProperty().get() - 1; journalAbbreviationsTable.scrollTo(lastRow); journalAbbreviationsTable.getSelectionModel().select(lastRow); journalAbbreviationsTable.getFocusModel().focus(lastRow); } @FXML private void removeAbbreviation() { viewModel.deleteAbbreviation(); } @FXML private void closeDialog() { Stage stage = (Stage) cancelButton.getScene().getWindow(); stage.close(); } @FXML private void saveAbbreviationsAndCloseDialog() { Task<Void> task = new Task<Void>() { @Override protected Void call() { viewModel.saveEverythingAndUpdateAutoCompleter(); return null; } }; new Thread(task).start(); closeDialog(); } /** * This class provides a editable text field that is used as table cell. * It handles the editing of the name column. */ public class JournalAbbreviationsNameTableEditingCell extends TableCell<AbbreviationViewModel, String> { private TextField textField; private String oldName; private int editingIndex; @Override public void startEdit() { if (!isEmpty() && viewModel.isAbbreviationEditableAndRemovableProperty().get()) { oldName = viewModel.currentAbbreviationProperty().get().getName(); super.startEdit(); createTextField(); setText(null); setGraphic(textField); editingIndex = journalAbbreviationsTable.getSelectionModel().getSelectedIndex(); textField.requestFocus(); textField.selectAll(); } } @Override public void cancelEdit() { super.cancelEdit(); setText(getItem()); setGraphic(null); journalAbbreviationsTable.itemsProperty().get().get(editingIndex).setName(oldName); } @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (empty) { setText(null); setGraphic(null); } else { if (isEditing()) { if (textField != null) { textField.setText(getString()); } setText(null); setGraphic(textField); } else { setText(getString()); setGraphic(null); } } } @Override public void commitEdit(String name) { journalAbbreviationsTable.getSelectionModel().select(editingIndex); AbbreviationViewModel current = viewModel.currentAbbreviationProperty().get(); super.commitEdit(name); current.setName(oldName); viewModel.editAbbreviation(name, current.getAbbreviation()); } private void createTextField() { textField = new TextField(getString()); textField.setMinWidth(this.getWidth() - (this.getGraphicTextGap() * 2)); textField.focusedProperty().addListener((observable, oldValue, newValue) -> { if (!newValue) { commitEdit(textField.getText()); } }); textField.setOnKeyPressed(t -> { if (t.getCode() == KeyCode.ENTER) { if (isEditing()) { journalAbbreviationsTable.requestFocus(); } else { startEdit(); } } else if (t.getCode() == KeyCode.ESCAPE) { cancelEdit(); } }); } private String getString() { return getItem() == null ? "" : getItem(); } } /** * This class provides a editable text field that is used as table cell. * It handles the editing of the abbreviation column. */ public class JournalAbbreviationsAbbreviationTableEditingCell extends TableCell<AbbreviationViewModel, String> { private TextField textField; private String oldAbbreviation; private int editingIndex; @Override public void startEdit() { if (!isEmpty() && viewModel.isAbbreviationEditableAndRemovableProperty().get()) { oldAbbreviation = viewModel.currentAbbreviationProperty().get().getAbbreviation(); super.startEdit(); createTextField(); setText(null); setGraphic(textField); editingIndex = journalAbbreviationsTable.getSelectionModel().getSelectedIndex(); textField.requestFocus(); textField.selectAll(); } } @Override public void cancelEdit() { super.cancelEdit(); setText(getItem()); setGraphic(null); journalAbbreviationsTable.itemsProperty().get().get(editingIndex).setAbbreviation(oldAbbreviation); } @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (empty) { setText(null); setGraphic(null); } else { if (isEditing()) { if (textField != null) { textField.setText(getString()); } setText(null); setGraphic(textField); } else { setText(getString()); setGraphic(null); } } } @Override public void commitEdit(String abbreviation) { journalAbbreviationsTable.getSelectionModel().select(editingIndex); AbbreviationViewModel current = viewModel.currentAbbreviationProperty().get(); super.commitEdit(abbreviation); current.setAbbreviation(oldAbbreviation); viewModel.editAbbreviation(current.getName(), abbreviation); } private void createTextField() { textField = new TextField(getString()); textField.setMinWidth(this.getWidth() - (this.getGraphicTextGap() * 2)); textField.focusedProperty().addListener((observable, oldValue, newValue) -> { if (!newValue) { commitEdit(textField.getText()); } }); textField.setOnKeyPressed(t -> { if (t.getCode() == KeyCode.ENTER) { if (isEditing()) { journalAbbreviationsTable.requestFocus(); } else { startEdit(); } } else if (t.getCode() == KeyCode.ESCAPE) { cancelEdit(); } }); } private String getString() { return getItem() == null ? "" : getItem(); } } }