优化导航底部工具区

This commit is contained in:
张家训
2026-08-01 20:54:22 +08:00
parent bd959825a3
commit 4c873b3f4f
5 changed files with 111 additions and 86 deletions
@@ -8,10 +8,7 @@ import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
@@ -88,9 +85,9 @@ public class MainWindow {
stage.setOnCloseRequest(event -> embeddedCache.clear());
BorderPane root = new BorderPane();
root.setTop(buildUnifiedHeader(openSettings));
root.setTop(buildUnifiedHeader());
navigationRail = new NavigationRail(navItems, this::navigateTo);
navigationRail = new NavigationRail(navItems, this::navigateTo, openSettings);
contentArea = new StackPane();
contentArea.getStyleClass().add(Theme.CSS_CONTENT_AREA);
HBox.setHgrow(contentArea, Priority.ALWAYS);
@@ -104,7 +101,7 @@ public class MainWindow {
showWelcomePage();
}
private HBox buildUnifiedHeader(Runnable openSettings) {
private HBox buildUnifiedHeader() {
HBox bar = new HBox(Theme.S1);
bar.setId("app-header");
bar.setAlignment(Pos.CENTER_LEFT);
@@ -114,13 +111,6 @@ public class MainWindow {
bar.setMaxHeight(DesignTokens.HEADER_HEIGHT);
bar.getStyleClass().add(Theme.CSS_HEADER_BAR);
Button menuButton = new Button(null, IconFactory.createButtonIcon(AppIcon.MENU, "切换导航栏"));
menuButton.setId("menu-button");
menuButton.setTooltip(new Tooltip("切换导航栏"));
menuButton.setAccessibleText("切换导航栏");
menuButton.setFocusTraversable(true);
menuButton.setOnAction(event -> navigationRail.toggle());
FontIcon brandIcon = IconFactory.create(AppIcon.APP, 18);
StackPane brandIconContainer = new StackPane(brandIcon);
brandIconContainer.setId("app-brand-icon-container");
@@ -148,17 +138,7 @@ public class MainWindow {
Region spacerRight = new Region();
HBox.setHgrow(spacerRight, Priority.ALWAYS);
Button settingsButton = new Button(
"系统设置", IconFactory.createButtonIcon(AppIcon.SETTINGS, "系统设置"));
settingsButton.setId("settings-button");
settingsButton.setTooltip(new Tooltip("系统设置"));
settingsButton.setAccessibleText("系统设置");
settingsButton.setContentDisplay(ContentDisplay.LEFT);
settingsButton.setFocusTraversable(true);
settingsButton.setOnAction(event -> openSettings.run());
bar.getChildren().addAll(
menuButton, brand, toolbarChevron, toolbarTitle, spacerRight, settingsButton);
bar.getChildren().addAll(brand, toolbarChevron, toolbarTitle, spacerRight);
return bar;
}
@@ -237,7 +217,7 @@ public class MainWindow {
private void switchToEmbedded(String pluginId, EmbeddedEntry entry) {
if ("__settings__".equals(pluginId)) {
navigationRail.clearSelection();
navigationRail.selectSettings();
}
if (currentEmbedded != null && currentEmbedded != entry) {
contentArea.getChildren().remove(currentEmbedded.wrapper);
@@ -39,6 +39,8 @@ public final class NavigationRail extends VBox {
private final List<ItemView> itemViews = new ArrayList<>();
private final Map<String, ItemView> viewsByPluginId = new LinkedHashMap<>();
private final VBox itemBox = new VBox();
private final VBox utilityBox = new VBox();
private final ToggleButton settingsButton = new ToggleButton();
private final Button collapseButton = new Button();
private MainWindow.NavItem selectedItem;
@@ -46,14 +48,26 @@ public final class NavigationRail extends VBox {
public NavigationRail(List<MainWindow.NavItem> items,
Consumer<MainWindow.NavItem> navigator) {
this(items, navigator, () -> { });
}
public NavigationRail(List<MainWindow.NavItem> items,
Consumer<MainWindow.NavItem> navigator,
Runnable openSettings) {
requireFxThread();
this.navigator = Objects.requireNonNull(navigator, "navigator must not be null");
Objects.requireNonNull(openSettings, "openSettings must not be null");
getStyleClass().addAll(Theme.CSS_NAV_BAR, "navigation-rail");
itemBox.getStyleClass().add("navigation-rail-items");
VBox.setVgrow(itemBox, Priority.ALWAYS);
buildSettingsEntry(openSettings);
buildBottomToggle();
utilityBox.setId("navigation-rail-tools");
utilityBox.getStyleClass().add("navigation-rail-tools");
utilityBox.getChildren().addAll(settingsButton, collapseButton);
Separator separator = new Separator();
separator.setId("navigation-rail-separator");
separator.getStyleClass().add(Theme.CSS_NAV_SEP);
@@ -62,7 +76,7 @@ public final class NavigationRail extends VBox {
separator.setPrefHeight(1);
separator.setMaxHeight(1);
separator.setFocusTraversable(false);
getChildren().addAll(itemBox, separator, collapseButton);
getChildren().addAll(itemBox, separator, utilityBox);
expanded.addListener((observable, oldValue, newValue) -> updateAppearance());
setItems(items);
@@ -106,6 +120,18 @@ public final class NavigationRail extends VBox {
requireFxThread();
selection.selectToggle(null);
itemViews.forEach(view -> view.button().getStyleClass().remove(Theme.CSS_NAV_CELL_ACTIVE));
settingsButton.getStyleClass().remove(Theme.CSS_NAV_CELL_ACTIVE);
selectedItem = null;
selectedPluginId = null;
}
public void selectSettings() {
requireFxThread();
selection.selectToggle(settingsButton);
itemViews.forEach(view -> view.button().getStyleClass().remove(Theme.CSS_NAV_CELL_ACTIVE));
if (!settingsButton.getStyleClass().contains(Theme.CSS_NAV_CELL_ACTIVE)) {
settingsButton.getStyleClass().add(Theme.CSS_NAV_CELL_ACTIVE);
}
selectedItem = null;
selectedPluginId = null;
}
@@ -137,6 +163,24 @@ public final class NavigationRail extends VBox {
return view == null ? null : view.tooltip();
}
private void buildSettingsEntry(Runnable openSettings) {
settingsButton.setId("navigation-rail-settings");
settingsButton.getStyleClass().addAll(Theme.CSS_NAV_CELL, "navigation-rail-settings");
settingsButton.setToggleGroup(selection);
settingsButton.setContentDisplay(ContentDisplay.LEFT);
settingsButton.setGraphicTextGap(Theme.S3);
settingsButton.setMinHeight(DesignTokens.ROW_HEIGHT);
settingsButton.setPrefHeight(DesignTokens.ROW_HEIGHT);
settingsButton.setMaxHeight(DesignTokens.ROW_HEIGHT);
settingsButton.setMaxWidth(Double.MAX_VALUE);
settingsButton.setAccessibleText("系统设置");
settingsButton.setFocusTraversable(true);
settingsButton.setOnAction(event -> {
selectSettings();
openSettings.run();
});
}
private void buildBottomToggle() {
collapseButton.setId("navigation-rail-toggle");
collapseButton.getStyleClass().addAll(Theme.CSS_NAV_CELL, "navigation-rail-toggle");
@@ -182,6 +226,7 @@ public final class NavigationRail extends VBox {
private void activate(MainWindow.NavItem item, ToggleButton button) {
selection.selectToggle(button);
settingsButton.getStyleClass().remove(Theme.CSS_NAV_CELL_ACTIVE);
itemViews.forEach(view -> view.button().getStyleClass().remove(Theme.CSS_NAV_CELL_ACTIVE));
if (!button.getStyleClass().contains(Theme.CSS_NAV_CELL_ACTIVE)) {
button.getStyleClass().add(Theme.CSS_NAV_CELL_ACTIVE);
@@ -212,6 +257,10 @@ public final class NavigationRail extends VBox {
collapseButton.setAccessibleText(accessibleText);
collapseButton.setTooltip(new Tooltip(accessibleText));
collapseButton.setAlignment(isExpanded() ? Pos.CENTER_LEFT : Pos.CENTER);
settingsButton.setGraphic(IconFactory.createButtonIcon(AppIcon.SETTINGS, "系统设置"));
settingsButton.setText(isExpanded() ? "系统设置" : null);
settingsButton.setTooltip(isExpanded() ? null : new Tooltip("系统设置"));
settingsButton.setAlignment(isExpanded() ? Pos.CENTER_LEFT : Pos.CENTER);
updateItemAppearance();
}