diff --git a/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java b/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java index e15c3d0..fc1a831 100644 --- a/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java +++ b/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java @@ -43,6 +43,8 @@ public class AppConfig { shortcutKeys.add(createShortcutKey("openConfigItem", ALT_S)); shortcutKeys.add(createShortcutKey("pluginManager", "")); shortcutKeys.add(createShortcutKey("countItem", "")); + shortcutKeys.add(createShortcutKey("aboutItem", "")); + config.setShortcutKey(shortcutKeys); return config; } diff --git a/src/main/java/org/jcnc/jnotepad/app/manager/ApplicationManager.java b/src/main/java/org/jcnc/jnotepad/app/manager/ApplicationManager.java index af42fb0..3ee10fe 100644 --- a/src/main/java/org/jcnc/jnotepad/app/manager/ApplicationManager.java +++ b/src/main/java/org/jcnc/jnotepad/app/manager/ApplicationManager.java @@ -168,6 +168,7 @@ public class ApplicationManager { RootRightSideBarVerticalBoxManager.getInstance().initRootRightSideBarVerticalBox(); // 初始化根布局 RootBorderPaneManager.getInstance().initRootBorderPane(); + } public Pane getRoot() { diff --git a/src/main/java/org/jcnc/jnotepad/common/constants/AppConstants.java b/src/main/java/org/jcnc/jnotepad/common/constants/AppConstants.java index 9cb5f62..4c946b0 100644 --- a/src/main/java/org/jcnc/jnotepad/common/constants/AppConstants.java +++ b/src/main/java/org/jcnc/jnotepad/common/constants/AppConstants.java @@ -10,6 +10,18 @@ import java.util.regex.Pattern; * @author 许轲 */ public class AppConstants { + /** + * 版本号 + */ + public static final String VERSION = "1.0.12"; + /** + * 作者 + */ + public static final String AUTHOR = "JCNC"; + /** + * 软件名称 + */ + public static final String APP_NAME = "JNotepad"; /** * 初始宽度 */ diff --git a/src/main/java/org/jcnc/jnotepad/common/constants/TextConstants.java b/src/main/java/org/jcnc/jnotepad/common/constants/TextConstants.java index 0c8c514..9045874 100644 --- a/src/main/java/org/jcnc/jnotepad/common/constants/TextConstants.java +++ b/src/main/java/org/jcnc/jnotepad/common/constants/TextConstants.java @@ -16,9 +16,13 @@ public class TextConstants { public static final String SAVE_AS = "SAVE_AS"; public static final String RENAME = "RENAME"; public static final String SET = "SET"; + public static final String HELP = "HELP"; public static final String WORD_WRAP = "WORD_WRAP"; public static final String PLUGIN = "PLUGIN"; public static final String MANAGER_PLUGIN = "MANAGER_PLUGIN"; + + public static final String ABOUT = "ABOUT"; + public static final String STATISTICS = "STATISTICS"; public static final String OPEN_CONFIGURATION_FILE = "OPEN_CONFIGURATION_FILE"; public static final String TOP = "TOP"; diff --git a/src/main/java/org/jcnc/jnotepad/ui/titlebar/CustomTitleBar.java b/src/main/java/org/jcnc/jnotepad/ui/titlebar/CustomTitleBar.java index b243079..bec70f6 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/titlebar/CustomTitleBar.java +++ b/src/main/java/org/jcnc/jnotepad/ui/titlebar/CustomTitleBar.java @@ -19,7 +19,7 @@ import javafx.util.Duration; public class CustomTitleBar extends HBox { private static CustomTitleBar instance; - private CustomTitleBar() { + public CustomTitleBar() { // 设置样式和布局 this.setAlignment(Pos.CENTER); diff --git a/src/main/java/org/jcnc/jnotepad/views/manager/RootBorderPaneManager.java b/src/main/java/org/jcnc/jnotepad/views/manager/RootBorderPaneManager.java index 6e18f29..022a4fe 100644 --- a/src/main/java/org/jcnc/jnotepad/views/manager/RootBorderPaneManager.java +++ b/src/main/java/org/jcnc/jnotepad/views/manager/RootBorderPaneManager.java @@ -43,5 +43,6 @@ public class RootBorderPaneManager { rootBorderPane.setTopComponent(RootTopBorderPane.getInstance()); // 主界面的下面,底部边栏 rootBorderPane.setBottomComponent(RootBottomSideBarVerticalBox.getInstance()); + } } diff --git a/src/main/java/org/jcnc/jnotepad/views/manager/RootManager.java b/src/main/java/org/jcnc/jnotepad/views/manager/RootManager.java index 8bdcbdb..5a352f8 100644 --- a/src/main/java/org/jcnc/jnotepad/views/manager/RootManager.java +++ b/src/main/java/org/jcnc/jnotepad/views/manager/RootManager.java @@ -1,7 +1,15 @@ package org.jcnc.jnotepad.views.manager; +import atlantafx.base.controls.Notification; +import atlantafx.base.theme.Styles; +import atlantafx.base.util.Animations; +import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.layout.BorderPane; +import javafx.scene.layout.Region; +import javafx.scene.layout.StackPane; +import javafx.util.Duration; import org.jcnc.jnotepad.exception.AppException; import org.jcnc.jnotepad.views.root.RootBorderPane; @@ -15,7 +23,7 @@ import org.jcnc.jnotepad.views.root.RootBorderPane; public class RootManager { private static RootManager instance = null; - + StackPane rootStackPane; /** * 主布局 */ @@ -65,11 +73,41 @@ public class RootManager { * @param scene 与视图相关联的 JavaFX 场景。 */ public void initScreen(Scene scene) { + rootStackPane = new StackPane(); + // 创建主界面布局 - root = new BorderPane(); + BorderPane root = new BorderPane(); root.setCenter(RootBorderPane.getInstance()); - scene.setRoot(root); + rootStackPane.getChildren().addAll(root); + scene.setRoot(rootStackPane); } + + /** + * 将提示框添加到 StackPane 中。 + * + * @param stackPane 要添加提示框的 StackPane。 + * @param msg 要显示的提示框。 + */ + public void addNotificationToStackPane(StackPane stackPane, Notification msg) { + msg.getStyleClass().addAll(Styles.ACCENT, Styles.ELEVATED_1); + msg.setPrefHeight(Region.USE_PREF_SIZE); + msg.setMaxHeight(Region.USE_PREF_SIZE); + StackPane.setAlignment(msg, Pos.BOTTOM_RIGHT); + StackPane.setMargin(msg, new Insets(5, 10, 35, 0)); + + msg.setOnClose(e -> { + var out = Animations.slideOutUp(msg, Duration.millis(250)); + out.setOnFinished(f -> stackPane.getChildren().remove(msg)); + out.playFromStart(); + }); + + var in = Animations.slideInDown(msg, Duration.millis(250)); + if (!stackPane.getChildren().contains(msg)) { + stackPane.getChildren().add(msg); + } + in.playFromStart(); + } + } diff --git a/src/main/java/org/jcnc/jnotepad/views/manager/TopMenuBarManager.java b/src/main/java/org/jcnc/jnotepad/views/manager/TopMenuBarManager.java index 6b8c845..63d71d0 100644 --- a/src/main/java/org/jcnc/jnotepad/views/manager/TopMenuBarManager.java +++ b/src/main/java/org/jcnc/jnotepad/views/manager/TopMenuBarManager.java @@ -1,13 +1,23 @@ package org.jcnc.jnotepad.views.manager; +import atlantafx.base.controls.Notification; +import atlantafx.base.theme.Styles; import javafx.beans.value.ChangeListener; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.*; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.Clipboard; +import javafx.scene.input.ClipboardContent; import javafx.scene.input.KeyCombination; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; import javafx.stage.Stage; import org.jcnc.jnotepad.app.i18n.UiResourceBundle; import org.jcnc.jnotepad.controller.config.AppConfigController; @@ -22,6 +32,7 @@ import org.slf4j.Logger; import java.util.*; +import static org.jcnc.jnotepad.common.constants.AppConstants.*; import static org.jcnc.jnotepad.common.constants.TextConstants.*; /** @@ -39,6 +50,8 @@ public class TopMenuBarManager { private final Map pluginMenuItems = new HashMap<>(); + private final Map helpMenuItems = new HashMap<>(); + private final Map languageMenuItems = new HashMap<>(); Logger logger = LogUtil.getLogger(this.getClass()); AppConfigController appConfigController = AppConfigController.getInstance(); @@ -66,8 +79,11 @@ public class TopMenuBarManager { toggleLanguageCheck(appConfigController.getLanguage()); // 初始化设置菜单 initSettingMenu(); + // 初始化设置菜单 + initHelpMenu(); // 初始化插件菜单 initPluginMenu(); + // 刷新顶部菜单栏 refreshTopMenuBar(); // 初始化快捷键 @@ -125,6 +141,146 @@ public class TopMenuBarManager { }); registerPluginMenuItem(topMenuBar.getCountItem(), STATISTICS, "countItem", event -> { }); + + //帮助菜单 + registerHelpMenuItem(topMenuBar.getAboutItem(), ABOUT, "aboutItem", event -> { + Stage aboutStage = new Stage(); + String leftBtnText = " 复制并关闭 "; + + String rightBtnText = " 关闭 "; + Button leftBtn = new Button(); + leftBtn.getStyleClass().addAll(Styles.SMALL); + leftBtn.setText(leftBtnText); + + Button rightBtn = new Button(); + rightBtn.getStyleClass().addAll(Styles.SMALL); + rightBtn.setText(rightBtnText); + aboutStage.getIcons().add(UiUtil.getAppIcon()); + aboutStage.setTitle("关于 " + APP_NAME); + BorderPane root = new BorderPane(); + VBox textBox = new VBox(); + VBox iconBox = new VBox(); + ImageView iconImageView = new ImageView(new Image("icon.png")); + iconImageView.setFitWidth(50); + iconImageView.setFitHeight(50); + iconBox.setPadding(new Insets(20)); + + iconBox.getChildren().addAll(iconImageView); + + + textBox.setPadding(new Insets(10)); + + HBox titleBox = new HBox(5); + titleBox.setPadding(new Insets(10, 0, 0, 0)); + + Label titleLabel = new Label(APP_NAME); + titleLabel.setStyle("-fx-font-size: 16px; -fx-font-weight: bold;"); + + Label versionLabel = new Label(VERSION); + versionLabel.setPadding(new Insets(0.5, 0, 0, 0)); + versionLabel.setStyle("-fx-font-size: 15px; -fx-font-weight: bold;"); + + titleBox.getChildren().addAll(titleLabel, versionLabel); + + Label descriptionLabel = new Label(APP_NAME + "是一款自由的集成开发环境。"); + descriptionLabel.setPadding(new Insets(8, 0, 8, 0)); + descriptionLabel.setStyle("-fx-font-size: 14px;"); + + VBox linkBox = new VBox(7); + Hyperlink repositoryLink = new Hyperlink(); + repositoryLink.setText("仓库地址"); + repositoryLink.setOnAction(event1 -> { + openWebsite("https://gitee.com/jcnc-org/JNotepad"); + }); + repositoryLink.setVisited(true); + repositoryLink.setMnemonicParsing(true); + repositoryLink.setStyle("-color-link-fg-visited:-color-accent-fg;"); + + Hyperlink feedBackLink = new Hyperlink(); + feedBackLink.setText("提交反馈"); + feedBackLink.setOnAction(event1 -> { + openWebsite("https://gitee.com/jcnc-org/JNotepad/issues/new/choose"); + }); + feedBackLink.setVisited(true); + feedBackLink.setMnemonicParsing(true); + feedBackLink.setStyle("-color-link-fg-visited:-color-accent-fg;"); + + Hyperlink qLink = new Hyperlink(); + qLink.setText("加入QQ群"); + qLink.setOnAction(event1 -> { + openWebsite("https://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=x3QF-jrJAKTiwu8kV5-giBk2ow66Kzyr&authKey=qNqrQauD7Ra4fXH%2Ftu4ylHXCyrf2EOYj9oMYOmFjlzYmrgDL8Yd0m2qhrQQEBL25&noverify=0&group_code=386279455"); + }); + qLink.setVisited(true); + qLink.setMnemonicParsing(true); + qLink.setStyle("-color-link-fg-visited:-color-accent-fg;"); + + linkBox.getChildren().addAll(repositoryLink, feedBackLink, qLink); + + Label authorLabel = new Label("Copyleft © 2023 " + AUTHOR + "."); + authorLabel.setPadding(new Insets(8, 0, 8, 0)); + authorLabel.setStyle("-fx-font-size: 14px;"); + + textBox.getChildren().addAll(titleBox, descriptionLabel, linkBox, authorLabel); + + HBox bottomBox = new HBox(10); + bottomBox.setPadding(new Insets(7, 15, 7, 0)); + + bottomBox.setAlignment(Pos.BOTTOM_RIGHT); + + leftBtn.setOnAction(event1 -> { + + // 获取 RootManager 的实例 + RootManager rootManager = RootManager.getInstance(); + + // 创建一个新的 Notification + Notification notification = new Notification(); + notification.setMessage("已成功复制软件信息!"); + + // 调用 RootManager 中的方法来显示 Notification + rootManager.addNotificationToStackPane(rootManager.rootStackPane, notification); + + Clipboard clipboard = Clipboard.getSystemClipboard(); + ClipboardContent content = new ClipboardContent(); + String info = "软件名字:" + APP_NAME + "\t" + "版本:" + VERSION; + content.putString(info); + LogUtil.getLogger(this.getClass()).info("软件信息已经复制到剪贴板:" + info); + clipboard.setContent(content); + // 关闭当前的 Stage + Stage currentStage = (Stage) leftBtn.getScene().getWindow(); + currentStage.close(); + + }); + + rightBtn.setOnAction(event1 -> { + // 关闭当前的 Stage + Stage currentStage = (Stage) rightBtn.getScene().getWindow(); + currentStage.close(); + }); + bottomBox.getChildren().addAll(leftBtn, rightBtn); + + root.setLeft(iconBox); + root.setCenter(textBox); + + root.setBottom(bottomBox); + + Scene scene = new Scene(root, 450, 240); + aboutStage.setResizable(false); + aboutStage.setScene(scene); + aboutStage.show(); + + }); + } + + /** + * 打开网页方法 + */ + private void openWebsite(String url) { + try { + LogUtil.getLogger(this.getClass()).info("正在打开---" + url); + java.awt.Desktop.getDesktop().browse(java.net.URI.create(url)); + } catch (java.io.IOException e) { + LogUtil.getLogger(this.getClass()).info("打开失败---" + url); + } } /** @@ -165,6 +321,19 @@ public class TopMenuBarManager { setMenuItem(menuItem, buttonName, eventHandler); } + /** + * 注册帮助菜单项 + * + * @param menuItem 菜单项 + * @param menuItemName 菜单项名称 + * @param buttonName 按钮名称 + * @param eventHandler 操作事件 + */ + public void registerHelpMenuItem(MenuItem menuItem, String menuItemName, String buttonName, EventHandler eventHandler) { + helpMenuItems.put(menuItemName, menuItem); + setMenuItem(menuItem, buttonName, eventHandler); + } + /** * 注册设置菜单项 * @@ -300,6 +469,18 @@ public class TopMenuBarManager { initMenuItems(pluginMenuItems, pluginMenu); } + /** + * 初始化插件菜单 + */ + private void initHelpMenu() { + logger.info("初始化帮助菜单!"); + var helpMenu = topMenuBar.getHelpMenu(); + // 插件菜单 + UiResourceBundle.bindStringProperty(helpMenu.textProperty(), HELP); + + initMenuItems(helpMenuItems, helpMenu); + } + /** * 初始化设置菜单 */ diff --git a/src/main/java/org/jcnc/jnotepad/views/root/RootBorderPane.java b/src/main/java/org/jcnc/jnotepad/views/root/RootBorderPane.java index 34a9b76..2959c36 100644 --- a/src/main/java/org/jcnc/jnotepad/views/root/RootBorderPane.java +++ b/src/main/java/org/jcnc/jnotepad/views/root/RootBorderPane.java @@ -16,7 +16,6 @@ public class RootBorderPane extends AbstractBorderPane { private static final RootBorderPane INSTANCE = new RootBorderPane(); private RootBorderPane() { - } /** diff --git a/src/main/java/org/jcnc/jnotepad/views/root/top/menu/TopMenuBar.java b/src/main/java/org/jcnc/jnotepad/views/root/top/menu/TopMenuBar.java index 550293b..12c0f9f 100644 --- a/src/main/java/org/jcnc/jnotepad/views/root/top/menu/TopMenuBar.java +++ b/src/main/java/org/jcnc/jnotepad/views/root/top/menu/TopMenuBar.java @@ -32,11 +32,16 @@ public class TopMenuBar extends MenuBar { */ private final Menu setMenu = new Menu(); + /** + * 帮助菜单 + */ + private final Menu helpMenu = new Menu(); /// 菜单按钮 /** * 插件菜单 */ private final Menu pluginMenu = new Menu(); + /** * 语言菜单 */ @@ -45,6 +50,11 @@ public class TopMenuBar extends MenuBar { * 新建 */ private final MenuItem newItem = new MenuItem(); + + /** + * 新建 + */ + private final MenuItem aboutItem = new MenuItem(); /** * 打开 */ @@ -116,10 +126,17 @@ public class TopMenuBar extends MenuBar { return setMenu; } + public Menu getHelpMenu() { + return helpMenu; + } + + + public Menu getPluginMenu() { return pluginMenu; } + public Menu getLanguageMenu() { return languageMenu; } @@ -132,6 +149,11 @@ public class TopMenuBar extends MenuBar { return newItem; } + + public MenuItem getAboutItem() { + return aboutItem; + } + public MenuItem getOpenItem() { return openItem; } diff --git a/src/main/resources/i18n/i18n.properties b/src/main/resources/i18n/i18n.properties index 0c89879..f9a767e 100644 --- a/src/main/resources/i18n/i18n.properties +++ b/src/main/resources/i18n/i18n.properties @@ -9,6 +9,8 @@ PLUGIN=插件 CHINESE=中文 title=JNotepad OPEN=打开 +ABOUT=关于 +HELP=帮助 OPEN_CONFIGURATION_FILE=打开配置文件 RENAME=重命名 TOP=窗口置顶 diff --git a/src/main/resources/i18n/i18n_en.properties b/src/main/resources/i18n/i18n_en.properties index e37eab2..f09df8f 100644 --- a/src/main/resources/i18n/i18n_en.properties +++ b/src/main/resources/i18n/i18n_en.properties @@ -4,11 +4,13 @@ NEW_FILE=New File SET=Settings ENGLISH=English STATISTICS=Word Count +ABOUT=About COLUMN=Column PLUGIN=Plugins CHINESE=Chinese title=JNotepad OPEN=Open +HELP=Help OPEN_CONFIGURATION_FILE=Open Configuration File RENAME=Rename TOP=Window Top diff --git a/src/main/resources/i18n/i18n_zh_CN.properties b/src/main/resources/i18n/i18n_zh_CN.properties index 1fbb8bb..e9d8ba7 100644 --- a/src/main/resources/i18n/i18n_zh_CN.properties +++ b/src/main/resources/i18n/i18n_zh_CN.properties @@ -9,6 +9,8 @@ PLUGIN=插件 CHINESE=中文 title=JNotepad OPEN=打开 +HELP=帮助 +ABOUT=关于 OPEN_CONFIGURATION_FILE=打开配置文件 RENAME=重命名 TOP=窗口置顶