Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes koppor/jabref#521 - Allow to drag&drop selected bib entries to other library tabs #8982

Merged
merged 7 commits into from
Jul 18, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
- We added an extra option in the 'Find Unlinked Files' dialog view to ignore unnecessary files like Thumbs.db, DS_Store, etc. [koppor#373](https://github.com/koppor/jabref/issues/373)
- JabRef now writes log files. Linux: `$home/.cache/jabref/logs/version`, Windows: `%APPDATA%\..\Local\harawata\jabref\version\logs`, Mac: `Users/.../Library/Logs/jabref/version`
- We added an importer for Citavi backup files, support ".ctv5bak" and ".ctv6bak" file formats. [#8322](https://github.com/JabRef/jabref/issues/8322)
- We added a feature about allowing drag selected entries and drop them to other opened inactive library tabs.
GNAQ marked this conversation as resolved.
Show resolved Hide resolved

### Changed

Expand Down
48 changes: 48 additions & 0 deletions src/main/java/org/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,54 @@ private void initDragAndDrop() {
} else {
tabbedPane.getTabs().remove(dndIndicator);
}
// Accept drag entries from MainTable
if (event.getDragboard().hasContent(DragAndDropDataFormats.ENTRIES)) {
event.acceptTransferModes(TransferMode.COPY);
event.consume();
}
});

this.getScene().setOnDragEntered(event -> {
// It is necessary to setOnDragOver for newly opened tabs
// drag'n'drop on tabs covered dnd on tabbedPane, so dnd on tabs should contain all dnds on tabbedPane
tabbedPane.lookupAll(".tab").forEach(t -> {
t.setOnDragOver(tabDragEvent -> {
if (DragAndDropHelper.hasBibFiles(tabDragEvent.getDragboard())) {
tabDragEvent.acceptTransferModes(TransferMode.ANY);
if (!tabbedPane.getTabs().contains(dndIndicator)) {
tabbedPane.getTabs().add(dndIndicator);
}
event.consume();
} else {
tabbedPane.getTabs().remove(dndIndicator);
}

if (tabDragEvent.getDragboard().hasContent(DragAndDropDataFormats.ENTRIES)) {
tabDragEvent.acceptTransferModes(TransferMode.COPY);
tabDragEvent.consume();
}
});
t.setOnDragExited(event1 -> tabbedPane.getTabs().remove(dndIndicator));
t.setOnDragDropped(tabDragEvent -> {
if (DragAndDropHelper.hasBibFiles(tabDragEvent.getDragboard())) {
tabbedPane.getTabs().remove(dndIndicator);
List<Path> bibFiles = DragAndDropHelper.getBibFiles(tabDragEvent.getDragboard());
OpenDatabaseAction openDatabaseAction = this.getOpenDatabaseAction();
openDatabaseAction.openFiles(bibFiles, true);
tabDragEvent.setDropCompleted(true);
tabDragEvent.consume();
} else {
for (Tab libraryTab : tabbedPane.getTabs()) {
if (libraryTab.getId().equals(t.getId()) &&
!tabbedPane.getSelectionModel().getSelectedItem().equals(libraryTab)) {
((LibraryTab) libraryTab).dropEntry(stateManager.getLocalDragboard().getBibEntries());
}
}
tabDragEvent.consume();
}
});
});
event.consume();
});

this.getScene().setOnDragExited(event -> tabbedPane.getTabs().remove(dndIndicator));
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/org/jabref/gui/LibraryTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;

import javafx.animation.PauseTransition;
import javafx.application.Platform;
Expand Down Expand Up @@ -153,6 +154,10 @@ public LibraryTab(JabRefFrame frame,

this.entryEditor = new EntryEditor(this, externalFileTypes);

// set LibraryTab ID for drag'n'drop
// ID content doesn't matter, we only need different tabs to have different ID
this.setId(Long.valueOf(new Random().nextLong()).toString());

Platform.runLater(() -> {
EasyBind.subscribe(changedProperty, this::updateTabTitle);
stateManager.getOpenDatabases().addListener((ListChangeListener<BibDatabaseContext>) c ->
Expand Down Expand Up @@ -758,6 +763,10 @@ public void paste() {
mainTable.paste();
}

public void dropEntry(List<BibEntry> entriesToAdd) {
mainTable.dropEntry(entriesToAdd);
}

public void cut() {
mainTable.cut();
}
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/org/jabref/gui/maintable/MainTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,12 @@ public void paste() {
}
}

public void dropEntry(List<BibEntry> entriesToAdd) {
for (BibEntry entry : entriesToAdd) {
importHandler.importEntryWithDuplicateCheck(database, (BibEntry) entry.clone());
}
}

private void handleOnDragOver(TableRow<BibEntryTableViewModel> row, BibEntryTableViewModel item, DragEvent event) {
if (event.getDragboard().hasFiles()) {
event.acceptTransferModes(TransferMode.ANY);
Expand Down Expand Up @@ -350,8 +356,9 @@ private void handleOnDragDetected(TableRow<BibEntryTableViewModel> row, BibEntry

// The following is necesary to initiate the drag and drop in javafx, although we don't need the contents
// It doesn't 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.MOVE);
Dragboard dragboard = startDragAndDrop(TransferMode.COPY_OR_MOVE);
content.put(DragAndDropDataFormats.ENTRIES, "");
dragboard.setContent(content);

Expand Down