-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add welcome screen to JabRef GUI that displays when no database/library is open #12017
base: main
Are you sure you want to change the base?
Changes from 19 commits
13b1b58
3c63145
0715fcd
b27ddb6
e88edc5
e14b016
ec78771
69005e9
d9ae0ee
14984a9
eade258
a031c35
1b76f86
2e38635
64f7f38
90ca2d2
e9c04fd
5d50f08
325debb
e15cdb9
0a392f7
33dab83
eab1844
0c07f52
b616970
5b5a63c
89d6985
64a09e7
bd07c06
a495fe8
aab2694
f8dabfb
0e428ab
c72d89d
3ccd6d3
1dcf28e
f83de2a
e346076
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
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; | ||
|
||
|
@@ -45,6 +46,7 @@ | |
import org.jabref.gui.sidepane.SidePane; | ||
import org.jabref.gui.sidepane.SidePaneType; | ||
import org.jabref.gui.undo.CountingUndoManager; | ||
import org.jabref.gui.util.WelcomePage; | ||
import org.jabref.logic.UiCommand; | ||
import org.jabref.logic.ai.AiService; | ||
import org.jabref.logic.journals.JournalAbbreviationRepository; | ||
|
@@ -99,6 +101,9 @@ public class JabRefFrame extends BorderPane implements LibraryTabContainer, UiMe | |
|
||
private Subscription dividerSubscription; | ||
|
||
private final WelcomePage welcomePage; | ||
private final StackPane contentPane = new StackPane(); // Holds both WelcomePage and TabPane | ||
|
||
public JabRefFrame(Stage mainStage, | ||
DialogService dialogService, | ||
FileUpdateMonitor fileUpdateMonitor, | ||
|
@@ -120,6 +125,19 @@ public JabRefFrame(Stage mainStage, | |
this.clipBoardManager = clipBoardManager; | ||
this.taskExecutor = taskExecutor; | ||
|
||
this.welcomePage = new WelcomePage( | ||
this, | ||
preferences, | ||
aiService, | ||
dialogService, | ||
stateManager, | ||
fileUpdateMonitor, | ||
entryTypesManager, | ||
undoManager, | ||
clipBoardManager, | ||
taskExecutor | ||
); | ||
|
||
setId("frame"); | ||
|
||
// Create components | ||
|
@@ -181,10 +199,13 @@ public JabRefFrame(Stage mainStage, | |
} | ||
}); | ||
|
||
// Initialize layout and bindings | ||
initLayout(); | ||
initKeyBindings(); | ||
frameDndHandler.initDragAndDrop(); | ||
initBindings(); | ||
bindDatabaseChanges(); | ||
updateContent(); | ||
} | ||
|
||
private void initLayout() { | ||
|
@@ -223,12 +244,42 @@ private void initLayout() { | |
head.setSpacing(0d); | ||
setTop(head); | ||
|
||
splitPane.getItems().addAll(tabbedPane); | ||
contentPane.getChildren().addAll(welcomePage, tabbedPane); | ||
splitPane.getItems().add(contentPane); | ||
|
||
SplitPane.setResizableWithParent(sidePane, false); | ||
sidePane.widthProperty().addListener(c -> updateSidePane()); | ||
sidePane.getChildren().addListener((InvalidationListener) c -> updateSidePane()); | ||
updateSidePane(); | ||
|
||
setCenter(splitPane); | ||
updateContent(); // Ensure layout is consistent on load | ||
} | ||
|
||
private void updateContent() { | ||
boolean hasOpenDatabases = !stateManager.getOpenDatabases().isEmpty(); | ||
|
||
// Toggle visibility between welcome page and tabbed pane | ||
welcomePage.setVisible(!hasOpenDatabases); | ||
tabbedPane.setVisible(hasOpenDatabases); | ||
|
||
if (hasOpenDatabases) { | ||
if (!splitPane.getItems().contains(sidePane)) { | ||
sidePane.setPrefWidth(260); | ||
splitPane.getItems().addFirst(sidePane); | ||
|
||
// Ensure divider position is set before rendering | ||
splitPane.setDividerPositions(0.2); | ||
|
||
// Ensure smooth transition by updating the layout immediately | ||
Platform.runLater(() -> splitPane.setDividerPositions(0.2)); | ||
} | ||
} else { | ||
splitPane.getItems().remove(sidePane); | ||
} | ||
} | ||
|
||
private void bindDatabaseChanges() { | ||
stateManager.getOpenDatabases().addListener((InvalidationListener) obs -> Platform.runLater(this::updateContent)); | ||
} | ||
|
||
private void updateSidePane() { | ||
|
@@ -446,12 +497,31 @@ public void addTab(@NonNull BibDatabaseContext databaseContext, boolean raisePan | |
|
||
public void addTab(@NonNull LibraryTab libraryTab, boolean raisePanel) { | ||
tabbedPane.getTabs().add(libraryTab); | ||
|
||
if (raisePanel) { | ||
tabbedPane.getSelectionModel().select(libraryTab); | ||
tabbedPane.requestFocus(); | ||
} | ||
|
||
libraryTab.setContextMenu(createTabContextMenuFor(libraryTab)); | ||
|
||
// Ensure layout is updated | ||
updateContent(); | ||
updateSidePane(); | ||
|
||
// Set the preferred width and divider position explicitly | ||
sidePane.setPrefWidth(260); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
Platform.runLater(() -> { | ||
if (!sidePane.getChildren().isEmpty() && !splitPane.getItems().contains(sidePane)) { | ||
splitPane.getItems().addFirst(sidePane); | ||
|
||
// Force divider to a known position (e.g., 0.2 of the total width) | ||
LOGGER.info("Forcing divider position after adding tab."); | ||
splitPane.setDividerPositions(0.2); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above. |
||
|
||
updateDividerPosition(); // Ensure any further updates are applied | ||
} | ||
}); | ||
} | ||
|
||
private ContextMenu createTabContextMenuFor(LibraryTab tab) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package org.jabref.gui.util; | ||
|
||
import javafx.geometry.Pos; | ||
import javafx.scene.control.Hyperlink; | ||
import javafx.scene.control.Label; | ||
import javafx.scene.layout.VBox; | ||
import javafx.scene.text.Text; | ||
import javafx.scene.text.TextAlignment; | ||
import javafx.scene.text.TextFlow; | ||
|
||
import org.jabref.gui.ClipBoardManager; | ||
import org.jabref.gui.DialogService; | ||
import org.jabref.gui.StateManager; | ||
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.util.TaskExecutor; | ||
import org.jabref.model.entry.BibEntryTypesManager; | ||
import org.jabref.model.util.FileUpdateMonitor; | ||
|
||
/** | ||
* A simple Welcome Page for the JabRef application. | ||
*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove JavaDoc - the class name already says this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noted thanks! comments removed |
||
public class WelcomePage extends VBox { | ||
|
||
public WelcomePage(JabRefFrame frame, | ||
GuiPreferences preferences, | ||
AiService aiService, | ||
DialogService dialogService, | ||
StateManager stateManager, | ||
FileUpdateMonitor fileUpdateMonitor, | ||
BibEntryTypesManager entryTypesManager, | ||
CountingUndoManager undoManager, | ||
ClipBoardManager clipBoardManager, | ||
TaskExecutor taskExecutor) { | ||
|
||
setAlignment(Pos.CENTER); | ||
setSpacing(10); | ||
|
||
// Title | ||
Label welcomeLabel = new Label("Welcome to JabRef!"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not translated. You need to use @InAnYan How did you do it in the AiTab with links and sentences? Did we come up with a good solution. @HaynesCrossley-ANU I am asking for help here, because for translation, we aim for translating whole sentences. Reason: In different languages, the ordering of words within a sentence is different. (Because the grammar differs from langauge to langauge) |
||
welcomeLabel.getStyleClass().add("welcome-label"); | ||
|
||
// Text and hyperlink for "New Library" | ||
Text openNewLibraryText = new Text("Open a "); | ||
openNewLibraryText.getStyleClass().add("welcome-text"); | ||
|
||
Hyperlink newLibraryLink = new Hyperlink("New Library"); | ||
newLibraryLink.getStyleClass().add("welcome-hyperlink"); | ||
newLibraryLink.setOnAction(e -> new NewDatabaseAction(frame, preferences).execute()); | ||
|
||
// Text and hyperlink for "Open Library" | ||
Hyperlink openLibraryLink = new Hyperlink("Existing Library"); | ||
openLibraryLink.getStyleClass().add("welcome-hyperlink"); | ||
openLibraryLink.setOnAction(e -> new OpenDatabaseAction(frame, preferences, aiService, dialogService, | ||
stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, | ||
taskExecutor).execute()); | ||
|
||
Text orExistingDatabaseText = new Text(" or open an "); | ||
orExistingDatabaseText.getStyleClass().add("welcome-text"); | ||
|
||
// TextFlows for each section | ||
TextFlow newLibraryFlow = new TextFlow(openNewLibraryText, newLibraryLink); | ||
newLibraryFlow.setTextAlignment(TextAlignment.CENTER); | ||
|
||
TextFlow openLibraryFlow = new TextFlow(orExistingDatabaseText, openLibraryLink); | ||
openLibraryFlow.setTextAlignment(TextAlignment.CENTER); | ||
|
||
// Add elements to the VBox | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not add comments just stating the words of the statement. You can remove these kinds of comments. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noted thank you - comments removed. |
||
getChildren().addAll(welcomeLabel, newLibraryFlow, openLibraryFlow); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand that. Both values are equal. I think, only the statement on line 271 is required?
The code of
org.jabref.gui.frame.JabRefFrame#updateDividerPosition
shows different values. I think you should just callThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right -
splitPane.setDividerPositions(preferences.getGuiPreferences().getSidePaneWidth() / splitPane.getWidth());
works fine!eab1844