Skip to content

Commit d55afba

Browse files
committed
Post change notifications on JavaFX
Fixes #4817. The problem is that changes in other threads produce a "Not on FX application thread" exception. This is fixed by adding a wrapper around the list of entries. The wrapper only posts changes in the correct thread, without making a copy of the underlying list - so performance shouldn't be affected.
1 parent bb7b721 commit d55afba

File tree

5 files changed

+51
-5
lines changed

5 files changed

+51
-5
lines changed

src/main/java/org/jabref/gui/BasePanel.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ public void output(String s) {
255255

256256
private void setupActions() {
257257
SaveDatabaseAction saveAction = new SaveDatabaseAction(this, Globals.prefs);
258-
CleanupAction cleanUpAction = new CleanupAction(this, Globals.prefs);
258+
CleanupAction cleanUpAction = new CleanupAction(this, Globals.prefs, Globals.TASK_EXECUTOR);
259259

260260
actions.put(Actions.UNDO, undoAction);
261261
actions.put(Actions.REDO, redoAction);

src/main/java/org/jabref/gui/actions/CleanupAction.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import org.jabref.gui.cleanup.CleanupDialog;
1010
import org.jabref.gui.undo.NamedCompound;
1111
import org.jabref.gui.undo.UndoableFieldChange;
12+
import org.jabref.gui.util.BackgroundTask;
13+
import org.jabref.gui.util.TaskExecutor;
1214
import org.jabref.logic.cleanup.CleanupPreset;
1315
import org.jabref.logic.cleanup.CleanupWorker;
1416
import org.jabref.logic.l10n.Localization;
@@ -20,15 +22,17 @@ public class CleanupAction implements BaseAction {
2022

2123
private final BasePanel panel;
2224
private final DialogService dialogService;
25+
private final TaskExecutor taskExecutor;
2326

2427
private boolean isCanceled;
2528
private int modifiedEntriesCount;
2629
private final JabRefPreferences preferences;
2730

28-
public CleanupAction(BasePanel panel, JabRefPreferences preferences) {
31+
public CleanupAction(BasePanel panel, JabRefPreferences preferences, TaskExecutor taskExecutor) {
2932
this.panel = panel;
3033
this.preferences = preferences;
3134
this.dialogService = panel.frame().getDialogService();
35+
this.taskExecutor = taskExecutor;
3236
}
3337

3438
@Override
@@ -58,8 +62,9 @@ public void action() {
5862

5963
preferences.setCleanupPreset(chosenPreset.get());
6064

61-
this.cleanup(chosenPreset.get());
62-
this.showResults();
65+
BackgroundTask.wrap(() -> cleanup(chosenPreset.get()))
66+
.onSuccess(result -> showResults())
67+
.executeWith(taskExecutor);
6368
}
6469
}
6570

src/main/java/org/jabref/gui/maintable/MainTable.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.jabref.gui.keyboard.KeyBindingRepository;
3737
import org.jabref.gui.undo.NamedCompound;
3838
import org.jabref.gui.undo.UndoableInsertEntry;
39+
import org.jabref.gui.util.BindingsHelper;
3940
import org.jabref.gui.util.CustomLocalDragboard;
4041
import org.jabref.gui.util.ViewModelTableRowFactory;
4142
import org.jabref.logic.l10n.Localization;
@@ -108,7 +109,7 @@ public MainTable(MainTableDataModel model, JabRefFrame frame,
108109
}
109110
this.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
110111

111-
this.setItems(model.getEntriesFilteredAndSorted());
112+
this.setItems(BindingsHelper.forUI(model.getEntriesFilteredAndSorted()));
112113
// Enable sorting
113114
model.getEntriesFilteredAndSorted().comparatorProperty().bind(this.comparatorProperty());
114115

src/main/java/org/jabref/gui/util/BindingsHelper.java

+8
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,14 @@ protected String computeValue() {
176176
};
177177
}
178178

179+
/**
180+
* Returns a wrapper around the given list that posts changes on the JavaFX thread.
181+
*/
182+
public static <T> ObservableList<T> forUI(ObservableList<T> list) {
183+
return new UiThreadList<>(list);
184+
}
185+
186+
179187
private static class BidirectionalBinding<A, B> {
180188

181189
private final ObservableValue<A> propertyA;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.jabref.gui.util;
2+
3+
import javafx.application.Platform;
4+
import javafx.collections.ListChangeListener;
5+
import javafx.collections.ObservableList;
6+
import javafx.collections.transformation.TransformationList;
7+
8+
class UiThreadList<T> extends TransformationList<T, T> {
9+
public UiThreadList(ObservableList<? extends T> source) {
10+
super(source);
11+
}
12+
13+
@Override
14+
protected void sourceChanged(ListChangeListener.Change<? extends T> change) {
15+
Platform.runLater(() -> fireChange(change));
16+
}
17+
18+
@Override
19+
public int getSourceIndex(int index) {
20+
return index;
21+
}
22+
23+
@Override
24+
public T get(int index) {
25+
return getSource().get(index);
26+
}
27+
28+
@Override
29+
public int size() {
30+
return getSource().size();
31+
}
32+
}

0 commit comments

Comments
 (0)