diff --git a/src/main/java/org/jabref/gui/JabRefGUI.java b/src/main/java/org/jabref/gui/JabRefGUI.java index be4054302ff..aecad6e3994 100644 --- a/src/main/java/org/jabref/gui/JabRefGUI.java +++ b/src/main/java/org/jabref/gui/JabRefGUI.java @@ -264,7 +264,10 @@ private void openWindow() { } public void onShowing(WindowEvent event) { - Platform.runLater(() -> mainFrame.updateDividerPosition()); + Platform.runLater(() -> { + mainFrame.updateHorizontalDividerPosition(); + mainFrame.updateVerticalDividerPosition(); + }); // Open last edited databases if (uiCommands.stream().noneMatch(UiCommand.BlankWorkspace.class::isInstance) diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index f93ef8c6101..c5e6ef87f0d 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -7,7 +7,6 @@ import java.util.Objects; import java.util.Optional; import java.util.Random; -import java.util.function.Supplier; import java.util.stream.Collectors; import javax.swing.undo.UndoManager; @@ -23,13 +22,11 @@ import javafx.beans.value.ObservableBooleanValue; import javafx.collections.ListChangeListener; import javafx.event.Event; -import javafx.geometry.Orientation; import javafx.scene.Node; import javafx.scene.control.Alert; import javafx.scene.control.ButtonBar; import javafx.scene.control.ButtonType; import javafx.scene.control.ProgressIndicator; -import javafx.scene.control.SplitPane; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.control.Tooltip; @@ -45,7 +42,6 @@ import org.jabref.gui.autosaveandbackup.BackupManager; import org.jabref.gui.collab.DatabaseChangeMonitor; import org.jabref.gui.dialogs.AutosaveUiManager; -import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.exporter.SaveDatabaseAction; import org.jabref.gui.externalfiles.ImportHandler; import org.jabref.gui.fieldeditors.LinkedFileViewModel; @@ -57,8 +53,6 @@ import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.undo.NamedCompound; -import org.jabref.gui.undo.RedoAction; -import org.jabref.gui.undo.UndoAction; import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.gui.undo.UndoableInsertEntries; import org.jabref.gui.undo.UndoableRemoveEntries; @@ -112,11 +106,6 @@ * Represents the ui area where the notifier pane, the library table and the entry editor are shown. */ public class LibraryTab extends Tab { - /** - * Defines the different modes that the tab can operate in - */ - private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR } - private static final Logger LOGGER = LoggerFactory.getLogger(LibraryTab.class); private final LibraryTabContainer tabContainer; private final CountingUndoManager undoManager; @@ -131,10 +120,7 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR } private BibDatabaseContext bibDatabaseContext; private MainTableDataModel tableModel; private FileAnnotationCache annotationCache; - private EntryEditor entryEditor; private MainTable mainTable; - private PanelMode mode = PanelMode.MAIN_TABLE; - private SplitPane splitPane; private DatabaseNotification databaseNotificationPane; // Indicates whether the tab is loading data using a dataloading task @@ -242,7 +228,6 @@ private void initializeComponentsAndListeners(boolean isDummyContext) { setupAutoCompletion(); this.getDatabase().registerListener(new IndexUpdateListener()); - this.getDatabase().registerListener(new EntriesRemovedListener()); // ensure that at each addition of a new entry, the entry is added to the groups interface this.bibDatabaseContext.getDatabase().registerListener(new GroupTreeListener()); @@ -251,8 +236,6 @@ private void initializeComponentsAndListeners(boolean isDummyContext) { this.getDatabase().registerListener(new UpdateTimestampListener(preferences)); - this.entryEditor = createEntryEditor(); - aiService.setupDatabase(bibDatabaseContext); Platform.runLater(() -> { @@ -262,14 +245,6 @@ private void initializeComponentsAndListeners(boolean isDummyContext) { }); } - private EntryEditor createEntryEditor() { - Supplier tabSupplier = () -> this; - return new EntryEditor(this, - // Actions are recreated here since this avoids passing more parameters and the amount of additional memory consumption is neglegtable. - new UndoAction(tabSupplier, undoManager, dialogService, stateManager), - new RedoAction(tabSupplier, undoManager, dialogService, stateManager)); - } - private static void addChangedInformation(StringBuilder text, String fileName) { text.append("\n"); text.append(Localization.lang("Library '%0' has changed.", fileName)); @@ -498,34 +473,21 @@ private void createMainTable() { entryTypesManager, taskExecutor, importHandler); + // Add the listener that binds selection to state manager (TODO: should be replaced by proper JavaFX binding as soon as table is implemented in JavaFX) // content binding between StateManager#getselectedEntries and mainTable#getSelectedEntries does not work here as it does not trigger the ActionHelper#needsEntriesSelected checker for the menubar mainTable.addSelectionListener(event -> { List entries = event.getList().stream().map(BibEntryTableViewModel::getEntry).toList(); stateManager.setSelectedEntries(entries); - if (!entries.isEmpty()) { - // Update entry editor and preview according to selected entries - entryEditor.setCurrentlyEditedEntry(entries.getFirst()); - } }); } public void setupMainPanel() { - splitPane = new SplitPane(); - splitPane.setOrientation(Orientation.VERTICAL); - createMainTable(); - splitPane.getItems().add(mainTable); - databaseNotificationPane = new DatabaseNotification(splitPane); + databaseNotificationPane = new DatabaseNotification(mainTable); setContent(databaseNotificationPane); - // Saves the divider position as soon as it changes - // We need to keep a reference to the subscription, otherwise the binding gets garbage collected - dividerPositionSubscription = EasyBind.valueAt(splitPane.getDividers(), 0) - .mapObservable(SplitPane.Divider::positionProperty) - .subscribeToValues(this::saveDividerLocation); - // Add changePane in case a file is present - otherwise just add the splitPane to the panel Optional file = bibDatabaseContext.getDatabasePath(); if (file.isPresent()) { @@ -561,10 +523,6 @@ public SuggestionProvider getAutoCompleter() { return searchAutoCompleter; } - public EntryEditor getEntryEditor() { - return entryEditor; - } - /** * Sets the entry editor as the bottom component in the split pane. If an entry editor already was shown, makes sure that the divider doesn't move. Updates the mode to {@link PanelMode#MAIN_TABLE_AND_ENTRY_EDITOR}. * Then shows the given entry. @@ -617,17 +575,6 @@ public void entryEditorClosing() { mainTable.requestFocus(); } - /** - * Closes the entry editor if it is showing any of the given entries. - */ - private void ensureNotShowingBottomPanel(List entriesToCheck) { - // This method is not able to close the bottom pane currently - - if ((mode == PanelMode.MAIN_TABLE_AND_ENTRY_EDITOR) && (entriesToCheck.contains(entryEditor.getCurrentlyEditedEntry()))) { - closeBottomPane(); - } - } - /** * Put an asterisk behind the filename to indicate the database has changed. */ @@ -676,15 +623,6 @@ private boolean showDeleteConfirmationDialog(int numberOfEntries) { } } - /** - * Depending on whether a preview or an entry editor is showing, save the current divider location in the correct preference setting. - */ - private void saveDividerLocation(Number position) { - if (mode == PanelMode.MAIN_TABLE_AND_ENTRY_EDITOR) { - preferences.getEntryEditorPreferences().setDividerPosition(position.doubleValue()); - } - } - public boolean requestClose() { if (bibDatabaseContext.getLocation() == DatabaseLocation.LOCAL) { if (isModified()) { @@ -1014,7 +952,6 @@ private int doDeleteEntry(StandardActions mode, List entries) { } } - ensureNotShowingBottomPanel(entries); markBaseChanged(); // prevent the main table from loosing focus @@ -1130,14 +1067,6 @@ public void listen(EntriesAddedEvent addedEntriesEvent) { } } - private class EntriesRemovedListener { - - @Subscribe - public void listen(EntriesRemovedEvent entriesRemovedEvent) { - ensureNotShowingBottomPanel(entriesRemovedEvent.getBibEntries()); - } - } - private class IndexUpdateListener { @Subscribe diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index 3a2bd6f2258..5ba14c0679d 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -11,6 +11,7 @@ import java.util.Optional; import java.util.Set; import java.util.SortedSet; +import java.util.function.Supplier; import java.util.stream.Collectors; import javafx.fxml.FXML; @@ -42,6 +43,7 @@ import org.jabref.gui.menus.ChangeEntryTypeMenu; import org.jabref.gui.mergeentries.FetchAndMergeEntry; import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.gui.preview.PreviewControls; import org.jabref.gui.preview.PreviewPanel; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.undo.CountingUndoManager; @@ -70,8 +72,6 @@ import com.tobiasdiez.easybind.Subscription; import jakarta.inject.Inject; import org.jspecify.annotations.NonNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * GUI component that allows editing of the fields of a BibEntry (i.e. the one that shows up, when you double click on @@ -84,16 +84,10 @@ *

* The editors for fields are created via {@link org.jabref.gui.fieldeditors.FieldEditors}. */ -public class EntryEditor extends BorderPane { - - private static final Logger LOGGER = LoggerFactory.getLogger(EntryEditor.class); - - private final LibraryTab libraryTab; - private final BibDatabaseContext databaseContext; - private final EntryEditorPreferences entryEditorPreferences; +public class EntryEditor extends BorderPane implements PreviewControls { + private final Supplier tabSupplier; private final ExternalFilesEntryLinker fileLinker; private final PreviewPanel previewPanel; - private final DirectoryMonitorManager directoryMonitorManager; private final UndoAction undoAction; private final RedoAction redoAction; @@ -124,10 +118,8 @@ public class EntryEditor extends BorderPane { private final List allPossibleTabs; - public EntryEditor(LibraryTab libraryTab, UndoAction undoAction, RedoAction redoAction) { - this.libraryTab = libraryTab; - this.databaseContext = libraryTab.getBibDatabaseContext(); - this.directoryMonitorManager = libraryTab.getDirectoryMonitorManager(); + public EntryEditor(Supplier tabSupplier, UndoAction undoAction, RedoAction redoAction) { + this.tabSupplier = tabSupplier; this.undoAction = undoAction; this.redoAction = redoAction; @@ -135,8 +127,13 @@ public EntryEditor(LibraryTab libraryTab, UndoAction undoAction, RedoAction redo .root(this) .load(); - this.entryEditorPreferences = preferences.getEntryEditorPreferences(); - this.fileLinker = new ExternalFilesEntryLinker(preferences.getExternalApplicationsPreferences(), preferences.getFilePreferences(), dialogService, stateManager); + this.fileLinker = new ExternalFilesEntryLinker( + preferences.getExternalApplicationsPreferences(), + preferences.getFilePreferences(), + dialogService, + stateManager); + + // FixMe: Observable this.previewPanel = new PreviewPanel( dialogService, preferences.getKeyBindingRepository(), @@ -144,12 +141,13 @@ public EntryEditor(LibraryTab libraryTab, UndoAction undoAction, RedoAction redo themeManager, taskExecutor, stateManager, - libraryTab.searchQueryProperty()); - this.previewPanel.setDatabase(databaseContext); + tabSupplier.get().searchQueryProperty()); + this.previewPanel.setDatabase(tabSupplier.get().getBibDatabaseContext()); setupKeyBindings(); - this.allPossibleTabs = createTabs(); + // FixMe: Observable + this.allPossibleTabs = createTabs(tabSupplier.get()); setupDragAndDrop(); @@ -220,11 +218,11 @@ private void setupKeyBindings() { event.consume(); break; case ENTRY_EDITOR_NEXT_ENTRY: - libraryTab.selectNextEntry(); + tabSupplier.get().selectNextEntry(); event.consume(); break; case ENTRY_EDITOR_PREVIOUS_ENTRY: - libraryTab.selectPreviousEntry(); + tabSupplier.get().selectPreviousEntry(); event.consume(); break; case HELP: @@ -248,40 +246,42 @@ private void setupKeyBindings() { } @FXML - public void close() { - libraryTab.entryEditorClosing(); + private void close() { + tabSupplier.get().entryEditorClosing(); } @FXML private void deleteEntry() { - libraryTab.deleteEntry(currentlyEditedEntry); + tabSupplier.get().deleteEntry(currentlyEditedEntry); } @FXML - void generateCiteKeyButton() { - GenerateCitationKeySingleAction action = new GenerateCitationKeySingleAction(getCurrentlyEditedEntry(), databaseContext, + private void generateCiteKeyButton() { + GenerateCitationKeySingleAction action = new GenerateCitationKeySingleAction(getCurrentlyEditedEntry(), tabSupplier.get().getBibDatabaseContext(), dialogService, preferences, undoManager); action.execute(); } @FXML - void generateCleanupButton() { + private void generateCleanupButton() { CleanupSingleAction action = new CleanupSingleAction(getCurrentlyEditedEntry(), preferences, dialogService, stateManager, undoManager); action.execute(); } @FXML private void navigateToPreviousEntry() { - libraryTab.selectPreviousEntry(); + tabSupplier.get().selectPreviousEntry(); } @FXML private void navigateToNextEntry() { - libraryTab.selectNextEntry(); + tabSupplier.get().selectNextEntry(); } - private List createTabs() { + private List createTabs(LibraryTab libraryTab) { List tabs = new LinkedList<>(); + BibDatabaseContext databaseContext = libraryTab.getBibDatabaseContext(); + DirectoryMonitorManager directoryMonitorManager = libraryTab.getDirectoryMonitorManager(); tabs.add(new PreviewTab(databaseContext, preferences, previewPanel)); @@ -333,7 +333,7 @@ private List createTabs() { * @return Map of tab names and the fields to show in them. */ private Map> getAdditionalUserConfiguredTabs() { - Map> entryEditorTabList = new HashMap<>(entryEditorPreferences.getEntryEditorTabs()); + Map> entryEditorTabList = new HashMap<>(preferences.getEntryEditorPreferences().getEntryEditorTabs()); // Same order as in org.jabref.gui.entryeditor.EntryEditor.createTabs before the call of getAdditionalUserConfiguredTabs entryEditorTabList.remove(PreviewTab.NAME); @@ -403,13 +403,13 @@ public void setCurrentlyEditedEntry(@NonNull BibEntry currentlyEditedEntry) { typeSubscription.unsubscribe(); } typeSubscription = EasyBind.subscribe(this.currentlyEditedEntry.typeProperty(), type -> { - typeLabel.setText(new TypedBibEntry(currentlyEditedEntry, databaseContext.getMode()).getTypeForDisplay()); + typeLabel.setText(new TypedBibEntry(currentlyEditedEntry, tabSupplier.get().getBibDatabaseContext().getMode()).getTypeForDisplay()); adaptVisibleTabs(); setupToolBar(); getSelectedTab().notifyAboutFocus(currentlyEditedEntry); }); - if (entryEditorPreferences.showSourceTabByDefault()) { + if (preferences.getEntryEditorPreferences().showSourceTabByDefault()) { tabbed.getSelectionModel().select(sourceTab); } } @@ -420,11 +420,11 @@ private EntryEditorTab getSelectedTab() { private void setupToolBar() { // Update type label - TypedBibEntry typedEntry = new TypedBibEntry(currentlyEditedEntry, databaseContext.getMode()); + TypedBibEntry typedEntry = new TypedBibEntry(currentlyEditedEntry, tabSupplier.get().getBibDatabaseContext().getMode()); typeLabel.setText(typedEntry.getTypeForDisplay()); // Add type change menu - ContextMenu typeMenu = new ChangeEntryTypeMenu(Collections.singletonList(currentlyEditedEntry), databaseContext, undoManager, bibEntryTypesManager).asContextMenu(); + ContextMenu typeMenu = new ChangeEntryTypeMenu(Collections.singletonList(currentlyEditedEntry), tabSupplier.get().getBibDatabaseContext(), undoManager, bibEntryTypesManager).asContextMenu(); typeLabel.setOnMouseClicked(event -> typeMenu.show(typeLabel, Side.RIGHT, 0, 0)); typeChangeButton.setOnMouseClicked(event -> typeMenu.show(typeChangeButton, Side.RIGHT, 0, 0)); @@ -434,7 +434,7 @@ private void setupToolBar() { preferences.getImporterPreferences(), preferences.getImportFormatPreferences(), preferences.getFilePreferences(), - databaseContext); + tabSupplier.get().getBibDatabaseContext()); for (EntryBasedFetcher fetcher : entryBasedFetchers) { MenuItem fetcherMenuItem = new MenuItem(fetcher.getName()); if (fetcher instanceof PdfMergeMetadataImporter.EntryBasedFetcherWrapper) { @@ -445,7 +445,7 @@ private void setupToolBar() { new PdfMergeMetadataImporter.EntryBasedFetcherWrapper( preferences.getImportFormatPreferences(), preferences.getFilePreferences(), - databaseContext); + tabSupplier.get().getBibDatabaseContext()); fetchAndMerge(pdfMergeMetadataImporter); }); } else { @@ -458,7 +458,7 @@ private void setupToolBar() { } private void fetchAndMerge(EntryBasedFetcher fetcher) { - new FetchAndMergeEntry(libraryTab.getBibDatabaseContext(), taskExecutor, preferences, dialogService, undoManager).fetchAndMerge(currentlyEditedEntry, fetcher); + new FetchAndMergeEntry(tabSupplier.get().getBibDatabaseContext(), taskExecutor, preferences, dialogService, undoManager).fetchAndMerge(currentlyEditedEntry, fetcher); } public void setFocusToField(Field field) { @@ -473,10 +473,12 @@ public void setFocusToField(Field field) { }); } + @Override public void nextPreviewStyle() { this.previewPanel.nextPreviewStyle(); } + @Override public void previousPreviewStyle() { this.previewPanel.previousPreviewStyle(); } diff --git a/src/main/java/org/jabref/gui/entryeditor/PreviewSwitchAction.java b/src/main/java/org/jabref/gui/entryeditor/PreviewSwitchAction.java index aa98a5b7e24..1c75a8fbba8 100644 --- a/src/main/java/org/jabref/gui/entryeditor/PreviewSwitchAction.java +++ b/src/main/java/org/jabref/gui/entryeditor/PreviewSwitchAction.java @@ -1,10 +1,8 @@ package org.jabref.gui.entryeditor; -import java.util.function.Supplier; - -import org.jabref.gui.LibraryTab; import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.preview.PreviewControls; import static org.jabref.gui.actions.ActionHelper.needsDatabase; @@ -12,11 +10,11 @@ public class PreviewSwitchAction extends SimpleCommand { public enum Direction { PREVIOUS, NEXT } - private final Supplier tabSupplier; + private final PreviewControls previewControls; private final Direction direction; - public PreviewSwitchAction(Direction direction, Supplier tabSupplier, StateManager stateManager) { - this.tabSupplier = tabSupplier; + public PreviewSwitchAction(Direction direction, PreviewControls previewControls, StateManager stateManager) { + this.previewControls = previewControls; this.direction = direction; this.executable.bind(needsDatabase(stateManager)); @@ -25,9 +23,9 @@ public PreviewSwitchAction(Direction direction, Supplier tabSupplier @Override public void execute() { if (direction == Direction.NEXT) { - tabSupplier.get().getEntryEditor().nextPreviewStyle(); + previewControls.nextPreviewStyle(); } else { - tabSupplier.get().getEntryEditor().previousPreviewStyle(); + previewControls.previousPreviewStyle(); } } } diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index a57d4026dbc..958505415f1 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -14,6 +14,7 @@ import javafx.beans.binding.StringBinding; import javafx.collections.transformation.FilteredList; import javafx.event.Event; +import javafx.geometry.Orientation; import javafx.scene.control.ContextMenu; import javafx.scene.control.SeparatorMenuItem; import javafx.scene.control.SplitPane; @@ -34,6 +35,7 @@ import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.actions.StandardActions; import org.jabref.gui.desktop.os.NativeDesktop; +import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.importer.NewEntryAction; import org.jabref.gui.importer.actions.OpenDatabaseAction; import org.jabref.gui.keyboard.KeyBinding; @@ -45,6 +47,8 @@ import org.jabref.gui.sidepane.SidePane; import org.jabref.gui.sidepane.SidePaneType; import org.jabref.gui.undo.CountingUndoManager; +import org.jabref.gui.undo.RedoAction; +import org.jabref.gui.undo.UndoAction; import org.jabref.logic.UiCommand; import org.jabref.logic.ai.AiService; import org.jabref.logic.journals.JournalAbbreviationRepository; @@ -68,12 +72,15 @@ * Represents the inner frame of the JabRef window */ public class JabRefFrame extends BorderPane implements LibraryTabContainer, UiMessageHandler { + /** + * Defines the different modes that the tab can operate in + */ + private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR } public static final String FRAME_TITLE = "JabRef"; private static final Logger LOGGER = LoggerFactory.getLogger(JabRefFrame.class); - private final SplitPane splitPane = new SplitPane(); private final GuiPreferences preferences; private final AiService aiService; private final GlobalSearchBar globalSearchBar; @@ -94,10 +101,17 @@ public class JabRefFrame extends BorderPane implements LibraryTabContainer, UiMe private final JabRefFrameViewModel viewModel; private final PushToApplicationCommand pushToApplicationCommand; + private final SplitPane horizontalSplit = new SplitPane(); private final SidePane sidePane; + private final SplitPane verticalSplit = new SplitPane(); private final TabPane tabbedPane = new TabPane(); + private final EntryEditor entryEditor; - private Subscription dividerSubscription; + private PanelMode mode = PanelMode.MAIN_TABLE; + + // We need to keep a reference to the subscription, otherwise the binding gets garbage collected + private Subscription horizontalDividerSubscription; + private Subscription verticalDividerSubscription; public JabRefFrame(Stage mainStage, DialogService dialogService, @@ -163,6 +177,11 @@ public JabRefFrame(Stage mainStage, clipBoardManager, undoManager); + this.entryEditor = new EntryEditor(this::getCurrentLibraryTab, + // Actions are recreated here since this avoids passing more parameters and the amount of additional memory consumption is neglegtable. + new UndoAction(this::getCurrentLibraryTab, undoManager, dialogService, stateManager), + new RedoAction(this::getCurrentLibraryTab, undoManager, dialogService, stateManager)); + this.pushToApplicationCommand = new PushToApplicationCommand( stateManager, dialogService, @@ -217,38 +236,71 @@ private void initLayout() { undoManager, clipBoardManager, this::getOpenDatabaseAction, - aiService); + aiService, + entryEditor); VBox head = new VBox(mainMenu, mainToolBar); head.setSpacing(0d); setTop(head); - splitPane.getItems().addAll(tabbedPane); + verticalSplit.getItems().addAll(tabbedPane); + verticalSplit.setOrientation(Orientation.VERTICAL); + updateEditorPane(); + + horizontalSplit.getItems().addAll(verticalSplit); + horizontalSplit.setOrientation(Orientation.HORIZONTAL); + SplitPane.setResizableWithParent(sidePane, false); sidePane.widthProperty().addListener(c -> updateSidePane()); sidePane.getChildren().addListener((InvalidationListener) c -> updateSidePane()); updateSidePane(); - setCenter(splitPane); + setCenter(horizontalSplit); } private void updateSidePane() { if (sidePane.getChildren().isEmpty()) { - if (dividerSubscription != null) { - dividerSubscription.unsubscribe(); + if (horizontalDividerSubscription != null) { + horizontalDividerSubscription.unsubscribe(); + } + horizontalSplit.getItems().remove(sidePane); + } else { + if (!horizontalSplit.getItems().contains(sidePane)) { + horizontalSplit.getItems().addFirst(sidePane); + updateHorizontalDividerPosition(); + } + } + } + + private void updateEditorPane() { + if (mode == PanelMode.MAIN_TABLE) { + if (verticalDividerSubscription != null) { + verticalDividerSubscription.unsubscribe(); } - splitPane.getItems().remove(sidePane); + verticalSplit.getItems().remove(entryEditor); } else { - if (!splitPane.getItems().contains(sidePane)) { - splitPane.getItems().addFirst(sidePane); - updateDividerPosition(); + if (!verticalSplit.getItems().contains(entryEditor)) { + verticalSplit.getItems().addLast(entryEditor); + updateVerticalDividerPosition(); } } } - public void updateDividerPosition() { + public void updateHorizontalDividerPosition() { if (mainStage.isShowing() && !sidePane.getChildren().isEmpty()) { - splitPane.setDividerPositions(preferences.getGuiPreferences().getSidePaneWidth() / splitPane.getWidth()); - dividerSubscription = EasyBind.listen(sidePane.widthProperty(), (obs, old, newVal) -> preferences.getGuiPreferences().setSidePaneWidth(newVal.doubleValue())); + horizontalSplit.setDividerPositions(preferences.getGuiPreferences().getSidePaneWidth() / horizontalSplit.getWidth()); + horizontalDividerSubscription = EasyBind.valueAt(horizontalSplit.getDividers(), 0) + .mapObservable(SplitPane.Divider::positionProperty) + .listenToValues((oldValue, newValue) -> preferences.getGuiPreferences().setSidePaneWidth(newValue.doubleValue())); + } + } + + public void updateVerticalDividerPosition() { + if (mainStage.isShowing() && mode == PanelMode.MAIN_TABLE_AND_ENTRY_EDITOR) { + verticalSplit.setDividerPositions(preferences.getEntryEditorPreferences().getDividerPosition() / verticalSplit.getHeight()); + // ToDo: Move DividerPosition to GuiPreferences + verticalDividerSubscription = EasyBind.valueAt(verticalSplit.getDividers(), 0) + .mapObservable(SplitPane.Divider::positionProperty) + .listenToValues((oldValue, newValue) -> preferences.getEntryEditorPreferences().setDividerPosition(newValue.doubleValue())); } } diff --git a/src/main/java/org/jabref/gui/frame/MainMenu.java b/src/main/java/org/jabref/gui/frame/MainMenu.java index 4a90a556172..d6be636f97f 100644 --- a/src/main/java/org/jabref/gui/frame/MainMenu.java +++ b/src/main/java/org/jabref/gui/frame/MainMenu.java @@ -56,6 +56,7 @@ import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.preferences.ShowPreferencesAction; import org.jabref.gui.preview.CopyCitationAction; +import org.jabref.gui.preview.PreviewControls; import org.jabref.gui.push.PushToApplicationCommand; import org.jabref.gui.search.RebuildFulltextSearchIndexAction; import org.jabref.gui.shared.ConnectToSharedDatabaseCommand; @@ -100,6 +101,7 @@ public class MainMenu extends MenuBar { private final ClipBoardManager clipBoardManager; private final Supplier openDatabaseActionSupplier; private final AiService aiService; + private final PreviewControls previewControls; public MainMenu(JabRefFrame frame, FileHistoryMenu fileHistoryMenu, @@ -115,7 +117,8 @@ public MainMenu(JabRefFrame frame, CountingUndoManager undoManager, ClipBoardManager clipBoardManager, Supplier openDatabaseActionSupplier, - AiService aiService) { + AiService aiService, + PreviewControls previewControls) { this.frame = frame; this.fileHistoryMenu = fileHistoryMenu; this.sidePane = sidePane; @@ -131,6 +134,7 @@ public MainMenu(JabRefFrame frame, this.clipBoardManager = clipBoardManager; this.openDatabaseActionSupplier = openDatabaseActionSupplier; this.aiService = aiService; + this.previewControls = previewControls; createMenu(); } @@ -323,8 +327,8 @@ private void createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.NEXT_PREVIEW_STYLE, new PreviewSwitchAction(PreviewSwitchAction.Direction.NEXT, frame::getCurrentLibraryTab, stateManager)), - factory.createMenuItem(StandardActions.PREVIOUS_PREVIEW_STYLE, new PreviewSwitchAction(PreviewSwitchAction.Direction.PREVIOUS, frame::getCurrentLibraryTab, stateManager)), + factory.createMenuItem(StandardActions.NEXT_PREVIEW_STYLE, new PreviewSwitchAction(PreviewSwitchAction.Direction.NEXT, previewControls, stateManager)), + factory.createMenuItem(StandardActions.PREVIOUS_PREVIEW_STYLE, new PreviewSwitchAction(PreviewSwitchAction.Direction.PREVIOUS, previewControls, stateManager)), new SeparatorMenuItem(), diff --git a/src/main/java/org/jabref/gui/preview/PreviewControls.java b/src/main/java/org/jabref/gui/preview/PreviewControls.java new file mode 100644 index 00000000000..9b1eae12f3d --- /dev/null +++ b/src/main/java/org/jabref/gui/preview/PreviewControls.java @@ -0,0 +1,7 @@ +package org.jabref.gui.preview; + +public interface PreviewControls { + void nextPreviewStyle(); + + void previousPreviewStyle(); +} diff --git a/src/main/java/org/jabref/gui/preview/PreviewPanel.java b/src/main/java/org/jabref/gui/preview/PreviewPanel.java index a1e27d45820..d616efb46a1 100644 --- a/src/main/java/org/jabref/gui/preview/PreviewPanel.java +++ b/src/main/java/org/jabref/gui/preview/PreviewPanel.java @@ -38,7 +38,7 @@ /// Displays the entry preview /// /// The instance is re-used at each tab. The code ensures that the panel is moved across tabs when the user switches the tab. -public class PreviewPanel extends VBox { +public class PreviewPanel extends VBox implements PreviewControls { private final ExternalFilesEntryLinker fileLinker; private final KeyBindingRepository keyBindingRepository; @@ -156,10 +156,12 @@ public void print() { previewView.print(); } + @Override public void nextPreviewStyle() { cyclePreview(previewPreferences.getLayoutCyclePosition() + 1); } + @Override public void previousPreviewStyle() { cyclePreview(previewPreferences.getLayoutCyclePosition() - 1); } diff --git a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java index 6c70e7653f0..dc8f9d305f7 100644 --- a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java +++ b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java @@ -1,6 +1,7 @@ package org.jabref.gui.shared; import java.sql.SQLException; +import java.util.Collections; import java.util.Optional; import javax.swing.undo.UndoManager; @@ -15,7 +16,6 @@ import org.jabref.gui.LibraryTab; import org.jabref.gui.LibraryTabContainer; import org.jabref.gui.StateManager; -import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.exporter.SaveDatabaseAction; import org.jabref.gui.mergeentries.EntriesMergeResult; import org.jabref.gui.mergeentries.MergeEntriesDialog; @@ -142,16 +142,16 @@ public void listen(UpdateRefusedEvent updateRefusedEvent) { @Subscribe public void listen(SharedEntriesNotPresentEvent event) { LibraryTab libraryTab = tabContainer.getCurrentLibraryTab(); - EntryEditor entryEditor = libraryTab.getEntryEditor(); - libraryTab.getUndoManager().addEdit(new UndoableRemoveEntries(libraryTab.getDatabase(), event.bibEntries())); + if (libraryTab != null) { + undoManager.addEdit(new UndoableRemoveEntries(libraryTab.getDatabase(), event.bibEntries())); - if (entryEditor != null && (event.bibEntries().contains(entryEditor.getCurrentlyEditedEntry()))) { dialogService.showInformationDialogAndWait(Localization.lang("Shared entry is no longer present"), Localization.lang("The entry you currently work on has been deleted on the shared side.") + "\n" + Localization.lang("You can restore the entry using the \"Undo\" operation.")); - libraryTab.closeBottomPane(); + + stateManager.setSelectedEntries(Collections.emptyList()); } }