Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv

- We added a fallback for the "Convert to biblatex" cleanup when it failed to populate the `date` field if `year` contained a full date in ISO format (e.g., `2011-11-11`). [#11868](https://github.com/JabRef/jabref/issues/11868)
- We fixed an issue where directory check for relative path was not handled properly under library properties. [#13017](https://github.com/JabRef/jabref/issues/13017)
- We fixed an exception on tab dragging. [#12921](https://github.com/JabRef/jabref/issues/12921)
- We fixed an issue where the option for which method to use when parsing plaintext citations was unavailable in the 'Create New Entry' tool. [#8808](https://github.com/JabRef/jabref/issues/8808)
- We fixed an issue where the "Make/Sync bibliography" button in the OpenOffice/LibreOffice sidebar was not enabled when a jstyle was selected. [#13055](https://github.com/JabRef/jabref/pull/13055)
- We fixed an issue where CSL bibliography title properties would be saved even if the "Modify bibliography title" dialog was closed without pressing the "OK" button. [#13074](https://github.com/JabRef/jabref/pull/13074)
Expand Down
9 changes: 1 addition & 8 deletions jabgui/src/main/java/org/jabref/gui/frame/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.event.Event;
import javafx.geometry.Orientation;
import javafx.scene.control.ContextMenu;
Expand Down Expand Up @@ -374,13 +373,7 @@ private void initKeyBindings() {
}

private void initBindings() {
// Bind global state
FilteredList<Tab> filteredTabs = new FilteredList<>(tabbedPane.getTabs());
filteredTabs.setPredicate(LibraryTab.class::isInstance);

// This variable cannot be inlined, since otherwise the list created by EasyBind is being garbage collected
openDatabaseList = EasyBind.map(filteredTabs, tab -> ((LibraryTab) tab).getBibDatabaseContext());
EasyBind.bindContent(stateManager.getOpenDatabases(), openDatabaseList);
BindingsHelper.bindContentFiltered(tabbedPane.getTabs(), stateManager.getOpenDatabases(), LibraryTab.class::isInstance);

// the binding for stateManager.activeDatabaseProperty() is at org.jabref.gui.LibraryTab.onDatabaseLoadingSucceed

Expand Down
62 changes: 62 additions & 0 deletions jabgui/src/main/java/org/jabref/gui/util/BindingsHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

import javafx.beans.binding.BooleanBinding;
import javafx.beans.binding.ObjectBinding;
Expand All @@ -19,6 +20,10 @@
import javafx.collections.ObservableMap;
import javafx.css.PseudoClass;
import javafx.scene.Node;
import javafx.scene.control.Tab;

import org.jabref.gui.LibraryTab;
import org.jabref.model.database.BibDatabaseContext;

import com.tobiasdiez.easybind.EasyBind;
import com.tobiasdiez.easybind.PreboundBinding;
Expand Down Expand Up @@ -189,6 +194,63 @@ public static <T> Subscription subscribeFuture(ObservableValue<T> observable, Co
return () -> observable.removeListener(listener);
}

public static void bindContentFiltered(ObservableList<Tab> source, ObservableList<BibDatabaseContext> target, Predicate<Tab> filter) {
// FIXME: See https://github.com/JabRef/jabref-koppor/pull/713 - workaround in place until issue is resolved.
// Original code used FilteredList and EasyBind to filter and map tabs directly:
// FilteredList<Tab> filteredTabs = new FilteredList<>(tabbedPane.getTabs());
// filteredTabs.setPredicate(LibraryTab.class::isInstance);
// openDatabaseList = EasyBind.map(filteredTabs, tab -> ((LibraryTab) tab).getBibDatabaseContext());
// EasyBind.bindContent(stateManager.getOpenDatabases(), openDatabaseList);
// Once JabRef#713 is fixed, remove this comment and the bindContentFiltered() method, and restore the original code

Function<Tab, BibDatabaseContext> tabToContext = tab -> ((LibraryTab) tab).getBibDatabaseContext();
// Initial sync
target.setAll(source.stream()
.filter(filter)
.map(tabToContext)
.toList());

source.addListener((ListChangeListener<Tab>) change -> {
while (change.next()) {
if (change.wasPermutated()) {
// We need a fresh copy as permutation is much harder to mirror
List<BibDatabaseContext> reordered = source.stream()
.filter(filter)
.map(tabToContext)
.toList();
target.setAll(reordered);
}

if (change.wasRemoved()) {
for (Tab removed : change.getRemoved()) {
if (filter.test(removed)) {
target.remove(tabToContext.apply(removed));
}
}
}

if (change.wasAdded()) {
int sourceIndex = change.getFrom();
int targetIndex = 0;

// We need to add at the correct place - therefore, we need to find out the correct position
for (int i = 0; i < sourceIndex; i++) {
Tab tab = source.get(i);
if (filter.test(tab)) {
targetIndex++;
}
}

for (Tab added : change.getAddedSubList()) {
if (filter.test(added)) {
target.add(targetIndex++, tabToContext.apply(added));
}
}
}
}
});
}

private static class BidirectionalBinding<A, B> {

private final ObservableValue<A> propertyA;
Expand Down