From 930fa4efb4d59b021b69321aaff164010f081c51 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 12 Mar 2019 21:47:15 +0100 Subject: [PATCH] Rework external changes dialog in JavaFX (#4693) * Rework external changes dialog in JavaFX * fix exception by running in FX thread * Fix appearance * Improve display --- src/main/java/org/jabref/gui/BasePanel.java | 26 +-- .../java/org/jabref/gui/SidePaneManager.java | 2 - .../java/org/jabref/gui/SidePaneType.java | 4 +- .../gui/collab/ChangeDisplayDialog.java | 194 ++++++------------ .../org/jabref/gui/collab/ChangeScanner.java | 124 +++-------- .../jabref/gui/collab/ChangeViewModel.java | 67 ------ .../gui/collab/DatabaseChangeListener.java | 7 + .../gui/collab/DatabaseChangeMonitor.java | 119 +++-------- .../jabref/gui/collab/DatabaseChangePane.java | 46 +++++ .../gui/collab/DatabaseChangeViewModel.java | 49 +++++ .../gui/collab/EntryAddChangeViewModel.java | 33 +-- .../gui/collab/EntryChangeViewModel.java | 119 +++++------ .../collab/EntryDeleteChangeViewModel.java | 32 +-- .../jabref/gui/collab/FileUpdatePanel.java | 129 ------------ .../gui/collab/GroupChangeViewModel.java | 43 ++-- .../java/org/jabref/gui/collab/InfoPane.java | 23 --- .../gui/collab/MetaDataChangeViewModel.java | 22 +- .../gui/collab/PreambleChangeViewModel.java | 62 +++--- .../gui/collab/StringAddChangeViewModel.java | 51 ++--- .../gui/collab/StringChangeViewModel.java | 68 +++--- .../gui/collab/StringNameChangeViewModel.java | 37 +--- .../collab/StringRemoveChangeViewModel.java | 42 ++-- .../logic/bibtex/comparator/PreambleDiff.java | 12 +- src/main/resources/l10n/JabRef_en.properties | 15 +- 24 files changed, 431 insertions(+), 895 deletions(-) delete mode 100644 src/main/java/org/jabref/gui/collab/ChangeViewModel.java create mode 100644 src/main/java/org/jabref/gui/collab/DatabaseChangeListener.java create mode 100644 src/main/java/org/jabref/gui/collab/DatabaseChangePane.java create mode 100644 src/main/java/org/jabref/gui/collab/DatabaseChangeViewModel.java delete mode 100644 src/main/java/org/jabref/gui/collab/FileUpdatePanel.java delete mode 100644 src/main/java/org/jabref/gui/collab/InfoPane.java diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 89d54058434..ea88315f304 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -41,7 +41,7 @@ import org.jabref.gui.autocompleter.PersonNameSuggestionProvider; import org.jabref.gui.autocompleter.SuggestionProviders; import org.jabref.gui.collab.DatabaseChangeMonitor; -import org.jabref.gui.collab.FileUpdatePanel; +import org.jabref.gui.collab.DatabaseChangePane; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.gui.edit.ReplaceStringAction; import org.jabref.gui.entryeditor.EntryEditor; @@ -116,6 +116,7 @@ public class BasePanel extends StackPane { private final BibDatabaseContext bibDatabaseContext; private final MainTableDataModel tableModel; + private final DatabaseChangePane changePane; private final CitationStyleCache citationStyleCache; private final FileAnnotationCache annotationCache; @@ -189,7 +190,9 @@ public BasePanel(JabRefFrame frame, BasePanelPreferences preferences, BibDatabas Optional file = bibDatabaseContext.getDatabaseFile(); if (file.isPresent()) { // Register so we get notifications about outside changes to the file. - changeMonitor = Optional.of(new DatabaseChangeMonitor(bibDatabaseContext, Globals.getFileUpdateMonitor(), this)); + changeMonitor = Optional.of(new DatabaseChangeMonitor(bibDatabaseContext, Globals.getFileUpdateMonitor(), Globals.TASK_EXECUTOR)); + changePane = new DatabaseChangePane(mainTable.getPane(), bibDatabaseContext, changeMonitor.get()); + getChildren().add(changePane); } else { if (bibDatabaseContext.getDatabase().hasEntries()) { // if the database is not empty and no file is assigned, @@ -197,6 +200,7 @@ public BasePanel(JabRefFrame frame, BasePanelPreferences preferences, BibDatabas // -> mark as changed this.baseChanged = true; } + changePane = null; } this.getDatabase().registerListener(new UpdateTimestampListener(Globals.prefs)); @@ -1098,14 +1102,6 @@ private void saveDividerLocation(Number position) { */ public void cleanUp() { changeMonitor.ifPresent(DatabaseChangeMonitor::unregister); - - // Check if there is a FileUpdatePanel for this BasePanel being shown. If so remove it: - if (sidePaneManager.isComponentVisible(SidePaneType.FILE_UPDATE_NOTIFICATION)) { - FileUpdatePanel fup = (FileUpdatePanel) sidePaneManager.getComponent(SidePaneType.FILE_UPDATE_NOTIFICATION); - if (fup.getPanel() == this) { - sidePaneManager.hide(SidePaneType.FILE_UPDATE_NOTIFICATION); - } - } } /** @@ -1122,10 +1118,6 @@ public BibDatabaseContext getBibDatabaseContext() { return this.bibDatabaseContext; } - public boolean isUpdatedExternally() { - return changeMonitor.map(DatabaseChangeMonitor::hasBeenModifiedExternally).orElse(false); - } - public void markExternalChangesAsResolved() { changeMonitor.ifPresent(DatabaseChangeMonitor::markExternalChangesAsResolved); } @@ -1210,17 +1202,13 @@ public FileAnnotationCache getAnnotationCache() { public void resetChangeMonitor() { changeMonitor.ifPresent(DatabaseChangeMonitor::unregister); - changeMonitor = Optional.of(new DatabaseChangeMonitor(bibDatabaseContext, Globals.getFileUpdateMonitor(), this)); + changeMonitor = Optional.of(new DatabaseChangeMonitor(bibDatabaseContext, Globals.getFileUpdateMonitor(), Globals.TASK_EXECUTOR)); } public void updateTimeStamp() { changeMonitor.ifPresent(DatabaseChangeMonitor::markAsSaved); } - public Path getTempFile() { - return changeMonitor.map(DatabaseChangeMonitor::getTempFile).orElse(null); - } - public void copy() { mainTable.copy(); } diff --git a/src/main/java/org/jabref/gui/SidePaneManager.java b/src/main/java/org/jabref/gui/SidePaneManager.java index 173a11a07c3..324810dd6ed 100644 --- a/src/main/java/org/jabref/gui/SidePaneManager.java +++ b/src/main/java/org/jabref/gui/SidePaneManager.java @@ -8,7 +8,6 @@ import java.util.stream.Stream; import org.jabref.Globals; -import org.jabref.gui.collab.FileUpdatePanel; import org.jabref.gui.groups.GroupSidePane; import org.jabref.gui.importer.fetcher.WebSearchPane; import org.jabref.gui.openoffice.OpenOfficeSidePanel; @@ -31,7 +30,6 @@ public SidePaneManager(JabRefPreferences preferences, JabRefFrame frame) { OpenOfficePreferences openOfficePreferences = preferences.getOpenOfficePreferences(); Stream.of( - new FileUpdatePanel(this), new GroupSidePane(this, preferences, frame.getDialogService()), new WebSearchPane(this, preferences, frame), new OpenOfficeSidePanel(this, preferences, frame)) diff --git a/src/main/java/org/jabref/gui/SidePaneType.java b/src/main/java/org/jabref/gui/SidePaneType.java index cd60411cf61..01cec0cedb1 100644 --- a/src/main/java/org/jabref/gui/SidePaneType.java +++ b/src/main/java/org/jabref/gui/SidePaneType.java @@ -4,5 +4,7 @@ * Definition of all possible components in the side pane. */ public enum SidePaneType { - OPEN_OFFICE, WEB_SEARCH, FILE_UPDATE_NOTIFICATION, GROUPS + OPEN_OFFICE, + WEB_SEARCH, + GROUPS } diff --git a/src/main/java/org/jabref/gui/collab/ChangeDisplayDialog.java b/src/main/java/org/jabref/gui/collab/ChangeDisplayDialog.java index ff67d3e19bb..1a522953e24 100644 --- a/src/main/java/org/jabref/gui/collab/ChangeDisplayDialog.java +++ b/src/main/java/org/jabref/gui/collab/ChangeDisplayDialog.java @@ -1,145 +1,81 @@ package org.jabref.gui.collab; -import java.awt.BorderLayout; -import java.awt.Insets; -import java.util.Collections; -import java.util.Enumeration; +import java.util.List; + +import javafx.collections.FXCollections; +import javafx.scene.control.ButtonBar; +import javafx.scene.control.ButtonType; +import javafx.scene.control.CheckBox; +import javafx.scene.control.Label; +import javafx.scene.control.ListView; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.SplitPane; +import javafx.scene.layout.BorderPane; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTree; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; - -import org.jabref.gui.BasePanel; -import org.jabref.gui.JabRefDialog; import org.jabref.gui.undo.NamedCompound; +import org.jabref.gui.util.BaseDialog; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; - -class ChangeDisplayDialog extends JabRefDialog implements TreeSelectionListener { - - private final JTree tree; - private final JPanel infoPanel = new JPanel(); - private final JCheckBox cb = new JCheckBox(Localization.lang("Accept change")); - private final JLabel rootInfo = new JLabel(Localization.lang("Select the tree nodes to view and accept or reject changes") + '.'); - private ChangeViewModel selected; - private JComponent infoShown; - private boolean okPressed; - - public ChangeDisplayDialog(final BasePanel panel, - BibDatabase secondary, final DefaultMutableTreeNode root) { - super(Localization.lang("External changes"), true, ChangeDisplayDialog.class); - BibDatabase localSecondary; - - // Just to be sure, put in an empty secondary base if none is given: - if (secondary == null) { - localSecondary = new BibDatabase(); - } else { - localSecondary = secondary; - } - tree = new JTree(root); - tree.addTreeSelectionListener(this); - - JSplitPane pane = new JSplitPane(); - pane.setLeftComponent(new JScrollPane(tree)); - JPanel infoBorder = new JPanel(); - pane.setRightComponent(infoBorder); - - cb.setMargin(new Insets(2, 2, 2, 2)); - cb.setEnabled(false); - infoPanel.setLayout(new BorderLayout()); - infoBorder.setLayout(new BorderLayout()); - infoBorder.setBorder(BorderFactory.createEtchedBorder()); - infoBorder.add(infoPanel, BorderLayout.CENTER); - setInfo(rootInfo); - infoPanel.add(cb, BorderLayout.SOUTH); - - JButton ok = new JButton(Localization.lang("OK")); - JPanel buttonPanel = new JPanel(); - buttonPanel.add(ok); - JButton cancel = new JButton(Localization.lang("Cancel")); - buttonPanel.add(cancel); - - getContentPane().add(pane, BorderLayout.CENTER); - getContentPane().add(buttonPanel, BorderLayout.SOUTH); +import org.jabref.model.database.BibDatabaseContext; + +import org.fxmisc.easybind.EasyBind; + +class ChangeDisplayDialog extends BaseDialog { + + private final ListView tree; + private final BorderPane infoPanel = new BorderPane(); + private final CheckBox cb = new CheckBox(Localization.lang("Accept change")); + + public ChangeDisplayDialog(BibDatabaseContext database, List changes) { + this.setTitle(Localization.lang("External changes")); + this.getDialogPane().setPrefSize(800, 600); + + tree = new ListView<>(FXCollections.observableArrayList(changes)); + tree.setPrefWidth(190); + EasyBind.subscribe(tree.getSelectionModel().selectedItemProperty(), this::selectedChangeChanged); + + SplitPane pane = new SplitPane(); + pane.setDividerPositions(0.25); + pane.getItems().addAll(new ScrollPane(tree), infoPanel); + getDialogPane().setContent(pane); + + infoPanel.setBottom(cb); + Label rootInfo = new Label(Localization.lang("Select the tree nodes to view and accept or reject changes") + '.'); + infoPanel.setCenter(rootInfo); + + getDialogPane().getButtonTypes().setAll( + new ButtonType(Localization.lang("Accept changes"), ButtonBar.ButtonData.APPLY), + ButtonType.CANCEL + ); + + setResultConverter(button -> { + if (button == ButtonType.CANCEL) { + return false; + } else { + // Perform all accepted changes + NamedCompound ce = new NamedCompound(Localization.lang("Merged external changes")); + for (DatabaseChangeViewModel change : changes) { + if (change.isAccepted()) { + change.makeChange(database, ce); + } + } + ce.end(); + //TODO: panel.getUndoManager().addEdit(ce); - cb.addChangeListener(e -> { - if (selected != null) { - selected.setAccepted(cb.isSelected()); + return true; } }); - cancel.addActionListener(e -> dispose()); - - ok.addActionListener(e -> { - - // Perform all accepted changes: - // Store all edits in an Undoable object: - NamedCompound ce = new NamedCompound(Localization.lang("Merged external changes")); - Enumeration enumer = root.children(); - boolean anyDisabled = false; - for (ChangeViewModel c : Collections.list(enumer)) { - boolean allAccepted = false; - if (c.isAcceptable() && c.isAccepted()) { - allAccepted = c.makeChange(panel, localSecondary, ce); - } - - if (!allAccepted) { - anyDisabled = true; - } - } - ce.end(); - panel.getUndoManager().addEdit(ce); - if (anyDisabled) { - panel.markBaseChanged(); + EasyBind.subscribe(cb.selectedProperty(), selected -> { + if (selected != null && tree.getSelectionModel().getSelectedItem() != null) { + tree.getSelectionModel().getSelectedItem().setAccepted(selected); } - panel.markExternalChangesAsResolved(); - dispose(); - okPressed = true; }); - - pack(); - } - - public boolean isOkPressed() { - return okPressed; - } - - private void setInfo(JComponent comp) { - if (infoShown != null) { - infoPanel.remove(infoShown); - } - infoShown = comp; - infoPanel.add(infoShown, BorderLayout.CENTER); - infoPanel.revalidate(); - infoPanel.repaint(); } - /** - * valueChanged - * - * @param e TreeSelectionEvent - */ - @Override - public void valueChanged(TreeSelectionEvent e) { - Object o = tree.getLastSelectedPathComponent(); - if (o instanceof ChangeViewModel) { - selected = (ChangeViewModel) o; - setInfo(selected.description()); - cb.setSelected(selected.isAccepted()); - cb.setEnabled(selected.isAcceptable()); - } else { - setInfo(rootInfo); - selected = null; - cb.setEnabled(false); + private void selectedChangeChanged(DatabaseChangeViewModel currentChange) { + if (currentChange != null) { + infoPanel.setCenter(currentChange.description()); + cb.setSelected(currentChange.isAccepted()); } } } diff --git a/src/main/java/org/jabref/gui/collab/ChangeScanner.java b/src/main/java/org/jabref/gui/collab/ChangeScanner.java index 7fb1b74e388..021a941c87f 100644 --- a/src/main/java/org/jabref/gui/collab/ChangeScanner.java +++ b/src/main/java/org/jabref/gui/collab/ChangeScanner.java @@ -1,68 +1,33 @@ package org.jabref.gui.collab; -import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Optional; -import javax.swing.SwingUtilities; -import javax.swing.tree.DefaultMutableTreeNode; - import org.jabref.Globals; -import org.jabref.JabRefExecutorService; -import org.jabref.gui.BasePanel; -import org.jabref.gui.JabRefFrame; import org.jabref.logic.bibtex.DuplicateCheck; import org.jabref.logic.bibtex.comparator.BibDatabaseDiff; import org.jabref.logic.bibtex.comparator.BibEntryDiff; import org.jabref.logic.bibtex.comparator.BibStringDiff; -import org.jabref.logic.exporter.AtomicFileWriter; -import org.jabref.logic.exporter.BibDatabaseWriter; -import org.jabref.logic.exporter.BibtexDatabaseWriter; -import org.jabref.logic.exporter.SavePreferences; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.OpenDatabase; import org.jabref.logic.importer.ParserResult; -import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibtexString; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ChangeScanner implements Runnable { - - private static final Logger LOGGER = LoggerFactory.getLogger(ChangeScanner.class); +public class ChangeScanner { - private final Optional file; - private final Path tempFile; - private final BibDatabaseContext databaseInMemory; + private final Path referenceFile; + private final BibDatabaseContext database; + private final List changes = new ArrayList<>(); + private BibDatabaseContext referenceDatabase; - private final BasePanel panel; - private final JabRefFrame frame; - private BibDatabaseContext databaseInTemp; - - /** - * We create an ArrayList to hold the changes we find. These will be added in the form - * of UndoEdit objects. We instantiate these so that the changes found in the file on disk - * can be reproduced in memory by calling redo() on them. REDO, not UNDO! - */ - private final DefaultMutableTreeNode changes = new DefaultMutableTreeNode(Localization.lang("External changes")); - - // NamedCompound edit = new NamedCompound("Merged external changes") - - public ChangeScanner(JabRefFrame frame, BasePanel bp, Path file, Path tempFile) { - this.panel = bp; - this.frame = frame; - this.databaseInMemory = bp.getBibDatabaseContext(); - this.file = Optional.ofNullable(file); - this.tempFile = tempFile; - } - - public boolean changesFound() { - return changes.getChildCount() > 0; + public ChangeScanner(BibDatabaseContext database, Path referenceFile) { + this.database = database; + this.referenceFile = referenceFile; } /** @@ -75,101 +40,58 @@ private static BibEntry bestFit(BibEntry targetEntry, List entries) { .orElse(null); } - public void displayResult(final DisplayResultCallback fup) { - if (changes.getChildCount() > 0) { - SwingUtilities.invokeLater(() -> { - ChangeDisplayDialog changeDialog = new ChangeDisplayDialog(panel, databaseInTemp.getDatabase(), changes); - changeDialog.setVisible(true); - fup.scanResultsResolved(changeDialog.isOkPressed()); - if (changeDialog.isOkPressed()) { - // Overwrite the temp database: - storeTempDatabase(); - } - }); - } else { - frame.getDialogService().showInformationDialogAndWait(Localization.lang("External changes"), - Localization.lang("No actual changes found.")); - - fup.scanResultsResolved(true); - } - } - - private void storeTempDatabase() { - JabRefExecutorService.INSTANCE.execute(() -> { - try { - SavePreferences prefs = Globals.prefs.loadForSaveFromPreferences() - .withMakeBackup(false) - .withEncoding(panel.getBibDatabaseContext() - .getMetaData() - .getEncoding() - .orElse(Globals.prefs.getDefaultEncoding())); - - BibDatabaseWriter databaseWriter = new BibtexDatabaseWriter(new AtomicFileWriter(tempFile, prefs.getEncoding()), prefs); - databaseWriter.saveDatabase(databaseInTemp); - } catch (IOException ex) { - LOGGER.warn("Problem updating tmp file after accepting external changes", ex); - } - }); - } - - @Override - public void run() { - file.ifPresent(diskdb -> { + public List scanForChanges() { + database.getDatabasePath().ifPresent(diskdb -> { // Parse the temporary file. ImportFormatPreferences importFormatPreferences = Globals.prefs.getImportFormatPreferences(); - ParserResult result = OpenDatabase.loadDatabase(tempFile.toAbsolutePath().toString(), importFormatPreferences, Globals.getFileUpdateMonitor()); - databaseInTemp = result.getDatabaseContext(); + ParserResult result = OpenDatabase.loadDatabase(referenceFile.toAbsolutePath().toString(), importFormatPreferences, Globals.getFileUpdateMonitor()); + referenceDatabase = result.getDatabaseContext(); // Parse the modified file. result = OpenDatabase.loadDatabase(diskdb.toAbsolutePath().toString(), importFormatPreferences, Globals.getFileUpdateMonitor()); BibDatabaseContext databaseOnDisk = result.getDatabaseContext(); // Start looking at changes. - BibDatabaseDiff differences = BibDatabaseDiff.compare(databaseInTemp, databaseOnDisk); + BibDatabaseDiff differences = BibDatabaseDiff.compare(referenceDatabase, databaseOnDisk); differences.getMetaDataDifferences().ifPresent(diff -> { changes.add(new MetaDataChangeViewModel(diff)); diff.getGroupDifferences().ifPresent(groupDiff -> changes.add(new GroupChangeViewModel(groupDiff))); }); - differences.getPreambleDifferences().ifPresent(diff -> changes.add(new PreambleChangeViewModel(databaseInMemory.getDatabase().getPreamble().orElse(""), diff))); + differences.getPreambleDifferences().ifPresent(diff -> changes.add(new PreambleChangeViewModel(diff))); differences.getBibStringDifferences().forEach(diff -> changes.add(createBibStringDiff(diff))); differences.getEntryDifferences().forEach(diff -> changes.add(createBibEntryDiff(diff))); }); + return changes; } - private ChangeViewModel createBibStringDiff(BibStringDiff diff) { + private DatabaseChangeViewModel createBibStringDiff(BibStringDiff diff) { if (diff.getOriginalString() == null) { return new StringAddChangeViewModel(diff.getNewString()); } if (diff.getNewString() == null) { - Optional current = databaseInMemory.getDatabase().getStringByName(diff.getOriginalString().getName()); + Optional current = database.getDatabase().getStringByName(diff.getOriginalString().getName()); return new StringRemoveChangeViewModel(diff.getOriginalString(), current.orElse(null)); } if (diff.getOriginalString().getName().equals(diff.getNewString().getName())) { - Optional current = databaseInMemory.getDatabase().getStringByName(diff.getOriginalString().getName()); + Optional current = database.getDatabase().getStringByName(diff.getOriginalString().getName()); return new StringChangeViewModel(current.orElse(null), diff.getOriginalString(), diff.getNewString().getContent()); } - Optional current = databaseInMemory.getDatabase().getStringByName(diff.getOriginalString().getName()); + Optional current = database.getDatabase().getStringByName(diff.getOriginalString().getName()); return new StringNameChangeViewModel(current.orElse(null), diff.getOriginalString(), current.map(BibtexString::getName).orElse(""), diff.getNewString().getName()); } - private ChangeViewModel createBibEntryDiff(BibEntryDiff diff) { + private DatabaseChangeViewModel createBibEntryDiff(BibEntryDiff diff) { if (diff.getOriginalEntry() == null) { return new EntryAddChangeViewModel(diff.getNewEntry()); } if (diff.getNewEntry() == null) { - return new EntryDeleteChangeViewModel(bestFit(diff.getOriginalEntry(), databaseInMemory.getEntries()), diff.getOriginalEntry()); + return new EntryDeleteChangeViewModel(bestFit(diff.getOriginalEntry(), database.getEntries()), diff.getOriginalEntry()); } - return new EntryChangeViewModel(bestFit(diff.getOriginalEntry(), databaseInMemory.getEntries()), diff.getOriginalEntry(), diff.getNewEntry()); - } - - @FunctionalInterface - public interface DisplayResultCallback { - - void scanResultsResolved(boolean resolved); + return new EntryChangeViewModel(bestFit(diff.getOriginalEntry(), database.getEntries()), diff.getOriginalEntry(), diff.getNewEntry()); } } diff --git a/src/main/java/org/jabref/gui/collab/ChangeViewModel.java b/src/main/java/org/jabref/gui/collab/ChangeViewModel.java deleted file mode 100644 index 0561a799b24..00000000000 --- a/src/main/java/org/jabref/gui/collab/ChangeViewModel.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.jabref.gui.collab; - -import javax.swing.JComponent; -import javax.swing.tree.DefaultMutableTreeNode; - -import org.jabref.gui.BasePanel; -import org.jabref.gui.undo.NamedCompound; -import org.jabref.model.database.BibDatabase; - -abstract class ChangeViewModel extends DefaultMutableTreeNode { - - protected String name; - private boolean accepted = true; - - - ChangeViewModel() { - name = ""; - } - - ChangeViewModel(String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } - - public boolean isAccepted() { - return accepted; - } - - public void setAccepted(boolean a) { - accepted = a; - } - - /** - * This method is used to disable the "accept" box if the parent has been set to "not accepted". - * Thus the user can disable e.g. an entry change without having to disable all field changes. - * @return boolean false if the parent overrides by not being accepted. - */ - public boolean isAcceptable() { - if ((getParent() != null) && (getParent() instanceof ChangeViewModel)) { - return ((ChangeViewModel) getParent()).isAccepted(); - } else { - return true; - } - } - - /** - * This method returns a JComponent detailing the nature of the change. - * @return JComponent - */ - public abstract JComponent description(); - - /** - * Perform the change. This method is responsible for adding a proper undo edit to - * the NamedCompound, so the change can be undone. - * @param panel BasePanel The tab where the database lives. - * @param secondary BibDatabase The "tmp" database for which the change - * should also be made. - * @param undoEdit NamedCompound The compound to hold the undo edits. - * @return true if all changes were made, false if not all were accepted. - */ - public abstract boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit); - -} diff --git a/src/main/java/org/jabref/gui/collab/DatabaseChangeListener.java b/src/main/java/org/jabref/gui/collab/DatabaseChangeListener.java new file mode 100644 index 00000000000..cfb9ac2e1ff --- /dev/null +++ b/src/main/java/org/jabref/gui/collab/DatabaseChangeListener.java @@ -0,0 +1,7 @@ +package org.jabref.gui.collab; + +import java.util.List; + +public interface DatabaseChangeListener { + void databaseChanged(List changes); +} diff --git a/src/main/java/org/jabref/gui/collab/DatabaseChangeMonitor.java b/src/main/java/org/jabref/gui/collab/DatabaseChangeMonitor.java index 701679fed5f..2bf20a9b69d 100644 --- a/src/main/java/org/jabref/gui/collab/DatabaseChangeMonitor.java +++ b/src/main/java/org/jabref/gui/collab/DatabaseChangeMonitor.java @@ -3,14 +3,11 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Optional; +import java.util.ArrayList; +import java.util.List; -import javax.swing.SwingUtilities; - -import org.jabref.JabRefExecutorService; -import org.jabref.gui.BasePanel; -import org.jabref.gui.SidePaneManager; -import org.jabref.gui.SidePaneType; +import org.jabref.gui.util.BackgroundTask; +import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.util.FileUpdateListener; @@ -24,25 +21,22 @@ public class DatabaseChangeMonitor implements FileUpdateListener { private final BibDatabaseContext database; private final FileUpdateMonitor fileMonitor; - private final BasePanel panel; - private boolean updatedExternally; - private Path tmpFile; - private long timeStamp; - private long fileSize; + private final List listeners; + private Path referenceFile; + private TaskExecutor taskExecutor; - public DatabaseChangeMonitor(BibDatabaseContext database, FileUpdateMonitor fileMonitor, BasePanel panel) { + public DatabaseChangeMonitor(BibDatabaseContext database, FileUpdateMonitor fileMonitor, TaskExecutor taskExecutor) { this.database = database; this.fileMonitor = fileMonitor; - this.panel = panel; + this.taskExecutor = taskExecutor; + this.listeners = new ArrayList<>(); this.database.getDatabasePath().ifPresent(path -> { try { fileMonitor.addListenerForFile(path, this); - timeStamp = Files.getLastModifiedTime(path).toMillis(); - fileSize = Files.size(path); - tmpFile = Files.createTempFile("jabref", ".bib"); - tmpFile.toFile().deleteOnExit(); - copyToTemp(path); + referenceFile = Files.createTempFile("jabref", ".bib"); + referenceFile.toFile().deleteOnExit(); + setAsReference(path); } catch (IOException e) { LOGGER.error("Error while trying to monitor " + path, e); } @@ -51,93 +45,34 @@ public DatabaseChangeMonitor(BibDatabaseContext database, FileUpdateMonitor file @Override public void fileUpdated() { - if (panel.isSaving()) { - // We are just saving the file, so this message is most likely due to bad timing. - // If not, we'll handle it on the next polling. - return; - } - - updatedExternally = true; - - final ChangeScanner scanner = new ChangeScanner(panel.frame(), panel, database.getDatabasePath().orElse(null), tmpFile); - JabRefExecutorService.INSTANCE.executeInterruptableTaskAndWait(scanner); - - // Adding the sidepane component is Swing work, so we must do this in the Swing - // thread: - Runnable t = () -> { - - // Check if there is already a notification about external changes: - SidePaneManager sidePaneManager = panel.getSidePaneManager(); - boolean hasAlready = sidePaneManager.isComponentVisible(SidePaneType.FILE_UPDATE_NOTIFICATION); - if (hasAlready) { - sidePaneManager.hide(SidePaneType.FILE_UPDATE_NOTIFICATION); - } - - FileUpdatePanel component = (FileUpdatePanel) sidePaneManager.getComponent(SidePaneType.FILE_UPDATE_NOTIFICATION); - component.showForFile(panel, database.getDatabaseFile().orElse(null), scanner); - }; - - if (scanner.changesFound()) { - SwingUtilities.invokeLater(t); - } else { - updatedExternally = false; - } + // File on disk has changed, thus look for notable changes and notify listeners in case there are such changes + ChangeScanner scanner = new ChangeScanner(database, referenceFile); + BackgroundTask.wrap(scanner::scanForChanges) + .onSuccess(changes -> { + if (!changes.isEmpty()) { + listeners.forEach(listener -> listener.databaseChanged(changes)); + } + }) + .executeWith(taskExecutor); } - /** - * Forces a check on the file, and returns the result. Check if time stamp or the file size has changed. - * - * @return boolean true if the file has changed. - */ - private boolean hasBeenModified() { - Optional file = database.getDatabasePath(); - if (file.isPresent()) { - try { - long modified = Files.getLastModifiedTime(file.get()).toMillis(); - if (modified == 0L) { - // File deleted - return false; - } - long fileSizeNow = Files.size(file.get()); - return (timeStamp != modified) || (fileSize != fileSizeNow); - } catch (IOException ex) { - return false; - } - } - return false; + public void addListener(DatabaseChangeListener listener) { + listeners.add(listener); } public void unregister() { database.getDatabasePath().ifPresent(file -> fileMonitor.removeListener(file, this)); } - public boolean hasBeenModifiedExternally() { - return updatedExternally || hasBeenModified(); - } - public void markExternalChangesAsResolved() { - updatedExternally = false; markAsSaved(); } public void markAsSaved() { - database.getDatabasePath().ifPresent(file -> { - try { - timeStamp = Files.getLastModifiedTime(file).toMillis(); - fileSize = Files.size(file); - - copyToTemp(file); - } catch (IOException ex) { - LOGGER.error("Error while getting file information", ex); - } - }); - } - - private void copyToTemp(Path file) { - FileUtil.copyFile(file, tmpFile, true); + database.getDatabasePath().ifPresent(this::setAsReference); } - public Path getTempFile() { - return tmpFile; + private void setAsReference(Path file) { + FileUtil.copyFile(file, referenceFile, true); } } diff --git a/src/main/java/org/jabref/gui/collab/DatabaseChangePane.java b/src/main/java/org/jabref/gui/collab/DatabaseChangePane.java new file mode 100644 index 00000000000..17582a41ba9 --- /dev/null +++ b/src/main/java/org/jabref/gui/collab/DatabaseChangePane.java @@ -0,0 +1,46 @@ +package org.jabref.gui.collab; + +import java.util.List; + +import javafx.scene.Node; + +import org.jabref.gui.icon.IconTheme; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.database.BibDatabaseContext; + +import org.controlsfx.control.NotificationPane; +import org.controlsfx.control.action.Action; + +public class DatabaseChangePane extends NotificationPane { + + private final DatabaseChangeMonitor monitor; + private final BibDatabaseContext database; + + public DatabaseChangePane(Node parent, BibDatabaseContext database, DatabaseChangeMonitor monitor) { + super(parent); + this.database = database; + this.monitor = monitor; + + this.setGraphic(IconTheme.JabRefIcons.SAVE.getGraphicNode()); + this.setText(Localization.lang("The library has been modified by another program.")); + + monitor.addListener(this::onDatabaseChanged); + } + + private void onDatabaseChanged(List changes) { + this.getActions().setAll( + new Action(Localization.lang("Dismiss changes"), event -> { + monitor.markExternalChangesAsResolved(); + this.hide(); + }), + new Action(Localization.lang("Review changes"), event -> { + ChangeDisplayDialog changeDialog = new ChangeDisplayDialog(database, changes); + boolean changesHandled = changeDialog.showAndWait().orElse(false); + if (changesHandled) { + monitor.markExternalChangesAsResolved(); + this.hide(); + } + })); + this.show(); + } +} diff --git a/src/main/java/org/jabref/gui/collab/DatabaseChangeViewModel.java b/src/main/java/org/jabref/gui/collab/DatabaseChangeViewModel.java new file mode 100644 index 00000000000..88f4d200ed5 --- /dev/null +++ b/src/main/java/org/jabref/gui/collab/DatabaseChangeViewModel.java @@ -0,0 +1,49 @@ +package org.jabref.gui.collab; + +import javafx.scene.Node; + +import org.jabref.gui.undo.NamedCompound; +import org.jabref.model.database.BibDatabaseContext; + +abstract class DatabaseChangeViewModel { + + protected String name; + private boolean accepted = true; + + DatabaseChangeViewModel() { + name = ""; + } + + DatabaseChangeViewModel(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + + public boolean isAccepted() { + return accepted; + } + + public void setAccepted(boolean a) { + accepted = a; + } + + + /** + * This method returns a JComponent detailing the nature of the change. + * @return JComponent + */ + public abstract Node description(); + + /** + * Performs the change. This method is responsible for adding a proper undo edit to + * the NamedCompound, so the change can be undone. + * @param database the database that should be modified accordingly. + * @param undoEdit NamedCompound The compound to hold the undo edits. + */ + public abstract void makeChange(BibDatabaseContext database, NamedCompound undoEdit); + +} diff --git a/src/main/java/org/jabref/gui/collab/EntryAddChangeViewModel.java b/src/main/java/org/jabref/gui/collab/EntryAddChangeViewModel.java index 622dc4142cf..8284f544cab 100644 --- a/src/main/java/org/jabref/gui/collab/EntryAddChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/EntryAddChangeViewModel.java @@ -1,49 +1,36 @@ package org.jabref.gui.collab; -import javax.swing.JComponent; - -import javafx.embed.swing.JFXPanel; -import javafx.scene.Scene; +import javafx.scene.Node; import org.jabref.Globals; -import org.jabref.gui.BasePanel; import org.jabref.gui.FXDialogService; import org.jabref.gui.PreviewPanel; -import org.jabref.gui.customjfx.CustomJFXPanel; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableInsertEntry; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.IdGenerator; -class EntryAddChangeViewModel extends ChangeViewModel { +class EntryAddChangeViewModel extends DatabaseChangeViewModel { private final BibEntry diskEntry; - private final JFXPanel container; - public EntryAddChangeViewModel(BibEntry diskEntry) { super(Localization.lang("Added entry")); this.diskEntry = diskEntry; - - PreviewPanel previewPanel = new PreviewPanel(null, null, Globals.getKeyPrefs(), Globals.prefs.getPreviewPreferences(), new FXDialogService(), ExternalFileTypes.getInstance()); - previewPanel.setEntry(diskEntry); - container = CustomJFXPanel.wrap(new Scene(previewPanel)); } @Override - public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) { - diskEntry.setId(IdGenerator.next()); - panel.getDatabase().insertEntry(diskEntry); - secondary.insertEntry(diskEntry); - undoEdit.addEdit(new UndoableInsertEntry(panel.getDatabase(), diskEntry)); - return true; + public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { + database.getDatabase().insertEntry(diskEntry); + undoEdit.addEdit(new UndoableInsertEntry(database.getDatabase(), diskEntry)); } @Override - public JComponent description() { - return container; + public Node description() { + PreviewPanel previewPanel = new PreviewPanel(null, null, Globals.getKeyPrefs(), Globals.prefs.getPreviewPreferences(), new FXDialogService(), ExternalFileTypes.getInstance()); + previewPanel.setEntry(diskEntry); + return previewPanel; } } diff --git a/src/main/java/org/jabref/gui/collab/EntryChangeViewModel.java b/src/main/java/org/jabref/gui/collab/EntryChangeViewModel.java index 7a63b4aed8f..fcad087163d 100644 --- a/src/main/java/org/jabref/gui/collab/EntryChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/EntryChangeViewModel.java @@ -1,38 +1,36 @@ package org.jabref.gui.collab; -import java.util.Collections; -import java.util.Enumeration; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.TreeSet; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JScrollPane; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; -import org.jabref.gui.BasePanel; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.logic.bibtex.DuplicateCheck; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -class EntryChangeViewModel extends ChangeViewModel { +class EntryChangeViewModel extends DatabaseChangeViewModel { private static final Logger LOGGER = LoggerFactory.getLogger(EntryChangeViewModel.class); + private final List fieldChanges = new ArrayList<>(); + public EntryChangeViewModel(BibEntry memEntry, BibEntry tmpEntry, BibEntry diskEntry) { super(); - Optional key = tmpEntry.getCiteKeyOptional(); - if (key.isPresent()) { - name = Localization.lang("Modified entry") + ": '" + key.get() + '\''; - } else { - name = Localization.lang("Modified entry"); - } + name = tmpEntry.getCiteKeyOptional() + .map(key -> Localization.lang("Modified entry") + ": '" + key + '\'') + .orElse(Localization.lang("Modified entry")); // We know that tmpEntry is not equal to diskEntry. Check if it has been modified // locally as well, since last tempfile was saved. @@ -58,55 +56,48 @@ public EntryChangeViewModel(BibEntry memEntry, BibEntry tmpEntry, BibEntry diskE if ((tmp.isPresent()) && (disk.isPresent())) { if (!tmp.equals(disk)) { // Modified externally. - add(new FieldChangeViewModel(field, memEntry, tmpEntry, mem.orElse(null), tmp.get(), disk.get())); + fieldChanges.add(new FieldChangeViewModel(field, memEntry, tmpEntry, mem.orElse(null), tmp.get(), disk.get())); } } else if (((!tmp.isPresent()) && (disk.isPresent()) && !disk.get().isEmpty()) || ((!disk.isPresent()) && (tmp.isPresent()) && !tmp.get().isEmpty() && (mem.isPresent()) && !mem.get().isEmpty())) { // Added externally. - add(new FieldChangeViewModel(field, memEntry, tmpEntry, mem.orElse(null), tmp.orElse(null), - disk.orElse(null))); + fieldChanges.add(new FieldChangeViewModel(field, memEntry, tmpEntry, mem.orElse(null), tmp.orElse(null), disk.orElse(null))); } } } @Override - public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) { - boolean allAccepted = true; - - Enumeration e = children(); - for (ChangeViewModel c : Collections.list(e)) { - if (c.isAcceptable() && c.isAccepted()) { - c.makeChange(panel, secondary, undoEdit); - } else { - allAccepted = false; + public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { + for (DatabaseChangeViewModel c : fieldChanges) { + if (c.isAccepted()) { + c.makeChange(database, undoEdit); } } - - /*panel.database().removeEntry(memEntry.getId()); - try { - diskEntry.setId(Util.next()); - } catch (KeyCollisionException ex) {} - panel.database().removeEntry(memEntry.getId());*/ - - return allAccepted; } @Override - public JComponent description() { - return new JLabel(name); + public Node description() { + VBox container = new VBox(); + Label header = new Label(name); + header.getStyleClass().add("sectionHeader"); + container.getChildren().add(header); + + for (FieldChangeViewModel change : fieldChanges) { + container.getChildren().add(change.description()); + } + + return container; } - static class FieldChangeViewModel extends ChangeViewModel { + static class FieldChangeViewModel extends DatabaseChangeViewModel { private final BibEntry entry; private final BibEntry tmpEntry; private final String field; private final String inMem; + private final String onTmp; private final String onDisk; - private final InfoPane tp = new InfoPane(); - private final JScrollPane sp = new JScrollPane(tp); - public FieldChangeViewModel(String field, BibEntry memEntry, BibEntry tmpEntry, String inMem, String onTmp, String onDisk) { super(field); @@ -114,47 +105,39 @@ public FieldChangeViewModel(String field, BibEntry memEntry, BibEntry tmpEntry, this.tmpEntry = tmpEntry; this.field = field; this.inMem = inMem; + this.onTmp = onTmp; this.onDisk = onDisk; - - StringBuilder text = new StringBuilder(36); - text.append("

").append(Localization.lang("Modification of field")) - .append(" ").append(field).append("

"); - - if ((onDisk != null) && !onDisk.isEmpty()) { - text.append("

").append(Localization.lang("Value set externally")).append(":

").append(onDisk); - } else { - text.append("

").append(Localization.lang("Value cleared externally")).append("

"); - } - - if ((inMem != null) && !inMem.isEmpty()) { - text.append("

").append(Localization.lang("Current value")).append(":

").append(inMem); - } - if ((onTmp != null) && !onTmp.isEmpty()) { - text.append("

").append(Localization.lang("Current tmp value")).append(":

").append(onTmp); - } - tp.setContentType("text/html"); - tp.setText(text.toString()); } @Override - public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) { + public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { if (onDisk == null) { entry.clearField(field); } else { entry.setField(field, onDisk); } undoEdit.addEdit(new UndoableFieldChange(entry, field, inMem, onDisk)); - if (onDisk == null) { - tmpEntry.clearField(field); - } else { - tmpEntry.setField(field, onDisk); - } - return true; } @Override - public JComponent description() { - return sp; + public Node description() { + VBox container = new VBox(); + container.getChildren().add(new Label(Localization.lang("Modification of field") + " " + field)); + + if ((onDisk != null) && !onDisk.isEmpty()) { + container.getChildren().add(new Label(Localization.lang("Value set externally") + ": " + onDisk)); + } else { + container.getChildren().add(new Label(Localization.lang("Value cleared externally"))); + } + + if ((inMem != null) && !inMem.isEmpty()) { + container.getChildren().add(new Label(Localization.lang("Current value") + ": " + inMem)); + } + if ((onTmp != null) && !onTmp.isEmpty()) { + container.getChildren().add(new Label(Localization.lang("Current tmp value") + ": " + onTmp)); + } + + return container; } } diff --git a/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java b/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java index 37511d67830..22f4c9a80b9 100644 --- a/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java @@ -1,35 +1,27 @@ package org.jabref.gui.collab; -import javax.swing.JComponent; - -import javafx.embed.swing.JFXPanel; -import javafx.scene.Scene; +import javafx.scene.Node; import org.jabref.Globals; -import org.jabref.gui.BasePanel; import org.jabref.gui.FXDialogService; import org.jabref.gui.PreviewPanel; -import org.jabref.gui.customjfx.CustomJFXPanel; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableRemoveEntry; import org.jabref.logic.bibtex.DuplicateCheck; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -class EntryDeleteChangeViewModel extends ChangeViewModel { +class EntryDeleteChangeViewModel extends DatabaseChangeViewModel { private static final Logger LOGGER = LoggerFactory.getLogger(EntryDeleteChangeViewModel.class); private final BibEntry memEntry; private final BibEntry tmpEntry; - private final JFXPanel container; - - public EntryDeleteChangeViewModel(BibEntry memEntry, BibEntry tmpEntry) { super(Localization.lang("Deleted entry")); this.memEntry = memEntry; @@ -44,22 +36,18 @@ public EntryDeleteChangeViewModel(BibEntry memEntry, BibEntry tmpEntry) { LOGGER.debug("Modified entry: " + memEntry.getCiteKeyOptional().orElse("") + "\n Modified locally: " + isModifiedLocally); - - PreviewPanel previewPanel = new PreviewPanel(null, null, Globals.getKeyPrefs(), Globals.prefs.getPreviewPreferences(), new FXDialogService(), ExternalFileTypes.getInstance()); - previewPanel.setEntry(memEntry); - container = CustomJFXPanel.wrap(new Scene(previewPanel)); } @Override - public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) { - panel.getDatabase().removeEntry(memEntry); - undoEdit.addEdit(new UndoableRemoveEntry(panel.getDatabase(), memEntry, panel)); - secondary.removeEntry(tmpEntry); - return true; + public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { + database.getDatabase().removeEntry(memEntry); + undoEdit.addEdit(new UndoableRemoveEntry(database.getDatabase(), memEntry, null)); } @Override - public JComponent description() { - return container; + public Node description() { + PreviewPanel previewPanel = new PreviewPanel(null, null, Globals.getKeyPrefs(), Globals.prefs.getPreviewPreferences(), new FXDialogService(), ExternalFileTypes.getInstance()); + previewPanel.setEntry(memEntry); + return previewPanel; } } diff --git a/src/main/java/org/jabref/gui/collab/FileUpdatePanel.java b/src/main/java/org/jabref/gui/collab/FileUpdatePanel.java deleted file mode 100644 index ea270674a02..00000000000 --- a/src/main/java/org/jabref/gui/collab/FileUpdatePanel.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.jabref.gui.collab; - -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; - -import javafx.embed.swing.SwingNode; -import javafx.scene.Node; -import javafx.scene.layout.Priority; - -import org.jabref.gui.BasePanel; -import org.jabref.gui.SidePaneComponent; -import org.jabref.gui.SidePaneManager; -import org.jabref.gui.SidePaneType; -import org.jabref.gui.actions.Action; -import org.jabref.gui.icon.IconTheme; -import org.jabref.logic.l10n.Localization; - -public class FileUpdatePanel extends SidePaneComponent implements ActionListener, ChangeScanner.DisplayResultCallback { - - private final SidePaneManager manager; - private ChangeScanner scanner; - private File file; - private BasePanel panel; - - public FileUpdatePanel(SidePaneManager manager) { - super(manager, IconTheme.JabRefIcons.SAVE, Localization.lang("File changed")); - - this.manager = manager; - } - - public void showForFile(BasePanel panel, File file, ChangeScanner scanner) { - this.file = file; - this.panel = panel; - this.scanner = scanner; - - this.show(); - } - - /** - * We include a getter for the BasePanel this component refers to, because this - * component needs to be closed if the BasePanel is closed. - * @return the base panel this component refers to. - */ - public BasePanel getPanel() { - return panel; - } - - @Override - public Priority getResizePolicy() { - return Priority.NEVER; - } - - @Override - public ToggleCommand getToggleCommand() { - throw new UnsupportedOperationException(); - } - - @Override - public Action getToggleAction() { - throw new UnsupportedOperationException(); - } - - @Override - protected Node createContentPane() { - JPanel main = new JPanel(); - main.setLayout(new BorderLayout()); - - JLabel message = new JLabel("
" - + Localization.lang("The file
'%0'
has been modified
externally!", file.getName()) - + "
", SwingConstants.CENTER); - - main.add(message, BorderLayout.CENTER); - JButton reviewChanges = new JButton(Localization.lang("Review changes")); - reviewChanges.addActionListener(this); - main.add(reviewChanges, BorderLayout.SOUTH); - main.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); - - SwingNode swingNode = new SwingNode(); - SwingUtilities.invokeLater(() -> swingNode.setContent(main)); - return swingNode; - } - - @Override - public SidePaneType getType() { - return SidePaneType.FILE_UPDATE_NOTIFICATION; - } - - /** - * actionPerformed - * - * @param e - * ActionEvent - */ - @Override - public void actionPerformed(ActionEvent e) { - - // ChangeScanner scanner = new ChangeScanner(frame, panel); //, - // panel.database(), panel.metaData()); - // try { - scanner.displayResult(this); - // scanner.changeScan(panel.file()); - - // } catch (IOException ex) { - // ex.printStackTrace(); - // } - } - - /** - * Callback method for signalling that the change scanner has displayed the - * scan results to the user. - * @param resolved true if there were no changes, or if the user has resolved them. - */ - @Override - public void scanResultsResolved(boolean resolved) { - if (resolved) { - manager.hide(this.getType()); - panel.markExternalChangesAsResolved(); - } - } -} diff --git a/src/main/java/org/jabref/gui/collab/GroupChangeViewModel.java b/src/main/java/org/jabref/gui/collab/GroupChangeViewModel.java index 99826a5886c..e6b75feaa38 100644 --- a/src/main/java/org/jabref/gui/collab/GroupChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/GroupChangeViewModel.java @@ -1,40 +1,36 @@ package org.jabref.gui.collab; -import javax.swing.JComponent; -import javax.swing.JLabel; +import javafx.scene.Node; +import javafx.scene.control.Label; -import org.jabref.gui.BasePanel; import org.jabref.gui.groups.GroupTreeNodeViewModel; import org.jabref.gui.groups.UndoableModifySubtree; import org.jabref.gui.undo.NamedCompound; import org.jabref.logic.bibtex.comparator.GroupDiff; import org.jabref.logic.groups.DefaultGroupsFactory; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.groups.GroupTreeNode; -class GroupChangeViewModel extends ChangeViewModel { +class GroupChangeViewModel extends DatabaseChangeViewModel { private final GroupTreeNode changedGroups; - private final GroupTreeNode tmpGroupRoot; - public GroupChangeViewModel(GroupDiff diff) { super(diff.getOriginalGroupRoot() == null ? Localization.lang("Removed all groups") : Localization .lang("Modified groups tree")); - this.changedGroups = diff.getOriginalGroupRoot(); - this.tmpGroupRoot = diff.getNewGroupRoot(); + this.changedGroups = diff.getNewGroupRoot(); } @Override - public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) { - GroupTreeNode root = panel.getBibDatabaseContext().getMetaData().getGroups().orElse(null); + public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { + GroupTreeNode root = database.getMetaData().getGroups().orElse(null); if (root == null) { root = new GroupTreeNode(DefaultGroupsFactory.getAllEntriesGroup()); - panel.getBibDatabaseContext().getMetaData().setGroups(root); + database.getMetaData().setGroups(root); } final UndoableModifySubtree undo = new UndoableModifySubtree( - new GroupTreeNodeViewModel(panel.getBibDatabaseContext().getMetaData().getGroups().orElse(null)), + new GroupTreeNodeViewModel(database.getMetaData().getGroups().orElse(null)), new GroupTreeNodeViewModel(root), Localization.lang("Modified groups")); root.removeAllChildren(); if (changedGroups == null) { @@ -49,28 +45,13 @@ public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound } undoEdit.addEdit(undo); - - // Update tmp database: - if (tmpGroupRoot != null) { - tmpGroupRoot.removeAllChildren(); - if (changedGroups != null) { - GroupTreeNode copied = changedGroups.copySubtree(); - tmpGroupRoot.setGroup(copied.getGroup()); - for (GroupTreeNode child : copied.getChildren()) { - child.copySubtree().moveTo(tmpGroupRoot); - } - } - } - - return true; } @Override - public JComponent description() { - return new JLabel("" + toString() + '.' + public Node description() { + return new Label(toString() + '.' + (changedGroups == null ? "" : ' ' + Localization - .lang("Accepting the change replaces the complete groups tree with the externally modified groups tree.")) - + ""); + .lang("Accepting the change replaces the complete groups tree with the externally modified groups tree."))); } } diff --git a/src/main/java/org/jabref/gui/collab/InfoPane.java b/src/main/java/org/jabref/gui/collab/InfoPane.java deleted file mode 100644 index cec4658a5de..00000000000 --- a/src/main/java/org/jabref/gui/collab/InfoPane.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.jabref.gui.collab; - -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.RenderingHints; - -import javax.swing.JEditorPane; - -class InfoPane extends JEditorPane { - - public InfoPane() { - setEditable(false); - setContentType("text/html"); - } - - @Override - public void paint(Graphics g) { - Graphics2D g2 = (Graphics2D) g; - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - super.paint(g2); - } -} diff --git a/src/main/java/org/jabref/gui/collab/MetaDataChangeViewModel.java b/src/main/java/org/jabref/gui/collab/MetaDataChangeViewModel.java index 7418ff1695f..83b5b7f7b56 100644 --- a/src/main/java/org/jabref/gui/collab/MetaDataChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/MetaDataChangeViewModel.java @@ -1,30 +1,25 @@ package org.jabref.gui.collab; -import javax.swing.JComponent; -import javax.swing.JScrollPane; +import javafx.scene.Node; +import javafx.scene.control.Label; -import org.jabref.gui.BasePanel; import org.jabref.gui.undo.NamedCompound; import org.jabref.logic.bibtex.comparator.MetaDataDiff; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.metadata.MetaData; -class MetaDataChangeViewModel extends ChangeViewModel { +class MetaDataChangeViewModel extends DatabaseChangeViewModel { - private final InfoPane infoPane = new InfoPane(); - private final JScrollPane sp = new JScrollPane(infoPane); private final MetaData newMetaData; public MetaDataChangeViewModel(MetaDataDiff metaDataDiff) { super(Localization.lang("Metadata change")); this.newMetaData = metaDataDiff.getNewMetaData(); - - infoPane.setText("" + Localization.lang("Metadata change") + ""); } @Override - public JComponent description() { + public Node description() { /* // TODO: Show detailed description of the changes StringBuilder sb = new StringBuilder( @@ -34,12 +29,11 @@ public JComponent description() { sb.append(""); infoPane.setText(sb.toString()); */ - return sp; + return new Label(Localization.lang("Metadata change")); } @Override - public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) { - panel.getBibDatabaseContext().setMetaData(newMetaData); - return true; + public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { + database.setMetaData(newMetaData); } } diff --git a/src/main/java/org/jabref/gui/collab/PreambleChangeViewModel.java b/src/main/java/org/jabref/gui/collab/PreambleChangeViewModel.java index a3f707b5cd5..b8a17ccb840 100644 --- a/src/main/java/org/jabref/gui/collab/PreambleChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/PreambleChangeViewModel.java @@ -1,54 +1,48 @@ package org.jabref.gui.collab; -import javax.swing.JComponent; -import javax.swing.JScrollPane; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; -import org.jabref.gui.BasePanel; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoablePreambleChange; import org.jabref.logic.bibtex.comparator.PreambleDiff; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.strings.StringUtil; -class PreambleChangeViewModel extends ChangeViewModel { +class PreambleChangeViewModel extends DatabaseChangeViewModel { - private final String mem; - private final String disk; - private final InfoPane tp = new InfoPane(); - private final JScrollPane sp = new JScrollPane(tp); + private final PreambleDiff change; - public PreambleChangeViewModel(String mem, PreambleDiff diff) { + public PreambleChangeViewModel(PreambleDiff change) { super(Localization.lang("Changed preamble")); - this.disk = diff.getNewPreamble(); - this.mem = mem; - - StringBuilder text = new StringBuilder(34); - text.append("

").append(Localization.lang("Changed preamble")).append("

"); - - if (StringUtil.isNotBlank(disk)) { - text.append("

").append(Localization.lang("Value set externally")).append(":

" + "").append(disk).append(""); - } else { - text.append("

").append(Localization.lang("Value cleared externally")).append("

"); - } - - if (StringUtil.isNotBlank(mem)) { - text.append("

").append(Localization.lang("Current value")).append(":

" + "").append(mem).append(""); - } - - tp.setText(text.toString()); + this.change = change; } @Override - public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) { - panel.getDatabase().setPreamble(disk); - undoEdit.addEdit(new UndoablePreambleChange(panel.getDatabase(), mem, disk)); - secondary.setPreamble(disk); - return true; + public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { + database.getDatabase().setPreamble(change.getNewPreamble()); + undoEdit.addEdit(new UndoablePreambleChange(database.getDatabase(), change.getOriginalPreamble(), change.getNewPreamble())); } @Override - public JComponent description() { - return sp; + public Node description() { + VBox container = new VBox(); + Label header = new Label(Localization.lang("Changed preamble")); + header.getStyleClass().add("sectionHeader"); + container.getChildren().add(header); + + if (StringUtil.isNotBlank(change.getOriginalPreamble())) { + container.getChildren().add(new Label(Localization.lang("Current value") + ": " + change.getOriginalPreamble())); + } + + if (StringUtil.isNotBlank(change.getNewPreamble())) { + container.getChildren().add(new Label(Localization.lang("Value set externally") + ": " + change.getNewPreamble())); + } else { + container.getChildren().add(new Label(Localization.lang("Value cleared externally"))); + } + + return container; } } diff --git a/src/main/java/org/jabref/gui/collab/StringAddChangeViewModel.java b/src/main/java/org/jabref/gui/collab/StringAddChangeViewModel.java index dafb80b125f..f22535b875b 100644 --- a/src/main/java/org/jabref/gui/collab/StringAddChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/StringAddChangeViewModel.java @@ -1,63 +1,50 @@ package org.jabref.gui.collab; -import javax.swing.JComponent; -import javax.swing.JScrollPane; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; -import org.jabref.gui.BasePanel; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableInsertString; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.KeyCollisionException; import org.jabref.model.entry.BibtexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -class StringAddChangeViewModel extends ChangeViewModel { +class StringAddChangeViewModel extends DatabaseChangeViewModel { private static final Logger LOGGER = LoggerFactory.getLogger(StringAddChangeViewModel.class); - private final BibtexString string; - private final InfoPane tp = new InfoPane(); - - private final JScrollPane sp = new JScrollPane(tp); - public StringAddChangeViewModel(BibtexString string) { super(Localization.lang("Added string") + ": '" + string.getName() + '\''); this.string = string; - tp.setText("

" + Localization.lang("Added string") + "

" + - Localization.lang("Label") + ":

" + string.getName() + "

" + - Localization.lang("Content") + ":

" + string.getContent() + ""); } @Override - public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) { - - if (panel.getDatabase().hasStringLabel(string.getName())) { - // The name to change to is already in the database, so we can't comply. - LOGGER.info("Cannot add string '" + string.getName() + "' because the name " - + "is already in use."); - } - - try { - panel.getDatabase().addString(string); - undoEdit.addEdit(new UndoableInsertString(panel.getDatabase(), string)); - } catch (KeyCollisionException ex) { - LOGGER.info("Error: could not add string '" + string.getName() + "': " + ex.getMessage(), ex); - } + public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { try { - secondary.addString(new BibtexString(string.getName(), string.getContent())); + database.getDatabase().addString(string); + undoEdit.addEdit(new UndoableInsertString(database.getDatabase(), string)); } catch (KeyCollisionException ex) { - LOGGER.info("Error: could not add string '" + string.getName() + "' to tmp database: " + ex.getMessage(), ex); + LOGGER.warn("Error: could not add string '" + string.getName() + "': " + ex.getMessage(), ex); } - return true; } @Override - public JComponent description() { - return sp; + public Node description() { + VBox container = new VBox(); + Label header = new Label(Localization.lang("Added string")); + header.getStyleClass().add("sectionHeader"); + container.getChildren().addAll( + header, + new Label(Localization.lang("Label") + ": " + string.getName()), + new Label(Localization.lang("Content") + ": " + string.getContent()) + ); + return container; } } diff --git a/src/main/java/org/jabref/gui/collab/StringChangeViewModel.java b/src/main/java/org/jabref/gui/collab/StringChangeViewModel.java index d44ac099658..278715f4b43 100644 --- a/src/main/java/org/jabref/gui/collab/StringChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/StringChangeViewModel.java @@ -1,88 +1,70 @@ package org.jabref.gui.collab; -import javax.swing.JComponent; -import javax.swing.JScrollPane; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; -import org.jabref.gui.BasePanel; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableInsertString; import org.jabref.gui.undo.UndoableStringChange; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.KeyCollisionException; import org.jabref.model.entry.BibtexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -class StringChangeViewModel extends ChangeViewModel { +class StringChangeViewModel extends DatabaseChangeViewModel { private static final Logger LOGGER = LoggerFactory.getLogger(StringChangeViewModel.class); private final BibtexString string; private final String disk; - private final String label; - private final InfoPane tp = new InfoPane(); - private final JScrollPane sp = new JScrollPane(tp); - - private final BibtexString tmpString; - public StringChangeViewModel(BibtexString string, BibtexString tmpString, String disk) { super(Localization.lang("Modified string") + ": '" + tmpString.getName() + '\''); - this.tmpString = tmpString; this.string = string; this.label = tmpString.getName(); this.disk = disk; - - StringBuilder sb = new StringBuilder(46); - sb.append("

").append(Localization.lang("Modified string")).append("

") - .append(Localization.lang("Label")).append(":

").append(label).append("

") - .append(Localization.lang("New content")).append(":

").append(disk); - if (string == null) { - sb.append("

"); - sb.append(Localization.lang("Cannot merge this change")).append(": "); - sb.append(Localization.lang("The string has been removed locally")).append(""); - } else { - sb.append("

"); - sb.append(Localization.lang("Current content")).append(":

"); - sb.append(string.getContent()); - } - sb.append(""); - tp.setText(sb.toString()); } @Override - public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) { + public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { if (string == null) { // The string was removed or renamed locally. We guess that it was removed. BibtexString bs = new BibtexString(label, disk); try { - panel.getDatabase().addString(bs); - undoEdit.addEdit(new UndoableInsertString(panel.getDatabase(), bs)); + database.getDatabase().addString(bs); + undoEdit.addEdit(new UndoableInsertString(database.getDatabase(), bs)); } catch (KeyCollisionException ex) { - LOGGER.info("Error: could not add string '" + bs.getName() + "': " + ex.getMessage(), ex); + LOGGER.warn("Error: could not add string '" + bs.getName() + "': " + ex.getMessage(), ex); } } else { String mem = string.getContent(); string.setContent(disk); undoEdit.addEdit(new UndoableStringChange(string, false, mem, disk)); } + } - // Update tmp database: - if (tmpString == null) { - BibtexString bs = new BibtexString(label, disk); - secondary.addString(bs); + @Override + public Node description() { + VBox container = new VBox(); + Label header = new Label(Localization.lang("Modified string")); + header.getStyleClass().add("sectionHeader"); + container.getChildren().addAll( + header, + new Label(Localization.lang("Label") + ": " + label), + new Label(Localization.lang("Content") + ": " + disk) + ); + + if (string == null) { + container.getChildren().add(new Label(Localization.lang("Cannot merge this change") + ": " + Localization.lang("The string has been removed locally"))); } else { - tmpString.setContent(disk); + container.getChildren().add(new Label(Localization.lang("Current content") + ": " + string.getContent())); } - return true; - } - - @Override - public JComponent description() { - return sp; + return container; } } diff --git a/src/main/java/org/jabref/gui/collab/StringNameChangeViewModel.java b/src/main/java/org/jabref/gui/collab/StringNameChangeViewModel.java index b9cd5bb80fe..77aebba89e1 100644 --- a/src/main/java/org/jabref/gui/collab/StringNameChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/StringNameChangeViewModel.java @@ -1,21 +1,20 @@ package org.jabref.gui.collab; -import javax.swing.JComponent; -import javax.swing.JLabel; +import javafx.scene.Node; +import javafx.scene.control.Label; -import org.jabref.gui.BasePanel; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableInsertString; import org.jabref.gui.undo.UndoableStringChange; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.KeyCollisionException; import org.jabref.model.entry.BibtexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -class StringNameChangeViewModel extends ChangeViewModel { +class StringNameChangeViewModel extends DatabaseChangeViewModel { private static final Logger LOGGER = LoggerFactory.getLogger(StringNameChangeViewModel.class); private final BibtexString string; @@ -23,23 +22,17 @@ class StringNameChangeViewModel extends ChangeViewModel { private final String disk; private final String content; - private final BibtexString tmpString; - - public StringNameChangeViewModel(BibtexString string, BibtexString tmpString, String mem, String disk) { super(Localization.lang("Renamed string") + ": '" + tmpString.getName() + '\''); - this.tmpString = tmpString; this.string = string; this.content = tmpString.getContent(); this.mem = mem; this.disk = disk; - } @Override - public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) { - - if (panel.getDatabase().hasStringLabel(disk)) { + public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { + if (database.getDatabase().hasStringLabel(disk)) { // The name to change to is already in the database, so we can't comply. LOGGER.info("Cannot rename string '" + mem + "' to '" + disk + "' because the name " + "is already in use."); @@ -49,8 +42,8 @@ public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound // The string was removed or renamed locally. We guess that it was removed. BibtexString bs = new BibtexString(disk, content); try { - panel.getDatabase().addString(bs); - undoEdit.addEdit(new UndoableInsertString(panel.getDatabase(), bs)); + database.getDatabase().addString(bs); + undoEdit.addEdit(new UndoableInsertString(database.getDatabase(), bs)); } catch (KeyCollisionException ex) { LOGGER.info("Error: could not add string '" + bs.getName() + "': " + ex.getMessage(), ex); } @@ -58,21 +51,11 @@ public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound string.setName(disk); undoEdit.addEdit(new UndoableStringChange(string, true, mem, disk)); } - - // Update tmp database: - if (tmpString == null) { - BibtexString bs = new BibtexString(disk, content); - secondary.addString(bs); - } else { - tmpString.setName(disk); - } - - return true; } @Override - public JComponent description() { - return new JLabel(disk + " : " + content); + public Node description() { + return new Label(disk + " : " + content); } } diff --git a/src/main/java/org/jabref/gui/collab/StringRemoveChangeViewModel.java b/src/main/java/org/jabref/gui/collab/StringRemoveChangeViewModel.java index eaf66d47304..ba1b8066afb 100644 --- a/src/main/java/org/jabref/gui/collab/StringRemoveChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/StringRemoveChangeViewModel.java @@ -1,55 +1,51 @@ package org.jabref.gui.collab; -import javax.swing.JComponent; -import javax.swing.JScrollPane; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; -import org.jabref.gui.BasePanel; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableRemoveString; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibtexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -class StringRemoveChangeViewModel extends ChangeViewModel { +class StringRemoveChangeViewModel extends DatabaseChangeViewModel { private static final Logger LOGGER = LoggerFactory.getLogger(StringRemoveChangeViewModel.class); private final BibtexString string; private final BibtexString inMem; - private final InfoPane tp = new InfoPane(); - private final JScrollPane sp = new JScrollPane(tp); public StringRemoveChangeViewModel(BibtexString string, BibtexString inMem) { super(Localization.lang("Removed string") + ": '" + string.getName() + '\''); this.string = string; this.inMem = inMem; // Holds the version in memory. Check if it has been modified...? - - tp.setText("

" + Localization.lang("Removed string") + "

" + - Localization.lang("Label") + ":

" + string.getName() + "

" + - Localization.lang("Content") + ":

" + string.getContent() + ""); } @Override - public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) { - + public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { try { - panel.getDatabase().removeString(inMem.getId()); - undoEdit.addEdit(new UndoableRemoveString(panel.getDatabase(), string)); + database.getDatabase().removeString(inMem.getId()); + undoEdit.addEdit(new UndoableRemoveString(database.getDatabase(), string)); } catch (Exception ex) { - LOGGER.info("Error: could not add string '" + string.getName() + "': " + ex.getMessage(), ex); + LOGGER.warn("Error: could not add string '" + string.getName() + "': " + ex.getMessage(), ex); } - - // Update tmp database: - secondary.removeString(string.getId()); - - return true; } @Override - public JComponent description() { - return sp; + public Node description() { + VBox container = new VBox(); + Label header = new Label(Localization.lang("Removed string")); + header.getStyleClass().add("sectionHeader"); + container.getChildren().addAll( + header, + new Label(Localization.lang("Label") + ": " + string.getName()), + new Label(Localization.lang("Content") + ": " + string.getContent()) + ); + return container; } } diff --git a/src/main/java/org/jabref/logic/bibtex/comparator/PreambleDiff.java b/src/main/java/org/jabref/logic/bibtex/comparator/PreambleDiff.java index b7bb0f56d31..e54074a1f40 100644 --- a/src/main/java/org/jabref/logic/bibtex/comparator/PreambleDiff.java +++ b/src/main/java/org/jabref/logic/bibtex/comparator/PreambleDiff.java @@ -6,9 +6,11 @@ public class PreambleDiff { - private String newPreamble; + private final String originalPreamble; + private final String newPreamble; - private PreambleDiff(String newPreamble) { + private PreambleDiff(String originalPreamble, String newPreamble) { + this.originalPreamble = originalPreamble; this.newPreamble = newPreamble; } @@ -18,11 +20,15 @@ public static Optional compare(BibDatabaseContext originalDatabase if (originalPreamble.equals(newPreamble)) { return Optional.empty(); } else { - return Optional.of(new PreambleDiff(newPreamble.orElse(""))); + return Optional.of(new PreambleDiff(originalPreamble.orElse(""), newPreamble.orElse(""))); } } public String getNewPreamble() { return newPreamble; } + + public String getOriginalPreamble() { + return originalPreamble; + } } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 2f5131a84a9..6f889dd0133 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -385,9 +385,6 @@ File=File file=file File\ '%0'\ is\ already\ open.=File '%0' is already open. - -File\ changed=File changed - File\ directory\ is\ not\ set\ or\ does\ not\ exist\!=File directory is not set or does not exist! File\ exists=File exists @@ -604,9 +601,6 @@ nested\ AUX\ files=nested AUX files new=new New\ BibTeX\ sublibrary=New BibTeX sublibrary - -New\ content=New content - New\ library\ created.=New library created. New\ group=New group @@ -614,9 +608,6 @@ New\ group=New group New\ string=New string Next\ entry=Next entry - -No\ actual\ changes\ found.=No actual changes found. - no\ base-BibTeX-file\ specified=no base-BibTeX-file specified no\ library\ generated=no library generated @@ -950,9 +941,6 @@ The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Th the\ field\ %0=the field %0 - -The\ file
'%0'
has\ been\ modified
externally\!=The file
'%0'
has been modified
externally! - The\ group\ "%0"\ already\ contains\ the\ selection.=The group "%0" already contains the selection. The\ label\ of\ the\ string\ cannot\ be\ a\ number.=The label of the string cannot be a number. @@ -2138,3 +2126,6 @@ Find\ and\ replace=Find and replace Found\ documents\:=Found documents\: Use\ selected\ document=Use selected document +Accept\ changes=Accept changes +Dismiss\ changes=Dismiss changes +The\ library\ has\ been\ modified\ by\ another\ program.=The library has been modified by another program.