diff --git a/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTab.java b/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTab.java index a1bb0fa7869..5ba9cd7ad6f 100644 --- a/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTab.java @@ -1,18 +1,22 @@ package org.jabref.gui.entryeditor; -import java.util.Optional; -import java.util.stream.Collectors; - +import javafx.geometry.HPos; +import javafx.geometry.Pos; import javafx.scene.control.Button; +import javafx.scene.control.Label; import javafx.scene.control.ProgressIndicator; -import javafx.scene.control.ScrollPane; import javafx.scene.control.Tooltip; -import javafx.scene.layout.StackPane; +import javafx.scene.layout.ColumnConstraints; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.RowConstraints; import javafx.scene.layout.VBox; import javafx.scene.text.Text; import org.jabref.gui.DialogService; import org.jabref.gui.icon.IconTheme; +import org.jabref.gui.texparser.CitationsDisplay; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; @@ -24,14 +28,16 @@ public class LatexCitationsTab extends EntryEditorTab { private final LatexCitationsTabViewModel viewModel; - private final StackPane searchPane; + private final GridPane searchPane; private final ProgressIndicator progressIndicator; + private final CitationsDisplay citationsDisplay; public LatexCitationsTab(BibDatabaseContext databaseContext, PreferencesService preferencesService, TaskExecutor taskExecutor, DialogService dialogService) { this.viewModel = new LatexCitationsTabViewModel(databaseContext, preferencesService, taskExecutor, dialogService); - this.searchPane = new StackPane(); + this.searchPane = new GridPane(); this.progressIndicator = new ProgressIndicator(); + this.citationsDisplay = new CitationsDisplay(); setText(Localization.lang("LaTeX Citations")); setTooltip(new Tooltip(Localization.lang("Search citations for this entry in LaTeX files"))); @@ -41,81 +47,79 @@ public LatexCitationsTab(BibDatabaseContext databaseContext, PreferencesService private void setSearchPane() { progressIndicator.setMaxSize(100, 100); - searchPane.getStyleClass().add("related-articles-tab"); + citationsDisplay.basePathProperty().bindBidirectional(viewModel.directoryProperty()); + citationsDisplay.setItems(viewModel.getCitationList()); + + RowConstraints mainRow = new RowConstraints(); + mainRow.setVgrow(Priority.ALWAYS); + + RowConstraints bottomRow = new RowConstraints(40); + bottomRow.setVgrow(Priority.NEVER); + + ColumnConstraints column = new ColumnConstraints(); + column.setPercentWidth(100); + column.setHalignment(HPos.CENTER); + searchPane.getColumnConstraints().setAll(column); + searchPane.getRowConstraints().setAll(mainRow, bottomRow); setContent(searchPane); EasyBind.subscribe(viewModel.statusProperty(), status -> { + searchPane.getChildren().clear(); switch (status) { case IN_PROGRESS: - searchPane.getChildren().setAll(progressIndicator); + searchPane.add(progressIndicator, 0, 0); break; case CITATIONS_FOUND: - searchPane.getChildren().setAll(getCitationsPane()); + searchPane.add(getCitationsPane(), 0, 0); break; case NO_RESULTS: - searchPane.getChildren().setAll(getNotFoundPane()); + searchPane.add(getNotFoundPane(), 0, 0); break; case ERROR: - searchPane.getChildren().setAll(getErrorPane()); + searchPane.add(getErrorPane(), 0, 0); break; } + searchPane.add(getLatexDirectoryBox(), 0, 1); }); } - private VBox getLatexDirectoryBox() { - Text latexDirectoryText = new Text(String.format("%n%n%s: %s", Localization.lang("Current search directory"), - viewModel.directoryProperty().get())); - latexDirectoryText.setStyle("-fx-font-weight: bold;"); + private HBox getLatexDirectoryBox() { + Text latexDirectoryText = new Text(Localization.lang("Current search directory:")); + latexDirectoryText.setStyle("-fx-font-size: 0.9em;-fx-padding: 0;"); + Text latexDirectoryPath = new Text(viewModel.directoryProperty().get().toString()); + latexDirectoryPath.setStyle("-fx-font-family: 'Courier New', Courier, monospace;-fx-font-size: 0.9em;-fx-font-weight: bold;"); Button latexDirectoryButton = new Button(Localization.lang("Set LaTeX file directory")); + latexDirectoryButton.setStyle("-fx-border-width: 1;-fx-font-size: 0.85em;-fx-padding: 0.2em;"); + latexDirectoryButton.setGraphic(IconTheme.JabRefIcons.LATEX_FILE_DIRECTORY.getGraphicNode()); latexDirectoryButton.setOnAction(event -> viewModel.setLatexDirectory()); - - return new VBox(15, latexDirectoryText, latexDirectoryButton); + HBox latexDirectoryBox = new HBox(10, latexDirectoryText, latexDirectoryPath, latexDirectoryButton); + latexDirectoryBox.setAlignment(Pos.CENTER); + return latexDirectoryBox; } - private ScrollPane getCitationsPane() { - Text titleText = new Text(Localization.lang("Citations found")); - titleText.getStyleClass().add("recommendation-heading"); - - VBox citationsBox = new VBox(20, titleText); - citationsBox.getChildren().addAll(viewModel.getCitationList().stream().map( - citation -> citation.getDisplayGraphic(viewModel.directoryProperty().get(), Optional.empty())).collect(Collectors.toList())); - - citationsBox.getChildren().add(getLatexDirectoryBox()); - - ScrollPane citationsPane = new ScrollPane(); - citationsPane.setContent(citationsBox); - - return citationsPane; + private VBox getCitationsPane() { + VBox citationsBox = new VBox(30, citationsDisplay); + citationsBox.setStyle("-fx-padding: 0;"); + return citationsBox; } - private ScrollPane getNotFoundPane() { - Text notFoundTitleText = new Text(Localization.lang("No citations found")); - notFoundTitleText.getStyleClass().add("recommendation-heading"); - + private VBox getNotFoundPane() { + Label titleLabel = new Label(Localization.lang("No citations found")); + titleLabel.setStyle("-fx-font-size: 1.5em;-fx-font-weight: bold;-fx-text-fill: -jr-theme-text;"); Text notFoundText = new Text(Localization.lang("No LaTeX files containing this entry were found.")); - notFoundText.setStyle("-fx-font-size: 110%;"); - - VBox notFoundBox = new VBox(20, notFoundTitleText, notFoundText, getLatexDirectoryBox()); - ScrollPane notFoundPane = new ScrollPane(); - notFoundPane.setContent(notFoundBox); - - return notFoundPane; + VBox notFoundBox = new VBox(30, titleLabel, notFoundText); + notFoundBox.setStyle("-fx-padding: 30 0 0 30;"); + return notFoundBox; } - private ScrollPane getErrorPane() { - Text errorTitleText = new Text(Localization.lang("Error")); - errorTitleText.setStyle("-fx-fill: -fx-accent;"); - errorTitleText.getStyleClass().add("recommendation-heading"); - + private VBox getErrorPane() { + Label titleLabel = new Label(Localization.lang("Error")); + titleLabel.setStyle("-fx-font-size: 1.5em;-fx-font-weight: bold;-fx-text-fill: -fx-accent;"); Text errorMessageText = new Text(viewModel.searchErrorProperty().get()); - errorMessageText.setStyle("-fx-font-family: monospace;-fx-font-size: 120%;"); - - VBox errorBox = new VBox(20, errorTitleText, errorMessageText, getLatexDirectoryBox()); - ScrollPane errorPane = new ScrollPane(); - errorPane.setContent(errorBox); - - return errorPane; + VBox errorMessageBox = new VBox(30, titleLabel, errorMessageText); + errorMessageBox.setStyle("-fx-padding: 30 0 0 30;"); + return errorMessageBox; } @Override diff --git a/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java b/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java index f0bfedd16d3..b844475b1db 100644 --- a/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java +++ b/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java @@ -4,6 +4,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; @@ -21,7 +22,6 @@ import org.jabref.gui.AbstractViewModel; import org.jabref.gui.DialogService; -import org.jabref.gui.texparser.CitationViewModel; import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.gui.util.TaskExecutor; @@ -29,6 +29,7 @@ import org.jabref.logic.texparser.DefaultTexParser; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; +import org.jabref.model.texparser.Citation; import org.jabref.model.texparser.TexParserResult; import org.jabref.preferences.PreferencesService; @@ -51,11 +52,12 @@ enum Status { private final TaskExecutor taskExecutor; private final DialogService dialogService; private final ObjectProperty directory; - private final ObservableList citationList; + private final ObservableList citationList; private final ObjectProperty status; private final StringProperty searchError; private Future searchTask; private TexParserResult texParserResult; + private BibEntry currentEntry; public LatexCitationsTabViewModel(BibDatabaseContext databaseContext, PreferencesService preferencesService, TaskExecutor taskExecutor, DialogService dialogService) { @@ -63,7 +65,8 @@ public LatexCitationsTabViewModel(BibDatabaseContext databaseContext, Preference this.preferencesService = preferencesService; this.taskExecutor = taskExecutor; this.dialogService = dialogService; - this.directory = new SimpleObjectProperty<>(null); + this.directory = new SimpleObjectProperty<>(databaseContext.getMetaData().getLaTexFileDirectory(preferencesService.getUser()) + .orElseGet(preferencesService::getWorkingDir)); this.citationList = FXCollections.observableArrayList(); this.status = new SimpleObjectProperty<>(Status.IN_PROGRESS); this.searchError = new SimpleStringProperty(""); @@ -72,6 +75,7 @@ public LatexCitationsTabViewModel(BibDatabaseContext databaseContext, Preference public void init(BibEntry entry) { cancelSearch(); + currentEntry = entry; Optional citeKey = entry.getCiteKeyOptional(); if (citeKey.isPresent()) { startSearch(citeKey.get()); @@ -85,7 +89,7 @@ public ObjectProperty directoryProperty() { return directory; } - public ObservableList getCitationList() { + public ObservableList getCitationList() { return new ReadOnlyListWrapper<>(citationList); } @@ -100,7 +104,10 @@ public StringProperty searchErrorProperty() { private void startSearch(String citeKey) { searchTask = BackgroundTask.wrap(() -> searchAndParse(citeKey)) .onRunning(() -> status.set(Status.IN_PROGRESS)) - .onSuccess(status::set) + .onSuccess(result -> { + citationList.setAll(result); + status.set(citationList.isEmpty() ? Status.NO_RESULTS : Status.CITATIONS_FOUND); + }) .onFailure(error -> { searchError.set(error.getMessage()); status.set(Status.ERROR); @@ -117,14 +124,14 @@ private void cancelSearch() { searchTask.cancel(true); } - private Status searchAndParse(String citeKey) throws IOException { + private Collection searchAndParse(String citeKey) throws IOException { Path newDirectory = databaseContext.getMetaData().getLaTexFileDirectory(preferencesService.getUser()) .orElseGet(preferencesService::getWorkingDir); if (texParserResult == null || !newDirectory.equals(directory.get())) { directory.set(newDirectory); - if (Files.notExists(newDirectory)) { + if (!newDirectory.toFile().exists()) { throw new IOException(String.format("Current search directory does not exist: %s", newDirectory)); } @@ -132,9 +139,7 @@ private Status searchAndParse(String citeKey) throws IOException { texParserResult = new DefaultTexParser().parse(texFiles); } - citationList.setAll(texParserResult.getCitationsByKey(citeKey).stream().map(CitationViewModel::new).collect(Collectors.toList())); - - return citationList.isEmpty() ? Status.NO_RESULTS : Status.CITATIONS_FOUND; + return texParserResult.getCitationsByKey(citeKey); } private List searchDirectory(Path directory, List texFiles) { @@ -142,7 +147,7 @@ private List searchDirectory(Path directory, List texFiles) { try (Stream filesStream = Files.list(directory)) { fileListPartition = filesStream.collect(Collectors.partitioningBy(path -> path.toFile().isDirectory())); } catch (IOException e) { - LOGGER.error(String.format("Error searching files: %s", e.getMessage())); + LOGGER.error(String.format("%s while searching files: %s", e.getClass().getName(), e.getMessage())); return texFiles; } @@ -163,6 +168,8 @@ public void setLatexDirectory() { dialogService.showDirectorySelectionDialog(directoryDialogConfiguration).ifPresent(selectedDirectory -> databaseContext.getMetaData().setLaTexFileDirectory(preferencesService.getUser(), selectedDirectory.toAbsolutePath())); + + init(currentEntry); } public boolean shouldShow() { diff --git a/src/main/java/org/jabref/gui/icon/IconTheme.java b/src/main/java/org/jabref/gui/icon/IconTheme.java index e7d26a338b0..6e9dca496b1 100644 --- a/src/main/java/org/jabref/gui/icon/IconTheme.java +++ b/src/main/java/org/jabref/gui/icon/IconTheme.java @@ -317,7 +317,11 @@ public enum JabRefIcons implements JabRefIcon { CLOSE_JABREF(MaterialDesignIcon.GLASSDOOR), ARTICLE(MaterialDesignIcon.FILE_DOCUMENT), BOOK(MaterialDesignIcon.BOOK_OPEN_PAGE_VARIANT), - LATEX_CITATIONS(JabRefMaterialDesignIcon.TEX_STUDIO); + LATEX_CITATIONS(JabRefMaterialDesignIcon.TEX_STUDIO), + LATEX_FILE_DIRECTORY(MaterialDesignIcon.FOLDER_OUTLINE), + LATEX_FILE(MaterialDesignIcon.FILE_OUTLINE), + LATEX_COMMENT(MaterialDesignIcon.COMMENT_TEXT_OUTLINE), + LATEX_LINE(MaterialDesignIcon.FORMAT_LINE_SPACING); private final JabRefIcon icon; diff --git a/src/main/java/org/jabref/gui/texparser/CitationViewModel.java b/src/main/java/org/jabref/gui/texparser/CitationViewModel.java deleted file mode 100644 index fd2aa15b99c..00000000000 --- a/src/main/java/org/jabref/gui/texparser/CitationViewModel.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.jabref.gui.texparser; - -import java.nio.file.Path; -import java.util.Optional; - -import javafx.scene.Node; -import javafx.scene.layout.HBox; -import javafx.scene.layout.VBox; -import javafx.scene.text.Text; - -import org.jabref.model.strings.LatexToUnicodeAdapter; -import org.jabref.model.texparser.Citation; - -public class CitationViewModel { - - private final Citation citation; - - public CitationViewModel(Citation citation) { - this.citation = citation; - } - - public Path getPath() { - return citation.getPath(); - } - - public int getLine() { - return citation.getLine(); - } - - public int getColStart() { - return citation.getColStart(); - } - - public int getColEnd() { - return citation.getColEnd(); - } - - public String getContext() { - return citation.getContext(); - } - - public Node getDisplayGraphic(Path basePath, Optional wrappingWidth) { - Text contextText = new Text(LatexToUnicodeAdapter.format(getContext())); - wrappingWidth.ifPresent(contextText::setWrappingWidth); - - HBox contextBox = new HBox(contextText); - contextBox.setStyle("-fx-border-color: grey;-fx-border-insets: 10 0;-fx-border-style: dashed;-fx-border-width: 2;-fx-font-size: 110%;-fx-padding: 10;-fx-pref-width: 500"); - - Text positionText = new Text(String.format("%s (%s:%s-%s)", basePath.relativize(getPath()), getLine(), getColStart(), getColEnd())); - positionText.setStyle("-fx-font-family: monospace;"); - - return new VBox(contextBox, positionText); - } - - @Override - public String toString() { - return String.format("CitationViewModel{citation=%s}", this.citation); - } -} diff --git a/src/main/java/org/jabref/gui/texparser/CitationsDisplay.java b/src/main/java/org/jabref/gui/texparser/CitationsDisplay.java new file mode 100644 index 00000000000..c75257559d3 --- /dev/null +++ b/src/main/java/org/jabref/gui/texparser/CitationsDisplay.java @@ -0,0 +1,55 @@ +package org.jabref.gui.texparser; + +import java.nio.file.Path; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.control.ListView; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; +import javafx.scene.text.Text; + +import org.jabref.gui.icon.IconTheme; +import org.jabref.gui.util.ViewModelListCellFactory; +import org.jabref.model.strings.LatexToUnicodeAdapter; +import org.jabref.model.texparser.Citation; + +public class CitationsDisplay extends ListView { + + private ObjectProperty basePath; + + public CitationsDisplay() { + this.basePath = new SimpleObjectProperty<>(null); + new ViewModelListCellFactory().withGraphic(this::getDisplayGraphic) + .withTooltip(Citation::getLineText) + .install(this); + } + + public ObjectProperty basePathProperty() { + return basePath; + } + + public Node getDisplayGraphic(Citation item) { + if (basePath.get() == null) { + basePath.set(item.getPath().getRoot()); + } + + Node citationIcon = IconTheme.JabRefIcons.LATEX_COMMENT.getGraphicNode(); + Text contextText = new Text(LatexToUnicodeAdapter.format(item.getContext())); + contextText.wrappingWidthProperty().bind(this.widthProperty().subtract(85)); + HBox contextBox = new HBox(8, citationIcon, contextText); + contextBox.setStyle("-fx-border-color: grey;-fx-border-insets: 5;-fx-border-style: dashed;-fx-border-width: 2;-fx-padding: 12;"); + + Label fileNameLabel = new Label(String.format("%s", basePath.get().relativize(item.getPath()))); + fileNameLabel.setStyle("-fx-font-family: 'Courier New', Courier, monospace;-fx-font-weight: bold;-fx-label-padding: 5 0 10 10;"); + fileNameLabel.setGraphic(IconTheme.JabRefIcons.LATEX_FILE.getGraphicNode()); + Label positionLabel = new Label(String.format("(%s:%s-%s)", item.getLine(), item.getColStart(), item.getColEnd())); + positionLabel.setStyle("-fx-font-family: 'Courier New', Courier, monospace;-fx-font-weight: bold;-fx-label-padding: 5 0 10 10;"); + positionLabel.setGraphic(IconTheme.JabRefIcons.LATEX_LINE.getGraphicNode()); + HBox dataBox = new HBox(5, fileNameLabel, positionLabel); + + return new VBox(contextBox, dataBox); + } +} diff --git a/src/main/java/org/jabref/gui/texparser/ParseTexAction.java b/src/main/java/org/jabref/gui/texparser/ParseTexAction.java index 0ae73eab70f..215711e2f27 100644 --- a/src/main/java/org/jabref/gui/texparser/ParseTexAction.java +++ b/src/main/java/org/jabref/gui/texparser/ParseTexAction.java @@ -11,7 +11,6 @@ public class ParseTexAction extends SimpleCommand { public ParseTexAction(StateManager stateManager) { this.stateManager = stateManager; - executable.bind(ActionHelper.needsDatabase(stateManager)); } @@ -19,7 +18,6 @@ public ParseTexAction(StateManager stateManager) { public void execute() { BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(NullPointerException::new); ParseTexDialogView dialog = new ParseTexDialogView(database); - dialog.showAndWait(); } } diff --git a/src/main/java/org/jabref/gui/texparser/ParseTexDialogView.java b/src/main/java/org/jabref/gui/texparser/ParseTexDialogView.java index cae6ddabac0..7cdae4c8ed5 100644 --- a/src/main/java/org/jabref/gui/texparser/ParseTexDialogView.java +++ b/src/main/java/org/jabref/gui/texparser/ParseTexDialogView.java @@ -67,25 +67,23 @@ private void initialize() { fileTreeView.rootProperty().bind(EasyBind.map(viewModel.rootProperty(), fileNode -> new RecursiveTreeItem<>(fileNode, FileNodeViewModel::getChildren))); + new ViewModelTreeCellFactory() + .withText(FileNodeViewModel::getDisplayText) + .install(fileTreeView); + EasyBind.subscribe(fileTreeView.rootProperty(), root -> { ((CheckBoxTreeItem) root).setSelected(true); root.setExpanded(true); EasyBind.listBind(viewModel.getCheckedFileList(), fileTreeView.getCheckModel().getCheckedItems()); }); - new ViewModelTreeCellFactory() - .withText(FileNodeViewModel::getDisplayText) - .install(fileTreeView); - texDirectoryField.textProperty().bindBidirectional(viewModel.texDirectoryProperty()); validationVisualizer.setDecoration(new IconValidationDecorator()); validationVisualizer.initVisualization(viewModel.texDirectoryValidation(), texDirectoryField); - browseButton.disableProperty().bindBidirectional(viewModel.searchInProgressProperty()); searchButton.disableProperty().bind(viewModel.texDirectoryValidation().validProperty().not()); selectAllButton.disableProperty().bindBidirectional(viewModel.noFilesFoundProperty()); unselectAllButton.disableProperty().bindBidirectional(viewModel.noFilesFoundProperty()); - progressIndicator.visibleProperty().bindBidirectional(viewModel.searchInProgressProperty()); } diff --git a/src/main/java/org/jabref/gui/texparser/ParseTexDialogViewModel.java b/src/main/java/org/jabref/gui/texparser/ParseTexDialogViewModel.java index 7fd3b6eb3a4..ac2f0c596c6 100644 --- a/src/main/java/org/jabref/gui/texparser/ParseTexDialogViewModel.java +++ b/src/main/java/org/jabref/gui/texparser/ParseTexDialogViewModel.java @@ -57,17 +57,16 @@ public ParseTexDialogViewModel(BibDatabaseContext databaseContext, DialogService this.dialogService = dialogService; this.taskExecutor = taskExecutor; this.preferencesService = preferencesService; - this.texDirectory = new SimpleStringProperty( - databaseContext.getMetaData().getLaTexFileDirectory(preferencesService.getUser()) - .orElseGet(preferencesService::getWorkingDir) - .toAbsolutePath().toString()); + this.texDirectory = new SimpleStringProperty(databaseContext.getMetaData().getLaTexFileDirectory(preferencesService.getUser()) + .orElseGet(preferencesService::getWorkingDir) + .toAbsolutePath().toString()); this.root = new SimpleObjectProperty<>(); this.checkedFileList = FXCollections.observableArrayList(); this.noFilesFound = new SimpleBooleanProperty(true); this.searchInProgress = new SimpleBooleanProperty(false); this.successfulSearch = new SimpleBooleanProperty(false); - Predicate isDirectory = path -> Paths.get(path) != null && Paths.get(path).toFile().isDirectory(); + Predicate isDirectory = path -> Paths.get(path).toFile().isDirectory(); texDirectoryValidator = new FunctionBasedValidator<>(texDirectory, isDirectory, ValidationMessage.error(Localization.lang("Please enter a valid file path."))); } @@ -120,7 +119,6 @@ public void searchButtonClicked() { noFilesFound.set(true); searchInProgress.set(true); successfulSearch.set(false); - }) .onFinished(() -> searchInProgress.set(false)) .onSuccess(newRoot -> { @@ -133,8 +131,8 @@ public void searchButtonClicked() { } private FileNodeViewModel searchDirectory(Path directory) throws IOException { - if (directory == null || !directory.toFile().exists() || !directory.toFile().isDirectory()) { - throw new IOException(String.format("Error searching files: %s", directory)); + if (directory == null || !directory.toFile().isDirectory()) { + throw new IOException(String.format("Invalid directory for searching: %s", directory)); } FileNodeViewModel parent = new FileNodeViewModel(directory); @@ -143,7 +141,7 @@ private FileNodeViewModel searchDirectory(Path directory) throws IOException { try (Stream filesStream = Files.list(directory)) { fileListPartition = filesStream.collect(Collectors.partitioningBy(path -> path.toFile().isDirectory())); } catch (IOException e) { - LOGGER.error(String.format("Error searching files: %s", e.getMessage())); + LOGGER.error(String.format("%s while searching files: %s", e.getClass().getName(), e.getMessage())); return parent; } @@ -157,7 +155,7 @@ private FileNodeViewModel searchDirectory(Path directory) throws IOException { for (Path subDirectory : subDirectories) { FileNodeViewModel subRoot = searchDirectory(subDirectory); - if (subRoot != null && !subRoot.getChildren().isEmpty()) { + if (!subRoot.getChildren().isEmpty()) { fileCount += subRoot.getFileCount(); parent.getChildren().add(subRoot); } @@ -175,10 +173,11 @@ private FileNodeViewModel searchDirectory(Path directory) throws IOException { */ public void parseButtonClicked() { List fileList = checkedFileList.stream() - .map(item -> item.getValue().getPath().toAbsolutePath()) - .filter(path -> path != null && path.toFile().isFile()) + .map(item -> item.getValue().getPath()) + .filter(path -> path.toFile().isFile()) .collect(Collectors.toList()); if (fileList.isEmpty()) { + LOGGER.warn("There are no valid files checked"); return; } diff --git a/src/main/java/org/jabref/gui/texparser/ParseTexResult.fxml b/src/main/java/org/jabref/gui/texparser/ParseTexResult.fxml index 727f4f3a059..ff8ee769fcf 100644 --- a/src/main/java/org/jabref/gui/texparser/ParseTexResult.fxml +++ b/src/main/java/org/jabref/gui/texparser/ParseTexResult.fxml @@ -5,6 +5,7 @@ + - + diff --git a/src/main/java/org/jabref/gui/texparser/ParseTexResultView.java b/src/main/java/org/jabref/gui/texparser/ParseTexResultView.java index 1e3d9d71831..4d0e6b0a8b7 100644 --- a/src/main/java/org/jabref/gui/texparser/ParseTexResultView.java +++ b/src/main/java/org/jabref/gui/texparser/ParseTexResultView.java @@ -1,7 +1,6 @@ package org.jabref.gui.texparser; import java.nio.file.Path; -import java.util.Optional; import javafx.fxml.FXML; import javafx.scene.control.ListView; @@ -19,7 +18,8 @@ public class ParseTexResultView extends BaseDialog { private final TexParserResult texParserResult; private final Path basePath; @FXML private ListView referenceListView; - @FXML private ListView citationListView; + @FXML private CitationsDisplay citationsDisplay; + private ParseTexResultViewModel viewModel; public ParseTexResultView(TexParserResult texParserResult, Path basePath) { this.texParserResult = texParserResult; @@ -32,7 +32,7 @@ public ParseTexResultView(TexParserResult texParserResult, Path basePath) { @FXML private void initialize() { - ParseTexResultViewModel viewModel = new ParseTexResultViewModel(texParserResult); + viewModel = new ParseTexResultViewModel(texParserResult); referenceListView.setItems(viewModel.getReferenceList()); referenceListView.getSelectionModel().selectFirst(); @@ -40,12 +40,10 @@ private void initialize() { .withText(ReferenceViewModel::getDisplayText) .install(referenceListView); - citationListView.setItems(viewModel.getCitationListByReference()); - new ViewModelListCellFactory() - .withGraphic(citation -> citation.getDisplayGraphic(basePath, Optional.of(citationListView.getWidth() - 50))) - .install(citationListView); - EasyBind.subscribe(referenceListView.getSelectionModel().selectedItemProperty(), viewModel::activeReferenceChanged); + + citationsDisplay.basePathProperty().set(basePath); + citationsDisplay.setItems(viewModel.getCitationListByReference()); } } diff --git a/src/main/java/org/jabref/gui/texparser/ParseTexResultViewModel.java b/src/main/java/org/jabref/gui/texparser/ParseTexResultViewModel.java index 73684259883..8114f207f4d 100644 --- a/src/main/java/org/jabref/gui/texparser/ParseTexResultViewModel.java +++ b/src/main/java/org/jabref/gui/texparser/ParseTexResultViewModel.java @@ -5,27 +5,27 @@ import javafx.collections.ObservableList; import org.jabref.gui.AbstractViewModel; +import org.jabref.model.texparser.Citation; import org.jabref.model.texparser.TexParserResult; public class ParseTexResultViewModel extends AbstractViewModel { private final ObservableList referenceList; - private final ObservableList citationList; + private final ObservableList citationList; public ParseTexResultViewModel(TexParserResult texParserResult) { this.referenceList = FXCollections.observableArrayList(); this.citationList = FXCollections.observableArrayList(); - texParserResult.getCitations() - .asMap() - .forEach((entry, citations) -> referenceList.add(new ReferenceViewModel(entry, citations))); + texParserResult.getCitations().asMap().forEach((entry, citations) -> + referenceList.add(new ReferenceViewModel(entry, citations))); } public ObservableList getReferenceList() { return new ReadOnlyListWrapper<>(referenceList); } - public ObservableList getCitationListByReference() { + public ObservableList getCitationListByReference() { return new ReadOnlyListWrapper<>(citationList); } diff --git a/src/main/java/org/jabref/gui/texparser/ReferenceViewModel.java b/src/main/java/org/jabref/gui/texparser/ReferenceViewModel.java index 34a272a6b8f..59c5111d67a 100644 --- a/src/main/java/org/jabref/gui/texparser/ReferenceViewModel.java +++ b/src/main/java/org/jabref/gui/texparser/ReferenceViewModel.java @@ -1,7 +1,6 @@ package org.jabref.gui.texparser; import java.util.Collection; -import java.util.stream.Collectors; import javafx.beans.property.ReadOnlyListWrapper; import javafx.collections.FXCollections; @@ -12,16 +11,16 @@ public class ReferenceViewModel { private final String entry; - private final ObservableList citationList; + private final ObservableList citationList; public ReferenceViewModel(String entry, Collection citationColl) { this.entry = entry; this.citationList = FXCollections.observableArrayList(); - citationList.setAll(citationColl.stream().map(CitationViewModel::new).collect(Collectors.toList())); + citationList.setAll(citationColl); } - public ObservableList getCitationList() { + public ObservableList getCitationList() { return new ReadOnlyListWrapper<>(citationList); } diff --git a/src/main/java/org/jabref/logic/texparser/DefaultTexParser.java b/src/main/java/org/jabref/logic/texparser/DefaultTexParser.java index 2bd0d6f1bcf..a702fefb94a 100644 --- a/src/main/java/org/jabref/logic/texparser/DefaultTexParser.java +++ b/src/main/java/org/jabref/logic/texparser/DefaultTexParser.java @@ -23,13 +23,11 @@ public class DefaultTexParser implements TexParser { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultTexParser.class); + private static final String TEX_EXT = ".tex"; /** * It is allowed to add new cite commands for pattern matching. - * - *

Some valid examples: "citep", "[cC]ite", "[cC]ite(author|title|year|t|p)?" - * - *

TODO: Add support for multicite commands. + * Some valid examples: "citep", "[cC]ite", and "[cC]ite(author|title|year|t|p)?". */ private static final String[] CITE_COMMANDS = { "[cC]ite(alt|alp|author|authorfull|date|num|p|t|text|title|url|year|yearpar)?", @@ -45,8 +43,6 @@ public class DefaultTexParser implements TexParser { private static final Pattern INCLUDE_PATTERN = Pattern.compile( String.format("\\\\(?:include|input)\\{(?<%s>[^\\}]*)\\}", INCLUDE_GROUP)); - private static final String TEX_EXT = ".tex"; - private final TexParserResult texParserResult; public DefaultTexParser() { @@ -71,11 +67,10 @@ public TexParserResult parse(Path texFile) { @Override public TexParserResult parse(List texFiles) { texParserResult.addFiles(texFiles); - List referencedFiles = new ArrayList<>(); for (Path file : texFiles) { - if (Files.notExists(file)) { + if (!file.toFile().exists()) { LOGGER.error(String.format("File does not exist: %s", file)); continue; } @@ -93,7 +88,7 @@ public TexParserResult parse(List texFiles) { LOGGER.error("Parsing has been interrupted"); return null; } catch (IOException | UncheckedIOException e) { - LOGGER.error(String.format("Error searching files: %s", e.getMessage())); + LOGGER.error(String.format("%s while parsing files: %s", e.getClass().getName(), e.getMessage())); } } @@ -126,7 +121,7 @@ private void matchNestedFile(Path file, List texFiles, List referenc while (includeMatch.find()) { String include = includeMatch.group(INCLUDE_GROUP); - Path inputFile = file.toAbsolutePath().getParent().resolve( + Path inputFile = file.getParent().resolve( include.endsWith(TEX_EXT) ? include : String.format("%s%s", include, TEX_EXT)); diff --git a/src/main/java/org/jabref/model/texparser/Citation.java b/src/main/java/org/jabref/model/texparser/Citation.java index f574b08156b..6da4c0b7c94 100644 --- a/src/main/java/org/jabref/model/texparser/Citation.java +++ b/src/main/java/org/jabref/model/texparser/Citation.java @@ -64,7 +64,11 @@ public String getContext() { : lineLength - CONTEXT_WIDTH); int end = Math.min(lineLength, start + CONTEXT_WIDTH); - return lineText.substring(start, end); + // Add three dots when the string does not contain all the line. + return String.format("%s%s%s", + (start > 0) ? "... " : "", + lineText.substring(start, end).trim(), + (end < lineLength) ? " ..." : ""); } @Override diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index e08bc5b0f12..2d0503a5235 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2109,9 +2109,8 @@ files=files Show\ 'LaTeX\ Citations'\ tab=Show 'LaTeX Citations' tab LaTeX\ Citations=LaTeX Citations Search\ citations\ for\ this\ entry\ in\ LaTeX\ files=Search citations for this entry in LaTeX files -Citations\ found=Citations found No\ citations\ found=No citations found No\ LaTeX\ files\ containing\ this\ entry\ were\ found.=No LaTeX files containing this entry were found. Selected\ entry\ does\ not\ have\ an\ associated\ BibTeX\ key.=Selected entry does not have an associated BibTeX key. -Current\ search\ directory=Current search directory +Current\ search\ directory\:=Current search directory: Set\ LaTeX\ file\ directory=Set LaTeX file directory