diff --git a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java index a8a74ad21c2c4b7ba9d4f6d8aca54cf4343f3cb0..c424d35e51b4a95c69501e0f2176d1213a7bf3d6 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java +++ b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java @@ -7,6 +7,7 @@ import org.jcnc.jnotepad.controller.event.handler.menubar.OpenFile; import org.jcnc.jnotepad.model.entity.Cache; import java.io.File; +import java.util.Collections; import java.util.List; /** @@ -40,7 +41,12 @@ public class Controller implements ControllerAble { public void openAssociatedFileAndCreateTextArea(List rawParameters) { // 获取上次打开的页面 Cache cache = CACHE_MANAGER.getCache("tabs", "centerTabs"); - List fileTab = (List) cache.getCacheData(); + List fileTab; + if (cache == null) { + fileTab = Collections.emptyList(); + } else { + fileTab = (List) cache.getCacheData(); + } fileTab.forEach(filePath -> new OpenFile().openFile(new File(filePath))); if (!rawParameters.isEmpty()) { diff --git a/src/main/java/org/jcnc/jnotepad/ui/module/LineNumberTextArea.java b/src/main/java/org/jcnc/jnotepad/ui/module/LineNumberTextArea.java index dfd5905a6f95e0da1e7ad86e2c2e40dd45cc302f..908b4138e54d138d17c367dec536710562cab836 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/module/LineNumberTextArea.java +++ b/src/main/java/org/jcnc/jnotepad/ui/module/LineNumberTextArea.java @@ -59,7 +59,7 @@ public class LineNumberTextArea extends CodeArea { // 用于整体文本处理(文本块) "//[^\n]*" + "|" + "/\\*(.|\\R)*?\\*/" // 用于可见段落处理(逐行) - + "|" + "/\\*[^\\v]*" + "|" + "^\\h*\\*([^\\v]*|/)"; + + "|" + "/\\*[^\\v]*" + "|" + "^\\h*\\*([^\\v]*|/)"; /** @@ -149,18 +149,16 @@ public class LineNumberTextArea extends CodeArea { static class VisibleParagraphStyler implements Consumer>> { private final GenericStyledArea area; - private final Function> computeStyles; + private final Function> computeStyles; private int prevParagraph, prevTextLength; - public VisibleParagraphStyler( GenericStyledArea area, Function> computeStyles ) - { + public VisibleParagraphStyler(GenericStyledArea area, Function> computeStyles) { this.computeStyles = computeStyles; this.area = area; } @Override - public void accept( ListModification> lm ) - { + public void accept(ListModification> lm) { if (lm.getAddedSize() > 0) { Platform.runLater(() -> { int paragraph = Math.min(area.firstVisibleParToAllParIndex() + lm.getFrom(), area.getParagraphs().size() - 1); diff --git a/src/main/java/org/jcnc/jnotepad/ui/setstage/AbstractPaneStage.java b/src/main/java/org/jcnc/jnotepad/ui/setstage/AbstractPaneStage.java new file mode 100644 index 0000000000000000000000000000000000000000..17291a81fe9bf1c8ef9835eb14070aa9185bb84d --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/ui/setstage/AbstractPaneStage.java @@ -0,0 +1,58 @@ +package org.jcnc.jnotepad.ui.setstage; + +import javafx.scene.Scene; +import javafx.scene.image.Image; +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; + +/** + * 抽象窗格舞台 + * + * @author gewuyou + */ +public abstract class AbstractPaneStage extends BorderPane { + private final Stage stage = new Stage(); + + /** + * 获取舞台图标 + * + * @return 舞台图标 + */ + protected abstract Image getStageIcon(); + + /** + * 获取舞台标题 + * + * @return 舞台标题 + */ + protected abstract String getStageTitle(); + + /** + * 获取自定义舞台 + * + * @return 舞台 + */ + protected abstract Scene getCustomizationScene(); + + /** + * 初始化方法 + */ + protected abstract void initialize(); + + /** + * 自定义启动方法 + * + * @param stage 自定义舞台 + */ + public abstract void run(Stage stage); + + /** + * 启动方法 + */ + public void run() { + stage.getIcons().add(getStageIcon()); + stage.setTitle(getStageTitle()); + stage.setScene(getCustomizationScene()); + stage.show(); + } +} diff --git a/src/main/java/org/jcnc/jnotepad/ui/setstage/HelpPaneStage.java b/src/main/java/org/jcnc/jnotepad/ui/setstage/HelpPaneStage.java new file mode 100644 index 0000000000000000000000000000000000000000..5ad3a3a506c59ae14e35c32798206ad654d369bd --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/ui/setstage/HelpPaneStage.java @@ -0,0 +1,209 @@ +package org.jcnc.jnotepad.ui.setstage; + +import atlantafx.base.controls.Notification; +import atlantafx.base.theme.Styles; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Hyperlink; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.Clipboard; +import javafx.scene.input.ClipboardContent; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import org.jcnc.jnotepad.util.LogUtil; +import org.jcnc.jnotepad.util.UiUtil; +import org.jcnc.jnotepad.views.manager.RootManager; + +import static org.jcnc.jnotepad.common.constants.AppConstants.*; + +/** + * 帮助页面 + * + * @author gewuyou + */ +public class HelpPaneStage extends AbstractPaneStage { + public HelpPaneStage() { + initialize(); + } + + private static Button getButton(String text, EventHandler eventEventHandler) { + Button button = new Button(text); + button.getStyleClass().addAll(Styles.SMALL); + button.setOnAction(eventEventHandler); + return button; + } + + /** + * 获取舞台图标 + * + * @return 舞台图标 + */ + @Override + protected Image getStageIcon() { + return UiUtil.getAppIcon(); + } + + /** + * 获取舞台标题 + * + * @return 舞台标题 + */ + @Override + protected String getStageTitle() { + return "关于 " + APP_NAME; + } + + /** + * 获取自定义舞台 + * + * @return 舞台 + */ + @Override + protected Scene getCustomizationScene() { + return new Scene(this, 450, 240); + } + + /** + * 初始化方法 + */ + @Override + protected void initialize() { + initBottomBox(); + + initIconBox(); + + initTextBox(); + } + + private void initTextBox() { + VBox textBox = new VBox(); + 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 = getLabel(APP_NAME + "是一款自由的集成开发环境。", new Insets(8, 0, 8, 0)); + + VBox linkBox = new VBox(7); + Hyperlink repositoryLink = getHyperlink("仓库地址", "https://gitee.com/jcnc-org/JNotepad"); + Hyperlink feedBackLink = getHyperlink("提交反馈", "https://gitee.com/jcnc-org/JNotepad/issues/new/choose"); + Hyperlink qLink = getHyperlink("加入QQ群", "https://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=x3QF-jrJAKTiwu8kV5-giBk2ow66Kzyr&authKey=qNqrQauD7Ra4fXH%2Ftu4ylHXCyrf2EOYj9oMYOmFjlzYmrgDL8Yd0m2qhrQQEBL25&noverify=0&group_code=386279455"); + linkBox.getChildren().addAll(repositoryLink, feedBackLink, qLink); + + Label authorLabel = getLabel("Copyleft © 2023 " + AUTHOR + ".", new Insets(8, 0, 8, 0)); + textBox.getChildren().addAll(titleBox, descriptionLabel, linkBox, authorLabel); + this.setCenter(textBox); + } + + private void initIconBox() { + 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); + this.setLeft(iconBox); + } + + private void initBottomBox() { + HBox bottomBox = new HBox(10); + bottomBox.setPadding(new Insets(7, 15, 7, 0)); + + bottomBox.setAlignment(Pos.BOTTOM_RIGHT); + + Button leftBtn = getButton(" 复制并关闭 ", event -> { + // 获取 RootManager 的实例 + RootManager rootManager = RootManager.getInstance(); + + // 创建一个新的 Notification + Notification notification = new Notification(); + notification.setMessage("已成功复制软件信息!"); + + // 调用 RootManager 中的方法来显示 Notification + rootManager.addNotificationToStackPane(rootManager.getRootStackPane(), 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) ((Button) event.getSource()).getScene().getWindow(); + currentStage.close(); + + }); + Button rightBtn = getButton(" 关闭 ", event -> { + // 关闭当前的 Stage + Stage currentStage = (Stage) ((Button) event.getSource()).getScene().getWindow(); + currentStage.close(); + }); + bottomBox.getChildren().addAll(leftBtn, rightBtn); + this.setBottom(bottomBox); + } + + private Label getLabel(String text, Insets insets) { + Label label = new Label(text); + label.setPadding(insets); + label.setStyle("-fx-font-size: 14px;"); + return label; + } + + /** + * 获取超链接 + * + * @param text 链接文本 + * @param url 链接 + * @return 超链接 + */ + private Hyperlink getHyperlink(String text, String url) { + Hyperlink hyperlink = new Hyperlink(); + hyperlink.setText(text); + hyperlink.setOnAction(event -> openWebsite(url)); + hyperlink.setVisited(true); + hyperlink.setMnemonicParsing(true); + hyperlink.setStyle("-color-link-fg-visited:-color-accent-fg;"); + return hyperlink; + } + + /** + * 自定义启动方法 + * + * @param stage 舞台 + */ + @Override + public void run(Stage stage) { + stage.getIcons().add(getStageIcon()); + stage.setTitle(getStageTitle()); + stage.setScene(getCustomizationScene()); + stage.setResizable(false); + stage.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); + } + } +} diff --git a/src/main/java/org/jcnc/jnotepad/ui/pluginstage/CustomSplitPane.java b/src/main/java/org/jcnc/jnotepad/ui/setstage/pluginstage/CustomSplitPane.java similarity index 97% rename from src/main/java/org/jcnc/jnotepad/ui/pluginstage/CustomSplitPane.java rename to src/main/java/org/jcnc/jnotepad/ui/setstage/pluginstage/CustomSplitPane.java index 73fd2cd17838ac826f7039bd383c80215f2705b1..508bc5f23d9bd162bfd02b6ae2138cce399f2ecb 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/pluginstage/CustomSplitPane.java +++ b/src/main/java/org/jcnc/jnotepad/ui/setstage/pluginstage/CustomSplitPane.java @@ -1,4 +1,4 @@ -package org.jcnc.jnotepad.ui.pluginstage; +package org.jcnc.jnotepad.ui.setstage.pluginstage; import javafx.geometry.Orientation; import javafx.scene.control.SplitPane; diff --git a/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java b/src/main/java/org/jcnc/jnotepad/ui/setstage/pluginstage/PluginManagementPane.java similarity index 93% rename from src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java rename to src/main/java/org/jcnc/jnotepad/ui/setstage/pluginstage/PluginManagementPane.java index 90826bfb1d09ad87b2498f6aa51c898c79088771..9ede60f1ea63f464c16492fc7ac3ac0133c54177 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java +++ b/src/main/java/org/jcnc/jnotepad/ui/setstage/pluginstage/PluginManagementPane.java @@ -1,4 +1,4 @@ -package org.jcnc.jnotepad.ui.pluginstage; +package org.jcnc.jnotepad.ui.setstage.pluginstage; import atlantafx.base.controls.Tile; import atlantafx.base.controls.ToggleSwitch; @@ -8,6 +8,7 @@ import javafx.beans.property.BooleanProperty; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; +import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.MenuItem; import javafx.scene.control.ScrollPane; @@ -27,8 +28,10 @@ import org.commonmark.renderer.html.HtmlRenderer; import org.jcnc.jnotepad.model.entity.PluginDescriptor; import org.jcnc.jnotepad.plugin.manager.PluginManager; import org.jcnc.jnotepad.ui.module.CustomSetButton; +import org.jcnc.jnotepad.ui.setstage.AbstractPaneStage; import org.jcnc.jnotepad.util.LogUtil; import org.jcnc.jnotepad.util.PopUpUtil; +import org.jcnc.jnotepad.util.UiUtil; import org.slf4j.Logger; import java.awt.*; @@ -49,7 +52,7 @@ import java.util.Map; * * @author luke */ -public class PluginManagementPane extends BorderPane { +public class PluginManagementPane extends AbstractPaneStage { PluginManager pluginManager = PluginManager.getInstance(); /** @@ -78,11 +81,11 @@ public class PluginManagementPane extends BorderPane { public PluginManagementPane() { initialize(); } - /** * 初始化插件管理面板。 */ - private void initialize() { + @Override + protected void initialize() { // 初始化插件临时集合 pluginManager.initializeTemporaryPluginDescriptors(); // 创建选项卡面板 @@ -179,6 +182,17 @@ public class PluginManagementPane extends BorderPane { this.setBottom(bottomBox); } + /** + * 自定义启动方法 + * + * @param stage 舞台 + */ + @Override + public void run(Stage stage) { + // 在此添加自定义逻辑 + stage.show(); + } + /** * 创建包含插件列表的VBox,并将其包装在滚动面板中。 * @@ -420,4 +434,34 @@ public class PluginManagementPane extends BorderPane { }); return authorLink; } + + /** + * 获取舞台图标 + * + * @return 舞台图标 + */ + @Override + protected Image getStageIcon() { + return UiUtil.getAppIcon(); + } + + /** + * 获取舞台标题 + * + * @return 舞台标题 + */ + @Override + protected String getStageTitle() { + return "插件管理"; + } + + /** + * 获取舞台 + * + * @return 舞台 + */ + @Override + protected Scene getCustomizationScene() { + return new Scene(this, 900, 600); + } } diff --git a/src/main/java/org/jcnc/jnotepad/views/manager/AbstractManager.java b/src/main/java/org/jcnc/jnotepad/views/manager/AbstractManager.java new file mode 100644 index 0000000000000000000000000000000000000000..52371060505f61a05f3577b28fea054cae55f8b0 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/views/manager/AbstractManager.java @@ -0,0 +1,22 @@ +package org.jcnc.jnotepad.views.manager; + +import java.util.List; + +/** + * 抽象管理类 + * + * @author gewuyou + */ +public abstract class AbstractManager { + + /** + * 获取节点列表 + * + * @return 节点列表 + */ + public abstract List getNodeList(); + + public void registerNode(T node) { + getNodeList().add(node); + } +} 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 5a352f83c1aece177dd941cee61e309992fb03bc..b72f00321fa4cd5c1334b167277e4f01c4e30ee0 100644 --- a/src/main/java/org/jcnc/jnotepad/views/manager/RootManager.java +++ b/src/main/java/org/jcnc/jnotepad/views/manager/RootManager.java @@ -76,7 +76,6 @@ public class RootManager { rootStackPane = new StackPane(); // 创建主界面布局 - BorderPane root = new BorderPane(); root.setCenter(RootBorderPane.getInstance()); rootStackPane.getChildren().addAll(root); @@ -110,4 +109,7 @@ public class RootManager { in.playFromStart(); } + public StackPane getRootStackPane() { + return rootStackPane; + } } diff --git a/src/main/java/org/jcnc/jnotepad/views/manager/SidebarToolBarManager.java b/src/main/java/org/jcnc/jnotepad/views/manager/SidebarToolBarManager.java index 7a94012273bde5547ec5ff9b78ec2f22d43c441a..054e59040988f6e75f37ca1d56f701ba6ee39def 100644 --- a/src/main/java/org/jcnc/jnotepad/views/manager/SidebarToolBarManager.java +++ b/src/main/java/org/jcnc/jnotepad/views/manager/SidebarToolBarManager.java @@ -1,9 +1,10 @@ package org.jcnc.jnotepad.views.manager; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.scene.control.Button; +import javafx.scene.Node; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; import org.jcnc.jnotepad.controller.event.handler.setting.SetBtn; +import org.jcnc.jnotepad.views.manager.builder.SideBarButtonBuilder; import org.jcnc.jnotepad.views.root.left.sidebar.tools.SidebarToolBar; import java.util.ArrayList; @@ -14,13 +15,13 @@ import java.util.List; * * @author gewuyou */ -public class SidebarToolBarManager { +public class SidebarToolBarManager extends AbstractManager { private static final SidebarToolBarManager INSTANCE = new SidebarToolBarManager(); /** * 工具栏 */ SidebarToolBar sidebarToolBar = SidebarToolBar.getInstance(); - List