diff --git a/src/main/java/dev/bytevibe/hyperpoint/Controller.java b/src/main/java/dev/bytevibe/hyperpoint/Controller.java index c0fc26b..7486ea1 100644 --- a/src/main/java/dev/bytevibe/hyperpoint/Controller.java +++ b/src/main/java/dev/bytevibe/hyperpoint/Controller.java @@ -40,6 +40,7 @@ public class Controller implements Initializable { private DrawingCanvas drawingCanvas; private PropertyPanel propertyPanelComponent; private CommandHistory commandHistory; + private ThemeManager themeManager; Stage stage; @Override @@ -48,6 +49,13 @@ public class Controller implements Initializable { commandHistory = new CommandHistory(); commandHistory.setOnHistoryChanged(this::updateUndoRedoButtons); + // 初始化主题管理器 + themeManager = ThemeManager.getInstance(); + themeManager.setOnThemeChanged(this::applyTheme); + + // 应用初始主题 + applyTheme(); + pageListView.setDisable(true); // 添加页面列表选择监听 @@ -680,4 +688,70 @@ public class Controller implements Initializable { alert.setContentText(message); alert.showAndWait(); } + + /** + * 应用当前主题到界面 + */ + private void applyTheme() { + if (themeManager == null) { + return; + } + + // 应用菜单栏样式 + VBox menuBarBox = (VBox) scenePane.lookup("VBox"); + if (menuBarBox != null) { + menuBarBox.setStyle(themeManager.getMenuBarStyle()); + } + + // 应用主场景背景 + scenePane.setStyle(themeManager.getMainSceneStyle()); + } + + /** + * 浅色主题 + */ + @FXML + public void onThemeLight(ActionEvent actionEvent) { + themeManager.switchTheme("Light"); + } + + /** + * 深色主题 + */ + @FXML + public void onThemeDark(ActionEvent actionEvent) { + themeManager.switchTheme("Dark"); + } + + /** + * 蓝色主题 + */ + @FXML + public void onThemeBlue(ActionEvent actionEvent) { + themeManager.switchTheme("Blue"); + } + + /** + * 绿色主题 + */ + @FXML + public void onThemeGreen(ActionEvent actionEvent) { + themeManager.switchTheme("Green"); + } + + /** + * 紫色主题 + */ + @FXML + public void onThemePurple(ActionEvent actionEvent) { + themeManager.switchTheme("Purple"); + } + + /** + * 橙色主题 + */ + @FXML + public void onThemeOrange(ActionEvent actionEvent) { + themeManager.switchTheme("Orange"); + } } diff --git a/src/main/java/dev/bytevibe/hyperpoint/Theme.java b/src/main/java/dev/bytevibe/hyperpoint/Theme.java new file mode 100644 index 0000000..d7095c9 --- /dev/null +++ b/src/main/java/dev/bytevibe/hyperpoint/Theme.java @@ -0,0 +1,80 @@ +package dev.bytevibe.hyperpoint; + +import javafx.scene.paint.Color; + +/** + * 主题管理器,管理应用的颜色和样式主题 + */ +public class Theme { + // 主题名称 + private String name; + + // 背景颜色 + private Color backgroundColor; + + // 菜单栏颜色 + private Color menuBarColor; + + // 菜单栏文字颜色 + private Color menuTextColor; + + // 页面背景颜色 + private Color pageBackgroundColor; + + // 边框颜色 + private Color borderColor; + + // 主色调(用于按钮、选中状态等) + private Color primaryColor; + + // 次色调 + private Color secondaryColor; + + public Theme(String name, Color backgroundColor, Color menuBarColor, Color menuTextColor, + Color pageBackgroundColor, Color borderColor, Color primaryColor, Color secondaryColor) { + this.name = name; + this.backgroundColor = backgroundColor; + this.menuBarColor = menuBarColor; + this.menuTextColor = menuTextColor; + this.pageBackgroundColor = pageBackgroundColor; + this.borderColor = borderColor; + this.primaryColor = primaryColor; + this.secondaryColor = secondaryColor; + } + + // Getters and Setters + public String getName() { return name; } + public void setName(String name) { this.name = name; } + + public Color getBackgroundColor() { return backgroundColor; } + public void setBackgroundColor(Color backgroundColor) { this.backgroundColor = backgroundColor; } + + public Color getMenuBarColor() { return menuBarColor; } + public void setMenuBarColor(Color menuBarColor) { this.menuBarColor = menuBarColor; } + + public Color getMenuTextColor() { return menuTextColor; } + public void setMenuTextColor(Color menuTextColor) { this.menuTextColor = menuTextColor; } + + public Color getPageBackgroundColor() { return pageBackgroundColor; } + public void setPageBackgroundColor(Color pageBackgroundColor) { this.pageBackgroundColor = pageBackgroundColor; } + + public Color getBorderColor() { return borderColor; } + public void setBorderColor(Color borderColor) { this.borderColor = borderColor; } + + public Color getPrimaryColor() { return primaryColor; } + public void setPrimaryColor(Color primaryColor) { this.primaryColor = primaryColor; } + + public Color getSecondaryColor() { return secondaryColor; } + public void setSecondaryColor(Color secondaryColor) { this.secondaryColor = secondaryColor; } + + /** + * 转换颜色为十六进制字符串 + */ + public static String colorToHex(Color color) { + return String.format("#%02X%02X%02X", + (int) (color.getRed() * 255), + (int) (color.getGreen() * 255), + (int) (color.getBlue() * 255)); + } +} + diff --git a/src/main/java/dev/bytevibe/hyperpoint/ThemeManager.java b/src/main/java/dev/bytevibe/hyperpoint/ThemeManager.java new file mode 100644 index 0000000..db0491c --- /dev/null +++ b/src/main/java/dev/bytevibe/hyperpoint/ThemeManager.java @@ -0,0 +1,193 @@ +package dev.bytevibe.hyperpoint; + +import javafx.scene.paint.Color; +import java.util.HashMap; +import java.util.Map; + +/** + * 主题管理器,管理和切换应用主题 + */ +public class ThemeManager { + private static final ThemeManager instance = new ThemeManager(); + private Map themes; + private Theme currentTheme; + private Runnable onThemeChanged; + + private ThemeManager() { + themes = new HashMap<>(); + initializeDefaultThemes(); + currentTheme = themes.get("Light"); + } + + /** + * 获取单例实例 + */ + public static ThemeManager getInstance() { + return instance; + } + + /** + * 初始化默认主题 + */ + private void initializeDefaultThemes() { + // 浅色主题 + themes.put("Light", new Theme( + "Light", + Color.web("#FFFFFF"), // 背景颜色 - 白色 + Color.web("#F5F5F5"), // 菜单栏颜色 - 浅灰 + Color.web("#333333"), // 菜单文字 - 深灰 + Color.web("#FFFFFF"), // 页面背景 - 白色 + Color.web("#CCCCCC"), // 边框色 - 浅灰 + Color.web("#007AFF"), // 主色调 - 蓝色 + Color.web("#E8E8E8") // 次色调 - 浅灰 + )); + + // 深色主题 + themes.put("Dark", new Theme( + "Dark", + Color.web("#2B2B2B"), // 背景颜色 - 深灰 + Color.web("#1E1E1E"), // 菜单栏颜色 - 更深灰 + Color.web("#E0E0E0"), // 菜单文字 - 浅灰 + Color.web("#333333"), // 页面背景 - 深灰 + Color.web("#444444"), // 边框色 - 中灰 + Color.web("#0A84FF"), // 主色调 - 亮蓝 + Color.web("#555555") // 次色调 - 中灰 + )); + + // 蓝色主题 + themes.put("Blue", new Theme( + "Blue", + Color.web("#E3F2FD"), // 背景颜色 - 浅蓝 + Color.web("#1976D2"), // 菜单栏颜色 - 蓝色 + Color.web("#FFFFFF"), // 菜单文字 - 白色 + Color.web("#FFFFFF"), // 页面背景 - 白色 + Color.web("#1976D2"), // 边框色 - 蓝色 + Color.web("#1976D2"), // 主色调 - 蓝色 + Color.web("#E3F2FD") // 次色调 - 浅蓝 + )); + + // 绿色主题 + themes.put("Green", new Theme( + "Green", + Color.web("#E8F5E9"), // 背景颜色 - 浅绿 + Color.web("#388E3C"), // 菜单栏颜色 - 绿色 + Color.web("#FFFFFF"), // 菜单文字 - 白色 + Color.web("#FFFFFF"), // 页面背景 - 白色 + Color.web("#388E3C"), // 边框色 - 绿色 + Color.web("#388E3C"), // 主色调 - 绿色 + Color.web("#E8F5E9") // 次色调 - 浅绿 + )); + + // 紫色主题 + themes.put("Purple", new Theme( + "Purple", + Color.web("#F3E5F5"), // 背景颜色 - 浅紫 + Color.web("#7B1FA2"), // 菜单栏颜色 - 紫色 + Color.web("#FFFFFF"), // 菜单文字 - 白色 + Color.web("#FFFFFF"), // 页面背景 - 白色 + Color.web("#7B1FA2"), // 边框色 - 紫色 + Color.web("#7B1FA2"), // 主色调 - 紫色 + Color.web("#F3E5F5") // 次色调 - 浅紫 + )); + + // 橙色主题 + themes.put("Orange", new Theme( + "Orange", + Color.web("#FFE0B2"), // 背景颜色 - 浅橙 + Color.web("#F57C00"), // 菜单栏颜色 - 橙色 + Color.web("#FFFFFF"), // 菜单文字 - 白色 + Color.web("#FFFFFF"), // 页面背景 - 白色 + Color.web("#F57C00"), // 边框色 - 橙色 + Color.web("#F57C00"), // 主色调 - 橙色 + Color.web("#FFE0B2") // 次色调 - 浅橙 + )); + } + + /** + * 获取主题列表 + */ + public String[] getThemeNames() { + return themes.keySet().toArray(new String[0]); + } + + /** + * 获取指定主题 + */ + public Theme getTheme(String name) { + return themes.get(name); + } + + /** + * 切换主题 + */ + public void switchTheme(String themeName) { + Theme theme = themes.get(themeName); + if (theme != null) { + currentTheme = theme; + notifyThemeChanged(); + } + } + + /** + * 获取当前主题 + */ + public Theme getCurrentTheme() { + return currentTheme; + } + + /** + * 设置主题变化回调 + */ + public void setOnThemeChanged(Runnable callback) { + this.onThemeChanged = callback; + } + + /** + * 通知主题已改变 + */ + private void notifyThemeChanged() { + if (onThemeChanged != null) { + onThemeChanged.run(); + } + } + + /** + * 生成菜单栏样式字符串 + */ + public String getMenuBarStyle() { + Theme theme = getCurrentTheme(); + String bgColor = Theme.colorToHex(theme.getMenuBarColor()); + return String.format("-fx-background-color: %s; -fx-text-fill: %s;", + bgColor, Theme.colorToHex(theme.getMenuTextColor())); + } + + /** + * 生成主场景样式字符串 + */ + public String getMainSceneStyle() { + Theme theme = getCurrentTheme(); + String bgColor = Theme.colorToHex(theme.getBackgroundColor()); + return String.format("-fx-background-color: %s;", bgColor); + } + + /** + * 生成页面列表样式字符串 + */ + public String getPageListStyle() { + Theme theme = getCurrentTheme(); + String bgColor = Theme.colorToHex(theme.getPageBackgroundColor()); + String borderColor = Theme.colorToHex(theme.getBorderColor()); + return String.format("-fx-background-color: %s; -fx-border-color: %s; -fx-border-width: 0 1 0 0;", + bgColor, borderColor); + } + + /** + * 生成页面编辑区样式字符串 + */ + public String getPageEditStyle() { + Theme theme = getCurrentTheme(); + String bgColor = Theme.colorToHex(theme.getBackgroundColor()); + return String.format("-fx-background-color: %s; -fx-padding: 10;", bgColor); + } +} + diff --git a/src/main/resources/dev/bytevibe/hyperpoint/main.fxml b/src/main/resources/dev/bytevibe/hyperpoint/main.fxml index 0fbbc08..f68a664 100644 --- a/src/main/resources/dev/bytevibe/hyperpoint/main.fxml +++ b/src/main/resources/dev/bytevibe/hyperpoint/main.fxml @@ -67,6 +67,18 @@ + + + + + + + + + + + +