package org.jabref.gui.documentviewer; import java.io.IOException; import java.nio.file.Path; import java.util.List; import java.util.Objects; import javafx.beans.property.BooleanProperty; import javafx.beans.property.IntegerProperty; import javafx.beans.property.ListProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleListProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import org.jabref.Globals; import org.jabref.gui.AbstractViewModel; import org.jabref.gui.StateManager; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; import org.apache.pdfbox.pdmodel.PDDocument; import org.fxmisc.easybind.EasyBind; public class DocumentViewerViewModel extends AbstractViewModel { private StateManager stateManager; private ObjectProperty<DocumentViewModel> currentDocument = new SimpleObjectProperty<>(); private ListProperty<LinkedFile> files = new SimpleListProperty<>(); private BooleanProperty liveMode = new SimpleBooleanProperty(); private ObjectProperty<Integer> currentPage = new SimpleObjectProperty<>(); private IntegerProperty maxPages = new SimpleIntegerProperty(); public DocumentViewerViewModel(StateManager stateManager) { this.stateManager = Objects.requireNonNull(stateManager); this.stateManager.getSelectedEntries().addListener((ListChangeListener<? super BibEntry>) c -> { // Switch to currently selected entry in live mode if (isLiveMode()) { setCurrentEntries(this.stateManager.getSelectedEntries()); } }); this.liveMode.addListener((observable, oldValue, newValue) -> { // Switch to currently selected entry if mode is changed to live if (oldValue != newValue && newValue) { setCurrentEntries(this.stateManager.getSelectedEntries()); } }); maxPages.bindBidirectional( EasyBind.monadic(currentDocument).selectProperty(DocumentViewModel::maxPagesProperty)); setCurrentEntries(this.stateManager.getSelectedEntries()); } private int getCurrentPage() { return currentPage.get(); } public ObjectProperty<Integer> currentPageProperty() { return currentPage; } public IntegerProperty maxPagesProperty() { return maxPages; } private boolean isLiveMode() { return liveMode.get(); } public ObjectProperty<DocumentViewModel> currentDocumentProperty() { return currentDocument; } public ListProperty<LinkedFile> filesProperty() { return files; } private void setCurrentEntries(List<BibEntry> entries) { if (!entries.isEmpty()) { BibEntry firstSelectedEntry = entries.get(0); setCurrentEntry(firstSelectedEntry); } } private void setCurrentEntry(BibEntry entry) { stateManager.getActiveDatabase().ifPresent(database -> { List<LinkedFile> linkedFiles = entry.getFiles(); // We don't need to switch to the first file, this is done automatically in the UI part files.setValue(FXCollections.observableArrayList(linkedFiles)); }); } private void setCurrentDocument(Path path) { try { currentDocument.set(new PdfDocumentViewModel(PDDocument.load(path.toFile()))); } catch (IOException e) { e.printStackTrace(); } } public void switchToFile(LinkedFile file) { if (file != null) { stateManager.getActiveDatabase().ifPresent(database -> file.findIn(database, Globals.prefs.getFileDirectoryPreferences()) .ifPresent(this::setCurrentDocument)); } } public BooleanProperty liveModeProperty() { return liveMode; } public void showNextPage() { currentPage.set(getCurrentPage() + 1); } public void showPreviousPage() { currentPage.set(getCurrentPage() - 1); } }