From efe7747cb34bab95013263e9df112d7e0c46c40b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E8=BD=B2?= Date: Sat, 23 Sep 2023 09:25:08 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E4=B8=93=E5=B1=9E?= =?UTF-8?q?=E4=BA=8E=E6=AF=8F=E4=B8=AA=E6=8F=92=E4=BB=B6=E7=9A=84CustomSpl?= =?UTF-8?q?itPane=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/pluginstage/PluginManagementPane.java | 90 ++++++++++++++----- 1 file changed, 69 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java b/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java index 2c5b3e9..b32a0cd 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java +++ b/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java @@ -5,12 +5,14 @@ import atlantafx.base.controls.ToggleSwitch; import atlantafx.base.theme.PrimerLight; import javafx.application.Application; import javafx.scene.Node; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.Tab; -import javafx.scene.control.TabPane; +import javafx.scene.control.*; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.scene.shape.Circle; +import javafx.scene.shape.StrokeType; import org.jcnc.jnotepad.util.LogUtil; import org.slf4j.Logger; @@ -26,6 +28,7 @@ import java.util.Map; */ public class PluginManagementPane extends BorderPane { + public static int ICON_SIZE = 40; Logger logger = LogUtil.getLogger(this.getClass()); @@ -66,8 +69,7 @@ public class PluginManagementPane extends BorderPane { marketTabContent.setCenter(customSplitPane); // 获取插件列表 - var box = getBox(); - customSplitPane.setLeftContent(box); + customSplitPane.setLeftContent(getScrollPane()); // 创建示例按钮并添加到已安装和设置选项卡中 installedTabContent.setCenter(new Button("2")); @@ -86,20 +88,46 @@ public class PluginManagementPane extends BorderPane { } /** - * 创建包含插件列表的VBox。 + * 创建包含插件列表的VBox,并将其包装在滚动面板中。 * - * @return 包含插件列表的VBox + * @return 包含插件列表的滚动面板 */ - private VBox getBox() { + private ScrollPane getScrollPane() { // 创建示例插件列表项 - var tile1 = createTile("运行插件", "这是一个运行插件\t\t\t\t\t\t\t "); - var tile2 = createTile("终端插件", "这是一个终端插件"); - var tile3 = createTile("构建插件", "这是一个构建插件"); + var image1 = new Image("icon.png"); + var tile1 = createTile("运行插件", "这是一个运行插件\t\t\t\t\t\t", image1); + + var image2 = new Image("icon.png"); + var tile2 = createTile("终端插件", "这是一个终端插件", image2); + + var image3 = new Image("icon.png"); + var tile3 = createTile("构建插件", "这是一个构建插件", image3); + + var image4 = new Image("icon.png"); + var tile4 = createTile("1", "这是一个构建插件", image4); + + var image5 = new Image("icon.png"); + var tile5 = createTile("2", "这是一个构建插件", image5); + + var image6 = new Image("icon.png"); + var tile6 = createTile("4", "这是一个构建插件", image6); + + var image7 = new Image("icon.png"); + var tile7 = createTile("5", "这是一个构建插件", image7); // 创建VBox并将插件列表项添加到其中 - var box = new VBox(tile1, tile2, tile3); + var box = new VBox(tile1, tile2, tile3, tile4, tile5, tile6, tile7); + + // 创建滚动面板并将VBox设置为其内容 + var scrollPane = new ScrollPane(box); - return box; + // 设置滚动面板的宽度适应父容器 + scrollPane.setFitToWidth(true); + // 隐藏滚动条 + scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); + scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); + + return scrollPane; } /** @@ -107,39 +135,59 @@ public class PluginManagementPane extends BorderPane { * * @param title 插件标题 * @param description 插件描述 + * @param image 插件图标 * @return 创建的插件列表项Tile */ - private Tile createTile(String title, String description) { + private Tile createTile(String title, String description, Image image) { + // 创建一个title var tile = new Tile(title, description); + // 创建一个按钮 var tgl = new ToggleSwitch(); + // 创建一个图标 + ImageView icon = new ImageView(image); + // 指定要缩放的固定像素大小 + double iconSize = ICON_SIZE; + + // 设置图像视图的宽度和高度,以便等比例缩放到指定像素大小 + icon.setFitWidth(iconSize); + icon.setFitHeight(iconSize); + + // 设置Tile的图标 + tile.setGraphic(icon); + // 设置Tile的操作和操作处理程序 tile.setAction(tgl); tile.setActionHandler(() -> { customSplitPane.setRightContent(tileContentMap.get(tile)); logger.info("点击了" + tile); - }); // 创建专属的customSplitPane内容 var content = createCustomSplitPaneContent(title); - // 将内容与Tile关联起来 tileContentMap.put(tile, content); return tile; } + /** * 创建专属于每个插件的CustomSplitPane内容。 * - * @param title 插件标题 + * @param titleName 插件标题 * @return 创建的CustomSplitPane内容 */ - private Node createCustomSplitPaneContent(String title) { - // TODO: 2023/9/23 未完成 - return new Label("详情" + title); + private Node createCustomSplitPaneContent(String titleName) { + VBox content = new VBox(); + + Label titleLabel = new Label(titleName); + Label descriptionLabel = new Label("插件描述插件描述插件描述"); + + + content.getChildren().addAll(titleLabel, descriptionLabel); + return content; } } -- Gitee From 7bf7065ca792e4e5d7ce1bd4e2297c3d129ae016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E8=BD=B2?= Date: Sat, 23 Sep 2023 10:26:35 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E5=B8=83=E5=B1=80=E5=92=8C=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/module-info.java | 1 + .../ui/pluginstage/PluginManagementPane.java | 75 ++++++++++++++---- src/main/resources/plug.png | Bin 0 -> 10303 bytes 3 files changed, 59 insertions(+), 17 deletions(-) create mode 100644 src/main/resources/plug.png diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 63ed10b..56f1293 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -16,6 +16,7 @@ module org.jcnc.jnotepad { requires org.kordamp.ikonli.javafx; requires org.kordamp.ikonli.antdesignicons; requires richtextfx.fat; + requires java.desktop; exports org.jcnc.jnotepad; exports org.jcnc.jnotepad.model.enums; exports org.jcnc.jnotepad.app.config; diff --git a/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java b/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java index b32a0cd..c92718a 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java +++ b/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java @@ -2,20 +2,23 @@ package org.jcnc.jnotepad.ui.pluginstage; import atlantafx.base.controls.Tile; import atlantafx.base.controls.ToggleSwitch; -import atlantafx.base.theme.PrimerLight; -import javafx.application.Application; +import atlantafx.base.theme.Styles; +import javafx.geometry.Insets; import javafx.scene.Node; + +import java.awt.Desktop; + import javafx.scene.control.*; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; -import javafx.scene.paint.Color; -import javafx.scene.shape.Circle; -import javafx.scene.shape.StrokeType; +import javafx.scene.text.Text; import org.jcnc.jnotepad.util.LogUtil; import org.slf4j.Logger; +import java.net.URI; import java.util.HashMap; import java.util.Map; @@ -50,7 +53,7 @@ public class PluginManagementPane extends BorderPane { TabPane tabPane = new TabPane(); // 创建市场、已安装和设置选项卡 - Tab marketTab = new Tab("市场"); + Tab marketTab = new Tab("发现"); Tab installedTab = new Tab("已安装"); Tab myTab = new Tab("设置"); @@ -94,25 +97,25 @@ public class PluginManagementPane extends BorderPane { */ private ScrollPane getScrollPane() { // 创建示例插件列表项 - var image1 = new Image("icon.png"); + var image1 = new Image("plug.png"); var tile1 = createTile("运行插件", "这是一个运行插件\t\t\t\t\t\t", image1); - var image2 = new Image("icon.png"); + var image2 = new Image("plug.png"); var tile2 = createTile("终端插件", "这是一个终端插件", image2); - var image3 = new Image("icon.png"); + var image3 = new Image("plug.png"); var tile3 = createTile("构建插件", "这是一个构建插件", image3); - var image4 = new Image("icon.png"); + var image4 = new Image("plug.png"); var tile4 = createTile("1", "这是一个构建插件", image4); - var image5 = new Image("icon.png"); + var image5 = new Image("plug.png"); var tile5 = createTile("2", "这是一个构建插件", image5); - var image6 = new Image("icon.png"); + var image6 = new Image("plug.png"); var tile6 = createTile("4", "这是一个构建插件", image6); - var image7 = new Image("icon.png"); + var image7 = new Image("plug.png"); var tile7 = createTile("5", "这是一个构建插件", image7); // 创建VBox并将插件列表项添加到其中 @@ -180,13 +183,51 @@ public class PluginManagementPane extends BorderPane { * @return 创建的CustomSplitPane内容 */ private Node createCustomSplitPaneContent(String titleName) { - VBox content = new VBox(); + VBox content = new VBox(8); + content.setPadding(new Insets(10)); + var titleLabel = new Text(titleName); + titleLabel.getStyleClass().addAll(Styles.TITLE_1); + + var authorBox = new HBox(10); + var author = new Text("JCNC团队"); + var authorLink = new Hyperlink("插件仓库地址"); + authorLink.setVisited(true); + authorLink.setStyle("-fx-text-fill: blue; -fx-visited-link-color: blue;"); + authorLink.setOnAction(event -> { + // 定义要打开的链接 + String url = "https://gitee.com/jcnc-org/JNotepad"; + + try { + // 创建URI对象 + URI uri = new URI(url); + + // 检查系统是否支持Desktop类 + if (Desktop.isDesktopSupported()) { + Desktop desktop = Desktop.getDesktop(); + + // 检查是否支持浏览器启动 + if (desktop.isSupported(Desktop.Action.BROWSE)) { + // 打开默认浏览器并访问链接 + desktop.browse(uri); + } else { + logger.info("系统不支持浏览器启动操作!"); + } + } else { + logger.info("系统不支持Desktop类!"); + } + } catch (Exception e) { + logger.info("启动" + authorLink + "失败!"); + } + }); + + authorBox.getChildren().addAll(author, authorLink); + + - Label titleLabel = new Label(titleName); - Label descriptionLabel = new Label("插件描述插件描述插件描述"); + var descriptionLabel = new Text("插件描述插件描述插件描述"); - content.getChildren().addAll(titleLabel, descriptionLabel); + content.getChildren().addAll(titleLabel, authorBox, descriptionLabel); return content; } diff --git a/src/main/resources/plug.png b/src/main/resources/plug.png new file mode 100644 index 0000000000000000000000000000000000000000..68b925df731c9c302471b890cb6e6fbc03f6f1fe GIT binary patch literal 10303 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 Rvs(ZF002ovPDHLkV1mhvJLdoZ literal 0 HcmV?d00001 -- Gitee From b5b5cb060683ada057b2306544a312b9954c5f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E8=BD=B2?= Date: Sat, 23 Sep 2023 11:50:21 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 13 ++ src/main/java/module-info.java | 4 + .../ui/pluginstage/PluginManagementPane.java | 149 +++++++++++++++--- .../views/root/top/menu/TopMenuBar.java | 2 +- 4 files changed, 145 insertions(+), 23 deletions(-) diff --git a/pom.xml b/pom.xml index f9d8aa1..df454d8 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,19 @@ system ${project.basedir}/libs/richtextfx-fat-0.11.1.jar + + + org.commonmark + commonmark + 0.21.0 + + + + org.openjfx + javafx-web + ${javafx.version} + + diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 56f1293..dd4e960 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -17,6 +17,10 @@ module org.jcnc.jnotepad { requires org.kordamp.ikonli.antdesignicons; requires richtextfx.fat; requires java.desktop; + requires org.commonmark; + requires javafx.web; + + exports org.jcnc.jnotepad; exports org.jcnc.jnotepad.model.enums; exports org.jcnc.jnotepad.app.config; diff --git a/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java b/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java index c92718a..3a0566e 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java +++ b/src/main/java/org/jcnc/jnotepad/ui/pluginstage/PluginManagementPane.java @@ -5,9 +5,12 @@ import atlantafx.base.controls.ToggleSwitch; import atlantafx.base.theme.Styles; import javafx.geometry.Insets; import javafx.scene.Node; - -import java.awt.Desktop; - +import javafx.scene.control.Button; +import javafx.scene.web.WebEngine; +import javafx.scene.web.WebView; +import org.commonmark.parser.Parser; +import org.commonmark.renderer.html.HtmlRenderer; +import javafx.scene.control.ScrollPane; import javafx.scene.control.*; import javafx.scene.image.Image; import javafx.scene.image.ImageView; @@ -18,7 +21,11 @@ import javafx.scene.text.Text; import org.jcnc.jnotepad.util.LogUtil; import org.slf4j.Logger; +import java.awt.*; +import java.io.IOException; import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; @@ -31,11 +38,24 @@ import java.util.Map; */ public class PluginManagementPane extends BorderPane { + /** + * 图标大小常量 + */ public static int ICON_SIZE = 40; - Logger logger = LogUtil.getLogger(this.getClass()); + /** + * 日志记录器 + */ + Logger logger = LogUtil.getLogger(this.getClass()); + /** + * 自定义分割面板 + */ private CustomSplitPane customSplitPane; + + /** + * 用于存储Tile与其内容节点的映射关系 + */ private final Map tileContentMap = new HashMap<>(); /** @@ -50,10 +70,10 @@ public class PluginManagementPane extends BorderPane { */ private void init() { // 创建选项卡面板 - TabPane tabPane = new TabPane(); + TabPane rootTabPane = new TabPane(); // 创建市场、已安装和设置选项卡 - Tab marketTab = new Tab("发现"); + Tab marketTab = new Tab("市场"); Tab installedTab = new Tab("已安装"); Tab myTab = new Tab("设置"); @@ -75,8 +95,8 @@ public class PluginManagementPane extends BorderPane { customSplitPane.setLeftContent(getScrollPane()); // 创建示例按钮并添加到已安装和设置选项卡中 - installedTabContent.setCenter(new Button("2")); - myTabContent.setCenter(new Button("3")); + installedTabContent.setCenter(new Button("已安装")); + myTabContent.setCenter(new Button("设置")); // 将选项卡内容设置到选项卡中 marketTab.setContent(marketTabContent); @@ -84,10 +104,10 @@ public class PluginManagementPane extends BorderPane { myTab.setContent(myTabContent); // 将选项卡添加到选项卡面板中 - tabPane.getTabs().addAll(marketTab, installedTab, myTab); + rootTabPane.getTabs().addAll(marketTab, installedTab, myTab); // 将选项卡面板设置为插件管理面板的中心内容 - this.setCenter(tabPane); + this.setCenter(rootTabPane); } /** @@ -175,7 +195,6 @@ public class PluginManagementPane extends BorderPane { return tile; } - /** * 创建专属于每个插件的CustomSplitPane内容。 * @@ -190,6 +209,102 @@ public class PluginManagementPane extends BorderPane { var authorBox = new HBox(10); var author = new Text("JCNC团队"); + var authorLink = getAuthorLink(); + authorBox.getChildren().addAll(author, authorLink); + + var state = new Text("未启用"); + + var main = new VBox(10); + + // 创建TabPane并添加标签页 + TabPane tabPane = new TabPane(); + + Tab detailsTab = new Tab("细节"); + detailsTab.setClosable(false); + Tab featuresTab = new Tab("实现功能"); + featuresTab.setClosable(false); + Tab changelogTab = new Tab("更新日志"); + changelogTab.setClosable(false); + + // 在标签页中添加内容 + VBox detailsContent = new VBox(10); + + // 创建一个WebView来显示Markdown内容 + WebView webView = new WebView(); + WebEngine engine = webView.getEngine(); + + // 从外部文件加载Markdown内容 + String markdownContent = loadMarkdownFromFile("README.md"); + String htmlContent = markdownToHtml(markdownContent); + + // 加载HTML内容到WebView + engine.loadContent(htmlContent); + // 将WebView添加到detailsContent + detailsContent.getChildren().addAll(webView); + + VBox featuresContent = new VBox(10); + VBox changelogContent = new VBox(10); + + detailsTab.setContent(detailsContent); + featuresTab.setContent(featuresContent); + changelogTab.setContent(changelogContent); + + tabPane.getTabs().addAll(detailsTab, featuresTab, changelogTab); + + main.getChildren().addAll(tabPane); + + content.getChildren().addAll(titleLabel, authorBox, state, main); + + // 将内容包装在滚动面板中 + ScrollPane scrollPane = new ScrollPane(content); + scrollPane.setFitToWidth(true); + scrollPane.setFitToHeight(true); + + return scrollPane; + } + + /** + * 将Markdown内容转换为HTML格式。 + * + * @param markdownContent Markdown格式的内容 + * @return HTML格式的内容 + */ + private String markdownToHtml(String markdownContent) { + // 创建Markdown解析器 + Parser parser = Parser.builder().build(); + + // 解析Markdown内容 + + org.commonmark.node.Node document = parser.parse(markdownContent); + + // 创建HTML渲染器 + HtmlRenderer renderer = HtmlRenderer.builder().build(); + + // 将Markdown文档渲染为HTML + return renderer.render(document); + } + + /** + * 从文件加载Markdown内容。 + * + * @param filePath 文件路径 + * @return 加载的Markdown内容 + */ + private String loadMarkdownFromFile(String filePath) { + try { + return new String(Files.readAllBytes(Paths.get(filePath))); + } catch (IOException e) { + logger.info("正在运行" + "loadMarkdownFromFile"); + return ""; + } + } + + /** + * 获取作者链接。 + * + * @return 作者链接 + */ + private Hyperlink getAuthorLink() { var authorLink = new Hyperlink("插件仓库地址"); authorLink.setVisited(true); authorLink.setStyle("-fx-text-fill: blue; -fx-visited-link-color: blue;"); @@ -219,16 +334,6 @@ public class PluginManagementPane extends BorderPane { logger.info("启动" + authorLink + "失败!"); } }); - - authorBox.getChildren().addAll(author, authorLink); - - - - var descriptionLabel = new Text("插件描述插件描述插件描述"); - - - content.getChildren().addAll(titleLabel, authorBox, descriptionLabel); - - return content; + return authorLink; } } 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 18e1bb5..4798632 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 @@ -277,7 +277,7 @@ public class TopMenuBar extends MenuBar { PluginManagementPane pluginManagementPane = new PluginManagementPane(); - Scene scene = new Scene(pluginManagementPane, 900, 500); + Scene scene = new Scene(pluginManagementPane, 900, 600); newStage.setScene(scene); newStage.show(); }); -- Gitee