diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index ca143d2..232b63d 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -30,10 +30,12 @@ module org.jcnc.jnotepad { exports org.jcnc.jnotepad.util; exports org.jcnc.jnotepad.common.interfaces; opens org.jcnc.jnotepad.app.config; - exports org.jcnc.jnotepad.views.root.center.main.bottom.status; exports org.jcnc.jnotepad.plugin.interfaces; exports org.jcnc.jnotepad.ui.dialog; exports org.jcnc.jnotepad.ui.dialog.interfaces; exports org.jcnc.jnotepad.model.entity; + exports org.jcnc.jnotepad.views.root.bottom; + exports org.jcnc.jnotepad.views.root.bottom.status; + exports org.jcnc.jnotepad.views.root.bottom.cmd; } \ No newline at end of file diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/NewFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/NewFile.java index 91214b8..548f2b9 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/NewFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/NewFile.java @@ -7,7 +7,7 @@ import org.jcnc.jnotepad.app.i18n.UiResourceBundle; import org.jcnc.jnotepad.common.constants.AppConstants; import org.jcnc.jnotepad.common.constants.TextConstants; import org.jcnc.jnotepad.ui.module.LineNumberTextArea; -import org.jcnc.jnotepad.views.root.center.main.bottom.status.BottomStatusBox; +import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane; 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 64b570c..e13cc1d 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/module/LineNumberTextArea.java +++ b/src/main/java/org/jcnc/jnotepad/ui/module/LineNumberTextArea.java @@ -4,7 +4,7 @@ import javafx.geometry.Insets; import org.fxmisc.richtext.LineNumberFactory; import org.fxmisc.richtext.StyleClassedTextArea; import org.jcnc.jnotepad.util.LogUtil; -import org.jcnc.jnotepad.views.root.center.main.bottom.status.BottomStatusBox; +import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane; import org.slf4j.Logger; diff --git a/src/main/java/org/jcnc/jnotepad/ui/module/TerminalEmulatorComponent.java b/src/main/java/org/jcnc/jnotepad/ui/module/TerminalEmulatorComponent.java new file mode 100644 index 0000000..e18094c --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/ui/module/TerminalEmulatorComponent.java @@ -0,0 +1,75 @@ +package org.jcnc.jnotepad.ui.module; + +import javafx.application.Platform; +import javafx.geometry.Pos; +import javafx.scene.control.TextField; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.VBox; +import org.fxmisc.richtext.CodeArea; +import org.fxmisc.richtext.LineNumberFactory; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class TerminalEmulatorComponent extends VBox { + + private CodeArea terminalOutput; + private Process process; + + public TerminalEmulatorComponent() { + initializeUI(); + } + + private void initializeUI() { + terminalOutput = new CodeArea(); + TextField commandInput = new TextField(); + + // 设置行号 + terminalOutput.setParagraphGraphicFactory(LineNumberFactory.get(terminalOutput)); + + commandInput.setOnKeyPressed(event -> { + if (event.getCode() == KeyCode.ENTER) { + String command = commandInput.getText(); + executeCommand(command); + commandInput.clear(); + } + }); + + getChildren().addAll(terminalOutput, commandInput); + setAlignment(Pos.CENTER); + + // 设置布局样式和大小 + setSpacing(10); + setMinSize(800, 600); + } + + private void executeCommand(String command) { + try { + ProcessBuilder processBuilder = new ProcessBuilder(command.split(" ")); + processBuilder.redirectErrorStream(true); + process = processBuilder.start(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK")); + String line; + while ((line = reader.readLine()) != null) { + appendToTerminalOutput(line + "\n"); + } + + int exitCode = process.waitFor(); + appendToTerminalOutput("Exit Code: " + exitCode + "\n"); + + } catch (IOException | InterruptedException e) { + appendToTerminalOutput("Error: " + e.getMessage() + "\n"); + } + } + + private void appendToTerminalOutput(String text) { + Platform.runLater(() -> { + terminalOutput.appendText(text); + // 将滚动条滚动到最后一行 + terminalOutput.moveTo(terminalOutput.getLength()); + terminalOutput.requestFollowCaret(); + }); + } +} diff --git a/src/main/java/org/jcnc/jnotepad/views/root/bottom/RootBottomSideBarVerticalBox.java b/src/main/java/org/jcnc/jnotepad/views/root/bottom/RootBottomSideBarVerticalBox.java index 0e649d6..f238555 100644 --- a/src/main/java/org/jcnc/jnotepad/views/root/bottom/RootBottomSideBarVerticalBox.java +++ b/src/main/java/org/jcnc/jnotepad/views/root/bottom/RootBottomSideBarVerticalBox.java @@ -1,7 +1,12 @@ package org.jcnc.jnotepad.views.root.bottom; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; import org.jcnc.jnotepad.ui.module.AbstractVerticalBox; -import org.jcnc.jnotepad.views.root.center.main.bottom.status.BottomStatusBox; +import org.jcnc.jnotepad.views.root.bottom.cmd.CmdStatusBox; +import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox; +import org.jcnc.jnotepad.views.root.left.sidebar.tools.SidebarToolBar; /** * 底部根侧边栏垂直布局 @@ -12,12 +17,6 @@ import org.jcnc.jnotepad.views.root.center.main.bottom.status.BottomStatusBox; */ public class RootBottomSideBarVerticalBox extends AbstractVerticalBox { - private static final RootBottomSideBarVerticalBox INSTANCE = new RootBottomSideBarVerticalBox(); - - private RootBottomSideBarVerticalBox() { - initSidebarVerticalBox(); - } - /** * 获取 RootBottomSideBarVerticalBox 的唯一实例。 * @@ -28,6 +27,19 @@ public class RootBottomSideBarVerticalBox extends AbstractVerticalBox { } private void initSidebarVerticalBox() { - getChildren().addAll(BottomStatusBox.getInstance()); + VBox bottomSideBarVerticalBox = new VBox(); + + bottomSideBarVerticalBox.getChildren().addAll(CmdStatusBox.getInstance(), BottomStatusBox.getInstance()); + + + getChildren().addAll(bottomSideBarVerticalBox); + } + + private static final RootBottomSideBarVerticalBox INSTANCE = new RootBottomSideBarVerticalBox(); + + private RootBottomSideBarVerticalBox() { + initSidebarVerticalBox(); + } + } diff --git a/src/main/java/org/jcnc/jnotepad/views/root/bottom/cmd/CmdStatusBox.java b/src/main/java/org/jcnc/jnotepad/views/root/bottom/cmd/CmdStatusBox.java new file mode 100644 index 0000000..01df016 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/views/root/bottom/cmd/CmdStatusBox.java @@ -0,0 +1,78 @@ +package org.jcnc.jnotepad.views.root.bottom.cmd; + +import javafx.application.Platform; +import javafx.geometry.Insets; +import javafx.scene.Scene; +import javafx.scene.control.Label; +import javafx.scene.control.Menu; +import javafx.scene.control.MenuBar; +import javafx.scene.control.TextArea; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.text.Text; +import javafx.stage.Modality; +import javafx.stage.Stage; +import org.jcnc.jnotepad.controller.event.handler.menubar.SaveAsFile; +import org.jcnc.jnotepad.util.LogUtil; + +/** + * @author luke + */ +public class CmdStatusBox extends HBox { + + private static final CmdStatusBox CMD_STATUS_BOX = new CmdStatusBox(); + + private CmdStatusBox() { + initStatusBox(); + } + + public static CmdStatusBox getInstance() { + return CMD_STATUS_BOX; + } + + /** + * 初始化底部CMD按钮组件 + */ + public void initStatusBox() { + + + var menuBar = new MenuBar(); + HBox.setHgrow(menuBar, Priority.ALWAYS); + menuBar.setPadding(new Insets(-3, 0, -3, 35)); + + // 创建菜单项 1 + var runMenu = new Menu(); + var cmdMenu = new Menu(); + var buildMenu = new Menu(); + + // 创建菜单项 2 + var runLabel = new Label("运行"); + var cmdLabel = new Label("终端"); + var buildLabel = new Label("构建"); + + // 创建菜单点击事件 2 + runMenu.setGraphic(runLabel); + cmdMenu.setGraphic(cmdLabel); + buildMenu.setGraphic(buildLabel); + + cmdLabel.setOnMouseClicked(mouseEvent -> { + showTerminal(); + LogUtil.getLogger(this.getClass()).info("打开终端成功!"); + }); + + // 将一级菜单添加到菜单栏 + menuBar.getMenus().addAll(runMenu, cmdMenu, buildMenu); + + // 将菜单栏添加到CmdStatusBox + this.getChildren().add(menuBar); + + + } + + /** + * 在菜单上方创建一个终端 + */ + private void showTerminal() { + + } +} diff --git a/src/main/java/org/jcnc/jnotepad/views/root/center/main/bottom/status/BottomStatusBox.java b/src/main/java/org/jcnc/jnotepad/views/root/bottom/status/BottomStatusBox.java similarity index 98% rename from src/main/java/org/jcnc/jnotepad/views/root/center/main/bottom/status/BottomStatusBox.java rename to src/main/java/org/jcnc/jnotepad/views/root/bottom/status/BottomStatusBox.java index 4cf2baa..8675bb3 100644 --- a/src/main/java/org/jcnc/jnotepad/views/root/center/main/bottom/status/BottomStatusBox.java +++ b/src/main/java/org/jcnc/jnotepad/views/root/bottom/status/BottomStatusBox.java @@ -1,4 +1,4 @@ -package org.jcnc.jnotepad.views.root.center.main.bottom.status; +package org.jcnc.jnotepad.views.root.bottom.status; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; @@ -131,8 +131,9 @@ public class BottomStatusBox extends AbstractHorizontalBox { /** * 更新行列信息 + * * @param caretPosition 光标位置 - * @param text 文本内容 + * @param text 文本内容 */ private void updateRowColumnLabel(int caretPosition, String text) { int row = getRow(caretPosition, text); diff --git a/src/main/java/org/jcnc/jnotepad/views/root/center/main/center/tab/CenterTabPane.java b/src/main/java/org/jcnc/jnotepad/views/root/center/main/center/tab/CenterTabPane.java index d934939..28cfd1b 100644 --- a/src/main/java/org/jcnc/jnotepad/views/root/center/main/center/tab/CenterTabPane.java +++ b/src/main/java/org/jcnc/jnotepad/views/root/center/main/center/tab/CenterTabPane.java @@ -2,7 +2,7 @@ package org.jcnc.jnotepad.views.root.center.main.center.tab; import javafx.scene.control.TabPane; import org.jcnc.jnotepad.controller.config.AppConfigController; -import org.jcnc.jnotepad.views.root.center.main.bottom.status.BottomStatusBox; +import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox; import org.jcnc.jnotepad.views.root.top.menu.TopMenuBar; /** 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 b581e4d..a826e91 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 @@ -1,6 +1,7 @@ package org.jcnc.jnotepad.views.root.top.menu; import javafx.event.ActionEvent; +import javafx.geometry.Insets; import javafx.scene.control.*; import javafx.scene.input.KeyCombination; import javafx.stage.Stage; @@ -141,6 +142,7 @@ public class TopMenuBar extends MenuBar { * 初始化菜单栏 */ public void initMenuBar() { + setPadding(new Insets(-3,0,-3,0)); initFileMenu(); initLanguageMenu(); initSettingMenu();