From 75d3ca3ff475f515eef0525e804c5de83e06a48a Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Mon, 6 May 2019 10:20:20 +0200 Subject: [PATCH] fix merge, move code to new PreviewViewer --- src/main/java/org/jabref/gui/BasePanel.java | 1 - .../java/org/jabref/gui/PreviewPanel.java | 402 ------------------ .../org/jabref/gui/preview/PreviewViewer.java | 60 ++- 3 files changed, 44 insertions(+), 419 deletions(-) delete mode 100644 src/main/java/org/jabref/gui/PreviewPanel.java diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 932491c4800..f4ae905560a 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -185,7 +185,6 @@ public BasePanel(JabRefFrame frame, BasePanelPreferences preferences, BibDatabas this.entryEditor = new EntryEditor(this, preferences.getEntryEditorPreferences(), Globals.getFileUpdateMonitor(), dialogService, externalFileTypes, Globals.TASK_EXECUTOR); this.preview = new PreviewPanel(getBibDatabaseContext(), this, dialogService, externalFileTypes, Globals.getKeyPrefs(), preferences.getPreviewPreferences()); - frame().getGlobalSearchBar().getSearchQueryHighlightObservable().addSearchListener(preview); } @Subscribe diff --git a/src/main/java/org/jabref/gui/PreviewPanel.java b/src/main/java/org/jabref/gui/PreviewPanel.java deleted file mode 100644 index 90b0b723c11..00000000000 --- a/src/main/java/org/jabref/gui/PreviewPanel.java +++ /dev/null @@ -1,402 +0,0 @@ -package org.jabref.gui; - -import java.io.File; -import java.io.IOException; -import java.io.StringReader; -import java.nio.file.Path; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.Future; -import java.util.stream.Collectors; - -import javafx.beans.value.ObservableValue; -import javafx.concurrent.Worker; -import javafx.print.PrinterJob; -import javafx.scene.control.ContextMenu; -import javafx.scene.control.MenuItem; -import javafx.scene.control.ScrollPane; -import javafx.scene.control.SeparatorMenuItem; -import javafx.scene.input.ClipboardContent; -import javafx.scene.input.DataFormat; -import javafx.scene.input.Dragboard; -import javafx.scene.input.KeyEvent; -import javafx.scene.input.TransferMode; -import javafx.scene.web.WebView; - -import org.jabref.Globals; -import org.jabref.gui.externalfiles.ExternalFilesEntryLinker; -import org.jabref.gui.externalfiletype.ExternalFileTypes; -import org.jabref.gui.icon.IconTheme; -import org.jabref.gui.keyboard.KeyBinding; -import org.jabref.gui.keyboard.KeyBindingRepository; -import org.jabref.gui.util.BackgroundTask; -import org.jabref.gui.util.DefaultTaskExecutor; -import org.jabref.logic.citationstyle.CitationStyle; -import org.jabref.logic.exporter.ExporterFactory; -import org.jabref.logic.l10n.Localization; -import org.jabref.logic.layout.Layout; -import org.jabref.logic.layout.LayoutFormatterPreferences; -import org.jabref.logic.layout.LayoutHelper; -import org.jabref.model.database.BibDatabaseContext; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.event.FieldChangedEvent; -import org.jabref.preferences.PreviewPreferences; - -import com.google.common.eventbus.Subscribe; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -/** - * Displays an BibEntry using the given layout format. - */ -public class PreviewPanel extends ScrollPane implements EntryContainer { - - private static final Logger LOGGER = LoggerFactory.getLogger(PreviewPanel.class); - - private static String JS_HIGHLIGHT_FUNCTION = " "; - - private final ClipBoardManager clipBoardManager; - private final DialogService dialogService; - private final KeyBindingRepository keyBindingRepository; - - private final String defaultPreviewStyle = "Preview"; - private String previewStyle; - private CitationStyle citationStyle; - private Optional basePanel = Optional.empty(); - - private boolean fixedLayout; - private Optional layout = Optional.empty(); - /** - * The entry currently shown - */ - private Optional bibEntry = Optional.empty(); - - /** - * If a database is set, the preview will attempt to resolve strings in the previewed entry using that database. - */ - private BibDatabaseContext databaseContext; - private final WebView previewView; - private Optional> citationStyleFuture = Optional.empty(); - - private final ExternalFilesEntryLinker fileLinker; - - /** - * @param panel (may be null) Only set this if the preview is associated to the main window. - * @param databaseContext Used for resolving pdf directories for links. Must not be null, just pass a new empty BibDatabaseContext() - */ - public PreviewPanel(BasePanel panel, BibDatabaseContext databaseContext, KeyBindingRepository keyBindingRepository, PreviewPreferences preferences, DialogService dialogService, ExternalFileTypes externalFileTypes) { - this.databaseContext = Objects.requireNonNull(databaseContext); - this.basePanel = Optional.ofNullable(panel); - this.dialogService = dialogService; - this.clipBoardManager = Globals.clipboardManager; - this.keyBindingRepository = keyBindingRepository; - - fileLinker = new ExternalFilesEntryLinker(externalFileTypes, Globals.prefs.getFilePreferences(), databaseContext); - - // Set up scroll pane for preview pane - setFitToHeight(true); - setFitToWidth(true); - previewView = new WebView(); - setContent(previewView); - previewView.setContextMenuEnabled(false); - setContextMenu(createPopupMenu()); - - if (this.basePanel.isPresent()) { - // Handler for drag content of preview to different window - // only created for main window (not for windows like the search results dialog) - setOnDragDetected(event -> { - startFullDrag(); - - Dragboard dragboard = startDragAndDrop(TransferMode.COPY); - ClipboardContent content = new ClipboardContent(); - content.putHtml((String) previewView.getEngine().executeScript("window.getSelection().toString()")); - dragboard.setContent(content); - - event.consume(); - }); - } - this.previewView.setOnDragOver(event -> { - if (event.getDragboard().hasFiles()) { - event.acceptTransferModes(TransferMode.COPY, TransferMode.MOVE, TransferMode.LINK); - } - event.consume(); - }); - - this.previewView.setOnDragDropped(event -> { - BibEntry entry = this.getEntry(); - boolean success = false; - if (event.getDragboard().hasContent(DataFormat.FILES)) { - List files = event.getDragboard().getFiles().stream().map(File::toPath).collect(Collectors.toList()); - - if (event.getTransferMode() == TransferMode.MOVE) { - LOGGER.debug("Mode MOVE"); //shift on win or no modifier - fileLinker.moveFilesToFileDirAndAddToEntry(entry, files); - } - if (event.getTransferMode() == TransferMode.LINK) { - LOGGER.debug("Node LINK"); //alt on win - fileLinker.addFilesToEntry(entry, files); - } - if (event.getTransferMode() == TransferMode.COPY) { - LOGGER.debug("Mode Copy"); //ctrl on win, no modifier on Xubuntu - fileLinker.copyFilesToFileDirAndAddToEntry(entry, files); - } - success = true; - } - - event.setDropCompleted(success); - event.consume(); - - }); - - createKeyBindings(); - updateLayout(preferences, true); - - - } - - private void createKeyBindings() { - addEventFilter(KeyEvent.KEY_PRESSED, event -> { - Optional keyBinding = keyBindingRepository.mapToKeyBinding(event); - if (keyBinding.isPresent()) { - switch (keyBinding.get()) { - case COPY_PREVIEW: - copyPreviewToClipBoard(); - event.consume(); - break; - case CLOSE: - close(); - event.consume(); - break; - default: - } - } - }); - } - - private ContextMenu createPopupMenu() { - MenuItem copyPreview = new MenuItem(Localization.lang("Copy preview"), IconTheme.JabRefIcons.COPY.getGraphicNode()); - copyPreview.setAccelerator(keyBindingRepository.getKeyCombination(KeyBinding.COPY_PREVIEW)); - copyPreview.setOnAction(event -> copyPreviewToClipBoard()); - MenuItem printEntryPreview = new MenuItem(Localization.lang("Print entry preview"), IconTheme.JabRefIcons.PRINTED.getGraphicNode()); - printEntryPreview.setOnAction(event -> print()); - MenuItem previousPreviewLayout = new MenuItem(Localization.lang("Previous preview layout")); - previousPreviewLayout.setAccelerator(keyBindingRepository.getKeyCombination(KeyBinding.PREVIOUS_PREVIEW_LAYOUT)); - previousPreviewLayout.setOnAction(event -> basePanel.ifPresent(BasePanel::previousPreviewStyle)); - MenuItem nextPreviewLayout = new MenuItem(Localization.lang("Next preview layout")); - nextPreviewLayout.setAccelerator(keyBindingRepository.getKeyCombination(KeyBinding.NEXT_PREVIEW_LAYOUT)); - nextPreviewLayout.setOnAction(event -> basePanel.ifPresent(BasePanel::nextPreviewStyle)); - - ContextMenu menu = new ContextMenu(); - menu.getItems().add(copyPreview); - menu.getItems().add(printEntryPreview); - menu.getItems().add(new SeparatorMenuItem()); - menu.getItems().add(nextPreviewLayout); - menu.getItems().add(previousPreviewLayout); - return menu; - } - - public void setDatabaseContext(BibDatabaseContext databaseContext) { - this.databaseContext = databaseContext; - } - - public Optional getBasePanel() { - return this.basePanel; - } - - public void setBasePanel(BasePanel basePanel) { - this.basePanel = Optional.ofNullable(basePanel); - } - - public void updateLayout(PreviewPreferences previewPreferences) { - updateLayout(previewPreferences, false); - Globals.stateManager.fireSearchQueryHighlightEvent(); - } - - private void updateLayout(PreviewPreferences previewPreferences, boolean init) { - if (fixedLayout) { - LOGGER.debug("cannot change the layout because the layout is fixed"); - return; - } - - String style = previewPreferences.getCurrentPreviewStyle(); - if (previewStyle == null) { - previewStyle = style; - CitationStyle.createCitationStyleFromFile(style).ifPresent(cs -> citationStyle = cs); - } - if (basePanel.isPresent() && !previewStyle.equals(style)) { - if (CitationStyle.isCitationStyleFile(style)) { - layout = Optional.empty(); - CitationStyle.createCitationStyleFromFile(style) - .ifPresent(cs -> { - citationStyle = cs; - if (!init) { - basePanel.get().output(Localization.lang("Preview style changed to: %0", citationStyle.getTitle())); - } - }); - previewStyle = style; - } - } else { - previewStyle = defaultPreviewStyle; - updatePreviewLayout(previewPreferences.getPreviewStyle(), previewPreferences.getLayoutFormatterPreferences()); - if (!init) { - basePanel.get().output(Localization.lang("Preview style changed to: %0", Localization.lang("Preview"))); - } - } - - update(); - } - - private void updatePreviewLayout(String layoutFile, LayoutFormatterPreferences layoutFormatterPreferences) { - StringReader sr = new StringReader(layoutFile.replace("__NEWLINE__", "\n")); - try { - layout = Optional.of(new LayoutHelper(sr, layoutFormatterPreferences).getLayoutFromText()); - } catch (IOException e) { - layout = Optional.empty(); - LOGGER.debug("no layout could be set", e); - } - } - - public void setLayout(Layout layout) { - this.layout = Optional.ofNullable(layout); - update(); - } - - public void setEntry(BibEntry newEntry) { - bibEntry.filter(e -> e != newEntry).ifPresent(e -> e.unregisterListener(this)); - bibEntry = Optional.ofNullable(newEntry); - newEntry.registerListener(this); - - update(); - } - - /** - * Listener for ChangedFieldEvent. - */ - @SuppressWarnings("unused") - @Subscribe - public void listen(FieldChangedEvent fieldChangedEvent) { - update(); - } - - @Override - public BibEntry getEntry() { - return this.bibEntry.orElse(null); - } - - public void update() { - ExporterFactory.entryNumber = 1; // Set entry number in case that is included in the preview layout. - - if (citationStyleFuture.isPresent()) { - citationStyleFuture.get().cancel(true); - citationStyleFuture = Optional.empty(); - } - - if (layout.isPresent()) { - StringBuilder sb = new StringBuilder(); - bibEntry.ifPresent(entry -> sb.append(layout.get() - .doLayout(entry, databaseContext.getDatabase()))); - setPreviewLabel(sb.toString()); - } else if (basePanel.isPresent() && bibEntry.isPresent()) { - if ((citationStyle != null) && !previewStyle.equals(defaultPreviewStyle)) { - basePanel.get().getCitationStyleCache().setCitationStyle(citationStyle); - } - Future citationStyleWorker = BackgroundTask - .wrap(() -> basePanel.get().getCitationStyleCache().getCitationFor(bibEntry.get())) - .onRunning(() -> { - CitationStyle citationStyle = basePanel.get().getCitationStyleCache().getCitationStyle(); - setPreviewLabel("" + Localization.lang("Processing %0", Localization.lang("Citation Style")) + - ": " + citationStyle.getTitle() + " ..." + ""); - }) - .onSuccess(this::setPreviewLabel) - .onFailure(exception -> { - LOGGER.error("Error while generating citation style", exception); - setPreviewLabel(Localization.lang("Error while generating citation style")); - }) - .executeWith(Globals.TASK_EXECUTOR); - this.citationStyleFuture = Optional.of(citationStyleWorker); - } - } - - private void setPreviewLabel(String text) { - String myText = JS_HIGHLIGHT_FUNCTION + "
"; - previewView.getEngine().setJavaScriptEnabled(true); - - DefaultTaskExecutor.runInJavaFXThread(() -> previewView.getEngine().loadContent(myText)); - this.setHvalue(0); - previewView.getEngine().getLoadWorker().stateProperty().addListener((ObservableValue observable, - Worker.State oldValue, - Worker.State newValue) -> { - if (newValue != Worker.State.SUCCEEDED) { - return; - } - Globals.stateManager.addSearchQueryHighlightListener(highlightPattern -> { - if (highlightPattern.isPresent()) { - String pattern = highlightPattern.get().pattern().replace("\\Q", "").replace("\\E", ""); - - previewView.getEngine().executeScript("highlight('" + pattern + "');"); - - } - }); - }); - } - - /** - * this fixes the Layout, the user cannot change it anymore. Useful for testing the styles in the settings - * - * @param layout should be either a {@link String} (for the old PreviewStyle) or a {@link CitationStyle}. - */ - public void setFixedLayout(String layout) { - this.fixedLayout = true; - updatePreviewLayout(layout, Globals.prefs.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader)); - } - - public void print() { - PrinterJob job = PrinterJob.createPrinterJob(); - boolean proceed = dialogService.showPrintDialog(job); - if (!proceed) { - return; - } - - BackgroundTask.wrap(() -> { - job.getJobSettings().setJobName(bibEntry.flatMap(BibEntry::getCiteKeyOptional).orElse("NO ENTRY")); - previewView.getEngine().print(job); - job.endJob(); - return null; - }) - .onFailure(exception -> dialogService.showErrorDialogAndWait(Localization.lang("Could not print preview"), exception)) - .executeWith(Globals.TASK_EXECUTOR); - } - - public void close() { - basePanel.ifPresent(BasePanel::closeBottomPane); - } - - private void copyPreviewToClipBoard() { - StringBuilder previewStringContent = new StringBuilder(); - Document document = previewView.getEngine().getDocument(); - - NodeList nodeList = document.getElementsByTagName("html"); - - //Nodelist does not implement iterable - for (int i = 0; i < nodeList.getLength(); i++) { - Element element = (Element) nodeList.item(i); - previewStringContent.append(element.getTextContent()); - } - - ClipboardContent content = new ClipboardContent(); - content.putString(previewStringContent.toString()); - content.putHtml((String) previewView.getEngine().executeScript("document.documentElement.outerHTML")); - - clipBoardManager.setContent(content); - } -} diff --git a/src/main/java/org/jabref/gui/preview/PreviewViewer.java b/src/main/java/org/jabref/gui/preview/PreviewViewer.java index 6432ef4cc3b..9fdfad3e23f 100644 --- a/src/main/java/org/jabref/gui/preview/PreviewViewer.java +++ b/src/main/java/org/jabref/gui/preview/PreviewViewer.java @@ -5,6 +5,8 @@ import javafx.beans.InvalidationListener; import javafx.beans.Observable; +import javafx.beans.value.ObservableValue; +import javafx.concurrent.Worker; import javafx.print.PrinterJob; import javafx.scene.control.ScrollPane; import javafx.scene.input.ClipboardContent; @@ -46,6 +48,14 @@ public class PreviewViewer extends ScrollPane implements InvalidationListener { private Optional entry = Optional.empty(); private BibDatabaseContext database; + private static String JS_HIGHLIGHT_FUNCTION = " "; + /** * @param database Used for resolving strings and pdf directories for links. */ @@ -93,18 +103,36 @@ private void update() { ExporterFactory.entryNumber = 1; // Set entry number in case that is included in the preview layout. BackgroundTask - .wrap(() -> layout.generatePreview(entry.get(), database.getDatabase())) - .onRunning(() -> setPreviewText("" + Localization.lang("Processing %0", Localization.lang("Citation Style")) + ": " + layout.getName() + " ..." + "")) - .onSuccess(this::setPreviewText) - .onFailure(exception -> { - LOGGER.error("Error while generating citation style", exception); - setPreviewText(Localization.lang("Error while generating citation style")); - }) - .executeWith(taskExecutor); + .wrap(() -> layout.generatePreview(entry.get(), database.getDatabase())) + .onRunning(() -> setPreviewText("" + Localization.lang("Processing %0", Localization.lang("Citation Style")) + ": " + layout.getName() + " ..." + "")) + .onSuccess(this::setPreviewText) + .onFailure(exception -> { + LOGGER.error("Error while generating citation style", exception); + setPreviewText(Localization.lang("Error while generating citation style")); + }) + .executeWith(taskExecutor); } private void setPreviewText(String text) { - previewView.getEngine().loadContent(text); + String myText = JS_HIGHLIGHT_FUNCTION + "
"; + previewView.getEngine().setJavaScriptEnabled(true); + previewView.getEngine().loadContent(myText); + + previewView.getEngine().getLoadWorker().stateProperty().addListener((ObservableValue observable, + Worker.State oldValue, + Worker.State newValue) -> { + if (newValue != Worker.State.SUCCEEDED) { + return; + } + Globals.stateManager.addSearchQueryHighlightListener(highlightPattern -> { + if (highlightPattern.isPresent()) { + String pattern = highlightPattern.get().pattern().replace("\\Q", "").replace("\\E", ""); + + previewView.getEngine().executeScript("highlight('" + pattern + "');"); + + } + }); + }); this.setHvalue(0); } @@ -116,13 +144,13 @@ public void print() { } BackgroundTask - .wrap(() -> { - job.getJobSettings().setJobName(entry.flatMap(BibEntry::getCiteKeyOptional).orElse("NO ENTRY")); - previewView.getEngine().print(job); - job.endJob(); - }) - .onFailure(exception -> dialogService.showErrorDialogAndWait(Localization.lang("Could not print preview"), exception)) - .executeWith(taskExecutor); + .wrap(() -> { + job.getJobSettings().setJobName(entry.flatMap(BibEntry::getCiteKeyOptional).orElse("NO ENTRY")); + previewView.getEngine().print(job); + job.endJob(); + }) + .onFailure(exception -> dialogService.showErrorDialogAndWait(Localization.lang("Could not print preview"), exception)) + .executeWith(taskExecutor); } public void copyPreviewToClipBoard() {