feature:初步实现主题
This commit is contained in:
@@ -40,6 +40,7 @@ public class Controller implements Initializable {
|
|||||||
private DrawingCanvas drawingCanvas;
|
private DrawingCanvas drawingCanvas;
|
||||||
private PropertyPanel propertyPanelComponent;
|
private PropertyPanel propertyPanelComponent;
|
||||||
private CommandHistory commandHistory;
|
private CommandHistory commandHistory;
|
||||||
|
private ThemeManager themeManager;
|
||||||
Stage stage;
|
Stage stage;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -48,6 +49,13 @@ public class Controller implements Initializable {
|
|||||||
commandHistory = new CommandHistory();
|
commandHistory = new CommandHistory();
|
||||||
commandHistory.setOnHistoryChanged(this::updateUndoRedoButtons);
|
commandHistory.setOnHistoryChanged(this::updateUndoRedoButtons);
|
||||||
|
|
||||||
|
// 初始化主题管理器
|
||||||
|
themeManager = ThemeManager.getInstance();
|
||||||
|
themeManager.setOnThemeChanged(this::applyTheme);
|
||||||
|
|
||||||
|
// 应用初始主题
|
||||||
|
applyTheme();
|
||||||
|
|
||||||
pageListView.setDisable(true);
|
pageListView.setDisable(true);
|
||||||
|
|
||||||
// 添加页面列表选择监听
|
// 添加页面列表选择监听
|
||||||
@@ -680,4 +688,70 @@ public class Controller implements Initializable {
|
|||||||
alert.setContentText(message);
|
alert.setContentText(message);
|
||||||
alert.showAndWait();
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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<String, Theme> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -67,6 +67,18 @@
|
|||||||
</items>
|
</items>
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
|
|
||||||
|
<!-- 主题菜单 -->
|
||||||
|
<MenuButton mnemonicParsing="false" text="主题">
|
||||||
|
<items>
|
||||||
|
<MenuItem mnemonicParsing="false" onAction="#onThemeLight" text="浅色主题" />
|
||||||
|
<MenuItem mnemonicParsing="false" onAction="#onThemeDark" text="深色主题" />
|
||||||
|
<MenuItem mnemonicParsing="false" onAction="#onThemeBlue" text="蓝色主题" />
|
||||||
|
<MenuItem mnemonicParsing="false" onAction="#onThemeGreen" text="绿色主题" />
|
||||||
|
<MenuItem mnemonicParsing="false" onAction="#onThemePurple" text="紫色主题" />
|
||||||
|
<MenuItem mnemonicParsing="false" onAction="#onThemeOrange" text="橙色主题" />
|
||||||
|
</items>
|
||||||
|
</MenuButton>
|
||||||
|
|
||||||
<Label text=" | " />
|
<Label text=" | " />
|
||||||
|
|
||||||
<!-- 退出菜单 -->
|
<!-- 退出菜单 -->
|
||||||
|
|||||||
Reference in New Issue
Block a user