diff --git a/src/main/java/org/jabref/gui/ClipBoardManager.java b/src/main/java/org/jabref/gui/ClipBoardManager.java index 78b58100534..8b80078c30c 100644 --- a/src/main/java/org/jabref/gui/ClipBoardManager.java +++ b/src/main/java/org/jabref/gui/ClipBoardManager.java @@ -7,7 +7,6 @@ import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import java.util.List; -import java.util.Optional; import javafx.application.Platform; import javafx.scene.control.TextInputControl; @@ -87,10 +86,6 @@ public static String getContents() { return result; } - public Optional getBibTeXEntriesFromClipboard() { - return Optional.ofNullable(clipboard.getContent(DragAndDropDataFormats.ENTRIES)).map(String.class::cast); - } - /** * Get the String residing on the primary clipboard (if it exists). * @@ -150,7 +145,9 @@ public void setContent(List entries) throws IOException { final ClipboardContent content = new ClipboardContent(); BibEntryWriter writer = new BibEntryWriter(new FieldWriter(preferencesService.getFieldPreferences()), Globals.entryTypesManager); String serializedEntries = writer.serializeAll(entries, BibDatabaseMode.BIBTEX); - content.put(DragAndDropDataFormats.ENTRIES, serializedEntries); + // BibEntry is not Java serializable. Thus, we need to do the serialization manually + // At reading of the clipboard in JabRef, we parse the plain string in all cases, so we don't need to flag we put BibEntries here + // Furthermore, storing a string also enables other applications to work with the data content.putString(serializedEntries); clipboard.setContent(content); setPrimaryClipboardContent(content); diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 4b4f3c44cc8..95e60916d73 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -253,9 +253,9 @@ private void initDragAndDrop() { Dragboard dragboard = tabDragEvent.getDragboard(); - if (DragAndDropHelper.hasBibFiles(tabDragEvent.getDragboard())) { + if (DragAndDropHelper.hasBibFiles(dragboard)) { tabbedPane.getTabs().remove(dndIndicator); - List bibFiles = DragAndDropHelper.getBibFiles(tabDragEvent.getDragboard()); + List bibFiles = DragAndDropHelper.getBibFiles(dragboard); OpenDatabaseAction openDatabaseAction = this.getOpenDatabaseAction(); openDatabaseAction.openFiles(bibFiles); tabDragEvent.setDropCompleted(true); @@ -265,8 +265,8 @@ private void initDragAndDrop() { if (libraryTab.getId().equals(destinationTabNode.getId()) && !tabbedPane.getSelectionModel().getSelectedItem().equals(libraryTab)) { LibraryTab destinationLibraryTab = (LibraryTab) libraryTab; - if (DragAndDropHelper.hasGroups(tabDragEvent.getDragboard())) { - List groupPathToSources = DragAndDropHelper.getGroups(tabDragEvent.getDragboard()); + if (DragAndDropHelper.hasGroups(dragboard)) { + List groupPathToSources = DragAndDropHelper.getGroups(dragboard); copyRootNode(destinationLibraryTab); diff --git a/src/main/java/org/jabref/gui/edit/EditAction.java b/src/main/java/org/jabref/gui/edit/EditAction.java index 95eadcd8d0c..b0daa482cb0 100644 --- a/src/main/java/org/jabref/gui/edit/EditAction.java +++ b/src/main/java/org/jabref/gui/edit/EditAction.java @@ -46,45 +46,47 @@ public String toString() { public void execute() { stateManager.getFocusOwner().ifPresent(focusOwner -> { LOGGER.debug("focusOwner: {}; Action: {}", focusOwner, action.getText()); - - if (focusOwner instanceof TextInputControl) { + if (focusOwner instanceof TextInputControl textInput) { // Focus is on text field -> copy/paste/cut selected text - TextInputControl textInput = (TextInputControl) focusOwner; // DELETE_ENTRY in text field should do forward delete switch (action) { + case SELECT_ALL -> textInput.selectAll(); case COPY -> textInput.copy(); - case UNDO -> textInput.undo(); - case REDO -> textInput.redo(); case CUT -> textInput.cut(); case PASTE -> textInput.paste(); case DELETE -> textInput.clear(); - case SELECT_ALL -> textInput.selectAll(); case DELETE_ENTRY -> textInput.deleteNextChar(); - default -> throw new IllegalStateException("Only cut/copy/paste supported in TextInputControl but got " + action); + case UNDO -> textInput.undo(); + case REDO -> textInput.redo(); + default -> { + String message = "Only cut/copy/paste supported in TextInputControl but got " + action; + LOGGER.error(message); + throw new IllegalStateException(message); + } } } else if ((focusOwner instanceof CodeArea) || (focusOwner instanceof WebView)) { + LOGGER.debug("Ignoring request in CodeArea or WebView"); return; } else { LOGGER.debug("Else: {}", focusOwner.getClass().getSimpleName()); // Not sure what is selected -> copy/paste/cut selected entries except for Preview and CodeArea - // ToDo: Should be handled by BibDatabaseContext instead of LibraryTab switch (action) { case COPY -> frame.getCurrentLibraryTab().copy(); case CUT -> frame.getCurrentLibraryTab().cut(); case PASTE -> frame.getCurrentLibraryTab().paste(); case DELETE_ENTRY -> frame.getCurrentLibraryTab().delete(false); - case REDO -> { - if (frame.getUndoManager().canRedo()) { - frame.getUndoManager().redo(); - } - } case UNDO -> { if (frame.getUndoManager().canUndo()) { frame.getUndoManager().undo(); } } - default -> LOGGER.debug("Only cut/copy/paste/delete supported but got: {} and focus owner {}", action, focusOwner); + case REDO -> { + if (frame.getUndoManager().canRedo()) { + frame.getUndoManager().redo(); + } + } + default -> LOGGER.debug("Only cut/copy/paste/deleteEntry supported but got: {} and focus owner {}", action, focusOwner); } } }); diff --git a/src/main/java/org/jabref/gui/maintable/MainTable.java b/src/main/java/org/jabref/gui/maintable/MainTable.java index 56a68e66bed..94585b1742e 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTable.java +++ b/src/main/java/org/jabref/gui/maintable/MainTable.java @@ -3,7 +3,6 @@ import java.io.File; import java.io.IOException; import java.nio.file.Path; -import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -267,6 +266,11 @@ public void cut() { } private void setupKeyBindings(KeyBindingRepository keyBindings) { + EditAction pasteAction = new EditAction(StandardActions.PASTE, libraryTab.frame(), stateManager); + EditAction copyAction = new EditAction(StandardActions.COPY, libraryTab.frame(), stateManager); + EditAction cutAction = new EditAction(StandardActions.CUT, libraryTab.frame(), stateManager); + EditAction deleteAction = new EditAction(StandardActions.DELETE_ENTRY, libraryTab.frame(), stateManager); + this.addEventFilter(KeyEvent.KEY_PRESSED, event -> { if (event.getCode() == KeyCode.ENTER) { getSelectedEntries().stream() @@ -288,19 +292,19 @@ private void setupKeyBindings(KeyBindingRepository keyBindings) { event.consume(); break; case PASTE: - new EditAction(StandardActions.PASTE, libraryTab.frame(), stateManager).execute(); + pasteAction.execute(); event.consume(); break; case COPY: - new EditAction(StandardActions.COPY, libraryTab.frame(), stateManager).execute(); + copyAction.execute(); event.consume(); break; case CUT: - new EditAction(StandardActions.CUT, libraryTab.frame(), stateManager).execute(); + cutAction.execute(); event.consume(); break; case DELETE_ENTRY: - new EditAction(StandardActions.DELETE_ENTRY, libraryTab.frame(), stateManager).execute(); + deleteAction.execute(); event.consume(); break; default: @@ -324,23 +328,22 @@ private void clearAndSelectLast() { public void paste() { List entriesToAdd; - entriesToAdd = this.clipBoardManager.getBibTeXEntriesFromClipboard() - .map(importHandler::handleBibTeXData) - .orElseGet(this::handleNonBibTeXStringData); - + String content = ClipBoardManager.getContents(); + entriesToAdd = importHandler.handleBibTeXData(content); + if (entriesToAdd.isEmpty()) { + entriesToAdd = handleNonBibTeXStringData(content); + } + if (entriesToAdd.isEmpty()) { + return; + } for (BibEntry entry : entriesToAdd) { importHandler.importEntryWithDuplicateCheck(database, entry); } - if (!entriesToAdd.isEmpty()) { - this.requestFocus(); - } } - private List handleNonBibTeXStringData() { - String data = ClipBoardManager.getContents(); - List entries = new ArrayList<>(); + private List handleNonBibTeXStringData(String data) { try { - entries = this.importHandler.handleStringData(data); + return this.importHandler.handleStringData(data); } catch (FetcherException exception) { if (exception instanceof FetcherClientException) { dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("No data was found for the identifier")); @@ -349,8 +352,8 @@ private List handleNonBibTeXStringData() { } else { dialogService.showErrorDialogAndWait(exception); } + return List.of(); } - return entries; } public void dropEntry(List entriesToAdd) { @@ -393,8 +396,8 @@ private void handleOnDragDetected(TableRow row, BibEntry List entries = getSelectionModel().getSelectedItems().stream().map(BibEntryTableViewModel::getEntry).collect(Collectors.toList()); - // The following is necesary to initiate the drag and drop in javafx, although we don't need the contents - // It doesn't work without + // The following is necessary to initiate the drag and drop in JavaFX, + // although we don't need the contents, it does not work without // Drag'n'drop to other tabs use COPY TransferMode, drop to group sidepane use MOVE ClipboardContent content = new ClipboardContent(); Dragboard dragboard = startDragAndDrop(TransferMode.COPY_OR_MOVE);