diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index 0016b222116..bd0d2c276bb 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -20,7 +20,6 @@ import javafx.scene.control.MenuItem; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; -import javafx.scene.input.DataFormat; import javafx.scene.input.KeyEvent; import javafx.scene.input.TransferMode; import javafx.scene.layout.BorderPane; @@ -79,6 +78,9 @@ public class EntryEditor extends BorderPane { private Subscription typeSubscription; private BibEntry entry; // A reference to the entry this editor works on. private SourceTab sourceTab; + private List draggedFiles; + private boolean inDragDropMode = false; + private TransferMode transferMode; @FXML private TabPane tabbed; @FXML private Button typeChangeButton; @FXML private Button fetcherButton; @@ -121,41 +123,57 @@ public EntryEditor(BasePanel panel, ExternalFileTypes externalFileTypes) { this.tabs = createTabs(); - this.setOnDragOver(event -> { - if (event.getDragboard().hasFiles()) { - event.acceptTransferModes(TransferMode.COPY, TransferMode.MOVE, TransferMode.LINK); - } - event.consume(); - }); + this.setOnMouseEntered(event -> { + // When registering using this.setOnDragDetected, the code is never called. Thus, using the workaround on "mouseEntered" + // onMouseEntered is called AFTER onDragDropped. We need it BEFORE. So we do this workaround with inDragDropMode + if (this.inDragDropMode) { + boolean dragDropModifierPressed = event.isAltDown() || event.isShiftDown() || event.isControlDown(); - this.setOnDragDropped(event -> { - BibEntry entry = this.getEntry(); - boolean success = false; + BibEntry entry = this.getEntry(); - if (event.getDragboard().hasContent(DataFormat.FILES)) { - List files = event.getDragboard().getFiles().stream().map(File::toPath).collect(Collectors.toList()); FileDragDropPreferenceType dragDropPreferencesType = preferencesService.getEntryEditorFileLinkPreference(); - if (dragDropPreferencesType == FileDragDropPreferenceType.MOVE) { - LOGGER.debug("Mode MOVE"); - fileLinker.moveFilesToFileDirAndAddToEntry(entry, files); - success = true; + // determine transfer mode -- JabRef's preferences are the default; modifier keys override the default + TransferMode determinedTransferMode; + if (dragDropModifierPressed) { + LOGGER.debug("Modifier pressed"); + determinedTransferMode = transferMode; + } else { + LOGGER.debug("No modifier pressed"); + determinedTransferMode = dragDropPreferencesType.getTransferMode(); } - if (dragDropPreferencesType == FileDragDropPreferenceType.COPY) { - LOGGER.debug("Mode COPY"); - fileLinker.copyFilesToFileDirAndAddToEntry(entry, files); - success = true; + // obey the determined transfer mode and take action accordingly + switch (determinedTransferMode) { + case LINK: + LOGGER.debug("Mode LINK"); + fileLinker.addFilesToEntry(entry, this.draggedFiles); + break; + case COPY: + LOGGER.debug("Mode COPY"); + fileLinker.copyFilesToFileDirAndAddToEntry(entry, this.draggedFiles); + break; + default: + LOGGER.debug("Mode MOVE"); + fileLinker.moveFilesToFileDirAndAddToEntry(entry, this.draggedFiles); + break; } + inDragDropMode = false; + } + }); - if (dragDropPreferencesType == FileDragDropPreferenceType.LINK) { - LOGGER.debug("Mode LINK"); - fileLinker.addFilesToEntry(entry, files); - success = true; - } + this.setOnDragOver(event -> { + if (event.getDragboard().hasFiles()) { + event.acceptTransferModes(TransferMode.COPY, TransferMode.MOVE, TransferMode.LINK); + this.draggedFiles = event.getDragboard().getFiles().stream().map(File::toPath).collect(Collectors.toList()); + this.inDragDropMode = true; + this.transferMode = event.getTransferMode(); } + event.consume(); + }); - event.setDropCompleted(success); + this.setOnDragDropped(event -> { + event.setDropCompleted(true); event.consume(); }); } @@ -245,6 +263,7 @@ private List createTabs() { entryEditorTabs.add(new OtherFieldsTab(databaseContext, panel.getSuggestionProviders(), undoManager, entryEditorPreferences.getCustomTabFieldNames(), dialogService, Globals.prefs, Globals.entryTypesManager, ExternalFileTypes.getInstance(), Globals.TASK_EXECUTOR, Globals.journalAbbreviationLoader)); // General fields from preferences + // Examples: "General", "Abstract", and "Comments" for (Map.Entry> tab : entryEditorPreferences.getEntryEditorTabList().entrySet()) { entryEditorTabs.add(new UserDefinedFieldsTab(tab.getKey(), tab.getValue(), databaseContext, panel.getSuggestionProviders(), undoManager, dialogService, Globals.prefs, Globals.entryTypesManager, ExternalFileTypes.getInstance(), Globals.TASK_EXECUTOR, Globals.journalAbbreviationLoader)); } diff --git a/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java b/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java index 603450b39ce..8fcb370ef90 100644 --- a/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -52,7 +53,7 @@ abstract class FieldsEditorTab extends EntryEditorTab { private final JournalAbbreviationLoader journalAbbreviationLoader; private PreviewPanel previewPanel; private UndoManager undoManager; - private Collection fields = new ArrayList<>(); + private Collection fields = Collections.emptyList(); private GridPane gridPane; public FieldsEditorTab(boolean compressed, BibDatabaseContext databaseContext, SuggestionProviders suggestionProviders, UndoManager undoManager, DialogService dialogService, JabRefPreferences preferences, ExternalFileTypes externalFileTypes, TaskExecutor taskExecutor, JournalAbbreviationLoader journalAbbreviationLoader) { diff --git a/src/main/java/org/jabref/gui/entryeditor/FileDragDropPreferenceType.java b/src/main/java/org/jabref/gui/entryeditor/FileDragDropPreferenceType.java index c4593487e39..ecd90daff1c 100644 --- a/src/main/java/org/jabref/gui/entryeditor/FileDragDropPreferenceType.java +++ b/src/main/java/org/jabref/gui/entryeditor/FileDragDropPreferenceType.java @@ -1,16 +1,26 @@ package org.jabref.gui.entryeditor; +import javafx.scene.input.TransferMode; + public enum FileDragDropPreferenceType { + COPY(TransferMode.COPY), + LINK(TransferMode.LINK), + MOVE(TransferMode.MOVE); + + private final TransferMode transferMode; + /** - * Copy file to default file folder - */ - COPY, - /** - * Link file (without copying) - */ - LINK, - /** - * Copy, rename and link file + * Initializes the enum with the mapping to JavaFX's TransferMode. We use this straight-forward implementation as + * this class resides in `org.jabref.gui` and thus has access to JavaFX classes. The alternative is to use an + * EnumMap. + * + * @param transferMode the JavaFX TransferMode which the enum corresponds to. */ - MOVE; + FileDragDropPreferenceType(TransferMode transferMode) { + this.transferMode = transferMode; + } + + public TransferMode getTransferMode() { + return transferMode; + } } diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java index d41c7beafcf..ba524c115cf 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java @@ -45,6 +45,9 @@ import com.airhacks.afterburner.views.ViewLoader; +/** + * Without customization of JabRef, this contains the "File" field in the "General" tab. + */ public class LinkedFilesEditor extends HBox implements FieldEditorFX { @FXML private final LinkedFilesEditorViewModel viewModel; diff --git a/src/main/java/org/jabref/gui/preferences/EntryEditorTab.fxml b/src/main/java/org/jabref/gui/preferences/EntryEditorTab.fxml index 0d62000f0d2..0d56040e08d 100644 --- a/src/main/java/org/jabref/gui/preferences/EntryEditorTab.fxml +++ b/src/main/java/org/jabref/gui/preferences/EntryEditorTab.fxml @@ -63,5 +63,5 @@