From 08ec5d87347159d35f2121bd05c760c24a29feec Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Tue, 4 Feb 2025 15:46:30 +0530 Subject: [PATCH 01/41] Fix #12272 - Show a welcome screen if no database is open --- src/main/java/org/jabref/gui/Base.css | 34 ++++- .../org/jabref/gui/frame/JabRefFrame.java | 54 +++++++- .../java/org/jabref/gui/util/WelcomePage.java | 123 ++++++++++++++++++ 3 files changed, 205 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/jabref/gui/util/WelcomePage.java diff --git a/src/main/java/org/jabref/gui/Base.css b/src/main/java/org/jabref/gui/Base.css index 20227768a80..b4ae86e4dbf 100644 --- a/src/main/java/org/jabref/gui/Base.css +++ b/src/main/java/org/jabref/gui/Base.css @@ -1734,9 +1734,41 @@ We want to have a look that matches our icons in the tool-bar */ -fx-effect: dropshadow(three-pass-box, rgba(0, 0, 0, 0.6), 8, 0.0, 0, 0); } +.welcome-label { + -fx-font-size: 40px; + -fx-text-fill: -jr-theme-text; + -fx-font-family: "Arial"; +} + +.description-label { + -fx-font-size: 25px; + -fx-font-family: "Arial"; +} + +.header-label { + -fx-font-size: 20px; + -fx-font-weight: bold; + -fx-font-family: "Arial"; +} + +.no-recent-label { + -fx-font-size: 18px; + -fx-text-fill: -jr-theme; + -fx-font-family: "Arial"; +} + +.welcome-hyperlink { + -fx-font-size: 18px; + -fx-text-fill: -jr-theme; +} + +.welcome-hyperlink:visited { + -fx-text-fill: -jr-theme; +} + /* AboutDialog */ #aboutDialog .about-heading { - -fx-font-size: 30; + -fx-font-size: 31; -fx-text-fill: -jr-theme; } diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 37afcfa9002..928bb1a41f9 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -18,12 +18,14 @@ import javafx.collections.transformation.FilteredList; import javafx.event.Event; import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; import javafx.scene.control.SeparatorMenuItem; import javafx.scene.control.SplitPane; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.input.KeyEvent; import javafx.scene.layout.BorderPane; +import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.stage.Stage; @@ -49,6 +51,7 @@ import org.jabref.gui.sidepane.SidePaneType; import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.util.BindingsHelper; +import org.jabref.gui.util.WelcomePage; import org.jabref.logic.UiCommand; import org.jabref.logic.ai.AiService; import org.jabref.logic.journals.JournalAbbreviationRepository; @@ -104,6 +107,9 @@ public class JabRefFrame extends BorderPane implements LibraryTabContainer, UiMe private Subscription dividerSubscription; + private final WelcomePage welcomePage; + private final StackPane contentPane = new StackPane(); + public JabRefFrame(Stage mainStage, DialogService dialogService, FileUpdateMonitor fileUpdateMonitor, @@ -125,6 +131,30 @@ public JabRefFrame(Stage mainStage, this.clipBoardManager = clipBoardManager; this.taskExecutor = taskExecutor; + this.fileHistory = new FileHistoryMenu( + this.preferences.getLastFilesOpenedPreferences().getFileHistory(), + dialogService, + getOpenDatabaseAction()); + + this.fileHistory.getItems().addListener((ListChangeListener) change -> { + boolean hasRecentFiles = !fileHistory.getItems().isEmpty(); + fileHistory.setDisable(!hasRecentFiles); + }); + + this.welcomePage = new WelcomePage( + this, + preferences, + aiService, + dialogService, + stateManager, + fileUpdateMonitor, + entryTypesManager, + undoManager, + clipBoardManager, + taskExecutor, + fileHistory + ); + setId("frame"); // Create components @@ -174,10 +204,6 @@ public JabRefFrame(Stage mainStage, this.preferences, taskExecutor); - this.fileHistory = new FileHistoryMenu( - this.preferences.getLastFilesOpenedPreferences().getFileHistory(), - dialogService, - getOpenDatabaseAction()); this.setOnKeyTyped(key -> { if (this.fileHistory.isShowing()) { if (this.fileHistory.openFileByKey(key)) { @@ -191,6 +217,8 @@ public JabRefFrame(Stage mainStage, frameDndHandler.initDragAndDrop(); initBindings(); initTabBarManager(); + bindDatabaseChanges(); + updateContent(); } private void initLayout() { @@ -230,11 +258,27 @@ private void initLayout() { setTop(head); splitPane.getItems().addAll(tabbedPane); + contentPane.getChildren().addAll(welcomePage, splitPane); SplitPane.setResizableWithParent(sidePane, false); sidePane.widthProperty().addListener(c -> updateSidePane()); sidePane.getChildren().addListener((InvalidationListener) c -> updateSidePane()); updateSidePane(); - setCenter(splitPane); + setCenter(contentPane); + updateSidePane(); + updateContent(); + } + + private void updateContent() { + boolean hasOpenDatabases = !stateManager.getOpenDatabases().isEmpty(); + welcomePage.setVisible(!hasOpenDatabases); + splitPane.setVisible(hasOpenDatabases); + + boolean hasRecentFiles = !fileHistory.getItems().isEmpty(); + fileHistory.setDisable(!hasRecentFiles); + } + + private void bindDatabaseChanges() { + stateManager.getOpenDatabases().addListener((InvalidationListener) obs -> Platform.runLater(this::updateContent)); } private void updateSidePane() { diff --git a/src/main/java/org/jabref/gui/util/WelcomePage.java b/src/main/java/org/jabref/gui/util/WelcomePage.java new file mode 100644 index 00000000000..7769c2a33f9 --- /dev/null +++ b/src/main/java/org/jabref/gui/util/WelcomePage.java @@ -0,0 +1,123 @@ +package org.jabref.gui.util; + +import javafx.collections.ListChangeListener; +import javafx.geometry.Pos; +import javafx.scene.control.Hyperlink; +import javafx.scene.control.Label; +import javafx.scene.control.MenuItem; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; + +import org.jabref.gui.ClipBoardManager; +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.frame.FileHistoryMenu; +import org.jabref.gui.frame.JabRefFrame; +import org.jabref.gui.importer.NewDatabaseAction; +import org.jabref.gui.importer.actions.OpenDatabaseAction; +import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.gui.undo.CountingUndoManager; +import org.jabref.logic.ai.AiService; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.TaskExecutor; +import org.jabref.model.entry.BibEntryTypesManager; +import org.jabref.model.util.FileUpdateMonitor; + +public class WelcomePage extends VBox { + + private final VBox recentLibrariesBox; + + public WelcomePage(JabRefFrame frame, + GuiPreferences preferences, + AiService aiService, + DialogService dialogService, + StateManager stateManager, + FileUpdateMonitor fileUpdateMonitor, + BibEntryTypesManager entryTypesManager, + CountingUndoManager undoManager, + ClipBoardManager clipBoardManager, + TaskExecutor taskExecutor, + FileHistoryMenu fileHistoryMenu) { + + setAlignment(Pos.CENTER); + setSpacing(10); + + this.recentLibrariesBox = new VBox(5); + + VBox welcomeBox = createWelcomeBox(); + VBox startBox = createStartBox(frame, preferences, aiService, dialogService, stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, taskExecutor); + VBox recentBox = createRecentBox(fileHistoryMenu); + + VBox container = new VBox(20, welcomeBox, startBox, recentBox); + container.setAlignment(Pos.CENTER); + + HBox mainContainer = new HBox(20, container); + mainContainer.setAlignment(Pos.CENTER); + + getChildren().add(mainContainer); + } + + private VBox createWelcomeBox() { + Label welcomeLabel = new Label(Localization.lang("Welcome to JabRef")); + welcomeLabel.getStyleClass().add("welcome-label"); + + Label descriptionLabel = new Label(Localization.lang("Stay on top of your Literature")); + descriptionLabel.getStyleClass().add("description-label"); + + return createBox(Pos.TOP_LEFT, welcomeLabel, descriptionLabel); + } + + private VBox createStartBox(JabRefFrame frame, GuiPreferences preferences, AiService aiService, DialogService dialogService, StateManager stateManager, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager, CountingUndoManager undoManager, ClipBoardManager clipBoardManager, TaskExecutor taskExecutor) { + Label startLabel = new Label(Localization.lang("Start")); + startLabel.getStyleClass().add("header-label"); + + Hyperlink newLibrary = new Hyperlink(Localization.lang("New Library")); + newLibrary.getStyleClass().add("welcome-hyperlink"); + newLibrary.setOnAction(e -> new NewDatabaseAction(frame, preferences).execute()); + + Hyperlink openLibrary = new Hyperlink(Localization.lang("Open Library")); + openLibrary.getStyleClass().add("welcome-hyperlink"); + openLibrary.setOnAction(e -> new OpenDatabaseAction(frame, preferences, aiService, dialogService, + stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, + taskExecutor).execute()); + + return createBox(Pos.TOP_LEFT, startLabel, newLibrary, openLibrary); + } + + private VBox createRecentBox(FileHistoryMenu fileHistoryMenu) { + Label recentLabel = new Label(Localization.lang("Recent")); + recentLabel.getStyleClass().add("header-label"); + + recentLibrariesBox.setAlignment(Pos.TOP_LEFT); + updateRecentLibraries(fileHistoryMenu); + + fileHistoryMenu.getItems().addListener((ListChangeListener) change -> updateRecentLibraries(fileHistoryMenu)); + + return createBox(Pos.TOP_LEFT, recentLabel, recentLibrariesBox); + } + + private void updateRecentLibraries(FileHistoryMenu fileHistoryMenu) { + recentLibrariesBox.getChildren().clear(); + + if (fileHistoryMenu.getItems().isEmpty()) { + Label noRecentLibrariesLabel = new Label(Localization.lang("No Recent Libraries")); + noRecentLibrariesLabel.getStyleClass().add("no-recent-label"); + recentLibrariesBox.getChildren().add(noRecentLibrariesLabel); + } else { + for (MenuItem item : fileHistoryMenu.getItems()) { + String filePath = item.getText(); + Hyperlink recentLibraryLink = new Hyperlink(filePath); + recentLibraryLink.getStyleClass().add("welcome-hyperlink"); + recentLibraryLink.setOnAction(item.getOnAction()); + recentLibrariesBox.getChildren().add(recentLibraryLink); + } + } + } + + private VBox createBox(Pos alignment, javafx.scene.Node... nodes) { + VBox box = new VBox(5); + box.setAlignment(alignment); + box.getChildren().addAll(nodes); + return box; + } +} From 684f7df4bd80cd1475a7414eb442dd60c8f5a84a Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Tue, 4 Feb 2025 16:30:25 +0530 Subject: [PATCH 02/41] Fix #12272 - Fix missing localisation keys for WelcomePage --- src/main/java/org/jabref/gui/util/WelcomePage.java | 3 ++- src/main/resources/l10n/JabRef_en.properties | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/util/WelcomePage.java b/src/main/java/org/jabref/gui/util/WelcomePage.java index 7769c2a33f9..6e1d131a916 100644 --- a/src/main/java/org/jabref/gui/util/WelcomePage.java +++ b/src/main/java/org/jabref/gui/util/WelcomePage.java @@ -2,6 +2,7 @@ import javafx.collections.ListChangeListener; import javafx.geometry.Pos; +import javafx.scene.Node; import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; import javafx.scene.control.MenuItem; @@ -114,7 +115,7 @@ private void updateRecentLibraries(FileHistoryMenu fileHistoryMenu) { } } - private VBox createBox(Pos alignment, javafx.scene.Node... nodes) { + private VBox createBox(Pos alignment, Node... nodes) { VBox box = new VBox(5); box.setAlignment(alignment); box.getChildren().addAll(nodes); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 1e90419d3d8..04e8b1006f2 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2832,3 +2832,11 @@ Include=Include Exclude=Exclude Include\ or\ exclude\ cross-referenced\ entries=Include or exclude cross-referenced entries Would\ you\ like\ to\ include\ cross-reference\ entries\ in\ the\ current\ operation?=Would you like to include cross-reference entries in the current operation? + +New=Library=New Library +No\ Recent\ Libraries=No Recent Libraries +Open\Library=Open Library +Recent=Recent +Start=Start +Stay\ on\ top\ of\ your\ Literature=Stay on top of your Literature +Welcome\ to\ JabRef=Welcome to JabRef From 3759e249d20951ee54d9d26050a8d369173d666f Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Tue, 4 Feb 2025 16:40:51 +0530 Subject: [PATCH 03/41] Fix #12272 - Fix missing localisation keys for WelcomePage --- src/main/resources/l10n/JabRef_en.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 04e8b1006f2..67331f76be6 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2833,9 +2833,9 @@ Exclude=Exclude Include\ or\ exclude\ cross-referenced\ entries=Include or exclude cross-referenced entries Would\ you\ like\ to\ include\ cross-reference\ entries\ in\ the\ current\ operation?=Would you like to include cross-reference entries in the current operation? -New=Library=New Library +New\ Library=New Library No\ Recent\ Libraries=No Recent Libraries -Open\Library=Open Library +Open\ Library=Open Library Recent=Recent Start=Start Stay\ on\ top\ of\ your\ Literature=Stay on top of your Literature From 4e576e9d2941feffb80983048f41d511e0ce4cac Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Thu, 6 Feb 2025 01:33:11 +0530 Subject: [PATCH 04/41] Fix #12272 - Addressed 1st Review Changes --- buildres/abbrv.jabref.org | 2 +- src/main/java/org/jabref/gui/Base.css | 8 +- src/main/java/org/jabref/gui/WelcomeTab.java | 15 +++ .../jabref/gui/exporter/ExportCommand.java | 31 ++++--- .../gui/exporter/SaveDatabaseAction.java | 12 +++ .../org/jabref/gui/frame/JabRefFrame.java | 21 ++--- .../importer/actions/OpenDatabaseAction.java | 11 ++- .../java/org/jabref/gui/util/WelcomePage.java | 91 ++++++++++++------- src/main/resources/csl-styles | 2 +- 9 files changed, 125 insertions(+), 68 deletions(-) create mode 100644 src/main/java/org/jabref/gui/WelcomeTab.java diff --git a/buildres/abbrv.jabref.org b/buildres/abbrv.jabref.org index 2a0e38c30bc..e74e6eb800b 160000 --- a/buildres/abbrv.jabref.org +++ b/buildres/abbrv.jabref.org @@ -1 +1 @@ -Subproject commit 2a0e38c30bc79a164158733759272c00243f43c9 +Subproject commit e74e6eb800b10aa7e4afe9a2a38b359653168c34 diff --git a/src/main/java/org/jabref/gui/Base.css b/src/main/java/org/jabref/gui/Base.css index b4ae86e4dbf..1a881834249 100644 --- a/src/main/java/org/jabref/gui/Base.css +++ b/src/main/java/org/jabref/gui/Base.css @@ -1740,18 +1740,18 @@ We want to have a look that matches our icons in the tool-bar */ -fx-font-family: "Arial"; } -.description-label { +.welcome-description-label { -fx-font-size: 25px; -fx-font-family: "Arial"; } -.header-label { +.welcome-header-label { -fx-font-size: 20px; -fx-font-weight: bold; -fx-font-family: "Arial"; } -.no-recent-label { +.welcome-no-recent-label { -fx-font-size: 18px; -fx-text-fill: -jr-theme; -fx-font-family: "Arial"; @@ -1768,7 +1768,7 @@ We want to have a look that matches our icons in the tool-bar */ /* AboutDialog */ #aboutDialog .about-heading { - -fx-font-size: 31; + -fx-font-size: 30; -fx-text-fill: -jr-theme; } diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java new file mode 100644 index 00000000000..1b8d191426d --- /dev/null +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -0,0 +1,15 @@ +package org.jabref.gui; + +import javafx.scene.control.Tab; + +import org.jabref.gui.util.WelcomePage; + +public class WelcomeTab extends Tab { + + public WelcomeTab(WelcomePage welcomePage) { + setText("Welcome"); + setContent(welcomePage.getWelcomeMainContainer()); + + setClosable(true); + } +} diff --git a/src/main/java/org/jabref/gui/exporter/ExportCommand.java b/src/main/java/org/jabref/gui/exporter/ExportCommand.java index 5cf0024cb9b..7e047b2d0f8 100644 --- a/src/main/java/org/jabref/gui/exporter/ExportCommand.java +++ b/src/main/java/org/jabref/gui/exporter/ExportCommand.java @@ -133,19 +133,24 @@ private void export(Path file, FileChooser.ExtensionFilter selectedExtensionFilt return null; // can not use BackgroundTask.wrap(Runnable) because Runnable.run() can't throw Exceptions }) .onSuccess(save -> { - LibraryTab.DatabaseNotification notificationPane = tabSupplier.get().getNotificationPane(); - notificationPane.notify( - IconTheme.JabRefIcons.FOLDER.getGraphicNode(), - Localization.lang("Export operation finished successfully."), - List.of(new Action(Localization.lang("Reveal in File Explorer"), event -> { - try { - NativeDesktop.openFolderAndSelectFile(file, preferences.getExternalApplicationsPreferences(), dialogService); - } catch (IOException e) { - LOGGER.error("Could not open export folder.", e); - } - notificationPane.hide(); - })), - Duration.seconds(5)); + if (tabSupplier.get() != null) { + LibraryTab.DatabaseNotification notificationPane = tabSupplier.get().getNotificationPane(); + notificationPane.notify( + IconTheme.JabRefIcons.FOLDER.getGraphicNode(), + Localization.lang("Export operation finished successfully."), + List.of(new Action(Localization.lang("Reveal in File Explorer"), event -> { + try { + NativeDesktop.openFolderAndSelectFile(file, preferences.getExternalApplicationsPreferences(), dialogService); + } catch ( + IOException e) { + LOGGER.error("Could not open export folder.", e); + } + notificationPane.hide(); + })), + Duration.seconds(5)); + } else { + LOGGER.warn("Library Tab is null as Welcome Tab is open"); + } }) .onFailure(this::handleError) .executeWith(taskExecutor); diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 10487ead6ad..4b98dada475 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -77,10 +77,16 @@ public SaveDatabaseAction(LibraryTab libraryTab, } public boolean save() { + if (libraryTab == null) { + return false; + } return save(libraryTab.getBibDatabaseContext(), SaveDatabaseMode.NORMAL); } public boolean save(SaveDatabaseMode mode) { + if (libraryTab == null) { + return false; + } return save(libraryTab.getBibDatabaseContext(), mode); } @@ -88,10 +94,16 @@ public boolean save(SaveDatabaseMode mode) { * Asks the user for the path and saves afterward */ public void saveAs() { + if (libraryTab == null) { + return; + } askForSavePath().ifPresent(this::saveAs); } public boolean saveAs(Path file) { + if (libraryTab == null) { + return false; + } return this.saveAs(file, SaveDatabaseMode.NORMAL); } diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 928bb1a41f9..8a14af50b36 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -25,7 +25,6 @@ import javafx.scene.control.TabPane; import javafx.scene.input.KeyEvent; import javafx.scene.layout.BorderPane; -import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.stage.Stage; @@ -34,6 +33,7 @@ import org.jabref.gui.LibraryTab; import org.jabref.gui.LibraryTabContainer; import org.jabref.gui.StateManager; +import org.jabref.gui.WelcomeTab; import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; @@ -108,7 +108,6 @@ public class JabRefFrame extends BorderPane implements LibraryTabContainer, UiMe private Subscription dividerSubscription; private final WelcomePage welcomePage; - private final StackPane contentPane = new StackPane(); public JabRefFrame(Stage mainStage, DialogService dialogService, @@ -257,22 +256,18 @@ private void initLayout() { head.setSpacing(0d); setTop(head); - splitPane.getItems().addAll(tabbedPane); - contentPane.getChildren().addAll(welcomePage, splitPane); + WelcomeTab welcomeTab = new WelcomeTab(welcomePage); + tabbedPane.getTabs().add(welcomeTab); + splitPane.getItems().add(tabbedPane); + setCenter(splitPane); SplitPane.setResizableWithParent(sidePane, false); sidePane.widthProperty().addListener(c -> updateSidePane()); sidePane.getChildren().addListener((InvalidationListener) c -> updateSidePane()); updateSidePane(); - setCenter(contentPane); - updateSidePane(); updateContent(); } private void updateContent() { - boolean hasOpenDatabases = !stateManager.getOpenDatabases().isEmpty(); - welcomePage.setVisible(!hasOpenDatabases); - splitPane.setVisible(hasOpenDatabases); - boolean hasRecentFiles = !fileHistory.getItems().isEmpty(); fileHistory.setDisable(!hasRecentFiles); } @@ -495,10 +490,8 @@ private void maintainInitialTabBarState(boolean show) { * Returns the currently viewed LibraryTab. */ public LibraryTab getCurrentLibraryTab() { - if (tabbedPane.getSelectionModel().getSelectedItem() == null) { - return null; - } - return (LibraryTab) tabbedPane.getSelectionModel().getSelectedItem(); + return (LibraryTab) Optional.ofNullable(tabbedPane.getSelectionModel().getSelectedItem()) + .filter(tab -> tab instanceof LibraryTab).orElse(null); } public void showLibraryTab(@NonNull LibraryTab libraryTab) { diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java index 748c78db227..8a0dbeae4fc 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -147,10 +147,15 @@ public FileDialogConfiguration getFileDialogConfiguration(Path initialDirectory) Path getInitialDirectory() { if (tabContainer.getLibraryTabs().isEmpty()) { return preferences.getFilePreferences().getWorkingDirectory(); - } else { - Optional databasePath = tabContainer.getCurrentLibraryTab().getBibDatabaseContext().getDatabasePath(); - return databasePath.map(Path::getParent).orElse(preferences.getFilePreferences().getWorkingDirectory()); } + + LibraryTab currentTab = tabContainer.getCurrentLibraryTab(); + if (currentTab == null) { + return preferences.getFilePreferences().getWorkingDirectory(); + } + + Optional databasePath = currentTab.getBibDatabaseContext().getDatabasePath(); + return databasePath.map(Path::getParent).orElse(preferences.getFilePreferences().getWorkingDirectory()); } /** diff --git a/src/main/java/org/jabref/gui/util/WelcomePage.java b/src/main/java/org/jabref/gui/util/WelcomePage.java index 6e1d131a916..574db070735 100644 --- a/src/main/java/org/jabref/gui/util/WelcomePage.java +++ b/src/main/java/org/jabref/gui/util/WelcomePage.java @@ -24,9 +24,22 @@ import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.util.FileUpdateMonitor; -public class WelcomePage extends VBox { +public class WelcomePage { + private final VBox welcomePageContainer; + private final HBox welcomeMainContainer; private final VBox recentLibrariesBox; + private final JabRefFrame frame; + private final GuiPreferences preferences; + private final AiService aiService; + private final DialogService dialogService; + private final StateManager stateManager; + private final FileUpdateMonitor fileUpdateMonitor; + private final BibEntryTypesManager entryTypesManager; + private final CountingUndoManager undoManager; + private final ClipBoardManager clipBoardManager; + private final TaskExecutor taskExecutor; + private final FileHistoryMenu fileHistoryMenu; public WelcomePage(JabRefFrame frame, GuiPreferences preferences, @@ -40,22 +53,37 @@ public WelcomePage(JabRefFrame frame, TaskExecutor taskExecutor, FileHistoryMenu fileHistoryMenu) { - setAlignment(Pos.CENTER); - setSpacing(10); + this.frame = frame; + this.preferences = preferences; + this.aiService = aiService; + this.dialogService = dialogService; + this.stateManager = stateManager; + this.fileUpdateMonitor = fileUpdateMonitor; + this.entryTypesManager = entryTypesManager; + this.undoManager = undoManager; + this.clipBoardManager = clipBoardManager; + this.taskExecutor = taskExecutor; + this.fileHistoryMenu = fileHistoryMenu; this.recentLibrariesBox = new VBox(5); + this.welcomePageContainer = new VBox(20); + welcomePageContainer.setAlignment(Pos.CENTER); + + this.welcomeMainContainer = new HBox(20); + welcomeMainContainer.setAlignment(Pos.CENTER); + VBox welcomeBox = createWelcomeBox(); - VBox startBox = createStartBox(frame, preferences, aiService, dialogService, stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, taskExecutor); - VBox recentBox = createRecentBox(fileHistoryMenu); + VBox startBox = createWelcomeStartBox(); + VBox recentBox = createWelcomeRecentBox(); - VBox container = new VBox(20, welcomeBox, startBox, recentBox); - container.setAlignment(Pos.CENTER); + welcomePageContainer.getChildren().addAll(welcomeBox, startBox, recentBox); - HBox mainContainer = new HBox(20, container); - mainContainer.setAlignment(Pos.CENTER); + welcomeMainContainer.getChildren().add(welcomePageContainer); + } - getChildren().add(mainContainer); + public HBox getWelcomeMainContainer() { + return welcomeMainContainer; } private VBox createWelcomeBox() { @@ -63,51 +91,50 @@ private VBox createWelcomeBox() { welcomeLabel.getStyleClass().add("welcome-label"); Label descriptionLabel = new Label(Localization.lang("Stay on top of your Literature")); - descriptionLabel.getStyleClass().add("description-label"); + descriptionLabel.getStyleClass().add("welcome-description-label"); - return createBox(Pos.TOP_LEFT, welcomeLabel, descriptionLabel); + return createVBoxContainer(welcomeLabel, descriptionLabel); } - private VBox createStartBox(JabRefFrame frame, GuiPreferences preferences, AiService aiService, DialogService dialogService, StateManager stateManager, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager, CountingUndoManager undoManager, ClipBoardManager clipBoardManager, TaskExecutor taskExecutor) { + private VBox createWelcomeStartBox() { Label startLabel = new Label(Localization.lang("Start")); - startLabel.getStyleClass().add("header-label"); + startLabel.getStyleClass().add("welcome-header-label"); - Hyperlink newLibrary = new Hyperlink(Localization.lang("New Library")); - newLibrary.getStyleClass().add("welcome-hyperlink"); - newLibrary.setOnAction(e -> new NewDatabaseAction(frame, preferences).execute()); + Hyperlink newLibraryLink = new Hyperlink(Localization.lang("New Library")); + newLibraryLink.getStyleClass().add("welcome-hyperlink"); + newLibraryLink.setOnAction(e -> new NewDatabaseAction(frame, preferences).execute()); - Hyperlink openLibrary = new Hyperlink(Localization.lang("Open Library")); - openLibrary.getStyleClass().add("welcome-hyperlink"); - openLibrary.setOnAction(e -> new OpenDatabaseAction(frame, preferences, aiService, dialogService, + Hyperlink openLibraryLink = new Hyperlink(Localization.lang("Open Library")); + openLibraryLink.getStyleClass().add("welcome-hyperlink"); + openLibraryLink.setOnAction(e -> new OpenDatabaseAction(frame, preferences, aiService, dialogService, stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, taskExecutor).execute()); - return createBox(Pos.TOP_LEFT, startLabel, newLibrary, openLibrary); + return createVBoxContainer(startLabel, newLibraryLink, openLibraryLink); } - private VBox createRecentBox(FileHistoryMenu fileHistoryMenu) { + private VBox createWelcomeRecentBox() { Label recentLabel = new Label(Localization.lang("Recent")); - recentLabel.getStyleClass().add("header-label"); + recentLabel.getStyleClass().add("welcome-header-label"); recentLibrariesBox.setAlignment(Pos.TOP_LEFT); - updateRecentLibraries(fileHistoryMenu); + updateWelcomeRecentLibraries(); - fileHistoryMenu.getItems().addListener((ListChangeListener) change -> updateRecentLibraries(fileHistoryMenu)); + fileHistoryMenu.getItems().addListener((ListChangeListener) change -> updateWelcomeRecentLibraries()); - return createBox(Pos.TOP_LEFT, recentLabel, recentLibrariesBox); + return createVBoxContainer(recentLabel, recentLibrariesBox); } - private void updateRecentLibraries(FileHistoryMenu fileHistoryMenu) { + private void updateWelcomeRecentLibraries() { recentLibrariesBox.getChildren().clear(); if (fileHistoryMenu.getItems().isEmpty()) { Label noRecentLibrariesLabel = new Label(Localization.lang("No Recent Libraries")); - noRecentLibrariesLabel.getStyleClass().add("no-recent-label"); + noRecentLibrariesLabel.getStyleClass().add("welcome-no-recent-label"); recentLibrariesBox.getChildren().add(noRecentLibrariesLabel); } else { for (MenuItem item : fileHistoryMenu.getItems()) { - String filePath = item.getText(); - Hyperlink recentLibraryLink = new Hyperlink(filePath); + Hyperlink recentLibraryLink = new Hyperlink(item.getText()); recentLibraryLink.getStyleClass().add("welcome-hyperlink"); recentLibraryLink.setOnAction(item.getOnAction()); recentLibrariesBox.getChildren().add(recentLibraryLink); @@ -115,9 +142,9 @@ private void updateRecentLibraries(FileHistoryMenu fileHistoryMenu) { } } - private VBox createBox(Pos alignment, Node... nodes) { + private VBox createVBoxContainer(Node... nodes) { VBox box = new VBox(5); - box.setAlignment(alignment); + box.setAlignment(Pos.TOP_LEFT); box.getChildren().addAll(nodes); return box; } diff --git a/src/main/resources/csl-styles b/src/main/resources/csl-styles index 22617f9b946..2e90b3afc1a 160000 --- a/src/main/resources/csl-styles +++ b/src/main/resources/csl-styles @@ -1 +1 @@ -Subproject commit 22617f9b94681402113eeca2ab7148e259b698f1 +Subproject commit 2e90b3afc1aa6fc90c46d674798936cd438af1fa From 52409bd16b6274bf7732d7660cfafb0fda6b1d34 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Thu, 6 Feb 2025 01:42:15 +0530 Subject: [PATCH 05/41] Fix #12272 - Checkstyle issue fix in ExportCommand file --- src/main/java/org/jabref/gui/exporter/ExportCommand.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/exporter/ExportCommand.java b/src/main/java/org/jabref/gui/exporter/ExportCommand.java index 7e047b2d0f8..f905eaefe15 100644 --- a/src/main/java/org/jabref/gui/exporter/ExportCommand.java +++ b/src/main/java/org/jabref/gui/exporter/ExportCommand.java @@ -141,8 +141,7 @@ private void export(Path file, FileChooser.ExtensionFilter selectedExtensionFilt List.of(new Action(Localization.lang("Reveal in File Explorer"), event -> { try { NativeDesktop.openFolderAndSelectFile(file, preferences.getExternalApplicationsPreferences(), dialogService); - } catch ( - IOException e) { + } catch (IOException e) { LOGGER.error("Could not open export folder.", e); } notificationPane.hide(); From f130244bdfb42b1611c92e404c335f5f755f1f02 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Thu, 6 Feb 2025 03:33:28 +0530 Subject: [PATCH 06/41] Reverted csl-styles submodule changes --- src/main/resources/csl-styles | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/csl-styles b/src/main/resources/csl-styles index 2e90b3afc1a..22617f9b946 160000 --- a/src/main/resources/csl-styles +++ b/src/main/resources/csl-styles @@ -1 +1 @@ -Subproject commit 2e90b3afc1aa6fc90c46d674798936cd438af1fa +Subproject commit 22617f9b94681402113eeca2ab7148e259b698f1 From 2559f220364fd9721f0dc6c8204b92a586adbef0 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Thu, 6 Feb 2025 03:34:31 +0530 Subject: [PATCH 07/41] Reverted abbrv.jabref.org submodule changes --- buildres/abbrv.jabref.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildres/abbrv.jabref.org b/buildres/abbrv.jabref.org index e74e6eb800b..2a0e38c30bc 160000 --- a/buildres/abbrv.jabref.org +++ b/buildres/abbrv.jabref.org @@ -1 +1 @@ -Subproject commit e74e6eb800b10aa7e4afe9a2a38b359653168c34 +Subproject commit 2a0e38c30bc79a164158733759272c00243f43c9 From 669083d9c61fee9548f96da3d7d6bfd0733bf212 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Thu, 13 Feb 2025 23:02:14 +0530 Subject: [PATCH 08/41] Integrated WelcomePage in WelcomeTab and code changes --- src/main/java/org/jabref/gui/LibraryTab.java | 5 + src/main/java/org/jabref/gui/WelcomeTab.java | 139 +++++++++++++++- .../jabref/gui/exporter/ExportCommand.java | 6 +- .../gui/exporter/SaveDatabaseAction.java | 12 -- .../org/jabref/gui/frame/JabRefFrame.java | 31 ++-- .../java/org/jabref/gui/util/WelcomePage.java | 151 ------------------ 6 files changed, 156 insertions(+), 188 deletions(-) delete mode 100644 src/main/java/org/jabref/gui/util/WelcomePage.java diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index cf00d78197a..b8b22ad8bb8 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -809,6 +809,11 @@ private void onClosed(Event event) { if (tableModel != null) { tableModel.unbind(); } + + if (stateManager.getOpenDatabases().isEmpty() && stateManager.activeDatabaseProperty().isPresent().get()) { + stateManager.activeDatabaseProperty().setValue(Optional.empty()); + } + // clean up the groups map stateManager.clearSelectedGroups(bibDatabaseContext); } diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 1b8d191426d..5434e5433ae 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -1,15 +1,146 @@ package org.jabref.gui; +import javafx.collections.ListChangeListener; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Hyperlink; +import javafx.scene.control.Label; +import javafx.scene.control.MenuItem; import javafx.scene.control.Tab; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; -import org.jabref.gui.util.WelcomePage; +import org.jabref.gui.frame.FileHistoryMenu; +import org.jabref.gui.importer.NewDatabaseAction; +import org.jabref.gui.importer.actions.OpenDatabaseAction; +import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.gui.undo.CountingUndoManager; +import org.jabref.logic.ai.AiService; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.TaskExecutor; +import org.jabref.model.entry.BibEntryTypesManager; +import org.jabref.model.util.FileUpdateMonitor; public class WelcomeTab extends Tab { - public WelcomeTab(WelcomePage welcomePage) { - setText("Welcome"); - setContent(welcomePage.getWelcomeMainContainer()); + private final VBox recentLibrariesBox; + private final LibraryTabContainer tabContainer; + private final GuiPreferences preferences; + private final AiService aiService; + private final DialogService dialogService; + private final StateManager stateManager; + private final FileUpdateMonitor fileUpdateMonitor; + private final BibEntryTypesManager entryTypesManager; + private final CountingUndoManager undoManager; + private final ClipBoardManager clipBoardManager; + private final TaskExecutor taskExecutor; + private final FileHistoryMenu fileHistoryMenu; + public WelcomeTab(LibraryTabContainer tabContainer, + GuiPreferences preferences, + AiService aiService, + DialogService dialogService, + StateManager stateManager, + FileUpdateMonitor fileUpdateMonitor, + BibEntryTypesManager entryTypesManager, + CountingUndoManager undoManager, + ClipBoardManager clipBoardManager, + TaskExecutor taskExecutor, + FileHistoryMenu fileHistoryMenu) { + + super("Welcome"); setClosable(true); + + this.tabContainer = tabContainer; + this.preferences = preferences; + this.aiService = aiService; + this.dialogService = dialogService; + this.stateManager = stateManager; + this.fileUpdateMonitor = fileUpdateMonitor; + this.entryTypesManager = entryTypesManager; + this.undoManager = undoManager; + this.clipBoardManager = clipBoardManager; + this.taskExecutor = taskExecutor; + this.fileHistoryMenu = fileHistoryMenu; + + this.recentLibrariesBox = new VBox(5); + + VBox welcomePageContainer = new VBox(20); + welcomePageContainer.setAlignment(Pos.CENTER); + + HBox welcomeMainContainer = new HBox(20); + welcomeMainContainer.setAlignment(Pos.CENTER); + + VBox welcomeBox = createWelcomeBox(); + VBox startBox = createWelcomeStartBox(); + VBox recentBox = createWelcomeRecentBox(); + + welcomePageContainer.getChildren().addAll(welcomeBox, startBox, recentBox); + welcomeMainContainer.getChildren().add(welcomePageContainer); + + setContent(welcomeMainContainer); + } + + private VBox createWelcomeBox() { + Label welcomeLabel = new Label(Localization.lang("Welcome to JabRef")); + welcomeLabel.getStyleClass().add("welcome-label"); + + Label descriptionLabel = new Label(Localization.lang("Stay on top of your Literature")); + descriptionLabel.getStyleClass().add("welcome-description-label"); + + return createVBoxContainer(welcomeLabel, descriptionLabel); + } + + private VBox createWelcomeStartBox() { + Label startLabel = new Label(Localization.lang("Start")); + startLabel.getStyleClass().add("welcome-header-label"); + + Hyperlink newLibraryLink = new Hyperlink(Localization.lang("New Library")); + newLibraryLink.getStyleClass().add("welcome-hyperlink"); + newLibraryLink.setOnAction(e -> new NewDatabaseAction(tabContainer, preferences).execute()); + + Hyperlink openLibraryLink = new Hyperlink(Localization.lang("Open Library")); + openLibraryLink.getStyleClass().add("welcome-hyperlink"); + openLibraryLink.setOnAction(e -> new OpenDatabaseAction(tabContainer, preferences, aiService, dialogService, + stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, + taskExecutor).execute()); + + return createVBoxContainer(startLabel, newLibraryLink, openLibraryLink); + } + + private VBox createWelcomeRecentBox() { + Label recentLabel = new Label(Localization.lang("Recent")); + recentLabel.getStyleClass().add("welcome-header-label"); + + recentLibrariesBox.setAlignment(Pos.TOP_LEFT); + updateWelcomeRecentLibraries(); + + fileHistoryMenu.getItems().addListener((ListChangeListener) change -> updateWelcomeRecentLibraries()); + + return createVBoxContainer(recentLabel, recentLibrariesBox); + } + + private void updateWelcomeRecentLibraries() { + recentLibrariesBox.getChildren().clear(); + + if (fileHistoryMenu.getItems().isEmpty()) { + Label noRecentLibrariesLabel = new Label(Localization.lang("No Recent Libraries")); + noRecentLibrariesLabel.getStyleClass().add("welcome-no-recent-label"); + recentLibrariesBox.getChildren().add(noRecentLibrariesLabel); + } else { + for (MenuItem item : fileHistoryMenu.getItems()) { + Hyperlink recentLibraryLink = new Hyperlink(item.getText()); + recentLibraryLink.getStyleClass().add("welcome-hyperlink"); + recentLibraryLink.setOnAction(item.getOnAction()); + recentLibrariesBox.getChildren().add(recentLibraryLink); + } + } + } + + private VBox createVBoxContainer(Node... nodes) { + VBox box = new VBox(5); + box.setAlignment(Pos.TOP_LEFT); + box.getChildren().addAll(nodes); + return box; } } diff --git a/src/main/java/org/jabref/gui/exporter/ExportCommand.java b/src/main/java/org/jabref/gui/exporter/ExportCommand.java index f905eaefe15..abbee75fa77 100644 --- a/src/main/java/org/jabref/gui/exporter/ExportCommand.java +++ b/src/main/java/org/jabref/gui/exporter/ExportCommand.java @@ -133,7 +133,9 @@ private void export(Path file, FileChooser.ExtensionFilter selectedExtensionFilt return null; // can not use BackgroundTask.wrap(Runnable) because Runnable.run() can't throw Exceptions }) .onSuccess(save -> { - if (tabSupplier.get() != null) { + boolean libraryTab = tabSupplier.get() != null; + // libraryTab is null in case of Welcome Tab + if (libraryTab) { LibraryTab.DatabaseNotification notificationPane = tabSupplier.get().getNotificationPane(); notificationPane.notify( IconTheme.JabRefIcons.FOLDER.getGraphicNode(), @@ -147,8 +149,6 @@ private void export(Path file, FileChooser.ExtensionFilter selectedExtensionFilt notificationPane.hide(); })), Duration.seconds(5)); - } else { - LOGGER.warn("Library Tab is null as Welcome Tab is open"); } }) .onFailure(this::handleError) diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 4b98dada475..10487ead6ad 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -77,16 +77,10 @@ public SaveDatabaseAction(LibraryTab libraryTab, } public boolean save() { - if (libraryTab == null) { - return false; - } return save(libraryTab.getBibDatabaseContext(), SaveDatabaseMode.NORMAL); } public boolean save(SaveDatabaseMode mode) { - if (libraryTab == null) { - return false; - } return save(libraryTab.getBibDatabaseContext(), mode); } @@ -94,16 +88,10 @@ public boolean save(SaveDatabaseMode mode) { * Asks the user for the path and saves afterward */ public void saveAs() { - if (libraryTab == null) { - return; - } askForSavePath().ifPresent(this::saveAs); } public boolean saveAs(Path file) { - if (libraryTab == null) { - return false; - } return this.saveAs(file, SaveDatabaseMode.NORMAL); } diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 8a14af50b36..5dc66d6ba6f 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -51,7 +51,6 @@ import org.jabref.gui.sidepane.SidePaneType; import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.util.BindingsHelper; -import org.jabref.gui.util.WelcomePage; import org.jabref.logic.UiCommand; import org.jabref.logic.ai.AiService; import org.jabref.logic.journals.JournalAbbreviationRepository; @@ -107,8 +106,6 @@ public class JabRefFrame extends BorderPane implements LibraryTabContainer, UiMe private Subscription dividerSubscription; - private final WelcomePage welcomePage; - public JabRefFrame(Stage mainStage, DialogService dialogService, FileUpdateMonitor fileUpdateMonitor, @@ -140,20 +137,6 @@ public JabRefFrame(Stage mainStage, fileHistory.setDisable(!hasRecentFiles); }); - this.welcomePage = new WelcomePage( - this, - preferences, - aiService, - dialogService, - stateManager, - fileUpdateMonitor, - entryTypesManager, - undoManager, - clipBoardManager, - taskExecutor, - fileHistory - ); - setId("frame"); // Create components @@ -256,7 +239,19 @@ private void initLayout() { head.setSpacing(0d); setTop(head); - WelcomeTab welcomeTab = new WelcomeTab(welcomePage); + WelcomeTab welcomeTab = new WelcomeTab( + this, + preferences, + aiService, + dialogService, + stateManager, + fileUpdateMonitor, + entryTypesManager, + undoManager, + clipBoardManager, + taskExecutor, + fileHistory + ); tabbedPane.getTabs().add(welcomeTab); splitPane.getItems().add(tabbedPane); setCenter(splitPane); diff --git a/src/main/java/org/jabref/gui/util/WelcomePage.java b/src/main/java/org/jabref/gui/util/WelcomePage.java deleted file mode 100644 index 574db070735..00000000000 --- a/src/main/java/org/jabref/gui/util/WelcomePage.java +++ /dev/null @@ -1,151 +0,0 @@ -package org.jabref.gui.util; - -import javafx.collections.ListChangeListener; -import javafx.geometry.Pos; -import javafx.scene.Node; -import javafx.scene.control.Hyperlink; -import javafx.scene.control.Label; -import javafx.scene.control.MenuItem; -import javafx.scene.layout.HBox; -import javafx.scene.layout.VBox; - -import org.jabref.gui.ClipBoardManager; -import org.jabref.gui.DialogService; -import org.jabref.gui.StateManager; -import org.jabref.gui.frame.FileHistoryMenu; -import org.jabref.gui.frame.JabRefFrame; -import org.jabref.gui.importer.NewDatabaseAction; -import org.jabref.gui.importer.actions.OpenDatabaseAction; -import org.jabref.gui.preferences.GuiPreferences; -import org.jabref.gui.undo.CountingUndoManager; -import org.jabref.logic.ai.AiService; -import org.jabref.logic.l10n.Localization; -import org.jabref.logic.util.TaskExecutor; -import org.jabref.model.entry.BibEntryTypesManager; -import org.jabref.model.util.FileUpdateMonitor; - -public class WelcomePage { - - private final VBox welcomePageContainer; - private final HBox welcomeMainContainer; - private final VBox recentLibrariesBox; - private final JabRefFrame frame; - private final GuiPreferences preferences; - private final AiService aiService; - private final DialogService dialogService; - private final StateManager stateManager; - private final FileUpdateMonitor fileUpdateMonitor; - private final BibEntryTypesManager entryTypesManager; - private final CountingUndoManager undoManager; - private final ClipBoardManager clipBoardManager; - private final TaskExecutor taskExecutor; - private final FileHistoryMenu fileHistoryMenu; - - public WelcomePage(JabRefFrame frame, - GuiPreferences preferences, - AiService aiService, - DialogService dialogService, - StateManager stateManager, - FileUpdateMonitor fileUpdateMonitor, - BibEntryTypesManager entryTypesManager, - CountingUndoManager undoManager, - ClipBoardManager clipBoardManager, - TaskExecutor taskExecutor, - FileHistoryMenu fileHistoryMenu) { - - this.frame = frame; - this.preferences = preferences; - this.aiService = aiService; - this.dialogService = dialogService; - this.stateManager = stateManager; - this.fileUpdateMonitor = fileUpdateMonitor; - this.entryTypesManager = entryTypesManager; - this.undoManager = undoManager; - this.clipBoardManager = clipBoardManager; - this.taskExecutor = taskExecutor; - this.fileHistoryMenu = fileHistoryMenu; - - this.recentLibrariesBox = new VBox(5); - - this.welcomePageContainer = new VBox(20); - welcomePageContainer.setAlignment(Pos.CENTER); - - this.welcomeMainContainer = new HBox(20); - welcomeMainContainer.setAlignment(Pos.CENTER); - - VBox welcomeBox = createWelcomeBox(); - VBox startBox = createWelcomeStartBox(); - VBox recentBox = createWelcomeRecentBox(); - - welcomePageContainer.getChildren().addAll(welcomeBox, startBox, recentBox); - - welcomeMainContainer.getChildren().add(welcomePageContainer); - } - - public HBox getWelcomeMainContainer() { - return welcomeMainContainer; - } - - private VBox createWelcomeBox() { - Label welcomeLabel = new Label(Localization.lang("Welcome to JabRef")); - welcomeLabel.getStyleClass().add("welcome-label"); - - Label descriptionLabel = new Label(Localization.lang("Stay on top of your Literature")); - descriptionLabel.getStyleClass().add("welcome-description-label"); - - return createVBoxContainer(welcomeLabel, descriptionLabel); - } - - private VBox createWelcomeStartBox() { - Label startLabel = new Label(Localization.lang("Start")); - startLabel.getStyleClass().add("welcome-header-label"); - - Hyperlink newLibraryLink = new Hyperlink(Localization.lang("New Library")); - newLibraryLink.getStyleClass().add("welcome-hyperlink"); - newLibraryLink.setOnAction(e -> new NewDatabaseAction(frame, preferences).execute()); - - Hyperlink openLibraryLink = new Hyperlink(Localization.lang("Open Library")); - openLibraryLink.getStyleClass().add("welcome-hyperlink"); - openLibraryLink.setOnAction(e -> new OpenDatabaseAction(frame, preferences, aiService, dialogService, - stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, - taskExecutor).execute()); - - return createVBoxContainer(startLabel, newLibraryLink, openLibraryLink); - } - - private VBox createWelcomeRecentBox() { - Label recentLabel = new Label(Localization.lang("Recent")); - recentLabel.getStyleClass().add("welcome-header-label"); - - recentLibrariesBox.setAlignment(Pos.TOP_LEFT); - updateWelcomeRecentLibraries(); - - fileHistoryMenu.getItems().addListener((ListChangeListener) change -> updateWelcomeRecentLibraries()); - - return createVBoxContainer(recentLabel, recentLibrariesBox); - } - - private void updateWelcomeRecentLibraries() { - recentLibrariesBox.getChildren().clear(); - - if (fileHistoryMenu.getItems().isEmpty()) { - Label noRecentLibrariesLabel = new Label(Localization.lang("No Recent Libraries")); - noRecentLibrariesLabel.getStyleClass().add("welcome-no-recent-label"); - recentLibrariesBox.getChildren().add(noRecentLibrariesLabel); - } else { - for (MenuItem item : fileHistoryMenu.getItems()) { - Hyperlink recentLibraryLink = new Hyperlink(item.getText()); - recentLibraryLink.getStyleClass().add("welcome-hyperlink"); - recentLibraryLink.setOnAction(item.getOnAction()); - recentLibrariesBox.getChildren().add(recentLibraryLink); - } - } - } - - private VBox createVBoxContainer(Node... nodes) { - VBox box = new VBox(5); - box.setAlignment(Pos.TOP_LEFT); - box.getChildren().addAll(nodes); - return box; - } -} From cf3188e84f0a3a7ae811548da689d6a7d1755099 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Fri, 14 Feb 2025 19:34:14 +0530 Subject: [PATCH 09/41] Implemented Review Changes 5 --- src/main/java/org/jabref/gui/LibraryTab.java | 1 + src/main/java/org/jabref/gui/WelcomeTab.java | 8 ++++---- .../jabref/gui/importer/actions/OpenDatabaseAction.java | 1 + src/main/resources/l10n/JabRef_en.properties | 4 +--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index b8b22ad8bb8..c033a258c2d 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -810,6 +810,7 @@ private void onClosed(Event event) { tableModel.unbind(); } + // This check is needed, because the WelcomeTab is a tab, but not a database. if (stateManager.getOpenDatabases().isEmpty() && stateManager.activeDatabaseProperty().isPresent().get()) { stateManager.activeDatabaseProperty().setValue(Optional.empty()); } diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 5434e5433ae..27f2dde3a5d 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -48,7 +48,7 @@ public WelcomeTab(LibraryTabContainer tabContainer, TaskExecutor taskExecutor, FileHistoryMenu fileHistoryMenu) { - super("Welcome"); + super(Localization.lang("Welcome")); setClosable(true); this.tabContainer = tabContainer; @@ -85,7 +85,7 @@ private VBox createWelcomeBox() { Label welcomeLabel = new Label(Localization.lang("Welcome to JabRef")); welcomeLabel.getStyleClass().add("welcome-label"); - Label descriptionLabel = new Label(Localization.lang("Stay on top of your Literature")); + Label descriptionLabel = new Label(Localization.lang("Stay on top of your literature")); descriptionLabel.getStyleClass().add("welcome-description-label"); return createVBoxContainer(welcomeLabel, descriptionLabel); @@ -95,11 +95,11 @@ private VBox createWelcomeStartBox() { Label startLabel = new Label(Localization.lang("Start")); startLabel.getStyleClass().add("welcome-header-label"); - Hyperlink newLibraryLink = new Hyperlink(Localization.lang("New Library")); + Hyperlink newLibraryLink = new Hyperlink(Localization.lang("New library")); newLibraryLink.getStyleClass().add("welcome-hyperlink"); newLibraryLink.setOnAction(e -> new NewDatabaseAction(tabContainer, preferences).execute()); - Hyperlink openLibraryLink = new Hyperlink(Localization.lang("Open Library")); + Hyperlink openLibraryLink = new Hyperlink(Localization.lang("Open library")); openLibraryLink.getStyleClass().add("welcome-hyperlink"); openLibraryLink.setOnAction(e -> new OpenDatabaseAction(tabContainer, preferences, aiService, dialogService, stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java index 8a0dbeae4fc..bcd99147a37 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -149,6 +149,7 @@ Path getInitialDirectory() { return preferences.getFilePreferences().getWorkingDirectory(); } + // This is because of the WelcomeTab class. LibraryTab currentTab = tabContainer.getCurrentLibraryTab(); if (currentTab == null) { return preferences.getFilePreferences().getWorkingDirectory(); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 802a8f7bbd8..3e5c0ca219a 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2855,10 +2855,8 @@ Exclude=Exclude Include\ or\ exclude\ cross-referenced\ entries=Include or exclude cross-referenced entries Would\ you\ like\ to\ include\ cross-reference\ entries\ in\ the\ current\ operation?=Would you like to include cross-reference entries in the current operation? -New\ Library=New Library No\ Recent\ Libraries=No Recent Libraries -Open\ Library=Open Library Recent=Recent Start=Start -Stay\ on\ top\ of\ your\ Literature=Stay on top of your Literature +Stay\ on\ top\ of\ your\ Literature=Stay on top of your literature Welcome\ to\ JabRef=Welcome to JabRef From d4332c6a1018e3d18f5f64a68a19a02ae4f1ca6a Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Fri, 14 Feb 2025 20:59:12 +0530 Subject: [PATCH 10/41] Fix #12272 - Localization key fix in JabRef_en.properties --- src/main/resources/l10n/JabRef_en.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 3e5c0ca219a..6faec13c1d7 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2858,5 +2858,6 @@ Would\ you\ like\ to\ include\ cross-reference\ entries\ in\ the\ current\ opera No\ Recent\ Libraries=No Recent Libraries Recent=Recent Start=Start -Stay\ on\ top\ of\ your\ Literature=Stay on top of your literature +Stay\ on\ top\ of\ your\ literature=Stay on top of your literature Welcome\ to\ JabRef=Welcome to JabRef +Welcome=Welcome From 5c0b6ee25f641d07c581048ddbe1fe631d42642f Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Tue, 18 Feb 2025 05:12:45 +0530 Subject: [PATCH 11/41] Implemented Open Welcome tab in help menu option and open welcome tab if no library is open --- .../org/jabref/cli/ArgumentProcessor.java | 4 ++ .../jabref/gui/actions/StandardActions.java | 2 +- .../org/jabref/gui/frame/JabRefFrame.java | 59 ++++++++++++++----- .../java/org/jabref/gui/frame/MainMenu.java | 11 ++++ src/main/resources/l10n/JabRef_en.properties | 6 +- 5 files changed, 65 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/jabref/cli/ArgumentProcessor.java b/src/main/java/org/jabref/cli/ArgumentProcessor.java index d9b2ead382b..a21811cfe96 100644 --- a/src/main/java/org/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/org/jabref/cli/ArgumentProcessor.java @@ -296,6 +296,10 @@ public void processArguments() { uiCommands.add(new UiCommand.OpenDatabases(loaded)); } + if (cli.isBlank() && loaded.isEmpty()) { + uiCommands.add(new UiCommand.BlankWorkspace()); + } + if (cli.isCheckConsistency()) { checkConsistency(cliPreferences, entryTypesManager); } diff --git a/src/main/java/org/jabref/gui/actions/StandardActions.java b/src/main/java/org/jabref/gui/actions/StandardActions.java index 611844e912a..267c783f32e 100644 --- a/src/main/java/org/jabref/gui/actions/StandardActions.java +++ b/src/main/java/org/jabref/gui/actions/StandardActions.java @@ -184,6 +184,7 @@ public enum StandardActions implements Action { ERROR_CONSOLE(Localization.lang("View event log"), Localization.lang("Display all error messages")), SEARCH_FOR_UPDATES(Localization.lang("Check for updates")), ABOUT(Localization.lang("About JabRef"), Localization.lang("About JabRef")), + OPEN_WELCOME_TAB(Localization.lang("Open Welcome Tab")), EDIT_LIST(Localization.lang("Edit"), IconTheme.JabRefIcons.EDIT), VIEW_LIST(Localization.lang("View"), IconTheme.JabRefIcons.FILE), @@ -207,7 +208,6 @@ public enum StandardActions implements Action { GROUP_ENTRIES_REMOVE(Localization.lang("Remove selected entries from this group")), CLEAR_EMBEDDINGS_CACHE(Localization.lang("Clear embeddings cache")); - private String text; private final String description; private final Optional icon; diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 7a7baa4f482..549a854e5a1 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -233,20 +233,26 @@ private void initLayout() { head.setSpacing(0d); setTop(head); - WelcomeTab welcomeTab = new WelcomeTab( - this, - preferences, - aiService, - dialogService, - stateManager, - fileUpdateMonitor, - entryTypesManager, - undoManager, - clipBoardManager, - taskExecutor, - fileHistory - ); - tabbedPane.getTabs().add(welcomeTab); + boolean hasPreviousFiles = !stateManager.getOpenDatabases().isEmpty(); + + if (!hasPreviousFiles) { + WelcomeTab welcomeTab = new WelcomeTab( + this, + preferences, + aiService, + dialogService, + stateManager, + fileUpdateMonitor, + entryTypesManager, + undoManager, + clipBoardManager, + taskExecutor, + fileHistory + ); + + tabbedPane.getTabs().add(welcomeTab); + } + splitPane.getItems().add(tabbedPane); setCenter(splitPane); SplitPane.setResizableWithParent(sidePane, false); @@ -468,6 +474,31 @@ public void showLibraryTab(@NonNull LibraryTab libraryTab) { tabbedPane.getSelectionModel().select(libraryTab); } + public void showWelcomeTab() { + for (Tab tab : tabbedPane.getTabs()) { + if (!(tab instanceof LibraryTab)) { + tabbedPane.getSelectionModel().select(tab); + return; + } + + WelcomeTab welcomeTab = new WelcomeTab( + this, + preferences, + aiService, + dialogService, + stateManager, + fileUpdateMonitor, + entryTypesManager, + undoManager, + clipBoardManager, + taskExecutor, + fileHistory + ); + tabbedPane.getTabs().add(welcomeTab); + tabbedPane.getSelectionModel().select(welcomeTab); + } + } + /** * Opens a new tab with existing data. * Asynchronous loading is done at {@link LibraryTab#createLibraryTab}. diff --git a/src/main/java/org/jabref/gui/frame/MainMenu.java b/src/main/java/org/jabref/gui/frame/MainMenu.java index a320bdd6348..8ef13aa7d2a 100644 --- a/src/main/java/org/jabref/gui/frame/MainMenu.java +++ b/src/main/java/org/jabref/gui/frame/MainMenu.java @@ -12,6 +12,7 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionFactory; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.actions.StandardActions; import org.jabref.gui.ai.ClearEmbeddingsAction; import org.jabref.gui.auximport.NewSubLibraryAction; @@ -364,6 +365,16 @@ private void createMenu() { factory.createMenuItem(StandardActions.OPEN_DEV_VERSION_LINK, new OpenBrowserAction("https://builds.jabref.org/master/", dialogService, preferences.getExternalApplicationsPreferences())), factory.createMenuItem(StandardActions.OPEN_CHANGELOG, new OpenBrowserAction("https://github.com/JabRef/jabref/blob/main/CHANGELOG.md", dialogService, preferences.getExternalApplicationsPreferences())) ), + + factory.createMenuItem(StandardActions.OPEN_WELCOME_TAB, new SimpleCommand() { + @Override + public void execute() { + frame.showWelcomeTab(); + } + }), + + new SeparatorMenuItem(), + factory.createMenuItem(StandardActions.ABOUT, new AboutAction()) ); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index ec7f4cf7b71..8fa5c0e12f9 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2855,11 +2855,13 @@ Exclude=Exclude Include\ or\ exclude\ cross-referenced\ entries=Include or exclude cross-referenced entries Would\ you\ like\ to\ include\ cross-reference\ entries\ in\ the\ current\ operation?=Would you like to include cross-reference entries in the current operation? +Entries\ copied\ successfully,\ including\ cross-references.=Entries copied successfully, including cross-references. +Entries\ copied\ successfully,\ without\ cross-references.=Entries copied successfully, without cross-references. + No\ Recent\ Libraries=No Recent Libraries Recent=Recent Start=Start Stay\ on\ top\ of\ your\ literature=Stay on top of your literature Welcome\ to\ JabRef=Welcome to JabRef Welcome=Welcome -Entries\ copied\ successfully,\ including\ cross-references.=Entries copied successfully, including cross-references. -Entries\ copied\ successfully,\ without\ cross-references.=Entries copied successfully, without cross-references. +Open\ Welcome\ Tab=Open Welcome Tab From cdc1977227ca547b0155e0e82249e7503661adc8 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Wed, 19 Feb 2025 02:02:24 +0530 Subject: [PATCH 12/41] Implemented Review Changes 6 --- .../org/jabref/gui/LibraryTabContainer.java | 3 +- src/main/java/org/jabref/gui/WelcomeTab.java | 2 +- .../jabref/gui/actions/StandardActions.java | 3 +- .../gui/auximport/FromAuxDialogViewModel.java | 6 +- .../jabref/gui/exporter/ExportCommand.java | 4 +- .../org/jabref/gui/frame/JabRefFrame.java | 59 ++++++++--------- .../gui/frame/JabRefFrameViewModel.java | 12 ++-- .../java/org/jabref/gui/frame/MainMenu.java | 65 ++++++++++--------- .../org/jabref/gui/frame/MainToolBar.java | 26 ++++---- .../jabref/gui/importer/ImportCommand.java | 8 ++- .../importer/actions/OpenDatabaseAction.java | 2 +- .../jabref/gui/search/GlobalSearchBar.java | 7 +- .../gui/shared/SharedDatabaseUIManager.java | 7 +- .../gui/slr/ExistingStudySearchAction.java | 3 +- src/main/resources/l10n/JabRef_en.properties | 4 +- 15 files changed, 113 insertions(+), 98 deletions(-) diff --git a/src/main/java/org/jabref/gui/LibraryTabContainer.java b/src/main/java/org/jabref/gui/LibraryTabContainer.java index 139653c87ca..3f8e47f661c 100644 --- a/src/main/java/org/jabref/gui/LibraryTabContainer.java +++ b/src/main/java/org/jabref/gui/LibraryTabContainer.java @@ -1,6 +1,7 @@ package org.jabref.gui; import java.util.List; +import java.util.Optional; import org.jabref.model.database.BibDatabaseContext; @@ -13,7 +14,7 @@ public interface LibraryTabContainer { List getLibraryTabs(); @Nullable - LibraryTab getCurrentLibraryTab(); + Optional getCurrentLibraryTab(); void showLibraryTab(LibraryTab libraryTab); diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 27f2dde3a5d..1c1da0c04e4 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -124,7 +124,7 @@ private void updateWelcomeRecentLibraries() { recentLibrariesBox.getChildren().clear(); if (fileHistoryMenu.getItems().isEmpty()) { - Label noRecentLibrariesLabel = new Label(Localization.lang("No Recent Libraries")); + Label noRecentLibrariesLabel = new Label(Localization.lang("No recent libraries")); noRecentLibrariesLabel.getStyleClass().add("welcome-no-recent-label"); recentLibrariesBox.getChildren().add(noRecentLibrariesLabel); } else { diff --git a/src/main/java/org/jabref/gui/actions/StandardActions.java b/src/main/java/org/jabref/gui/actions/StandardActions.java index 267c783f32e..a3d6c7ee683 100644 --- a/src/main/java/org/jabref/gui/actions/StandardActions.java +++ b/src/main/java/org/jabref/gui/actions/StandardActions.java @@ -184,7 +184,7 @@ public enum StandardActions implements Action { ERROR_CONSOLE(Localization.lang("View event log"), Localization.lang("Display all error messages")), SEARCH_FOR_UPDATES(Localization.lang("Check for updates")), ABOUT(Localization.lang("About JabRef"), Localization.lang("About JabRef")), - OPEN_WELCOME_TAB(Localization.lang("Open Welcome Tab")), + OPEN_WELCOME_TAB(Localization.lang("Open welcome tab")), EDIT_LIST(Localization.lang("Edit"), IconTheme.JabRefIcons.EDIT), VIEW_LIST(Localization.lang("View"), IconTheme.JabRefIcons.FILE), @@ -208,6 +208,7 @@ public enum StandardActions implements Action { GROUP_ENTRIES_REMOVE(Localization.lang("Remove selected entries from this group")), CLEAR_EMBEDDINGS_CACHE(Localization.lang("Clear embeddings cache")); + private String text; private final String description; private final Optional icon; diff --git a/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java b/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java index 4f197767dde..82b1571d408 100644 --- a/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java +++ b/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java @@ -1,6 +1,7 @@ package org.jabref.gui.auximport; import java.nio.file.Path; +import java.util.Objects; import java.util.Optional; import javafx.beans.property.BooleanProperty; @@ -15,6 +16,7 @@ import javafx.collections.FXCollections; import org.jabref.gui.DialogService; +import org.jabref.gui.LibraryTab; import org.jabref.gui.LibraryTabContainer; import org.jabref.gui.StateManager; import org.jabref.gui.util.FileDialogConfiguration; @@ -58,7 +60,9 @@ public FromAuxDialogViewModel(LibraryTabContainer tabContainer, this.stateManager = stateManager; librariesProperty.setAll(stateManager.getOpenDatabases()); - selectedLibraryProperty.set(tabContainer.getCurrentLibraryTab().getBibDatabaseContext()); + selectedLibraryProperty.set( + Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).map(LibraryTab::getBibDatabaseContext).orElse(null) + ); EasyBind.listen(selectedLibraryProperty, (obs, oldValue, newValue) -> { if (auxParserResult != null) { parse(); diff --git a/src/main/java/org/jabref/gui/exporter/ExportCommand.java b/src/main/java/org/jabref/gui/exporter/ExportCommand.java index abbee75fa77..55656fe385a 100644 --- a/src/main/java/org/jabref/gui/exporter/ExportCommand.java +++ b/src/main/java/org/jabref/gui/exporter/ExportCommand.java @@ -133,9 +133,9 @@ private void export(Path file, FileChooser.ExtensionFilter selectedExtensionFilt return null; // can not use BackgroundTask.wrap(Runnable) because Runnable.run() can't throw Exceptions }) .onSuccess(save -> { - boolean libraryTab = tabSupplier.get() != null; + boolean currentTabIsLibraryTab = tabSupplier.get() != null; // libraryTab is null in case of Welcome Tab - if (libraryTab) { + if (currentTabIsLibraryTab) { LibraryTab.DatabaseNotification notificationPane = tabSupplier.get().getNotificationPane(); notificationPane.notify( IconTheme.JabRefIcons.FOLDER.getGraphicNode(), diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 549a854e5a1..001afd663cf 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -129,6 +129,14 @@ public JabRefFrame(Stage mainStage, dialogService, getOpenDatabaseAction()); + this.setOnKeyTyped(key -> { + if (this.fileHistory.isShowing()) { + if (this.fileHistory.openFileByKey(key)) { + this.fileHistory.getParentMenu().hide(); + } + } + }); + this.fileHistory.getItems().addListener((ListChangeListener) change -> { boolean hasRecentFiles = !fileHistory.getItems().isEmpty(); fileHistory.setDisable(!hasRecentFiles); @@ -183,14 +191,6 @@ public JabRefFrame(Stage mainStage, this.preferences, taskExecutor); - this.setOnKeyTyped(key -> { - if (this.fileHistory.isShowing()) { - if (this.fileHistory.openFileByKey(key)) { - this.fileHistory.getParentMenu().hide(); - } - } - }); - initLayout(); initKeyBindings(); frameDndHandler.initDragAndDrop(); @@ -233,9 +233,7 @@ private void initLayout() { head.setSpacing(0d); setTop(head); - boolean hasPreviousFiles = !stateManager.getOpenDatabases().isEmpty(); - - if (!hasPreviousFiles) { + if (stateManager.getOpenDatabases().isEmpty()) { WelcomeTab welcomeTab = new WelcomeTab( this, preferences, @@ -298,7 +296,7 @@ private void initKeyBindings() { if (keyBinding.isPresent()) { switch (keyBinding.get()) { case FOCUS_ENTRY_TABLE: - getCurrentLibraryTab().getMainTable().requestFocus(); + Objects.requireNonNull(getCurrentLibraryTab()).ifPresent(tab -> tab.getMainTable().requestFocus()); event.consume(); break; case FOCUS_GROUP_LIST: @@ -320,31 +318,31 @@ private void initKeyBindings() { globalSearchBar.openGlobalSearchDialog(); break; case NEW_ARTICLE: - new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.Article, dialogService, preferences, stateManager).execute(); + new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.Article, dialogService, preferences, stateManager).execute(); break; case NEW_BOOK: - new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.Book, dialogService, preferences, stateManager).execute(); + new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.Book, dialogService, preferences, stateManager).execute(); break; case NEW_INBOOK: - new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.InBook, dialogService, preferences, stateManager).execute(); + new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.InBook, dialogService, preferences, stateManager).execute(); break; case NEW_MASTERSTHESIS: - new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.MastersThesis, dialogService, preferences, stateManager).execute(); + new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.MastersThesis, dialogService, preferences, stateManager).execute(); break; case NEW_PHDTHESIS: - new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.PhdThesis, dialogService, preferences, stateManager).execute(); + new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.PhdThesis, dialogService, preferences, stateManager).execute(); break; case NEW_PROCEEDINGS: - new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.Proceedings, dialogService, preferences, stateManager).execute(); + new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.Proceedings, dialogService, preferences, stateManager).execute(); break; case NEW_TECHREPORT: - new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.TechReport, dialogService, preferences, stateManager).execute(); + new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.TechReport, dialogService, preferences, stateManager).execute(); break; case NEW_UNPUBLISHED: - new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.Unpublished, dialogService, preferences, stateManager).execute(); + new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.Unpublished, dialogService, preferences, stateManager).execute(); break; case NEW_INPROCEEDINGS: - new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.InProceedings, dialogService, preferences, stateManager).execute(); + new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.InProceedings, dialogService, preferences, stateManager).execute(); break; case PASTE: if (OS.OS_X) { // Workaround for a jdk issue that executes paste twice when using cmd+v in a TextField @@ -368,15 +366,15 @@ private void initBindings() { filteredTabs.setPredicate(LibraryTab.class::isInstance); // This variable cannot be inlined, since otherwise the list created by EasyBind is being garbage collected - openDatabaseList = EasyBind.map(filteredTabs, tab -> ((LibraryTab) tab).getBibDatabaseContext()); + openDatabaseList = EasyBind.map(filteredTabs, tab -> Optional.of((LibraryTab) tab).map(LibraryTab::getBibDatabaseContext).orElse(null)); EasyBind.bindContent(stateManager.getOpenDatabases(), openDatabaseList); // the binding for stateManager.activeDatabaseProperty() is at org.jabref.gui.LibraryTab.onDatabaseLoadingSucceed // Subscribe to the search EasyBind.subscribe(stateManager.activeSearchQuery(SearchType.NORMAL_SEARCH), query -> { - if (getCurrentLibraryTab() != null) { - getCurrentLibraryTab().searchQueryProperty().set(query); + if (getCurrentLibraryTab().isPresent()) { + getCurrentLibraryTab().ifPresent(tab -> tab.searchQueryProperty().set(query)); } }); @@ -465,9 +463,10 @@ private void updateTabBarVisible() { /** * Returns the currently viewed LibraryTab. */ - public LibraryTab getCurrentLibraryTab() { - return (LibraryTab) Optional.ofNullable(tabbedPane.getSelectionModel().getSelectedItem()) - .filter(tab -> tab instanceof LibraryTab).orElse(null); + public Optional getCurrentLibraryTab() { + return Optional.ofNullable(tabbedPane.getSelectionModel().getSelectedItem()) + .filter(LibraryTab.class::isInstance) + .map(LibraryTab.class::cast); } public void showLibraryTab(@NonNull LibraryTab libraryTab) { @@ -475,12 +474,14 @@ public void showLibraryTab(@NonNull LibraryTab libraryTab) { } public void showWelcomeTab() { + // The loop iterates through all tabs in tabbedPane to check if a WelcomeTab already exists. If yes, it is selected for (Tab tab : tabbedPane.getTabs()) { if (!(tab instanceof LibraryTab)) { tabbedPane.getSelectionModel().select(tab); return; } + // If the WelcomeTab is not found, a new instance is created and added WelcomeTab welcomeTab = new WelcomeTab( this, preferences, @@ -665,11 +666,11 @@ public CloseDatabaseAction(LibraryTabContainer tabContainer, StateManager stateM public void execute() { Platform.runLater(() -> { if (libraryTab == null) { - if (tabContainer.getCurrentLibraryTab() == null) { + if (Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).isEmpty()) { LOGGER.error("No library tab to close"); return; } - tabContainer.closeTab(tabContainer.getCurrentLibraryTab()); + tabContainer.getCurrentLibraryTab().ifPresent(tabContainer::closeTab); } else { tabContainer.closeTab(libraryTab); } diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java b/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java index 274a316fee4..f760897a3ee 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java @@ -125,10 +125,10 @@ public boolean close() { .map(BibDatabaseContext::getDatabasePath) .flatMap(Optional::stream) .toList(); - Path focusedLibraries = Optional.ofNullable(tabContainer.getCurrentLibraryTab()) - .map(LibraryTab::getBibDatabaseContext) - .flatMap(BibDatabaseContext::getDatabasePath) - .orElse(null); + Path focusedLibraries = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()) + .map(LibraryTab::getBibDatabaseContext) + .flatMap(BibDatabaseContext::getDatabasePath) + .orElse(null); // Then ask if the user really wants to close, if the library has not been saved since last save. if (!tabContainer.closeTabs(tabContainer.getLibraryTabs())) { @@ -380,7 +380,7 @@ private Optional getLibraryTab(ParserResult parserResult) { private void addParserResult(ParserResult parserResult, boolean raisePanel) { if (parserResult.toOpenTab()) { LOGGER.trace("Adding the entries to the open tab."); - LibraryTab libraryTab = tabContainer.getCurrentLibraryTab(); + LibraryTab libraryTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); if (libraryTab == null) { LOGGER.debug("No open tab found to add entries to. Creating a new tab."); tabContainer.addTab(parserResult.getDatabaseContext(), raisePanel); @@ -455,7 +455,7 @@ private void waitForLoadingFinished(Runnable runnable) { private void jumpToEntry(String entryKey) { // check current library tab first - LibraryTab currentLibraryTab = tabContainer.getCurrentLibraryTab(); + LibraryTab currentLibraryTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); List sortedTabs = tabContainer.getLibraryTabs().stream() .sorted(Comparator.comparing(tab -> tab != currentLibraryTab)) .toList(); diff --git a/src/main/java/org/jabref/gui/frame/MainMenu.java b/src/main/java/org/jabref/gui/frame/MainMenu.java index 8ef13aa7d2a..d66a75edac6 100644 --- a/src/main/java/org/jabref/gui/frame/MainMenu.java +++ b/src/main/java/org/jabref/gui/frame/MainMenu.java @@ -1,5 +1,6 @@ package org.jabref.gui.frame; +import java.util.Objects; import java.util.function.Supplier; import javafx.event.ActionEvent; @@ -152,8 +153,8 @@ private void createMenu() { factory.createMenuItem(StandardActions.NEW_LIBRARY, new NewDatabaseAction(frame, preferences)), factory.createMenuItem(StandardActions.OPEN_LIBRARY, openDatabaseActionSupplier.get()), fileHistoryMenu, - factory.createMenuItem(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, frame::getCurrentLibraryTab, dialogService, preferences, stateManager)), - factory.createMenuItem(StandardActions.SAVE_LIBRARY_AS, new SaveAction(SaveAction.SaveMethod.SAVE_AS, frame::getCurrentLibraryTab, dialogService, preferences, stateManager)), + factory.createMenuItem(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager)), + factory.createMenuItem(StandardActions.SAVE_LIBRARY_AS, new SaveAction(SaveAction.SaveMethod.SAVE_AS, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager)), factory.createMenuItem(StandardActions.SAVE_ALL, new SaveAllAction(frame::getLibraryTabs, preferences, dialogService, stateManager)), factory.createMenuItem(StandardActions.CLOSE_LIBRARY, new JabRefFrame.CloseDatabaseAction(frame, stateManager)), @@ -164,9 +165,9 @@ private void createMenu() { factory.createMenuItem(StandardActions.IMPORT_INTO_NEW_LIBRARY, new ImportCommand(frame, ImportCommand.ImportMethod.AS_NEW, preferences, stateManager, fileUpdateMonitor, taskExecutor, dialogService))), factory.createSubMenu(StandardActions.EXPORT, - factory.createMenuItem(StandardActions.EXPORT_ALL, new ExportCommand(ExportCommand.ExportMethod.EXPORT_ALL, frame::getCurrentLibraryTab, stateManager, dialogService, preferences, entryTypesManager, abbreviationRepository, taskExecutor)), - factory.createMenuItem(StandardActions.EXPORT_SELECTED, new ExportCommand(ExportCommand.ExportMethod.EXPORT_SELECTED, frame::getCurrentLibraryTab, stateManager, dialogService, preferences, entryTypesManager, abbreviationRepository, taskExecutor)), - factory.createMenuItem(StandardActions.SAVE_SELECTED_AS_PLAIN_BIBTEX, new SaveAction(SaveAction.SaveMethod.SAVE_SELECTED, frame::getCurrentLibraryTab, dialogService, preferences, stateManager))), + factory.createMenuItem(StandardActions.EXPORT_ALL, new ExportCommand(ExportCommand.ExportMethod.EXPORT_ALL, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, dialogService, preferences, entryTypesManager, abbreviationRepository, taskExecutor)), + factory.createMenuItem(StandardActions.EXPORT_SELECTED, new ExportCommand(ExportCommand.ExportMethod.EXPORT_SELECTED, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, dialogService, preferences, entryTypesManager, abbreviationRepository, taskExecutor)), + factory.createMenuItem(StandardActions.SAVE_SELECTED_AS_PLAIN_BIBTEX, new SaveAction(SaveAction.SaveMethod.SAVE_SELECTED, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager))), new SeparatorMenuItem(), @@ -184,14 +185,14 @@ private void createMenu() { ); edit.getItems().addAll( - factory.createMenuItem(StandardActions.UNDO, new UndoAction(frame::getCurrentLibraryTab, undoManager, dialogService, stateManager)), - factory.createMenuItem(StandardActions.REDO, new RedoAction(frame::getCurrentLibraryTab, undoManager, dialogService, stateManager)), + factory.createMenuItem(StandardActions.UNDO, new UndoAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), undoManager, dialogService, stateManager)), + factory.createMenuItem(StandardActions.REDO, new RedoAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), undoManager, dialogService, stateManager)), new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.CUT, new EditAction(StandardActions.CUT, frame::getCurrentLibraryTab, stateManager, undoManager)), + factory.createMenuItem(StandardActions.CUT, new EditAction(StandardActions.CUT, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), - factory.createMenuItem(StandardActions.COPY, new EditAction(StandardActions.COPY, frame::getCurrentLibraryTab, stateManager, undoManager)), + factory.createMenuItem(StandardActions.COPY, new EditAction(StandardActions.COPY, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), factory.createSubMenu(StandardActions.COPY_MORE, factory.createMenuItem(StandardActions.COPY_TITLE, new CopyMoreAction(StandardActions.COPY_TITLE, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), factory.createMenuItem(StandardActions.COPY_KEY, new CopyMoreAction(StandardActions.COPY_KEY, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), @@ -201,12 +202,12 @@ private void createMenu() { factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new CopyCitationAction(CitationStyleOutputFormat.HTML, dialogService, stateManager, clipBoardManager, taskExecutor, preferences, abbreviationRepository)), factory.createMenuItem(StandardActions.EXPORT_SELECTED_TO_CLIPBOARD, new ExportToClipboardAction(dialogService, stateManager, clipBoardManager, taskExecutor, preferences))), - factory.createMenuItem(StandardActions.PASTE, new EditAction(StandardActions.PASTE, frame::getCurrentLibraryTab, stateManager, undoManager)), + factory.createMenuItem(StandardActions.PASTE, new EditAction(StandardActions.PASTE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.REPLACE_ALL, new ReplaceStringAction(frame::getCurrentLibraryTab, stateManager, dialogService)), - factory.createMenuItem(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(frame::getCurrentLibraryTab, dialogService, stateManager, taskExecutor, preferences, undoManager)), + factory.createMenuItem(StandardActions.REPLACE_ALL, new ReplaceStringAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, dialogService)), + factory.createMenuItem(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, taskExecutor, preferences, undoManager)), new SeparatorMenuItem(), @@ -219,12 +220,12 @@ private void createMenu() { specialFieldsSeparator, // ToDo: SpecialField needs the active BasePanel to mark it as changed. // Refactor BasePanel, should mark the BibDatabaseContext or the UndoManager as dirty instead! - SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.RANKING, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.RELEVANCE, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.QUALITY, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.PRINTED, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager), - SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.PRIORITY, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager), - SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.READ_STATUS, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager)); + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.RANKING, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.RELEVANCE, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.QUALITY, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.PRINTED, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager), + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.PRIORITY, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager), + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.READ_STATUS, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager)); edit.addEventHandler(ActionEvent.ACTION, event -> { // Work around for mac only issue, where cmd+v on a dialogue triggers the paste action of menu item, resulting in addition of the pasted content in the MainTable. // If the mainscreen is not focused, the actions captured by menu are consumed. @@ -234,9 +235,9 @@ private void createMenu() { }); library.getItems().addAll( - factory.createMenuItem(StandardActions.NEW_ENTRY, new NewEntryAction(frame::getCurrentLibraryTab, dialogService, preferences, stateManager)), + factory.createMenuItem(StandardActions.NEW_ENTRY, new NewEntryAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager)), factory.createMenuItem(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT, new PlainCitationParserAction(dialogService, stateManager)), - factory.createMenuItem(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, frame::getCurrentLibraryTab, stateManager, undoManager)), + factory.createMenuItem(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), new SeparatorMenuItem(), @@ -249,11 +250,11 @@ private void createMenu() { ); quality.getItems().addAll( - factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(frame::getCurrentLibraryTab, dialogService, stateManager, preferences, entryTypesManager, taskExecutor)), + factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences, entryTypesManager, taskExecutor)), factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(dialogService, stateManager, undoManager, preferences)), - factory.createMenuItem(StandardActions.CHECK_INTEGRITY, new IntegrityCheckAction(frame::getCurrentLibraryTab, preferences, dialogService, stateManager, (UiTaskExecutor) taskExecutor, abbreviationRepository)), - factory.createMenuItem(StandardActions.CHECK_CONSISTENCY, new ConsistencyCheckAction(frame::getCurrentLibraryTab, dialogService, stateManager, preferences, entryTypesManager, (UiTaskExecutor) taskExecutor)), - factory.createMenuItem(StandardActions.CLEANUP_ENTRIES, new CleanupAction(frame::getCurrentLibraryTab, preferences, dialogService, stateManager, taskExecutor, undoManager)), + factory.createMenuItem(StandardActions.CHECK_INTEGRITY, new IntegrityCheckAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), preferences, dialogService, stateManager, (UiTaskExecutor) taskExecutor, abbreviationRepository)), + factory.createMenuItem(StandardActions.CHECK_CONSISTENCY, new ConsistencyCheckAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences, entryTypesManager, (UiTaskExecutor) taskExecutor)), + factory.createMenuItem(StandardActions.CLEANUP_ENTRIES, new CleanupAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), preferences, dialogService, stateManager, taskExecutor, undoManager)), new SeparatorMenuItem(), @@ -262,11 +263,11 @@ private void createMenu() { new SeparatorMenuItem(), factory.createSubMenu(StandardActions.ABBREVIATE, - factory.createMenuItem(StandardActions.ABBREVIATE_DEFAULT, new AbbreviateAction(StandardActions.ABBREVIATE_DEFAULT, frame::getCurrentLibraryTab, dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)), - factory.createMenuItem(StandardActions.ABBREVIATE_DOTLESS, new AbbreviateAction(StandardActions.ABBREVIATE_DOTLESS, frame::getCurrentLibraryTab, dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)), - factory.createMenuItem(StandardActions.ABBREVIATE_SHORTEST_UNIQUE, new AbbreviateAction(StandardActions.ABBREVIATE_SHORTEST_UNIQUE, frame::getCurrentLibraryTab, dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager))), + factory.createMenuItem(StandardActions.ABBREVIATE_DEFAULT, new AbbreviateAction(StandardActions.ABBREVIATE_DEFAULT, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)), + factory.createMenuItem(StandardActions.ABBREVIATE_DOTLESS, new AbbreviateAction(StandardActions.ABBREVIATE_DOTLESS, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)), + factory.createMenuItem(StandardActions.ABBREVIATE_SHORTEST_UNIQUE, new AbbreviateAction(StandardActions.ABBREVIATE_SHORTEST_UNIQUE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager))), - factory.createMenuItem(StandardActions.UNABBREVIATE, new AbbreviateAction(StandardActions.UNABBREVIATE, frame::getCurrentLibraryTab, dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)) + factory.createMenuItem(StandardActions.UNABBREVIATE, new AbbreviateAction(StandardActions.UNABBREVIATE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)) ); Menu lookupIdentifiers = factory.createSubMenu(StandardActions.LOOKUP_DOC_IDENTIFIER); @@ -313,7 +314,7 @@ private void createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.REBUILD_FULLTEXT_SEARCH_INDEX, new RebuildFulltextSearchIndexAction(stateManager, frame::getCurrentLibraryTab, dialogService, preferences)), + factory.createMenuItem(StandardActions.REBUILD_FULLTEXT_SEARCH_INDEX, new RebuildFulltextSearchIndexAction(stateManager, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences)), factory.createMenuItem(StandardActions.CLEAR_EMBEDDINGS_CACHE, new ClearEmbeddingsAction(stateManager, dialogService, aiService, taskExecutor)), new SeparatorMenuItem(), @@ -331,13 +332,13 @@ 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, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager)), + factory.createMenuItem(StandardActions.PREVIOUS_PREVIEW_STYLE, new PreviewSwitchAction(PreviewSwitchAction.Direction.PREVIOUS, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager)), new SeparatorMenuItem(), factory.createMenuItem(StandardActions.SHOW_PDF_VIEWER, new ShowDocumentViewerAction(stateManager, preferences)), - factory.createMenuItem(StandardActions.EDIT_ENTRY, new OpenEntryEditorAction(frame::getCurrentLibraryTab, stateManager)), + factory.createMenuItem(StandardActions.EDIT_ENTRY, new OpenEntryEditorAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager)), factory.createMenuItem(StandardActions.OPEN_CONSOLE, new OpenConsoleAction(stateManager, preferences, dialogService)) ); diff --git a/src/main/java/org/jabref/gui/frame/MainToolBar.java b/src/main/java/org/jabref/gui/frame/MainToolBar.java index 9cd83cd28f0..39ecb068805 100644 --- a/src/main/java/org/jabref/gui/frame/MainToolBar.java +++ b/src/main/java/org/jabref/gui/frame/MainToolBar.java @@ -1,5 +1,7 @@ package org.jabref.gui.frame; +import java.util.Objects; + import javafx.concurrent.Task; import javafx.geometry.Orientation; import javafx.scene.Group; @@ -111,7 +113,7 @@ private void createToolBar() { new HBox( factory.createIconButton(StandardActions.NEW_LIBRARY, new NewDatabaseAction(frame, preferences)), factory.createIconButton(StandardActions.OPEN_LIBRARY, new OpenDatabaseAction(frame, preferences, aiService, dialogService, stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, taskExecutor)), - factory.createIconButton(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, frame::getCurrentLibraryTab, dialogService, preferences, stateManager))), + factory.createIconButton(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager))), leftSpacer, @@ -120,27 +122,27 @@ private void createToolBar() { rightSpacer, new HBox( - factory.createIconButton(StandardActions.NEW_ARTICLE, new NewEntryAction(frame::getCurrentLibraryTab, StandardEntryType.Article, dialogService, preferences, stateManager)), - factory.createIconButton(StandardActions.NEW_ENTRY, new NewEntryAction(frame::getCurrentLibraryTab, dialogService, preferences, stateManager)), + factory.createIconButton(StandardActions.NEW_ARTICLE, new NewEntryAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), StandardEntryType.Article, dialogService, preferences, stateManager)), + factory.createIconButton(StandardActions.NEW_ENTRY, new NewEntryAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager)), createNewEntryFromIdButton(), factory.createIconButton(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT, new PlainCitationParserAction(dialogService, stateManager)), - factory.createIconButton(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, frame::getCurrentLibraryTab, stateManager, undoManager))), + factory.createIconButton(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager))), new Separator(Orientation.VERTICAL), new HBox( - factory.createIconButton(StandardActions.UNDO, new UndoAction(frame::getCurrentLibraryTab, undoManager, dialogService, stateManager)), - factory.createIconButton(StandardActions.REDO, new RedoAction(frame::getCurrentLibraryTab, undoManager, dialogService, stateManager)), - factory.createIconButton(StandardActions.CUT, new EditAction(StandardActions.CUT, frame::getCurrentLibraryTab, stateManager, undoManager)), - factory.createIconButton(StandardActions.COPY, new EditAction(StandardActions.COPY, frame::getCurrentLibraryTab, stateManager, undoManager)), - factory.createIconButton(StandardActions.PASTE, new EditAction(StandardActions.PASTE, frame::getCurrentLibraryTab, stateManager, undoManager))), + factory.createIconButton(StandardActions.UNDO, new UndoAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), undoManager, dialogService, stateManager)), + factory.createIconButton(StandardActions.REDO, new RedoAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), undoManager, dialogService, stateManager)), + factory.createIconButton(StandardActions.CUT, new EditAction(StandardActions.CUT, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), + factory.createIconButton(StandardActions.COPY, new EditAction(StandardActions.COPY, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), + factory.createIconButton(StandardActions.PASTE, new EditAction(StandardActions.PASTE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager))), new Separator(Orientation.VERTICAL), new HBox( pushToApplicationButton, - factory.createIconButton(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(frame::getCurrentLibraryTab, dialogService, stateManager, taskExecutor, preferences, undoManager)), - factory.createIconButton(StandardActions.CLEANUP_ENTRIES, new CleanupAction(frame::getCurrentLibraryTab, preferences, dialogService, stateManager, taskExecutor, undoManager))), + factory.createIconButton(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, taskExecutor, preferences, undoManager)), + factory.createIconButton(StandardActions.CLEANUP_ENTRIES, new CleanupAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), preferences, dialogService, stateManager, taskExecutor, undoManager))), new Separator(Orientation.VERTICAL), @@ -169,7 +171,7 @@ Button createNewEntryFromIdButton() { newEntryFromIdButton.setFocusTraversable(false); newEntryFromIdButton.disableProperty().bind(ActionHelper.needsDatabase(stateManager).not()); newEntryFromIdButton.setOnMouseClicked(event -> { - GenerateEntryFromIdDialog entryFromId = new GenerateEntryFromIdDialog(frame.getCurrentLibraryTab(), dialogService, preferences, taskExecutor, stateManager); + GenerateEntryFromIdDialog entryFromId = new GenerateEntryFromIdDialog(Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, taskExecutor, stateManager); if (entryFromIdPopOver == null) { entryFromIdPopOver = new PopOver(entryFromId.getDialogPane()); diff --git a/src/main/java/org/jabref/gui/importer/ImportCommand.java b/src/main/java/org/jabref/gui/importer/ImportCommand.java index 58e268cd54e..6c983b5f18a 100644 --- a/src/main/java/org/jabref/gui/importer/ImportCommand.java +++ b/src/main/java/org/jabref/gui/importer/ImportCommand.java @@ -6,12 +6,14 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.SortedSet; import javafx.stage.FileChooser; import org.jabref.gui.DialogService; +import org.jabref.gui.LibraryTab; import org.jabref.gui.LibraryTabContainer; import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; @@ -117,7 +119,11 @@ private void importSingleFile(Path file, SortedSet importers, FileChoo }) .executeWith(taskExecutor); } else { - ImportEntriesDialog dialog = new ImportEntriesDialog(tabContainer.getCurrentLibraryTab().getBibDatabaseContext(), task); + LibraryTab currentTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); + ImportEntriesDialog dialog = new ImportEntriesDialog( + currentTab != null ? currentTab.getBibDatabaseContext() : null, + task + ); dialog.setTitle(Localization.lang("Import")); dialogService.showCustomDialogAndWait(dialog); } diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java index bcd99147a37..01afb2b0918 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -150,7 +150,7 @@ Path getInitialDirectory() { } // This is because of the WelcomeTab class. - LibraryTab currentTab = tabContainer.getCurrentLibraryTab(); + LibraryTab currentTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); if (currentTab == null) { return preferences.getFilePreferences().getWorkingDirectory(); } diff --git a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java index ea6633a2a34..9d36e36f4a6 100644 --- a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java +++ b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java @@ -151,10 +151,7 @@ public GlobalSearchBar(LibraryTabContainer tabContainer, if (keyBindingRepository.matches(event, KeyBinding.CLEAR_SEARCH)) { searchField.clear(); if (searchType == SearchType.NORMAL_SEARCH) { - LibraryTab currentLibraryTab = tabContainer.getCurrentLibraryTab(); - if (currentLibraryTab != null) { - currentLibraryTab.getMainTable().requestFocus(); - } + Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).ifPresent(currentLibraryTab -> currentLibraryTab.getMainTable().requestFocus()); } event.consume(); } @@ -258,7 +255,7 @@ private void initSearchModifierButtons() { if (!filePreferences.shouldFulltextIndexLinkedFiles() && newVal) { boolean enableFulltextSearch = dialogService.showConfirmationDialogAndWait(Localization.lang("Fulltext search"), Localization.lang("Fulltext search requires the setting 'Automatically index all linked files for fulltext search' to be enabled. Do you want to enable indexing now?"), Localization.lang("Enable indexing"), Localization.lang("Keep disabled")); - LibraryTab libraryTab = tabContainer.getCurrentLibraryTab(); + LibraryTab libraryTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); if (libraryTab != null && enableFulltextSearch) { filePreferences.setFulltextIndexLinkedFiles(true); searchPreferences.setSearchFlag(SearchFlags.FULLTEXT, true); diff --git a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java index 6c70e7653f0..1e0d3246d50 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.Objects; import java.util.Optional; import javax.swing.undo.UndoManager; @@ -94,7 +95,7 @@ public void listen(ConnectionLostEvent connectionLostEvent) { if (answer.isPresent()) { if (answer.get().equals(reconnect)) { - tabContainer.closeTab(tabContainer.getCurrentLibraryTab()); + Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).ifPresent(tabContainer::closeTab); dialogService.showCustomDialogAndWait(new SharedDatabaseLoginDialogView(tabContainer)); } else if (answer.get().equals(workOffline)) { connectionLostEvent.bibDatabaseContext().convertToLocalDatabase(); @@ -102,7 +103,7 @@ public void listen(ConnectionLostEvent connectionLostEvent) { dialogService.notify(Localization.lang("Working offline.")); } } else { - tabContainer.closeTab(tabContainer.getCurrentLibraryTab()); + Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).ifPresent(tabContainer::closeTab); } } @@ -141,7 +142,7 @@ public void listen(UpdateRefusedEvent updateRefusedEvent) { @Subscribe public void listen(SharedEntriesNotPresentEvent event) { - LibraryTab libraryTab = tabContainer.getCurrentLibraryTab(); + LibraryTab libraryTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); EntryEditor entryEditor = libraryTab.getEntryEditor(); libraryTab.getUndoManager().addEdit(new UndoableRemoveEntries(libraryTab.getDatabase(), event.bibEntries())); diff --git a/src/main/java/org/jabref/gui/slr/ExistingStudySearchAction.java b/src/main/java/org/jabref/gui/slr/ExistingStudySearchAction.java index 512bcfd075c..075bcbe22bc 100644 --- a/src/main/java/org/jabref/gui/slr/ExistingStudySearchAction.java +++ b/src/main/java/org/jabref/gui/slr/ExistingStudySearchAction.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.Objects; import java.util.function.Supplier; import org.jabref.gui.DialogService; @@ -147,6 +148,6 @@ protected void crawlPreparation(Path studyRepositoryRoot) throws IOException, Gi // The user focused an SLR // We hard close the tab // Future work: Properly close the tab (with saving, ...) - tabContainer.closeTab(tabContainer.getCurrentLibraryTab()); + Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).ifPresent(tabContainer::closeTab); } } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 8fa5c0e12f9..d5d2b610798 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2858,10 +2858,10 @@ Would\ you\ like\ to\ include\ cross-reference\ entries\ in\ the\ current\ opera Entries\ copied\ successfully,\ including\ cross-references.=Entries copied successfully, including cross-references. Entries\ copied\ successfully,\ without\ cross-references.=Entries copied successfully, without cross-references. -No\ Recent\ Libraries=No Recent Libraries +No\ recent\ libraries=No recent libraries Recent=Recent Start=Start Stay\ on\ top\ of\ your\ literature=Stay on top of your literature Welcome\ to\ JabRef=Welcome to JabRef Welcome=Welcome -Open\ Welcome\ Tab=Open Welcome Tab +Open\ welcome\ tab=Open welcome tab From 40c4ca30faa208e32f9683de9624dd65929d3a73 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Wed, 5 Mar 2025 02:05:59 +0530 Subject: [PATCH 13/41] Reverted Interface changes and fixed save as and save for welcome tab --- src/main/java/org/jabref/gui/LibraryTab.java | 5 -- .../org/jabref/gui/LibraryTabContainer.java | 3 +- .../gui/auximport/FromAuxDialogViewModel.java | 4 +- .../org/jabref/gui/frame/JabRefFrame.java | 59 ++++++---------- .../gui/frame/JabRefFrameViewModel.java | 12 ++-- .../java/org/jabref/gui/frame/MainMenu.java | 67 +++++++++---------- .../org/jabref/gui/frame/MainToolBar.java | 28 ++++---- .../jabref/gui/importer/ImportCommand.java | 8 +-- .../importer/actions/OpenDatabaseAction.java | 2 +- .../jabref/gui/search/GlobalSearchBar.java | 7 +- .../gui/shared/SharedDatabaseUIManager.java | 7 +- .../gui/slr/ExistingStudySearchAction.java | 3 +- 12 files changed, 85 insertions(+), 120 deletions(-) diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index c033a258c2d..a6d9dcffd84 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -810,11 +810,6 @@ private void onClosed(Event event) { tableModel.unbind(); } - // This check is needed, because the WelcomeTab is a tab, but not a database. - if (stateManager.getOpenDatabases().isEmpty() && stateManager.activeDatabaseProperty().isPresent().get()) { - stateManager.activeDatabaseProperty().setValue(Optional.empty()); - } - // clean up the groups map stateManager.clearSelectedGroups(bibDatabaseContext); } diff --git a/src/main/java/org/jabref/gui/LibraryTabContainer.java b/src/main/java/org/jabref/gui/LibraryTabContainer.java index 3f8e47f661c..139653c87ca 100644 --- a/src/main/java/org/jabref/gui/LibraryTabContainer.java +++ b/src/main/java/org/jabref/gui/LibraryTabContainer.java @@ -1,7 +1,6 @@ package org.jabref.gui; import java.util.List; -import java.util.Optional; import org.jabref.model.database.BibDatabaseContext; @@ -14,7 +13,7 @@ public interface LibraryTabContainer { List getLibraryTabs(); @Nullable - Optional getCurrentLibraryTab(); + LibraryTab getCurrentLibraryTab(); void showLibraryTab(LibraryTab libraryTab); diff --git a/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java b/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java index 82b1571d408..632af00f6e4 100644 --- a/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java +++ b/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java @@ -60,9 +60,7 @@ public FromAuxDialogViewModel(LibraryTabContainer tabContainer, this.stateManager = stateManager; librariesProperty.setAll(stateManager.getOpenDatabases()); - selectedLibraryProperty.set( - Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).map(LibraryTab::getBibDatabaseContext).orElse(null) - ); + selectedLibraryProperty.set(tabContainer.getCurrentLibraryTab().getBibDatabaseContext()); EasyBind.listen(selectedLibraryProperty, (obs, oldValue, newValue) -> { if (auxParserResult != null) { parse(); diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 001afd663cf..5461ea9cc42 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -16,7 +16,6 @@ import javafx.collections.transformation.FilteredList; import javafx.event.Event; import javafx.scene.control.ContextMenu; -import javafx.scene.control.MenuItem; import javafx.scene.control.SeparatorMenuItem; import javafx.scene.control.SplitPane; import javafx.scene.control.Tab; @@ -137,10 +136,7 @@ public JabRefFrame(Stage mainStage, } }); - this.fileHistory.getItems().addListener((ListChangeListener) change -> { - boolean hasRecentFiles = !fileHistory.getItems().isEmpty(); - fileHistory.setDisable(!hasRecentFiles); - }); + fileHistory.disableProperty().bind(Bindings.isEmpty(fileHistory.getItems())); setId("frame"); @@ -252,21 +248,11 @@ private void initLayout() { } splitPane.getItems().add(tabbedPane); - setCenter(splitPane); SplitPane.setResizableWithParent(sidePane, false); sidePane.widthProperty().addListener(_ -> updateSidePane()); sidePane.getChildren().addListener((InvalidationListener) _ -> updateSidePane()); updateSidePane(); - updateContent(); - } - - private void updateContent() { - boolean hasRecentFiles = !fileHistory.getItems().isEmpty(); - fileHistory.setDisable(!hasRecentFiles); - } - - private void bindDatabaseChanges() { - stateManager.getOpenDatabases().addListener((InvalidationListener) obs -> Platform.runLater(this::updateContent)); + setCenter(splitPane); } private void updateSidePane() { @@ -296,7 +282,7 @@ private void initKeyBindings() { if (keyBinding.isPresent()) { switch (keyBinding.get()) { case FOCUS_ENTRY_TABLE: - Objects.requireNonNull(getCurrentLibraryTab()).ifPresent(tab -> tab.getMainTable().requestFocus()); + getCurrentLibraryTab().getMainTable().requestFocus(); event.consume(); break; case FOCUS_GROUP_LIST: @@ -318,31 +304,31 @@ private void initKeyBindings() { globalSearchBar.openGlobalSearchDialog(); break; case NEW_ARTICLE: - new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.Article, dialogService, preferences, stateManager).execute(); + new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.Article, dialogService, preferences, stateManager).execute(); break; case NEW_BOOK: - new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.Book, dialogService, preferences, stateManager).execute(); + new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.Book, dialogService, preferences, stateManager).execute(); break; case NEW_INBOOK: - new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.InBook, dialogService, preferences, stateManager).execute(); + new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.InBook, dialogService, preferences, stateManager).execute(); break; case NEW_MASTERSTHESIS: - new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.MastersThesis, dialogService, preferences, stateManager).execute(); + new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.MastersThesis, dialogService, preferences, stateManager).execute(); break; case NEW_PHDTHESIS: - new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.PhdThesis, dialogService, preferences, stateManager).execute(); + new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.PhdThesis, dialogService, preferences, stateManager).execute(); break; case NEW_PROCEEDINGS: - new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.Proceedings, dialogService, preferences, stateManager).execute(); + new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.Proceedings, dialogService, preferences, stateManager).execute(); break; case NEW_TECHREPORT: - new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.TechReport, dialogService, preferences, stateManager).execute(); + new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.TechReport, dialogService, preferences, stateManager).execute(); break; case NEW_UNPUBLISHED: - new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.Unpublished, dialogService, preferences, stateManager).execute(); + new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.Unpublished, dialogService, preferences, stateManager).execute(); break; case NEW_INPROCEEDINGS: - new NewEntryAction(() -> Objects.requireNonNull(getCurrentLibraryTab()).orElse(null), StandardEntryType.InProceedings, dialogService, preferences, stateManager).execute(); + new NewEntryAction(this::getCurrentLibraryTab, StandardEntryType.InProceedings, dialogService, preferences, stateManager).execute(); break; case PASTE: if (OS.OS_X) { // Workaround for a jdk issue that executes paste twice when using cmd+v in a TextField @@ -366,15 +352,15 @@ private void initBindings() { filteredTabs.setPredicate(LibraryTab.class::isInstance); // This variable cannot be inlined, since otherwise the list created by EasyBind is being garbage collected - openDatabaseList = EasyBind.map(filteredTabs, tab -> Optional.of((LibraryTab) tab).map(LibraryTab::getBibDatabaseContext).orElse(null)); + openDatabaseList = EasyBind.map(filteredTabs, tab -> ((LibraryTab) tab).getBibDatabaseContext()); EasyBind.bindContent(stateManager.getOpenDatabases(), openDatabaseList); // the binding for stateManager.activeDatabaseProperty() is at org.jabref.gui.LibraryTab.onDatabaseLoadingSucceed // Subscribe to the search EasyBind.subscribe(stateManager.activeSearchQuery(SearchType.NORMAL_SEARCH), query -> { - if (getCurrentLibraryTab().isPresent()) { - getCurrentLibraryTab().ifPresent(tab -> tab.searchQueryProperty().set(query)); + if (getCurrentLibraryTab() != null) { + getCurrentLibraryTab().searchQueryProperty().set(query); } }); @@ -386,8 +372,8 @@ private void initBindings() { if (selectedTab instanceof LibraryTab libraryTab) { stateManager.setActiveDatabase(libraryTab.getBibDatabaseContext()); stateManager.activeTabProperty().set(Optional.of(libraryTab)); - } else if (selectedTab == null) { - // All databases are closed + } else if (selectedTab == null || selectedTab instanceof WelcomeTab) { + // All databases are closed or Welcome Tab is open stateManager.setActiveDatabase(null); stateManager.activeTabProperty().set(Optional.empty()); } @@ -463,10 +449,9 @@ private void updateTabBarVisible() { /** * Returns the currently viewed LibraryTab. */ - public Optional getCurrentLibraryTab() { - return Optional.ofNullable(tabbedPane.getSelectionModel().getSelectedItem()) - .filter(LibraryTab.class::isInstance) - .map(LibraryTab.class::cast); + public LibraryTab getCurrentLibraryTab() { + return (LibraryTab) Optional.ofNullable(tabbedPane.getSelectionModel().getSelectedItem()) + .filter(tab -> tab instanceof LibraryTab).orElse(null); } public void showLibraryTab(@NonNull LibraryTab libraryTab) { @@ -666,11 +651,11 @@ public CloseDatabaseAction(LibraryTabContainer tabContainer, StateManager stateM public void execute() { Platform.runLater(() -> { if (libraryTab == null) { - if (Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).isEmpty()) { + if (tabContainer.getCurrentLibraryTab() == null) { LOGGER.error("No library tab to close"); return; } - tabContainer.getCurrentLibraryTab().ifPresent(tabContainer::closeTab); + tabContainer.closeTab(tabContainer.getCurrentLibraryTab()); } else { tabContainer.closeTab(libraryTab); } diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java b/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java index f760897a3ee..274a316fee4 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java @@ -125,10 +125,10 @@ public boolean close() { .map(BibDatabaseContext::getDatabasePath) .flatMap(Optional::stream) .toList(); - Path focusedLibraries = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()) - .map(LibraryTab::getBibDatabaseContext) - .flatMap(BibDatabaseContext::getDatabasePath) - .orElse(null); + Path focusedLibraries = Optional.ofNullable(tabContainer.getCurrentLibraryTab()) + .map(LibraryTab::getBibDatabaseContext) + .flatMap(BibDatabaseContext::getDatabasePath) + .orElse(null); // Then ask if the user really wants to close, if the library has not been saved since last save. if (!tabContainer.closeTabs(tabContainer.getLibraryTabs())) { @@ -380,7 +380,7 @@ private Optional getLibraryTab(ParserResult parserResult) { private void addParserResult(ParserResult parserResult, boolean raisePanel) { if (parserResult.toOpenTab()) { LOGGER.trace("Adding the entries to the open tab."); - LibraryTab libraryTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); + LibraryTab libraryTab = tabContainer.getCurrentLibraryTab(); if (libraryTab == null) { LOGGER.debug("No open tab found to add entries to. Creating a new tab."); tabContainer.addTab(parserResult.getDatabaseContext(), raisePanel); @@ -455,7 +455,7 @@ private void waitForLoadingFinished(Runnable runnable) { private void jumpToEntry(String entryKey) { // check current library tab first - LibraryTab currentLibraryTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); + LibraryTab currentLibraryTab = tabContainer.getCurrentLibraryTab(); List sortedTabs = tabContainer.getLibraryTabs().stream() .sorted(Comparator.comparing(tab -> tab != currentLibraryTab)) .toList(); diff --git a/src/main/java/org/jabref/gui/frame/MainMenu.java b/src/main/java/org/jabref/gui/frame/MainMenu.java index d66a75edac6..96e88a25a76 100644 --- a/src/main/java/org/jabref/gui/frame/MainMenu.java +++ b/src/main/java/org/jabref/gui/frame/MainMenu.java @@ -1,6 +1,5 @@ package org.jabref.gui.frame; -import java.util.Objects; import java.util.function.Supplier; import javafx.event.ActionEvent; @@ -153,8 +152,8 @@ private void createMenu() { factory.createMenuItem(StandardActions.NEW_LIBRARY, new NewDatabaseAction(frame, preferences)), factory.createMenuItem(StandardActions.OPEN_LIBRARY, openDatabaseActionSupplier.get()), fileHistoryMenu, - factory.createMenuItem(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager)), - factory.createMenuItem(StandardActions.SAVE_LIBRARY_AS, new SaveAction(SaveAction.SaveMethod.SAVE_AS, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager)), + factory.createMenuItem(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, frame::getCurrentLibraryTab, dialogService, preferences, stateManager)), + factory.createMenuItem(StandardActions.SAVE_LIBRARY_AS, new SaveAction(SaveAction.SaveMethod.SAVE_AS, frame::getCurrentLibraryTab, dialogService, preferences, stateManager)), factory.createMenuItem(StandardActions.SAVE_ALL, new SaveAllAction(frame::getLibraryTabs, preferences, dialogService, stateManager)), factory.createMenuItem(StandardActions.CLOSE_LIBRARY, new JabRefFrame.CloseDatabaseAction(frame, stateManager)), @@ -165,10 +164,9 @@ private void createMenu() { factory.createMenuItem(StandardActions.IMPORT_INTO_NEW_LIBRARY, new ImportCommand(frame, ImportCommand.ImportMethod.AS_NEW, preferences, stateManager, fileUpdateMonitor, taskExecutor, dialogService))), factory.createSubMenu(StandardActions.EXPORT, - factory.createMenuItem(StandardActions.EXPORT_ALL, new ExportCommand(ExportCommand.ExportMethod.EXPORT_ALL, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, dialogService, preferences, entryTypesManager, abbreviationRepository, taskExecutor)), - factory.createMenuItem(StandardActions.EXPORT_SELECTED, new ExportCommand(ExportCommand.ExportMethod.EXPORT_SELECTED, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, dialogService, preferences, entryTypesManager, abbreviationRepository, taskExecutor)), - factory.createMenuItem(StandardActions.SAVE_SELECTED_AS_PLAIN_BIBTEX, new SaveAction(SaveAction.SaveMethod.SAVE_SELECTED, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager))), - + factory.createMenuItem(StandardActions.EXPORT_ALL, new ExportCommand(ExportCommand.ExportMethod.EXPORT_ALL, frame::getCurrentLibraryTab, stateManager, dialogService, preferences, entryTypesManager, abbreviationRepository, taskExecutor)), + factory.createMenuItem(StandardActions.EXPORT_SELECTED, new ExportCommand(ExportCommand.ExportMethod.EXPORT_SELECTED, frame::getCurrentLibraryTab, stateManager, dialogService, preferences, entryTypesManager, abbreviationRepository, taskExecutor)), + factory.createMenuItem(StandardActions.SAVE_SELECTED_AS_PLAIN_BIBTEX, new SaveAction(SaveAction.SaveMethod.SAVE_SELECTED, frame::getCurrentLibraryTab, dialogService, preferences, stateManager))), new SeparatorMenuItem(), factory.createSubMenu(StandardActions.REMOTE_DB, @@ -185,14 +183,14 @@ private void createMenu() { ); edit.getItems().addAll( - factory.createMenuItem(StandardActions.UNDO, new UndoAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), undoManager, dialogService, stateManager)), - factory.createMenuItem(StandardActions.REDO, new RedoAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), undoManager, dialogService, stateManager)), + factory.createMenuItem(StandardActions.UNDO, new UndoAction(frame::getCurrentLibraryTab, undoManager, dialogService, stateManager)), + factory.createMenuItem(StandardActions.REDO, new RedoAction(frame::getCurrentLibraryTab, undoManager, dialogService, stateManager)), new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.CUT, new EditAction(StandardActions.CUT, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), + factory.createMenuItem(StandardActions.CUT, new EditAction(StandardActions.CUT, frame::getCurrentLibraryTab, stateManager, undoManager)), - factory.createMenuItem(StandardActions.COPY, new EditAction(StandardActions.COPY, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), + factory.createMenuItem(StandardActions.COPY, new EditAction(StandardActions.COPY, frame::getCurrentLibraryTab, stateManager, undoManager)), factory.createSubMenu(StandardActions.COPY_MORE, factory.createMenuItem(StandardActions.COPY_TITLE, new CopyMoreAction(StandardActions.COPY_TITLE, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), factory.createMenuItem(StandardActions.COPY_KEY, new CopyMoreAction(StandardActions.COPY_KEY, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), @@ -202,12 +200,12 @@ private void createMenu() { factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new CopyCitationAction(CitationStyleOutputFormat.HTML, dialogService, stateManager, clipBoardManager, taskExecutor, preferences, abbreviationRepository)), factory.createMenuItem(StandardActions.EXPORT_SELECTED_TO_CLIPBOARD, new ExportToClipboardAction(dialogService, stateManager, clipBoardManager, taskExecutor, preferences))), - factory.createMenuItem(StandardActions.PASTE, new EditAction(StandardActions.PASTE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), + factory.createMenuItem(StandardActions.PASTE, new EditAction(StandardActions.PASTE, frame::getCurrentLibraryTab, stateManager, undoManager)), new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.REPLACE_ALL, new ReplaceStringAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, dialogService)), - factory.createMenuItem(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, taskExecutor, preferences, undoManager)), + factory.createMenuItem(StandardActions.REPLACE_ALL, new ReplaceStringAction(frame::getCurrentLibraryTab, stateManager, dialogService)), + factory.createMenuItem(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(frame::getCurrentLibraryTab, dialogService, stateManager, taskExecutor, preferences, undoManager)), new SeparatorMenuItem(), @@ -220,12 +218,12 @@ private void createMenu() { specialFieldsSeparator, // ToDo: SpecialField needs the active BasePanel to mark it as changed. // Refactor BasePanel, should mark the BibDatabaseContext or the UndoManager as dirty instead! - SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.RANKING, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.RELEVANCE, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.QUALITY, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.PRINTED, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager), - SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.PRIORITY, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager), - SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.READ_STATUS, factory, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, undoManager, stateManager)); + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.RANKING, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.RELEVANCE, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.QUALITY, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.PRINTED, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager), + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.PRIORITY, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager), + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.READ_STATUS, factory, frame::getCurrentLibraryTab, dialogService, preferences, undoManager, stateManager)); edit.addEventHandler(ActionEvent.ACTION, event -> { // Work around for mac only issue, where cmd+v on a dialogue triggers the paste action of menu item, resulting in addition of the pasted content in the MainTable. // If the mainscreen is not focused, the actions captured by menu are consumed. @@ -235,9 +233,9 @@ private void createMenu() { }); library.getItems().addAll( - factory.createMenuItem(StandardActions.NEW_ENTRY, new NewEntryAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager)), + factory.createMenuItem(StandardActions.NEW_ENTRY, new NewEntryAction(frame::getCurrentLibraryTab, dialogService, preferences, stateManager)), factory.createMenuItem(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT, new PlainCitationParserAction(dialogService, stateManager)), - factory.createMenuItem(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), + factory.createMenuItem(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, frame::getCurrentLibraryTab, stateManager, undoManager)), new SeparatorMenuItem(), @@ -250,11 +248,11 @@ private void createMenu() { ); quality.getItems().addAll( - factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences, entryTypesManager, taskExecutor)), + factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(frame::getCurrentLibraryTab, dialogService, stateManager, preferences, entryTypesManager, taskExecutor)), factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(dialogService, stateManager, undoManager, preferences)), - factory.createMenuItem(StandardActions.CHECK_INTEGRITY, new IntegrityCheckAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), preferences, dialogService, stateManager, (UiTaskExecutor) taskExecutor, abbreviationRepository)), - factory.createMenuItem(StandardActions.CHECK_CONSISTENCY, new ConsistencyCheckAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences, entryTypesManager, (UiTaskExecutor) taskExecutor)), - factory.createMenuItem(StandardActions.CLEANUP_ENTRIES, new CleanupAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), preferences, dialogService, stateManager, taskExecutor, undoManager)), + factory.createMenuItem(StandardActions.CHECK_INTEGRITY, new IntegrityCheckAction(frame::getCurrentLibraryTab, preferences, dialogService, stateManager, (UiTaskExecutor) taskExecutor, abbreviationRepository)), + factory.createMenuItem(StandardActions.CHECK_CONSISTENCY, new ConsistencyCheckAction(frame::getCurrentLibraryTab, dialogService, stateManager, preferences, entryTypesManager, (UiTaskExecutor) taskExecutor)), + factory.createMenuItem(StandardActions.CLEANUP_ENTRIES, new CleanupAction(frame::getCurrentLibraryTab, preferences, dialogService, stateManager, taskExecutor, undoManager)), new SeparatorMenuItem(), @@ -263,11 +261,11 @@ private void createMenu() { new SeparatorMenuItem(), factory.createSubMenu(StandardActions.ABBREVIATE, - factory.createMenuItem(StandardActions.ABBREVIATE_DEFAULT, new AbbreviateAction(StandardActions.ABBREVIATE_DEFAULT, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)), - factory.createMenuItem(StandardActions.ABBREVIATE_DOTLESS, new AbbreviateAction(StandardActions.ABBREVIATE_DOTLESS, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)), - factory.createMenuItem(StandardActions.ABBREVIATE_SHORTEST_UNIQUE, new AbbreviateAction(StandardActions.ABBREVIATE_SHORTEST_UNIQUE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager))), + factory.createMenuItem(StandardActions.ABBREVIATE_DEFAULT, new AbbreviateAction(StandardActions.ABBREVIATE_DEFAULT, frame::getCurrentLibraryTab, dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)), + factory.createMenuItem(StandardActions.ABBREVIATE_DOTLESS, new AbbreviateAction(StandardActions.ABBREVIATE_DOTLESS, frame::getCurrentLibraryTab, dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)), + factory.createMenuItem(StandardActions.ABBREVIATE_SHORTEST_UNIQUE, new AbbreviateAction(StandardActions.ABBREVIATE_SHORTEST_UNIQUE, frame::getCurrentLibraryTab, dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager))), - factory.createMenuItem(StandardActions.UNABBREVIATE, new AbbreviateAction(StandardActions.UNABBREVIATE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)) + factory.createMenuItem(StandardActions.UNABBREVIATE, new AbbreviateAction(StandardActions.UNABBREVIATE, frame::getCurrentLibraryTab, dialogService, stateManager, preferences.getJournalAbbreviationPreferences(), abbreviationRepository, taskExecutor, undoManager)) ); Menu lookupIdentifiers = factory.createSubMenu(StandardActions.LOOKUP_DOC_IDENTIFIER); @@ -314,7 +312,7 @@ private void createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.REBUILD_FULLTEXT_SEARCH_INDEX, new RebuildFulltextSearchIndexAction(stateManager, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences)), + factory.createMenuItem(StandardActions.REBUILD_FULLTEXT_SEARCH_INDEX, new RebuildFulltextSearchIndexAction(stateManager, frame::getCurrentLibraryTab, dialogService, preferences)), factory.createMenuItem(StandardActions.CLEAR_EMBEDDINGS_CACHE, new ClearEmbeddingsAction(stateManager, dialogService, aiService, taskExecutor)), new SeparatorMenuItem(), @@ -332,13 +330,12 @@ private void createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.NEXT_PREVIEW_STYLE, new PreviewSwitchAction(PreviewSwitchAction.Direction.NEXT, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager)), - factory.createMenuItem(StandardActions.PREVIOUS_PREVIEW_STYLE, new PreviewSwitchAction(PreviewSwitchAction.Direction.PREVIOUS, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager)), - + 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)), new SeparatorMenuItem(), factory.createMenuItem(StandardActions.SHOW_PDF_VIEWER, new ShowDocumentViewerAction(stateManager, preferences)), - factory.createMenuItem(StandardActions.EDIT_ENTRY, new OpenEntryEditorAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager)), + factory.createMenuItem(StandardActions.EDIT_ENTRY, new OpenEntryEditorAction(frame::getCurrentLibraryTab, stateManager)), factory.createMenuItem(StandardActions.OPEN_CONSOLE, new OpenConsoleAction(stateManager, preferences, dialogService)) ); diff --git a/src/main/java/org/jabref/gui/frame/MainToolBar.java b/src/main/java/org/jabref/gui/frame/MainToolBar.java index 39ecb068805..d05831311b3 100644 --- a/src/main/java/org/jabref/gui/frame/MainToolBar.java +++ b/src/main/java/org/jabref/gui/frame/MainToolBar.java @@ -1,7 +1,5 @@ package org.jabref.gui.frame; -import java.util.Objects; - import javafx.concurrent.Task; import javafx.geometry.Orientation; import javafx.scene.Group; @@ -113,8 +111,7 @@ private void createToolBar() { new HBox( factory.createIconButton(StandardActions.NEW_LIBRARY, new NewDatabaseAction(frame, preferences)), factory.createIconButton(StandardActions.OPEN_LIBRARY, new OpenDatabaseAction(frame, preferences, aiService, dialogService, stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, taskExecutor)), - factory.createIconButton(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager))), - + factory.createIconButton(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, frame::getCurrentLibraryTab, dialogService, preferences, stateManager))), leftSpacer, globalSearchBar, @@ -122,27 +119,26 @@ private void createToolBar() { rightSpacer, new HBox( - factory.createIconButton(StandardActions.NEW_ARTICLE, new NewEntryAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), StandardEntryType.Article, dialogService, preferences, stateManager)), - factory.createIconButton(StandardActions.NEW_ENTRY, new NewEntryAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, stateManager)), + factory.createIconButton(StandardActions.NEW_ARTICLE, new NewEntryAction(frame::getCurrentLibraryTab, StandardEntryType.Article, dialogService, preferences, stateManager)), + factory.createIconButton(StandardActions.NEW_ENTRY, new NewEntryAction(frame::getCurrentLibraryTab, dialogService, preferences, stateManager)), createNewEntryFromIdButton(), factory.createIconButton(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT, new PlainCitationParserAction(dialogService, stateManager)), - factory.createIconButton(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager))), - + factory.createIconButton(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, frame::getCurrentLibraryTab, stateManager, undoManager))), new Separator(Orientation.VERTICAL), new HBox( - factory.createIconButton(StandardActions.UNDO, new UndoAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), undoManager, dialogService, stateManager)), - factory.createIconButton(StandardActions.REDO, new RedoAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), undoManager, dialogService, stateManager)), - factory.createIconButton(StandardActions.CUT, new EditAction(StandardActions.CUT, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), - factory.createIconButton(StandardActions.COPY, new EditAction(StandardActions.COPY, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager)), - factory.createIconButton(StandardActions.PASTE, new EditAction(StandardActions.PASTE, () -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), stateManager, undoManager))), + factory.createIconButton(StandardActions.UNDO, new UndoAction(frame::getCurrentLibraryTab, undoManager, dialogService, stateManager)), + factory.createIconButton(StandardActions.REDO, new RedoAction(frame::getCurrentLibraryTab, undoManager, dialogService, stateManager)), + factory.createIconButton(StandardActions.CUT, new EditAction(StandardActions.CUT, frame::getCurrentLibraryTab, stateManager, undoManager)), + factory.createIconButton(StandardActions.COPY, new EditAction(StandardActions.COPY, frame::getCurrentLibraryTab, stateManager, undoManager)), + factory.createIconButton(StandardActions.PASTE, new EditAction(StandardActions.PASTE, frame::getCurrentLibraryTab, stateManager, undoManager))), new Separator(Orientation.VERTICAL), new HBox( pushToApplicationButton, - factory.createIconButton(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, stateManager, taskExecutor, preferences, undoManager)), - factory.createIconButton(StandardActions.CLEANUP_ENTRIES, new CleanupAction(() -> Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), preferences, dialogService, stateManager, taskExecutor, undoManager))), + factory.createIconButton(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(frame::getCurrentLibraryTab, dialogService, stateManager, taskExecutor, preferences, undoManager)), + factory.createIconButton(StandardActions.CLEANUP_ENTRIES, new CleanupAction(frame::getCurrentLibraryTab, preferences, dialogService, stateManager, taskExecutor, undoManager))), new Separator(Orientation.VERTICAL), @@ -171,7 +167,7 @@ Button createNewEntryFromIdButton() { newEntryFromIdButton.setFocusTraversable(false); newEntryFromIdButton.disableProperty().bind(ActionHelper.needsDatabase(stateManager).not()); newEntryFromIdButton.setOnMouseClicked(event -> { - GenerateEntryFromIdDialog entryFromId = new GenerateEntryFromIdDialog(Objects.requireNonNull(frame.getCurrentLibraryTab()).orElse(null), dialogService, preferences, taskExecutor, stateManager); + GenerateEntryFromIdDialog entryFromId = new GenerateEntryFromIdDialog(frame.getCurrentLibraryTab(), dialogService, preferences, taskExecutor, stateManager); if (entryFromIdPopOver == null) { entryFromIdPopOver = new PopOver(entryFromId.getDialogPane()); diff --git a/src/main/java/org/jabref/gui/importer/ImportCommand.java b/src/main/java/org/jabref/gui/importer/ImportCommand.java index 6c983b5f18a..58e268cd54e 100644 --- a/src/main/java/org/jabref/gui/importer/ImportCommand.java +++ b/src/main/java/org/jabref/gui/importer/ImportCommand.java @@ -6,14 +6,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Objects; import java.util.Optional; import java.util.SortedSet; import javafx.stage.FileChooser; import org.jabref.gui.DialogService; -import org.jabref.gui.LibraryTab; import org.jabref.gui.LibraryTabContainer; import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; @@ -119,11 +117,7 @@ private void importSingleFile(Path file, SortedSet importers, FileChoo }) .executeWith(taskExecutor); } else { - LibraryTab currentTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); - ImportEntriesDialog dialog = new ImportEntriesDialog( - currentTab != null ? currentTab.getBibDatabaseContext() : null, - task - ); + ImportEntriesDialog dialog = new ImportEntriesDialog(tabContainer.getCurrentLibraryTab().getBibDatabaseContext(), task); dialog.setTitle(Localization.lang("Import")); dialogService.showCustomDialogAndWait(dialog); } diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java index 01afb2b0918..bcd99147a37 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -150,7 +150,7 @@ Path getInitialDirectory() { } // This is because of the WelcomeTab class. - LibraryTab currentTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); + LibraryTab currentTab = tabContainer.getCurrentLibraryTab(); if (currentTab == null) { return preferences.getFilePreferences().getWorkingDirectory(); } diff --git a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java index 9d36e36f4a6..ea6633a2a34 100644 --- a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java +++ b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java @@ -151,7 +151,10 @@ public GlobalSearchBar(LibraryTabContainer tabContainer, if (keyBindingRepository.matches(event, KeyBinding.CLEAR_SEARCH)) { searchField.clear(); if (searchType == SearchType.NORMAL_SEARCH) { - Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).ifPresent(currentLibraryTab -> currentLibraryTab.getMainTable().requestFocus()); + LibraryTab currentLibraryTab = tabContainer.getCurrentLibraryTab(); + if (currentLibraryTab != null) { + currentLibraryTab.getMainTable().requestFocus(); + } } event.consume(); } @@ -255,7 +258,7 @@ private void initSearchModifierButtons() { if (!filePreferences.shouldFulltextIndexLinkedFiles() && newVal) { boolean enableFulltextSearch = dialogService.showConfirmationDialogAndWait(Localization.lang("Fulltext search"), Localization.lang("Fulltext search requires the setting 'Automatically index all linked files for fulltext search' to be enabled. Do you want to enable indexing now?"), Localization.lang("Enable indexing"), Localization.lang("Keep disabled")); - LibraryTab libraryTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); + LibraryTab libraryTab = tabContainer.getCurrentLibraryTab(); if (libraryTab != null && enableFulltextSearch) { filePreferences.setFulltextIndexLinkedFiles(true); searchPreferences.setSearchFlag(SearchFlags.FULLTEXT, true); diff --git a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java index 01e3f73f3ba..a1e73bcb96a 100644 --- a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java +++ b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java @@ -1,7 +1,6 @@ package org.jabref.gui.shared; import java.sql.SQLException; -import java.util.Objects; import java.util.Optional; import javax.swing.undo.UndoManager; @@ -95,7 +94,7 @@ public void listen(ConnectionLostEvent connectionLostEvent) { if (answer.isPresent()) { if (answer.get().equals(reconnect)) { - Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).ifPresent(tabContainer::closeTab); + tabContainer.closeTab(tabContainer.getCurrentLibraryTab()); dialogService.showCustomDialogAndWait(new SharedDatabaseLoginDialogView(tabContainer)); } else if (answer.get().equals(workOffline)) { connectionLostEvent.bibDatabaseContext().convertToLocalDatabase(); @@ -103,7 +102,7 @@ public void listen(ConnectionLostEvent connectionLostEvent) { dialogService.notify(Localization.lang("Working offline.")); } } else { - Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).ifPresent(tabContainer::closeTab); + tabContainer.closeTab(tabContainer.getCurrentLibraryTab()); } } @@ -142,7 +141,7 @@ public void listen(UpdateRefusedEvent updateRefusedEvent) { @Subscribe public void listen(SharedEntriesNotPresentEvent event) { - LibraryTab libraryTab = Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).orElse(null); + LibraryTab libraryTab = tabContainer.getCurrentLibraryTab(); EntryEditor entryEditor = libraryTab.getEntryEditor(); libraryTab.getUndoManager().addEdit(new UndoableRemoveEntries(libraryTab.getDatabase(), event.bibEntries())); diff --git a/src/main/java/org/jabref/gui/slr/ExistingStudySearchAction.java b/src/main/java/org/jabref/gui/slr/ExistingStudySearchAction.java index 075bcbe22bc..512bcfd075c 100644 --- a/src/main/java/org/jabref/gui/slr/ExistingStudySearchAction.java +++ b/src/main/java/org/jabref/gui/slr/ExistingStudySearchAction.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.nio.file.Path; -import java.util.Objects; import java.util.function.Supplier; import org.jabref.gui.DialogService; @@ -148,6 +147,6 @@ protected void crawlPreparation(Path studyRepositoryRoot) throws IOException, Gi // The user focused an SLR // We hard close the tab // Future work: Properly close the tab (with saving, ...) - Objects.requireNonNull(tabContainer.getCurrentLibraryTab()).ifPresent(tabContainer::closeTab); + tabContainer.closeTab(tabContainer.getCurrentLibraryTab()); } } From a8ee2c8b3828b882fd5df4f411fcda5fe1a6f0ad Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Wed, 5 Mar 2025 02:13:11 +0530 Subject: [PATCH 14/41] Fixed checkstyle import issue --- .../java/org/jabref/gui/auximport/FromAuxDialogViewModel.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java b/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java index 632af00f6e4..4f197767dde 100644 --- a/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java +++ b/src/main/java/org/jabref/gui/auximport/FromAuxDialogViewModel.java @@ -1,7 +1,6 @@ package org.jabref.gui.auximport; import java.nio.file.Path; -import java.util.Objects; import java.util.Optional; import javafx.beans.property.BooleanProperty; @@ -16,7 +15,6 @@ import javafx.collections.FXCollections; import org.jabref.gui.DialogService; -import org.jabref.gui.LibraryTab; import org.jabref.gui.LibraryTabContainer; import org.jabref.gui.StateManager; import org.jabref.gui.util.FileDialogConfiguration; From 76b1aba9ced39d7828f30dbcbfd166c9736cd0a6 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Thu, 6 Mar 2025 21:26:33 +0100 Subject: [PATCH 15/41] Simplify and fix casting --- .../org/jabref/gui/frame/JabRefFrame.java | 36 ++++++++++--------- .../java/org/jabref/gui/frame/MainMenu.java | 2 ++ .../importer/actions/OpenDatabaseAction.java | 15 +++----- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 5461ea9cc42..4725ead1587 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -123,21 +123,6 @@ public JabRefFrame(Stage mainStage, this.clipBoardManager = clipBoardManager; this.taskExecutor = taskExecutor; - this.fileHistory = new FileHistoryMenu( - this.preferences.getLastFilesOpenedPreferences().getFileHistory(), - dialogService, - getOpenDatabaseAction()); - - this.setOnKeyTyped(key -> { - if (this.fileHistory.isShowing()) { - if (this.fileHistory.openFileByKey(key)) { - this.fileHistory.getParentMenu().hide(); - } - } - }); - - fileHistory.disableProperty().bind(Bindings.isEmpty(fileHistory.getItems())); - setId("frame"); // Create components @@ -187,6 +172,21 @@ public JabRefFrame(Stage mainStage, this.preferences, taskExecutor); + this.fileHistory = new FileHistoryMenu( + this.preferences.getLastFilesOpenedPreferences().getFileHistory(), + dialogService, + getOpenDatabaseAction()); + + fileHistory.disableProperty().bind(Bindings.isEmpty(fileHistory.getItems())); + + this.setOnKeyTyped(key -> { + if (this.fileHistory.isShowing()) { + if (this.fileHistory.openFileByKey(key)) { + this.fileHistory.getParentMenu().hide(); + } + } + }); + initLayout(); initKeyBindings(); frameDndHandler.initDragAndDrop(); @@ -450,8 +450,10 @@ private void updateTabBarVisible() { * Returns the currently viewed LibraryTab. */ public LibraryTab getCurrentLibraryTab() { - return (LibraryTab) Optional.ofNullable(tabbedPane.getSelectionModel().getSelectedItem()) - .filter(tab -> tab instanceof LibraryTab).orElse(null); + if (tabbedPane.getSelectionModel().getSelectedItem() == null) { + return null; + } + return (LibraryTab) tabbedPane.getSelectionModel().getSelectedItem(); } public void showLibraryTab(@NonNull LibraryTab libraryTab) { diff --git a/src/main/java/org/jabref/gui/frame/MainMenu.java b/src/main/java/org/jabref/gui/frame/MainMenu.java index 96e88a25a76..8ef13aa7d2a 100644 --- a/src/main/java/org/jabref/gui/frame/MainMenu.java +++ b/src/main/java/org/jabref/gui/frame/MainMenu.java @@ -167,6 +167,7 @@ private void createMenu() { factory.createMenuItem(StandardActions.EXPORT_ALL, new ExportCommand(ExportCommand.ExportMethod.EXPORT_ALL, frame::getCurrentLibraryTab, stateManager, dialogService, preferences, entryTypesManager, abbreviationRepository, taskExecutor)), factory.createMenuItem(StandardActions.EXPORT_SELECTED, new ExportCommand(ExportCommand.ExportMethod.EXPORT_SELECTED, frame::getCurrentLibraryTab, stateManager, dialogService, preferences, entryTypesManager, abbreviationRepository, taskExecutor)), factory.createMenuItem(StandardActions.SAVE_SELECTED_AS_PLAIN_BIBTEX, new SaveAction(SaveAction.SaveMethod.SAVE_SELECTED, frame::getCurrentLibraryTab, dialogService, preferences, stateManager))), + new SeparatorMenuItem(), factory.createSubMenu(StandardActions.REMOTE_DB, @@ -332,6 +333,7 @@ private void createMenu() { 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)), + new SeparatorMenuItem(), factory.createMenuItem(StandardActions.SHOW_PDF_VIEWER, new ShowDocumentViewerAction(stateManager, preferences)), diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java index bcd99147a37..0d2e99b23f7 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -145,18 +145,13 @@ public FileDialogConfiguration getFileDialogConfiguration(Path initialDirectory) */ @VisibleForTesting Path getInitialDirectory() { - if (tabContainer.getLibraryTabs().isEmpty()) { + if (tabContainer.getLibraryTabs().isEmpty() || tabContainer.getCurrentLibraryTab() == null) { + // currentTab might not be a LibraryTab but the WelcomeTab return preferences.getFilePreferences().getWorkingDirectory(); + } else { + Optional databasePath = tabContainer.getCurrentLibraryTab().getBibDatabaseContext().getDatabasePath(); + return databasePath.map(Path::getParent).orElse(preferences.getFilePreferences().getWorkingDirectory()); } - - // This is because of the WelcomeTab class. - LibraryTab currentTab = tabContainer.getCurrentLibraryTab(); - if (currentTab == null) { - return preferences.getFilePreferences().getWorkingDirectory(); - } - - Optional databasePath = currentTab.getBibDatabaseContext().getDatabasePath(); - return databasePath.map(Path::getParent).orElse(preferences.getFilePreferences().getWorkingDirectory()); } /** From 970d7e83135738aeb34cf9619b608b7b0b8d0076 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Thu, 6 Mar 2025 22:09:04 +0100 Subject: [PATCH 16/41] Fix casting --- .../org/jabref/gui/frame/JabRefFrame.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 4725ead1587..2208d189056 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -450,7 +450,8 @@ private void updateTabBarVisible() { * Returns the currently viewed LibraryTab. */ public LibraryTab getCurrentLibraryTab() { - if (tabbedPane.getSelectionModel().getSelectedItem() == null) { + if (tabbedPane.getSelectionModel().getSelectedItem() == null + || !(tabbedPane.getSelectionModel().getSelectedItem() instanceof LibraryTab)) { return null; } return (LibraryTab) tabbedPane.getSelectionModel().getSelectedItem(); @@ -467,24 +468,24 @@ public void showWelcomeTab() { tabbedPane.getSelectionModel().select(tab); return; } - - // If the WelcomeTab is not found, a new instance is created and added - WelcomeTab welcomeTab = new WelcomeTab( - this, - preferences, - aiService, - dialogService, - stateManager, - fileUpdateMonitor, - entryTypesManager, - undoManager, - clipBoardManager, - taskExecutor, - fileHistory - ); - tabbedPane.getTabs().add(welcomeTab); - tabbedPane.getSelectionModel().select(welcomeTab); } + + // If the WelcomeTab is not found, a new instance is created and added + WelcomeTab welcomeTab = new WelcomeTab( + this, + preferences, + aiService, + dialogService, + stateManager, + fileUpdateMonitor, + entryTypesManager, + undoManager, + clipBoardManager, + taskExecutor, + fileHistory + ); + tabbedPane.getTabs().add(welcomeTab); + tabbedPane.getSelectionModel().select(welcomeTab); } /** From fc78dc5243c5556b1027be27d97c0196119c7a20 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Sat, 8 Mar 2025 11:49:37 +0530 Subject: [PATCH 17/41] Fixed Responsiveness --- src/main/java/org/jabref/gui/Base.css | 10 +++++----- src/main/java/org/jabref/gui/WelcomeTab.java | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/gui/Base.css b/src/main/java/org/jabref/gui/Base.css index 178a1ee2eef..f8074542ead 100644 --- a/src/main/java/org/jabref/gui/Base.css +++ b/src/main/java/org/jabref/gui/Base.css @@ -1729,30 +1729,30 @@ We want to have a look that matches our icons in the tool-bar */ } .welcome-label { - -fx-font-size: 40px; + -fx-font-size: 2.75em; -fx-text-fill: -jr-theme-text; -fx-font-family: "Arial"; } .welcome-description-label { - -fx-font-size: 25px; + -fx-font-size: 1.75em; -fx-font-family: "Arial"; } .welcome-header-label { - -fx-font-size: 20px; + -fx-font-size: 1.5em; -fx-font-weight: bold; -fx-font-family: "Arial"; } .welcome-no-recent-label { - -fx-font-size: 18px; + -fx-font-size: 1.25em; -fx-text-fill: -jr-theme; -fx-font-family: "Arial"; } .welcome-hyperlink { - -fx-font-size: 18px; + -fx-font-size: 1.25em; -fx-text-fill: -jr-theme; } diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 1c1da0c04e4..ed8ec1f0997 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -1,13 +1,16 @@ package org.jabref.gui; import javafx.collections.ListChangeListener; +import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; import javafx.scene.control.MenuItem; +import javafx.scene.control.ScrollPane; import javafx.scene.control.Tab; import javafx.scene.layout.HBox; +import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.jabref.gui.frame.FileHistoryMenu; @@ -71,6 +74,19 @@ public WelcomeTab(LibraryTabContainer tabContainer, HBox welcomeMainContainer = new HBox(20); welcomeMainContainer.setAlignment(Pos.CENTER); + welcomeMainContainer.setPadding(new Insets(10, 10, 10, 50)); + + ScrollPane scrollPane = new ScrollPane(welcomeMainContainer); + scrollPane.setFitToWidth(true); + scrollPane.setFitToHeight(true); + + scrollPane.widthProperty().addListener((_, _, newWidth) -> { + double dynamicPadding = Math.max(20, newWidth.doubleValue() * 0.05); + welcomeMainContainer.setPadding(new Insets(10, 10, 10, dynamicPadding)); + }); + + setContent(new StackPane(scrollPane)); + VBox welcomeBox = createWelcomeBox(); VBox startBox = createWelcomeStartBox(); VBox recentBox = createWelcomeRecentBox(); From 1e24223f9bb2f861c6ff22c401b8abc8f0292277 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Mon, 10 Mar 2025 22:11:50 +0100 Subject: [PATCH 18/41] Undo newlines in MainToolBar.java --- src/main/java/org/jabref/gui/frame/MainToolBar.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/jabref/gui/frame/MainToolBar.java b/src/main/java/org/jabref/gui/frame/MainToolBar.java index d05831311b3..9cd83cd28f0 100644 --- a/src/main/java/org/jabref/gui/frame/MainToolBar.java +++ b/src/main/java/org/jabref/gui/frame/MainToolBar.java @@ -112,6 +112,7 @@ private void createToolBar() { factory.createIconButton(StandardActions.NEW_LIBRARY, new NewDatabaseAction(frame, preferences)), factory.createIconButton(StandardActions.OPEN_LIBRARY, new OpenDatabaseAction(frame, preferences, aiService, dialogService, stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, taskExecutor)), factory.createIconButton(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, frame::getCurrentLibraryTab, dialogService, preferences, stateManager))), + leftSpacer, globalSearchBar, @@ -124,6 +125,7 @@ private void createToolBar() { createNewEntryFromIdButton(), factory.createIconButton(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT, new PlainCitationParserAction(dialogService, stateManager)), factory.createIconButton(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, frame::getCurrentLibraryTab, stateManager, undoManager))), + new Separator(Orientation.VERTICAL), new HBox( From afa8b5495be8d0a0ee62708f488773b2fd73dfc9 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Wed, 12 Mar 2025 03:19:39 +0530 Subject: [PATCH 19/41] Added Footer for Welcome Tab --- src/main/java/org/jabref/gui/Base.css | 29 ++++++ src/main/java/org/jabref/gui/WelcomeTab.java | 92 ++++++++++++++++++- .../org/jabref/gui/frame/JabRefFrame.java | 7 +- 3 files changed, 124 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/gui/Base.css b/src/main/java/org/jabref/gui/Base.css index f8074542ead..7256022fe92 100644 --- a/src/main/java/org/jabref/gui/Base.css +++ b/src/main/java/org/jabref/gui/Base.css @@ -1760,6 +1760,35 @@ We want to have a look that matches our icons in the tool-bar */ -fx-text-fill: -jr-theme; } +.welcome-footer-container { + -fx-padding: 15px; + -fx-alignment: center; + -fx-spacing: 15px; +} + +.welcome-footer-label { + -fx-font-size: 2.25em; + -fx-text-fill: -jr-theme-text; + -fx-font-family: "Arial"; +} + +.welcome-footer-link { + -fx-font-size: 1.2em; + -fx-text-fill: -jr-theme; + -fx-font-family: "Arial"; +} + +.welcome-footer-link:hover { + -fx-underline: true; + -fx-text-fill: derive(-jr-theme, -20%); +} + +.welcome-footer-version { + -fx-font-size: 1.2em; + -fx-text-fill: -jr-theme; + -fx-font-family: "Arial"; +} + /* AboutDialog */ #aboutDialog .about-heading { -fx-font-size: 30; diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index ed8ec1f0997..bc4a415b4f3 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -9,17 +9,23 @@ import javafx.scene.control.MenuItem; import javafx.scene.control.ScrollPane; import javafx.scene.control.Tab; +import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; +import org.jabref.gui.actions.StandardActions; +import org.jabref.gui.edit.OpenBrowserAction; import org.jabref.gui.frame.FileHistoryMenu; +import org.jabref.gui.icon.IconTheme; import org.jabref.gui.importer.NewDatabaseAction; import org.jabref.gui.importer.actions.OpenDatabaseAction; import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.undo.CountingUndoManager; import org.jabref.logic.ai.AiService; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.BuildInfo; import org.jabref.logic.util.TaskExecutor; import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.util.FileUpdateMonitor; @@ -38,6 +44,7 @@ public class WelcomeTab extends Tab { private final ClipBoardManager clipBoardManager; private final TaskExecutor taskExecutor; private final FileHistoryMenu fileHistoryMenu; + private final BuildInfo buildInfo; public WelcomeTab(LibraryTabContainer tabContainer, GuiPreferences preferences, @@ -49,7 +56,8 @@ public WelcomeTab(LibraryTabContainer tabContainer, CountingUndoManager undoManager, ClipBoardManager clipBoardManager, TaskExecutor taskExecutor, - FileHistoryMenu fileHistoryMenu) { + FileHistoryMenu fileHistoryMenu, + BuildInfo buildInfo) { super(Localization.lang("Welcome")); setClosable(true); @@ -65,6 +73,7 @@ public WelcomeTab(LibraryTabContainer tabContainer, this.clipBoardManager = clipBoardManager; this.taskExecutor = taskExecutor; this.fileHistoryMenu = fileHistoryMenu; + this.buildInfo = buildInfo; this.recentLibrariesBox = new VBox(5); @@ -94,7 +103,14 @@ public WelcomeTab(LibraryTabContainer tabContainer, welcomePageContainer.getChildren().addAll(welcomeBox, startBox, recentBox); welcomeMainContainer.getChildren().add(welcomePageContainer); - setContent(welcomeMainContainer); + BorderPane rootLayout = new BorderPane(); + rootLayout.setCenter(welcomeMainContainer); + rootLayout.setBottom(createFooter()); + + VBox container = new VBox(); + container.getChildren().add(rootLayout); + VBox.setVgrow(rootLayout, Priority.ALWAYS); + setContent(container); } private VBox createWelcomeBox() { @@ -159,4 +175,76 @@ private VBox createVBoxContainer(Node... nodes) { box.getChildren().addAll(nodes); return box; } + + private VBox createFooter() { + Label communityLabel = new Label(Localization.lang("Community")); + communityLabel.getStyleClass().add("welcome-footer-label"); + + HBox iconLinksContainer = new HBox(15); + iconLinksContainer.setAlignment(Pos.CENTER); + + Hyperlink onlineHelpLink = createFooterLink(Localization.lang("Online help"), StandardActions.HELP, IconTheme.JabRefIcons.HELP); + Hyperlink forumLink = createFooterLink(Localization.lang("Forum for support"), StandardActions.OPEN_FORUM, IconTheme.JabRefIcons.FORUM); + Hyperlink mastodonLink = createFooterLink(Localization.lang("Mastodon"), StandardActions.OPEN_MASTODON, IconTheme.JabRefIcons.MASTODON); + Hyperlink linkedInLink = createFooterLink(Localization.lang("LinkedIn"), StandardActions.OPEN_LINKEDIN, IconTheme.JabRefIcons.LINKEDIN); + Hyperlink donationLink = createFooterLink(Localization.lang("Donation"), StandardActions.DONATE, IconTheme.JabRefIcons.DONATE); + + iconLinksContainer.getChildren().addAll(onlineHelpLink, forumLink, mastodonLink, linkedInLink, donationLink); + + HBox textLinksContainer = new HBox(15); + textLinksContainer.setAlignment(Pos.CENTER); + + Hyperlink devVersionLink = createFooterLink(Localization.lang("Download Development version"), StandardActions.OPEN_DEV_VERSION_LINK, null); + Hyperlink changelogLink = createFooterLink(Localization.lang("CHANGELOG"), StandardActions.OPEN_CHANGELOG, null); + + textLinksContainer.getChildren().addAll(devVersionLink, changelogLink); + + HBox versionContainer = new HBox(15); + versionContainer.setAlignment(Pos.CENTER); + Label versionLabel = new Label(Localization.lang("Current JabRef Version: ") + buildInfo.version); + versionLabel.getStyleClass().add("welcome-footer-version"); + versionContainer.getChildren().add(versionLabel); + + VBox footerBox = new VBox(10); + footerBox.setAlignment(Pos.CENTER); + footerBox.getChildren().addAll(communityLabel, iconLinksContainer, textLinksContainer, versionContainer); + footerBox.setPadding(new Insets(10, 0, 10, 0)); + footerBox.getStyleClass().add("welcome-footer-container"); + + return footerBox; + } + + private Hyperlink createFooterLink(String text, StandardActions action, IconTheme.JabRefIcons icon) { + Hyperlink link = new Hyperlink(text); + link.getStyleClass().add("welcome-footer-link"); + + String url = switch (action) { + case HELP -> + "https://help.jabref.org/"; + case OPEN_FORUM -> + "https://discourse.jabref.org/"; + case OPEN_MASTODON -> + "https://foojay.social/@jabref"; + case OPEN_LINKEDIN -> + "https://linkedin.com/company/jabref/"; + case DONATE -> + "https://donate.jabref.org"; + case OPEN_DEV_VERSION_LINK -> + "https://builds.jabref.org/master/"; + case OPEN_CHANGELOG -> + "https://github.com/JabRef/jabref/blob/main/CHANGELOG.md"; + default -> + null; + }; + + if (url != null) { + link.setOnAction(e -> new OpenBrowserAction(url, dialogService, preferences.getExternalApplicationsPreferences()).execute()); + } + + if (icon != null) { + link.setGraphic(icon.getGraphicNode()); + } + + return link; + } } diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 2208d189056..a06005ef333 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -51,6 +51,7 @@ import org.jabref.logic.ai.AiService; import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.os.OS; +import org.jabref.logic.util.BuildInfo; import org.jabref.logic.util.TaskExecutor; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntryTypesManager; @@ -241,7 +242,8 @@ private void initLayout() { undoManager, clipBoardManager, taskExecutor, - fileHistory + fileHistory, + new BuildInfo() ); tabbedPane.getTabs().add(welcomeTab); @@ -482,7 +484,8 @@ public void showWelcomeTab() { undoManager, clipBoardManager, taskExecutor, - fileHistory + fileHistory, + new BuildInfo() ); tabbedPane.getTabs().add(welcomeTab); tabbedPane.getSelectionModel().select(welcomeTab); From d920d6c95bce2a3587ed0e2b50fb71ce23481d59 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Wed, 12 Mar 2025 03:33:18 +0530 Subject: [PATCH 20/41] Fixed Localization issues --- src/main/java/org/jabref/gui/WelcomeTab.java | 16 ++++++++-------- src/main/resources/l10n/JabRef_en.properties | 2 ++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index bc4a415b4f3..55a633a8e86 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -183,25 +183,25 @@ private VBox createFooter() { HBox iconLinksContainer = new HBox(15); iconLinksContainer.setAlignment(Pos.CENTER); - Hyperlink onlineHelpLink = createFooterLink(Localization.lang("Online help"), StandardActions.HELP, IconTheme.JabRefIcons.HELP); - Hyperlink forumLink = createFooterLink(Localization.lang("Forum for support"), StandardActions.OPEN_FORUM, IconTheme.JabRefIcons.FORUM); - Hyperlink mastodonLink = createFooterLink(Localization.lang("Mastodon"), StandardActions.OPEN_MASTODON, IconTheme.JabRefIcons.MASTODON); - Hyperlink linkedInLink = createFooterLink(Localization.lang("LinkedIn"), StandardActions.OPEN_LINKEDIN, IconTheme.JabRefIcons.LINKEDIN); - Hyperlink donationLink = createFooterLink(Localization.lang("Donation"), StandardActions.DONATE, IconTheme.JabRefIcons.DONATE); + Hyperlink onlineHelpLink = createFooterLink("Online help", StandardActions.HELP, IconTheme.JabRefIcons.HELP); + Hyperlink forumLink = createFooterLink("Forum for support", StandardActions.OPEN_FORUM, IconTheme.JabRefIcons.FORUM); + Hyperlink mastodonLink = createFooterLink("Mastodon", StandardActions.OPEN_MASTODON, IconTheme.JabRefIcons.MASTODON); + Hyperlink linkedInLink = createFooterLink("LinkedIn", StandardActions.OPEN_LINKEDIN, IconTheme.JabRefIcons.LINKEDIN); + Hyperlink donationLink = createFooterLink("Donation", StandardActions.DONATE, IconTheme.JabRefIcons.DONATE); iconLinksContainer.getChildren().addAll(onlineHelpLink, forumLink, mastodonLink, linkedInLink, donationLink); HBox textLinksContainer = new HBox(15); textLinksContainer.setAlignment(Pos.CENTER); - Hyperlink devVersionLink = createFooterLink(Localization.lang("Download Development version"), StandardActions.OPEN_DEV_VERSION_LINK, null); - Hyperlink changelogLink = createFooterLink(Localization.lang("CHANGELOG"), StandardActions.OPEN_CHANGELOG, null); + Hyperlink devVersionLink = createFooterLink("Download Development version", StandardActions.OPEN_DEV_VERSION_LINK, null); + Hyperlink changelogLink = createFooterLink("CHANGELOG", StandardActions.OPEN_CHANGELOG, null); textLinksContainer.getChildren().addAll(devVersionLink, changelogLink); HBox versionContainer = new HBox(15); versionContainer.setAlignment(Pos.CENTER); - Label versionLabel = new Label(Localization.lang("Current JabRef Version: ") + buildInfo.version); + Label versionLabel = new Label(Localization.lang("Current JabRef version") + ": " + buildInfo.version); versionLabel.getStyleClass().add("welcome-footer-version"); versionContainer.getChildren().add(versionLabel); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index aa947d65f98..6b7d6803f7d 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2877,3 +2877,5 @@ Stay\ on\ top\ of\ your\ literature=Stay on top of your literature Welcome\ to\ JabRef=Welcome to JabRef Welcome=Welcome Open\ welcome\ tab=Open welcome tab +Current\ JabRef\ version=Current JabRef version +Community=Community From fcc5be3cd495957cb2a65925aab89c3af63d975a Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Mon, 17 Mar 2025 15:49:46 +0530 Subject: [PATCH 21/41] Fixed Recents Library issue --- src/main/java/org/jabref/gui/WelcomeTab.java | 23 +++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 55a633a8e86..f3eef411eeb 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -159,16 +159,23 @@ private void updateWelcomeRecentLibraries() { Label noRecentLibrariesLabel = new Label(Localization.lang("No recent libraries")); noRecentLibrariesLabel.getStyleClass().add("welcome-no-recent-label"); recentLibrariesBox.getChildren().add(noRecentLibrariesLabel); - } else { - for (MenuItem item : fileHistoryMenu.getItems()) { - Hyperlink recentLibraryLink = new Hyperlink(item.getText()); - recentLibraryLink.getStyleClass().add("welcome-hyperlink"); - recentLibraryLink.setOnAction(item.getOnAction()); - recentLibrariesBox.getChildren().add(recentLibraryLink); - } + + fileHistoryMenu.disableProperty().unbind(); + fileHistoryMenu.setDisable(true); + return; } - } + fileHistoryMenu.disableProperty().unbind(); + fileHistoryMenu.setDisable(false); + + for (MenuItem item : fileHistoryMenu.getItems()) { + Hyperlink recentLibraryLink = new Hyperlink(item.getText()); + recentLibraryLink.getStyleClass().add("welcome-hyperlink"); + recentLibraryLink.setOnAction(item.getOnAction()); + recentLibrariesBox.getChildren().add(recentLibraryLink); + } + } + private VBox createVBoxContainer(Node... nodes) { VBox box = new VBox(5); box.setAlignment(Pos.TOP_LEFT); From a6d50e2f3cdab3c5ef563bae06bc9f09232a7c85 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Mon, 17 Mar 2025 15:56:08 +0530 Subject: [PATCH 22/41] Fixed Tragbot review for Footer --- src/main/java/org/jabref/gui/WelcomeTab.java | 66 +++++++++++++------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index f3eef411eeb..5ab8d8209a3 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -175,7 +175,7 @@ private void updateWelcomeRecentLibraries() { recentLibrariesBox.getChildren().add(recentLibraryLink); } } - + private VBox createVBoxContainer(Node... nodes) { VBox box = new VBox(5); box.setAlignment(Pos.TOP_LEFT); @@ -184,11 +184,30 @@ private VBox createVBoxContainer(Node... nodes) { } private VBox createFooter() { - Label communityLabel = new Label(Localization.lang("Community")); - communityLabel.getStyleClass().add("welcome-footer-label"); + Label communityLabel = createFooterLabel("Community"); + + HBox iconLinksContainer = createIconLinksContainer(); + HBox textLinksContainer = createTextLinksContainer(); + HBox versionContainer = createVersionContainer(); + + VBox footerBox = new VBox(10); + footerBox.setAlignment(Pos.CENTER); + footerBox.getChildren().addAll(communityLabel, iconLinksContainer, textLinksContainer, versionContainer); + footerBox.setPadding(new Insets(10, 0, 10, 0)); + footerBox.getStyleClass().add("welcome-footer-container"); - HBox iconLinksContainer = new HBox(15); - iconLinksContainer.setAlignment(Pos.CENTER); + return footerBox; + } + + private Label createFooterLabel(String text) { + Label label = new Label(Localization.lang(text)); + label.getStyleClass().add("welcome-footer-label"); + return label; + } + + private HBox createIconLinksContainer() { + HBox container = new HBox(15); + container.setAlignment(Pos.CENTER); Hyperlink onlineHelpLink = createFooterLink("Online help", StandardActions.HELP, IconTheme.JabRefIcons.HELP); Hyperlink forumLink = createFooterLink("Forum for support", StandardActions.OPEN_FORUM, IconTheme.JabRefIcons.FORUM); @@ -196,29 +215,19 @@ private VBox createFooter() { Hyperlink linkedInLink = createFooterLink("LinkedIn", StandardActions.OPEN_LINKEDIN, IconTheme.JabRefIcons.LINKEDIN); Hyperlink donationLink = createFooterLink("Donation", StandardActions.DONATE, IconTheme.JabRefIcons.DONATE); - iconLinksContainer.getChildren().addAll(onlineHelpLink, forumLink, mastodonLink, linkedInLink, donationLink); + container.getChildren().addAll(onlineHelpLink, forumLink, mastodonLink, linkedInLink, donationLink); + return container; + } - HBox textLinksContainer = new HBox(15); - textLinksContainer.setAlignment(Pos.CENTER); + private HBox createTextLinksContainer() { + HBox container = new HBox(15); + container.setAlignment(Pos.CENTER); Hyperlink devVersionLink = createFooterLink("Download Development version", StandardActions.OPEN_DEV_VERSION_LINK, null); Hyperlink changelogLink = createFooterLink("CHANGELOG", StandardActions.OPEN_CHANGELOG, null); - textLinksContainer.getChildren().addAll(devVersionLink, changelogLink); - - HBox versionContainer = new HBox(15); - versionContainer.setAlignment(Pos.CENTER); - Label versionLabel = new Label(Localization.lang("Current JabRef version") + ": " + buildInfo.version); - versionLabel.getStyleClass().add("welcome-footer-version"); - versionContainer.getChildren().add(versionLabel); - - VBox footerBox = new VBox(10); - footerBox.setAlignment(Pos.CENTER); - footerBox.getChildren().addAll(communityLabel, iconLinksContainer, textLinksContainer, versionContainer); - footerBox.setPadding(new Insets(10, 0, 10, 0)); - footerBox.getStyleClass().add("welcome-footer-container"); - - return footerBox; + container.getChildren().addAll(devVersionLink, changelogLink); + return container; } private Hyperlink createFooterLink(String text, StandardActions action, IconTheme.JabRefIcons icon) { @@ -254,4 +263,15 @@ private Hyperlink createFooterLink(String text, StandardActions action, IconThem return link; } + + private HBox createVersionContainer() { + HBox container = new HBox(15); + container.setAlignment(Pos.CENTER); + + Label versionLabel = new Label(Localization.lang("Current JabRef version") + ": " + buildInfo.version); + versionLabel.getStyleClass().add("welcome-footer-version"); + + container.getChildren().add(versionLabel); + return container; + } } From 2f9811f18552e7954a038ae53cc37df3b99dd016 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Mon, 17 Mar 2025 16:10:30 +0530 Subject: [PATCH 23/41] Refactored the code as suggested in review comments --- src/main/java/org/jabref/gui/WelcomeTab.java | 20 ++++++++----- .../jabref/gui/exporter/ExportCommand.java | 30 ++++++++----------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 5ab8d8209a3..a3e191b7d00 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -153,18 +153,12 @@ private VBox createWelcomeRecentBox() { } private void updateWelcomeRecentLibraries() { - recentLibrariesBox.getChildren().clear(); - if (fileHistoryMenu.getItems().isEmpty()) { - Label noRecentLibrariesLabel = new Label(Localization.lang("No recent libraries")); - noRecentLibrariesLabel.getStyleClass().add("welcome-no-recent-label"); - recentLibrariesBox.getChildren().add(noRecentLibrariesLabel); - - fileHistoryMenu.disableProperty().unbind(); - fileHistoryMenu.setDisable(true); + displayNoRecentLibrariesMessage(); return; } + recentLibrariesBox.getChildren().clear(); fileHistoryMenu.disableProperty().unbind(); fileHistoryMenu.setDisable(false); @@ -176,6 +170,16 @@ private void updateWelcomeRecentLibraries() { } } + private void displayNoRecentLibrariesMessage() { + recentLibrariesBox.getChildren().clear(); + Label noRecentLibrariesLabel = new Label(Localization.lang("No recent libraries")); + noRecentLibrariesLabel.getStyleClass().add("welcome-no-recent-label"); + recentLibrariesBox.getChildren().add(noRecentLibrariesLabel); + + fileHistoryMenu.disableProperty().unbind(); + fileHistoryMenu.setDisable(true); + } + private VBox createVBoxContainer(Node... nodes) { VBox box = new VBox(5); box.setAlignment(Pos.TOP_LEFT); diff --git a/src/main/java/org/jabref/gui/exporter/ExportCommand.java b/src/main/java/org/jabref/gui/exporter/ExportCommand.java index 55656fe385a..5cf0024cb9b 100644 --- a/src/main/java/org/jabref/gui/exporter/ExportCommand.java +++ b/src/main/java/org/jabref/gui/exporter/ExportCommand.java @@ -133,23 +133,19 @@ private void export(Path file, FileChooser.ExtensionFilter selectedExtensionFilt return null; // can not use BackgroundTask.wrap(Runnable) because Runnable.run() can't throw Exceptions }) .onSuccess(save -> { - boolean currentTabIsLibraryTab = tabSupplier.get() != null; - // libraryTab is null in case of Welcome Tab - if (currentTabIsLibraryTab) { - LibraryTab.DatabaseNotification notificationPane = tabSupplier.get().getNotificationPane(); - notificationPane.notify( - IconTheme.JabRefIcons.FOLDER.getGraphicNode(), - Localization.lang("Export operation finished successfully."), - List.of(new Action(Localization.lang("Reveal in File Explorer"), event -> { - try { - NativeDesktop.openFolderAndSelectFile(file, preferences.getExternalApplicationsPreferences(), dialogService); - } catch (IOException e) { - LOGGER.error("Could not open export folder.", e); - } - notificationPane.hide(); - })), - Duration.seconds(5)); - } + LibraryTab.DatabaseNotification notificationPane = tabSupplier.get().getNotificationPane(); + notificationPane.notify( + IconTheme.JabRefIcons.FOLDER.getGraphicNode(), + Localization.lang("Export operation finished successfully."), + List.of(new Action(Localization.lang("Reveal in File Explorer"), event -> { + try { + NativeDesktop.openFolderAndSelectFile(file, preferences.getExternalApplicationsPreferences(), dialogService); + } catch (IOException e) { + LOGGER.error("Could not open export folder.", e); + } + notificationPane.hide(); + })), + Duration.seconds(5)); }) .onFailure(this::handleError) .executeWith(taskExecutor); From 721a77fe1e01c0d802879fd1bf067d4464eb99b0 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Mon, 17 Mar 2025 16:52:25 +0530 Subject: [PATCH 24/41] Introduced URLs Util --- src/main/java/org/jabref/gui/WelcomeTab.java | 27 +++++++------------ .../java/org/jabref/gui/frame/MainMenu.java | 21 ++++++++------- .../jabref/gui/help/AboutDialogViewModel.java | 23 ++++++---------- src/main/java/org/jabref/gui/util/URLs.java | 24 +++++++++++++++++ 4 files changed, 53 insertions(+), 42 deletions(-) create mode 100644 src/main/java/org/jabref/gui/util/URLs.java diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index a3e191b7d00..3d6eb2ae2e9 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -23,6 +23,7 @@ import org.jabref.gui.importer.actions.OpenDatabaseAction; import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.undo.CountingUndoManager; +import org.jabref.gui.util.URLs; import org.jabref.logic.ai.AiService; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.BuildInfo; @@ -188,7 +189,7 @@ private VBox createVBoxContainer(Node... nodes) { } private VBox createFooter() { - Label communityLabel = createFooterLabel("Community"); + Label communityLabel = createFooterLabel(Localization.lang("Community")); HBox iconLinksContainer = createIconLinksContainer(); HBox textLinksContainer = createTextLinksContainer(); @@ -239,22 +240,14 @@ private Hyperlink createFooterLink(String text, StandardActions action, IconThem link.getStyleClass().add("welcome-footer-link"); String url = switch (action) { - case HELP -> - "https://help.jabref.org/"; - case OPEN_FORUM -> - "https://discourse.jabref.org/"; - case OPEN_MASTODON -> - "https://foojay.social/@jabref"; - case OPEN_LINKEDIN -> - "https://linkedin.com/company/jabref/"; - case DONATE -> - "https://donate.jabref.org"; - case OPEN_DEV_VERSION_LINK -> - "https://builds.jabref.org/master/"; - case OPEN_CHANGELOG -> - "https://github.com/JabRef/jabref/blob/main/CHANGELOG.md"; - default -> - null; + case HELP -> URLs.HELP_URL; + case OPEN_FORUM -> URLs.FORUM_URL; + case OPEN_MASTODON -> URLs.MASTODON_URL; + case OPEN_LINKEDIN -> URLs.LINKEDIN_URL; + case DONATE -> URLs.DONATE_URL; + case OPEN_DEV_VERSION_LINK -> URLs.DEV_VERSION_LINK_URL; + case OPEN_CHANGELOG -> URLs.CHANGELOG_URL; + default -> null; }; if (url != null) { diff --git a/src/main/java/org/jabref/gui/frame/MainMenu.java b/src/main/java/org/jabref/gui/frame/MainMenu.java index ba6748f77e9..e119bf449fd 100644 --- a/src/main/java/org/jabref/gui/frame/MainMenu.java +++ b/src/main/java/org/jabref/gui/frame/MainMenu.java @@ -72,6 +72,7 @@ import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.undo.RedoAction; import org.jabref.gui.undo.UndoAction; +import org.jabref.gui.util.URLs; import org.jabref.gui.util.UiTaskExecutor; import org.jabref.logic.ai.AiService; import org.jabref.logic.citationstyle.CitationStyleOutputFormat; @@ -343,7 +344,7 @@ private void createMenu() { help.getItems().addAll( factory.createMenuItem(StandardActions.HELP, new HelpAction(HelpFile.CONTENTS, dialogService, preferences.getExternalApplicationsPreferences())), - factory.createMenuItem(StandardActions.OPEN_FORUM, new OpenBrowserAction("http://discourse.jabref.org/", dialogService, preferences.getExternalApplicationsPreferences())), + factory.createMenuItem(StandardActions.OPEN_FORUM, new OpenBrowserAction(URLs.DONATE_URL, dialogService, preferences.getExternalApplicationsPreferences())), new SeparatorMenuItem(), @@ -351,20 +352,20 @@ private void createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.DONATE, new OpenBrowserAction("https://donations.jabref.org", dialogService, preferences.getExternalApplicationsPreferences())), + factory.createMenuItem(StandardActions.DONATE, new OpenBrowserAction(URLs.FORUM_URL, dialogService, preferences.getExternalApplicationsPreferences())), factory.createMenuItem(StandardActions.SEARCH_FOR_UPDATES, new SearchForUpdateAction(preferences, dialogService, taskExecutor)), factory.createSubMenu(StandardActions.WEB_MENU, - factory.createMenuItem(StandardActions.OPEN_WEBPAGE, new OpenBrowserAction("https://jabref.org/", dialogService, preferences.getExternalApplicationsPreferences())), - factory.createMenuItem(StandardActions.OPEN_BLOG, new OpenBrowserAction("https://blog.jabref.org/", dialogService, preferences.getExternalApplicationsPreferences())), - factory.createMenuItem(StandardActions.OPEN_LINKEDIN, new OpenBrowserAction("https://linkedin.com/company/jabref/", dialogService, preferences.getExternalApplicationsPreferences())), - factory.createMenuItem(StandardActions.OPEN_FACEBOOK, new OpenBrowserAction("https://www.facebook.com/JabRef/", dialogService, preferences.getExternalApplicationsPreferences())), - factory.createMenuItem(StandardActions.OPEN_MASTODON, new OpenBrowserAction("https://foojay.social/@jabref", dialogService, preferences.getExternalApplicationsPreferences())), - factory.createMenuItem(StandardActions.OPEN_GITHUB, new OpenBrowserAction("https://github.com/JabRef/jabref", dialogService, preferences.getExternalApplicationsPreferences())), + factory.createMenuItem(StandardActions.OPEN_WEBPAGE, new OpenBrowserAction(URLs.WEBPAGE_URL, dialogService, preferences.getExternalApplicationsPreferences())), + factory.createMenuItem(StandardActions.OPEN_BLOG, new OpenBrowserAction(URLs.BLOG_URL, dialogService, preferences.getExternalApplicationsPreferences())), + factory.createMenuItem(StandardActions.OPEN_LINKEDIN, new OpenBrowserAction(URLs.LINKEDIN_URL, dialogService, preferences.getExternalApplicationsPreferences())), + factory.createMenuItem(StandardActions.OPEN_FACEBOOK, new OpenBrowserAction(URLs.FACEBOOK_URL, dialogService, preferences.getExternalApplicationsPreferences())), + factory.createMenuItem(StandardActions.OPEN_MASTODON, new OpenBrowserAction(URLs.MASTODON_URL, dialogService, preferences.getExternalApplicationsPreferences())), + factory.createMenuItem(StandardActions.OPEN_GITHUB, new OpenBrowserAction(URLs.GITHUB_URL, dialogService, preferences.getExternalApplicationsPreferences())), new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.OPEN_DEV_VERSION_LINK, new OpenBrowserAction("https://builds.jabref.org/master/", dialogService, preferences.getExternalApplicationsPreferences())), - factory.createMenuItem(StandardActions.OPEN_CHANGELOG, new OpenBrowserAction("https://github.com/JabRef/jabref/blob/main/CHANGELOG.md", dialogService, preferences.getExternalApplicationsPreferences())) + factory.createMenuItem(StandardActions.OPEN_DEV_VERSION_LINK, new OpenBrowserAction(URLs.DEV_VERSION_LINK_URL, dialogService, preferences.getExternalApplicationsPreferences())), + factory.createMenuItem(StandardActions.OPEN_CHANGELOG, new OpenBrowserAction(URLs.CHANGELOG_URL, dialogService, preferences.getExternalApplicationsPreferences())) ), factory.createMenuItem(StandardActions.OPEN_WELCOME_TAB, new SimpleCommand() { diff --git a/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java b/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java index 44beaf93ab6..79b10c238ea 100644 --- a/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java +++ b/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java @@ -15,6 +15,7 @@ import org.jabref.gui.DialogService; import org.jabref.gui.desktop.os.NativeDesktop; import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.gui.util.URLs; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.BuildInfo; @@ -23,14 +24,6 @@ import org.slf4j.LoggerFactory; public class AboutDialogViewModel extends AbstractViewModel { - - private static final String HOMEPAGE_URL = "https://www.jabref.org"; - private static final String DONATION_URL = "https://donations.jabref.org"; - private static final String LIBRARIES_URL = "https://github.com/JabRef/jabref/blob/main/external-libraries.md"; - private static final String GITHUB_URL = "https://github.com/JabRef/jabref"; - private static final String LICENSE_URL = "https://github.com/JabRef/jabref/blob/main/LICENSE"; - private static final String CONTRIBUTORS_URL = "https://github.com/JabRef/jabref/graphs/contributors"; - private static final String PRIVACY_POLICY_URL = "https://github.com/JabRef/jabref/blob/main/PRIVACY.md"; private final String changelogUrl; private final String versionInfo; private final ReadOnlyStringWrapper environmentInfo = new ReadOnlyStringWrapper(); @@ -123,15 +116,15 @@ public void copyVersionToClipboard() { } public void openJabrefWebsite() { - openWebsite(HOMEPAGE_URL); + openWebsite(URLs.HOMEPAGE_URL); } public void openExternalLibrariesWebsite() { - openWebsite(LIBRARIES_URL); + openWebsite(URLs.LIBRARIES_URL); } public void openGithub() { - openWebsite(GITHUB_URL); + openWebsite(URLs.GITHUB_URL); } public void openChangeLog() { @@ -139,15 +132,15 @@ public void openChangeLog() { } public void openLicense() { - openWebsite(LICENSE_URL); + openWebsite(URLs.LICENSE_URL); } public void openContributors() { - openWebsite(CONTRIBUTORS_URL); + openWebsite(URLs.CONTRIBUTORS_URL); } public void openDonation() { - openWebsite(DONATION_URL); + openWebsite(URLs.DONATION_URL); } private void openWebsite(String url) { @@ -160,6 +153,6 @@ private void openWebsite(String url) { } public void openPrivacyPolicy() { - openWebsite(PRIVACY_POLICY_URL); + openWebsite(URLs.PRIVACY_POLICY_URL); } } diff --git a/src/main/java/org/jabref/gui/util/URLs.java b/src/main/java/org/jabref/gui/util/URLs.java new file mode 100644 index 00000000000..a982aff2db5 --- /dev/null +++ b/src/main/java/org/jabref/gui/util/URLs.java @@ -0,0 +1,24 @@ +package org.jabref.gui.util; + +public class URLs { + // MainMenu and Welcome Tab URLs + public static final String WEBPAGE_URL = "https://jabref.org/"; + public static final String FORUM_URL = "https://discourse.jabref.org/"; + public static final String BLOG_URL = "https://blog.jabref.org/"; + public static final String LINKEDIN_URL = "https://linkedin.com/company/jabref/"; + public static final String FACEBOOK_URL = "https://www.facebook.com/JabRef/"; + public static final String GITHUB_URL = "https://github.com/JabRef/jabref"; + public static final String MASTODON_URL = "https://foojay.social/@jabref"; + public static final String DONATE_URL = "https://donate.jabref.org"; + public static final String DEV_VERSION_LINK_URL = "https://builds.jabref.org/master/"; + public static final String CHANGELOG_URL = "https://github.com/JabRef/jabref/blob/main/CHANGELOG.md"; + public static final String HELP_URL = "https://docs.jabref.org/"; + + // AboutDialogViewModel URLs + public static final String HOMEPAGE_URL = "https://www.jabref.org"; + public static final String DONATION_URL = "https://donations.jabref.org"; + public static final String LIBRARIES_URL = "https://github.com/JabRef/jabref/blob/main/external-libraries.md"; + public static final String LICENSE_URL = "https://github.com/JabRef/jabref/blob/main/LICENSE"; + public static final String CONTRIBUTORS_URL = "https://github.com/JabRef/jabref/graphs/contributors"; + public static final String PRIVACY_POLICY_URL = "https://github.com/JabRef/jabref/blob/main/PRIVACY.md"; +} From 22347f84cd15b28fd8aac33aa4bcd5b5c111c3dc Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Mon, 17 Mar 2025 17:17:48 +0530 Subject: [PATCH 25/41] Fixed Localization issues --- src/main/java/org/jabref/gui/WelcomeTab.java | 2 +- src/main/resources/l10n/JabRef_en.properties | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 3d6eb2ae2e9..0873a82ead1 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -265,7 +265,7 @@ private HBox createVersionContainer() { HBox container = new HBox(15); container.setAlignment(Pos.CENTER); - Label versionLabel = new Label(Localization.lang("Current JabRef version") + ": " + buildInfo.version); + Label versionLabel = new Label("Current JabRef version: " + buildInfo.version); versionLabel.getStyleClass().add("welcome-footer-version"); container.getChildren().add(versionLabel); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 78c88ce437b..c705f4709b2 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2878,5 +2878,4 @@ Stay\ on\ top\ of\ your\ literature=Stay on top of your literature Welcome\ to\ JabRef=Welcome to JabRef Welcome=Welcome Open\ welcome\ tab=Open welcome tab -Current\ JabRef\ version=Current JabRef version Community=Community From a8ac3e553588da62bb15b66ca198891e2ffa6bb3 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Mon, 17 Mar 2025 17:26:51 +0530 Subject: [PATCH 26/41] Fixed Localization issues --- src/main/java/org/jabref/gui/WelcomeTab.java | 2 +- src/main/resources/l10n/JabRef_en.properties | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 0873a82ead1..3d6eb2ae2e9 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -265,7 +265,7 @@ private HBox createVersionContainer() { HBox container = new HBox(15); container.setAlignment(Pos.CENTER); - Label versionLabel = new Label("Current JabRef version: " + buildInfo.version); + Label versionLabel = new Label(Localization.lang("Current JabRef version") + ": " + buildInfo.version); versionLabel.getStyleClass().add("welcome-footer-version"); container.getChildren().add(versionLabel); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index c705f4709b2..78c88ce437b 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2878,4 +2878,5 @@ Stay\ on\ top\ of\ your\ literature=Stay on top of your literature Welcome\ to\ JabRef=Welcome to JabRef Welcome=Welcome Open\ welcome\ tab=Open welcome tab +Current\ JabRef\ version=Current JabRef version Community=Community From efc4767b17589ffecc9cab98ee9e95f8c919c7c6 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Mon, 17 Mar 2025 20:32:26 +0530 Subject: [PATCH 27/41] Fixed Localization issues --- src/main/java/org/jabref/gui/WelcomeTab.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 3d6eb2ae2e9..c273a076f7e 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -205,7 +205,7 @@ private VBox createFooter() { } private Label createFooterLabel(String text) { - Label label = new Label(Localization.lang(text)); + Label label = new Label(text); label.getStyleClass().add("welcome-footer-label"); return label; } From 7ba378d5a7a44b87375bdde681e90e58f1d7b430 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Tue, 18 Mar 2025 01:09:55 +0530 Subject: [PATCH 28/41] Fixed missing Localization in WelcomeTab --- src/main/java/org/jabref/gui/WelcomeTab.java | 4 ++-- src/main/resources/l10n/JabRef_en.properties | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index c273a076f7e..14a7b4c9db8 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -228,8 +228,8 @@ private HBox createTextLinksContainer() { HBox container = new HBox(15); container.setAlignment(Pos.CENTER); - Hyperlink devVersionLink = createFooterLink("Download Development version", StandardActions.OPEN_DEV_VERSION_LINK, null); - Hyperlink changelogLink = createFooterLink("CHANGELOG", StandardActions.OPEN_CHANGELOG, null); + Hyperlink devVersionLink = createFooterLink(Localization.lang("Download development version"), StandardActions.OPEN_DEV_VERSION_LINK, null); + Hyperlink changelogLink = createFooterLink(Localization.lang("CHANGELOG"), StandardActions.OPEN_CHANGELOG, null); container.getChildren().addAll(devVersionLink, changelogLink); return container; diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 78c88ce437b..7b2e062b759 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2880,3 +2880,5 @@ Welcome=Welcome Open\ welcome\ tab=Open welcome tab Current\ JabRef\ version=Current JabRef version Community=Community +Download\ development\ version=Download development version +CHANGELOG=CHANGELOG From 95a93eb257b53936d185e6c805b0fd9110743a58 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Tue, 18 Mar 2025 01:15:42 +0530 Subject: [PATCH 29/41] Fixed missing Localization in WelcomeTab --- src/main/java/org/jabref/gui/WelcomeTab.java | 10 +++++----- src/main/resources/l10n/JabRef_en.properties | 4 ++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 14a7b4c9db8..91b87bf005c 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -214,11 +214,11 @@ private HBox createIconLinksContainer() { HBox container = new HBox(15); container.setAlignment(Pos.CENTER); - Hyperlink onlineHelpLink = createFooterLink("Online help", StandardActions.HELP, IconTheme.JabRefIcons.HELP); - Hyperlink forumLink = createFooterLink("Forum for support", StandardActions.OPEN_FORUM, IconTheme.JabRefIcons.FORUM); - Hyperlink mastodonLink = createFooterLink("Mastodon", StandardActions.OPEN_MASTODON, IconTheme.JabRefIcons.MASTODON); - Hyperlink linkedInLink = createFooterLink("LinkedIn", StandardActions.OPEN_LINKEDIN, IconTheme.JabRefIcons.LINKEDIN); - Hyperlink donationLink = createFooterLink("Donation", StandardActions.DONATE, IconTheme.JabRefIcons.DONATE); + Hyperlink onlineHelpLink = createFooterLink(Localization.lang("Online help"), StandardActions.HELP, IconTheme.JabRefIcons.HELP); + Hyperlink forumLink = createFooterLink(Localization.lang("Forum for support"), StandardActions.OPEN_FORUM, IconTheme.JabRefIcons.FORUM); + Hyperlink mastodonLink = createFooterLink(Localization.lang("Mastodon"), StandardActions.OPEN_MASTODON, IconTheme.JabRefIcons.MASTODON); + Hyperlink linkedInLink = createFooterLink(Localization.lang("LinkedIn"), StandardActions.OPEN_LINKEDIN, IconTheme.JabRefIcons.LINKEDIN); + Hyperlink donationLink = createFooterLink(Localization.lang("Donation"), StandardActions.DONATE, IconTheme.JabRefIcons.DONATE); container.getChildren().addAll(onlineHelpLink, forumLink, mastodonLink, linkedInLink, donationLink); return container; diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 7b2e062b759..5a43d1c31eb 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2882,3 +2882,7 @@ Current\ JabRef\ version=Current JabRef version Community=Community Download\ development\ version=Download development version CHANGELOG=CHANGELOG +Forum\ for\ support=Forum for support +Mastodon=Mastodon +LinkedIn=LinkedIn +Donation=Donation From 0e786cc1793ad4f2c6d237470e39a1c11d577316 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Tue, 18 Mar 2025 01:43:50 +0530 Subject: [PATCH 30/41] Fixed Review changes --- src/main/java/org/jabref/gui/WelcomeTab.java | 16 ++++++++-------- .../java/org/jabref/gui/frame/JabRefFrame.java | 2 +- src/main/resources/l10n/JabRef_en.properties | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 91b87bf005c..44bc14db704 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -76,12 +76,12 @@ public WelcomeTab(LibraryTabContainer tabContainer, this.fileHistoryMenu = fileHistoryMenu; this.buildInfo = buildInfo; - this.recentLibrariesBox = new VBox(5); + this.recentLibrariesBox = new VBox(10); - VBox welcomePageContainer = new VBox(20); + VBox welcomePageContainer = new VBox(10); welcomePageContainer.setAlignment(Pos.CENTER); - HBox welcomeMainContainer = new HBox(20); + HBox welcomeMainContainer = new HBox(10); welcomeMainContainer.setAlignment(Pos.CENTER); welcomeMainContainer.setPadding(new Insets(10, 10, 10, 50)); @@ -182,7 +182,7 @@ private void displayNoRecentLibrariesMessage() { } private VBox createVBoxContainer(Node... nodes) { - VBox box = new VBox(5); + VBox box = new VBox(10); box.setAlignment(Pos.TOP_LEFT); box.getChildren().addAll(nodes); return box; @@ -211,7 +211,7 @@ private Label createFooterLabel(String text) { } private HBox createIconLinksContainer() { - HBox container = new HBox(15); + HBox container = new HBox(10); container.setAlignment(Pos.CENTER); Hyperlink onlineHelpLink = createFooterLink(Localization.lang("Online help"), StandardActions.HELP, IconTheme.JabRefIcons.HELP); @@ -225,7 +225,7 @@ private HBox createIconLinksContainer() { } private HBox createTextLinksContainer() { - HBox container = new HBox(15); + HBox container = new HBox(10); container.setAlignment(Pos.CENTER); Hyperlink devVersionLink = createFooterLink(Localization.lang("Download development version"), StandardActions.OPEN_DEV_VERSION_LINK, null); @@ -262,10 +262,10 @@ private Hyperlink createFooterLink(String text, StandardActions action, IconThem } private HBox createVersionContainer() { - HBox container = new HBox(15); + HBox container = new HBox(10); container.setAlignment(Pos.CENTER); - Label versionLabel = new Label(Localization.lang("Current JabRef version") + ": " + buildInfo.version); + Label versionLabel = new Label(Localization.lang("Current JabRef version: %0", buildInfo.version)); versionLabel.getStyleClass().add("welcome-footer-version"); container.getChildren().add(versionLabel); diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index a06005ef333..21c1b24d457 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -375,7 +375,7 @@ private void initBindings() { stateManager.setActiveDatabase(libraryTab.getBibDatabaseContext()); stateManager.activeTabProperty().set(Optional.of(libraryTab)); } else if (selectedTab == null || selectedTab instanceof WelcomeTab) { - // All databases are closed or Welcome Tab is open + /// All databases are closed or [WelcomeTab] is open stateManager.setActiveDatabase(null); stateManager.activeTabProperty().set(Optional.empty()); } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 5a43d1c31eb..b5cb2896311 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2878,7 +2878,7 @@ Stay\ on\ top\ of\ your\ literature=Stay on top of your literature Welcome\ to\ JabRef=Welcome to JabRef Welcome=Welcome Open\ welcome\ tab=Open welcome tab -Current\ JabRef\ version=Current JabRef version +Current\ JabRef\ version\:\ %0=Current JabRef version: %0 Community=Community Download\ development\ version=Download development version CHANGELOG=CHANGELOG From f6a5587763f9721f209ed474ede70372c4a322cb Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Tue, 18 Mar 2025 02:05:31 +0530 Subject: [PATCH 31/41] Added Changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d10da493072..8a8612a192b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv ### Added +- We added a new Welcome tab which shows a welcome screen if no database is open. [#12272](https://github.com/JabRef/jabref/issues/12272) - We added F5 as a shortcut key for fetching data and Alt+F as a shortcut for looking up data using DOI. [#11802](https://github.com/JabRef/jabref/issues/11802) - We added a feature to rename the subgroup, with the keybinding (F2) for quick access. [#11896](https://github.com/JabRef/jabref/issues/11896) - We added a new functionality that displays a drop-down list of matching suggestions when typing a citation key pattern. [#12502](https://github.com/JabRef/jabref/issues/12502) From ba1ad6f3f3ab6e037220f00f88a5649994287f9a Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 19 Mar 2025 19:54:14 +0100 Subject: [PATCH 32/41] Update src/main/java/org/jabref/gui/frame/JabRefFrame.java --- src/main/java/org/jabref/gui/frame/JabRefFrame.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 21c1b24d457..7d5f3699273 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -375,7 +375,7 @@ private void initBindings() { stateManager.setActiveDatabase(libraryTab.getBibDatabaseContext()); stateManager.activeTabProperty().set(Optional.of(libraryTab)); } else if (selectedTab == null || selectedTab instanceof WelcomeTab) { - /// All databases are closed or [WelcomeTab] is open + // All databases are closed or {@link WelcomeTab} is open stateManager.setActiveDatabase(null); stateManager.activeTabProperty().set(Optional.empty()); } From 23891b687960b345a854d485f6cf6c1239c5212b Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 19 Mar 2025 19:54:43 +0100 Subject: [PATCH 33/41] Update src/main/java/org/jabref/gui/WelcomeTab.java --- src/main/java/org/jabref/gui/WelcomeTab.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 44bc14db704..124603b02ce 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -215,7 +215,7 @@ private HBox createIconLinksContainer() { container.setAlignment(Pos.CENTER); Hyperlink onlineHelpLink = createFooterLink(Localization.lang("Online help"), StandardActions.HELP, IconTheme.JabRefIcons.HELP); - Hyperlink forumLink = createFooterLink(Localization.lang("Forum for support"), StandardActions.OPEN_FORUM, IconTheme.JabRefIcons.FORUM); + Hyperlink forumLink = createFooterLink(Localization.lang("Forum"), StandardActions.OPEN_FORUM, IconTheme.JabRefIcons.FORUM); Hyperlink mastodonLink = createFooterLink(Localization.lang("Mastodon"), StandardActions.OPEN_MASTODON, IconTheme.JabRefIcons.MASTODON); Hyperlink linkedInLink = createFooterLink(Localization.lang("LinkedIn"), StandardActions.OPEN_LINKEDIN, IconTheme.JabRefIcons.LINKEDIN); Hyperlink donationLink = createFooterLink(Localization.lang("Donation"), StandardActions.DONATE, IconTheme.JabRefIcons.DONATE); From 4bc74b6f457745c8dc429bb67e1f94e870cefd1b Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 19 Mar 2025 19:55:26 +0100 Subject: [PATCH 34/41] Update src/main/java/org/jabref/gui/frame/JabRefFrame.java --- src/main/java/org/jabref/gui/frame/JabRefFrame.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 7d5f3699273..64353a5cac7 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -464,7 +464,7 @@ public void showLibraryTab(@NonNull LibraryTab libraryTab) { } public void showWelcomeTab() { - // The loop iterates through all tabs in tabbedPane to check if a WelcomeTab already exists. If yes, it is selected + // The loop iterates through all tabs in tabbedPane to check if a WelcomeTab already exists. If yes, it is selected. for (Tab tab : tabbedPane.getTabs()) { if (!(tab instanceof LibraryTab)) { tabbedPane.getSelectionModel().select(tab); From 00769197ac8f363d58482d9d466da4b20812f414 Mon Sep 17 00:00:00 2001 From: Shlok Upadhyay Date: Thu, 20 Mar 2025 00:35:25 +0530 Subject: [PATCH 35/41] Fixed Localization issue --- src/main/resources/l10n/JabRef_en.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index b5cb2896311..05db4bbd821 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2882,7 +2882,7 @@ Current\ JabRef\ version\:\ %0=Current JabRef version: %0 Community=Community Download\ development\ version=Download development version CHANGELOG=CHANGELOG -Forum\ for\ support=Forum for support +Forum=Forum Mastodon=Mastodon LinkedIn=LinkedIn Donation=Donation From 3c14ba86b263065505c130f57c94614cb10e965d Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 19 Mar 2025 20:20:02 +0100 Subject: [PATCH 36/41] Fix position of showing welcome tab --- src/main/java/org/jabref/gui/JabRefGUI.java | 9 ++++++++ .../org/jabref/gui/frame/JabRefFrame.java | 21 +------------------ 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/jabref/gui/JabRefGUI.java b/src/main/java/org/jabref/gui/JabRefGUI.java index b85b2437d8f..409a5c3029c 100644 --- a/src/main/java/org/jabref/gui/JabRefGUI.java +++ b/src/main/java/org/jabref/gui/JabRefGUI.java @@ -260,6 +260,8 @@ private void openWindow() { LOGGER.debug("frame initialized"); Platform.runLater(() -> mainFrame.handleUiCommands(uiCommands)); + + // Lifecycle note: after this method, #onShowing will be called } public void onShowing(WindowEvent event) { @@ -270,6 +272,13 @@ public void onShowing(WindowEvent event) { && preferences.getWorkspacePreferences().shouldOpenLastEdited()) { mainFrame.openLastEditedDatabases(); } + + Platform.runLater(() -> { + // We need to check at this point, because here, all libraries are loaded (e.g., load previously opened libraries) and all UI commands (e.g., load libraries, blank workspace, ...) are handled. + if (stateManager.getOpenDatabases().isEmpty()) { + mainFrame.showWelcomeTab(); + } + }); } public void onCloseRequest(WindowEvent event) { diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 64353a5cac7..829cde6aa07 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -230,25 +230,6 @@ private void initLayout() { head.setSpacing(0d); setTop(head); - if (stateManager.getOpenDatabases().isEmpty()) { - WelcomeTab welcomeTab = new WelcomeTab( - this, - preferences, - aiService, - dialogService, - stateManager, - fileUpdateMonitor, - entryTypesManager, - undoManager, - clipBoardManager, - taskExecutor, - fileHistory, - new BuildInfo() - ); - - tabbedPane.getTabs().add(welcomeTab); - } - splitPane.getItems().add(tabbedPane); SplitPane.setResizableWithParent(sidePane, false); sidePane.widthProperty().addListener(_ -> updateSidePane()); @@ -485,7 +466,7 @@ public void showWelcomeTab() { clipBoardManager, taskExecutor, fileHistory, - new BuildInfo() + Injector.instantiateModelOrService(BuildInfo.class) ); tabbedPane.getTabs().add(welcomeTab); tabbedPane.getSelectionModel().select(welcomeTab); From c94fb15ba1dac99cf483daf0cffb367a3d1f169c Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 19 Mar 2025 20:29:52 +0100 Subject: [PATCH 37/41] Streamline wording --- src/main/java/org/jabref/gui/WelcomeTab.java | 2 +- .../org/jabref/gui/actions/StandardActions.java | 2 +- src/main/resources/l10n/JabRef_en.properties | 14 ++++++-------- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 124603b02ce..5da55794ef8 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -215,7 +215,7 @@ private HBox createIconLinksContainer() { container.setAlignment(Pos.CENTER); Hyperlink onlineHelpLink = createFooterLink(Localization.lang("Online help"), StandardActions.HELP, IconTheme.JabRefIcons.HELP); - Hyperlink forumLink = createFooterLink(Localization.lang("Forum"), StandardActions.OPEN_FORUM, IconTheme.JabRefIcons.FORUM); + Hyperlink forumLink = createFooterLink(Localization.lang("Community forum"), StandardActions.OPEN_FORUM, IconTheme.JabRefIcons.FORUM); Hyperlink mastodonLink = createFooterLink(Localization.lang("Mastodon"), StandardActions.OPEN_MASTODON, IconTheme.JabRefIcons.MASTODON); Hyperlink linkedInLink = createFooterLink(Localization.lang("LinkedIn"), StandardActions.OPEN_LINKEDIN, IconTheme.JabRefIcons.LINKEDIN); Hyperlink donationLink = createFooterLink(Localization.lang("Donation"), StandardActions.DONATE, IconTheme.JabRefIcons.DONATE); diff --git a/src/main/java/org/jabref/gui/actions/StandardActions.java b/src/main/java/org/jabref/gui/actions/StandardActions.java index 043046a3f5c..3f2f8b8ca15 100644 --- a/src/main/java/org/jabref/gui/actions/StandardActions.java +++ b/src/main/java/org/jabref/gui/actions/StandardActions.java @@ -181,7 +181,7 @@ public enum StandardActions implements Action { OPEN_CHANGELOG(Localization.lang("View change log"), Localization.lang("See what has been changed in the JabRef versions")), OPEN_GITHUB("GitHub", Localization.lang("Opens JabRef's GitHub page"), IconTheme.JabRefIcons.GITHUB), DONATE(Localization.lang("Donate to JabRef"), Localization.lang("Donate to JabRef"), IconTheme.JabRefIcons.DONATE), - OPEN_FORUM(Localization.lang("Online help forum"), Localization.lang("Online help forum"), IconTheme.JabRefIcons.FORUM), + OPEN_FORUM(Localization.lang("Community forum"), Localization.lang("Community forum"), IconTheme.JabRefIcons.FORUM), ERROR_CONSOLE(Localization.lang("View event log"), Localization.lang("Display all error messages")), SEARCH_FOR_UPDATES(Localization.lang("Check for updates")), ABOUT(Localization.lang("About JabRef"), Localization.lang("About JabRef")), diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index b5cb2896311..45f3caad1c3 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -249,8 +249,6 @@ Do\ not\ open\ any\ files\ at\ startup=Do not open any files at startup Do\ not\ wrap\ when\ saving=Do not wrap when saving -Donate\ to\ JabRef=Donate to JabRef - Download\ file=Download file Download\ '%0'\ was\ a\ HTML\ file.\ Removed.=Download '%0' was a HTML file. Removed. @@ -1344,9 +1342,14 @@ Save\ selected\ as\ plain\ BibTeX...=Save selected as plain BibTeX... Set\ read\ status\ to\ read=Set read status to read Set\ read\ status\ to\ skimmed=Set read status to skimmed +Donate\ to\ JabRef=Donate to JabRef +Donation=Donation + Opens\ JabRef's\ GitHub\ page=Opens JabRef's GitHub page Opens\ JabRef's\ LinkedIn\ page=Opens JabRef's LinkedIn page +LinkedIn=LinkedIn Opens\ JabRef's\ Mastodon\ page=Opens JabRef's Mastodon page +Mastodon=Mastodon Opens\ JabRef's\ Facebook\ page=Opens JabRef's Facebook page Opens\ JabRef's\ blog=Opens JabRef's blog Opens\ JabRef's\ website=Opens JabRef's website @@ -1661,7 +1664,7 @@ To\ see\ what\ is\ new\ view\ the\ changelog.=To see what is new view the change A\ new\ version\ of\ JabRef\ has\ been\ released.=A new version of JabRef has been released. JabRef\ is\ up-to-date.=JabRef is up-to-date. Latest\ version=Latest version -Online\ help\ forum=Online help forum +Community\ forum=Community forum Custom=Custom Export\ cited=Export cited @@ -2879,10 +2882,5 @@ Welcome\ to\ JabRef=Welcome to JabRef Welcome=Welcome Open\ welcome\ tab=Open welcome tab Current\ JabRef\ version\:\ %0=Current JabRef version: %0 -Community=Community Download\ development\ version=Download development version CHANGELOG=CHANGELOG -Forum\ for\ support=Forum for support -Mastodon=Mastodon -LinkedIn=LinkedIn -Donation=Donation From 5115579b48577bc360459070edc078e41e5fb3be Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 19 Mar 2025 20:35:27 +0100 Subject: [PATCH 38/41] Remove obsolete strings --- src/main/resources/l10n/JabRef_en.properties | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index cbfeb0f7357..45f3caad1c3 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2884,7 +2884,3 @@ Open\ welcome\ tab=Open welcome tab Current\ JabRef\ version\:\ %0=Current JabRef version: %0 Download\ development\ version=Download development version CHANGELOG=CHANGELOG -Forum=Forum -Mastodon=Mastodon -LinkedIn=LinkedIn -Donation=Donation From f7c0c3b22f130defc6e44e4e81f1d23ba9a278f8 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 19 Mar 2025 20:45:43 +0100 Subject: [PATCH 39/41] Fix obsolete code --- src/main/java/org/jabref/gui/WelcomeTab.java | 24 ++++---------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 5da55794ef8..7cabdb25d3f 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -7,12 +7,10 @@ import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; import javafx.scene.control.MenuItem; -import javafx.scene.control.ScrollPane; import javafx.scene.control.Tab; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; -import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.jabref.gui.actions.StandardActions; @@ -78,30 +76,18 @@ public WelcomeTab(LibraryTabContainer tabContainer, this.recentLibrariesBox = new VBox(10); + VBox welcomeBox = createWelcomeBox(); + VBox startBox = createWelcomeStartBox(); + VBox recentBox = createWelcomeRecentBox(); + VBox welcomePageContainer = new VBox(10); welcomePageContainer.setAlignment(Pos.CENTER); + welcomePageContainer.getChildren().addAll(welcomeBox, startBox, recentBox); HBox welcomeMainContainer = new HBox(10); welcomeMainContainer.setAlignment(Pos.CENTER); - welcomeMainContainer.setPadding(new Insets(10, 10, 10, 50)); - ScrollPane scrollPane = new ScrollPane(welcomeMainContainer); - scrollPane.setFitToWidth(true); - scrollPane.setFitToHeight(true); - - scrollPane.widthProperty().addListener((_, _, newWidth) -> { - double dynamicPadding = Math.max(20, newWidth.doubleValue() * 0.05); - welcomeMainContainer.setPadding(new Insets(10, 10, 10, dynamicPadding)); - }); - - setContent(new StackPane(scrollPane)); - - VBox welcomeBox = createWelcomeBox(); - VBox startBox = createWelcomeStartBox(); - VBox recentBox = createWelcomeRecentBox(); - - welcomePageContainer.getChildren().addAll(welcomeBox, startBox, recentBox); welcomeMainContainer.getChildren().add(welcomePageContainer); BorderPane rootLayout = new BorderPane(); From 5d84d8993935860d4e4e5fd7638f1d2d52781fb0 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 19 Mar 2025 20:47:12 +0100 Subject: [PATCH 40/41] Fix comment --- src/main/java/org/jabref/gui/frame/JabRefFrame.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 829cde6aa07..c6cf1aed44e 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -452,8 +452,8 @@ public void showWelcomeTab() { return; } } + // WelcomeTab not found - // If the WelcomeTab is not found, a new instance is created and added WelcomeTab welcomeTab = new WelcomeTab( this, preferences, From 37e24d29cee60355c0b45d4dbc608004b7bb5c62 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 19 Mar 2025 20:58:56 +0100 Subject: [PATCH 41/41] Fix localization --- src/main/java/org/jabref/gui/WelcomeTab.java | 1 + src/main/resources/l10n/JabRef_en.properties | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/org/jabref/gui/WelcomeTab.java b/src/main/java/org/jabref/gui/WelcomeTab.java index 7cabdb25d3f..3fa0a95393d 100644 --- a/src/main/java/org/jabref/gui/WelcomeTab.java +++ b/src/main/java/org/jabref/gui/WelcomeTab.java @@ -175,6 +175,7 @@ private VBox createVBoxContainer(Node... nodes) { } private VBox createFooter() { + // Heading for the footer area Label communityLabel = createFooterLabel(Localization.lang("Community")); HBox iconLinksContainer = createIconLinksContainer(); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 45f3caad1c3..e7496463445 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1664,6 +1664,7 @@ To\ see\ what\ is\ new\ view\ the\ changelog.=To see what is new view the change A\ new\ version\ of\ JabRef\ has\ been\ released.=A new version of JabRef has been released. JabRef\ is\ up-to-date.=JabRef is up-to-date. Latest\ version=Latest version +Community=Community Community\ forum=Community forum Custom=Custom