Merge branch 'release-v1.1.13' of https://gitee.com/jcnc-org/JNotepad into develop
This commit is contained in:
commit
26977a0876
@ -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;
|
||||
|
||||
}
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
package org.jcnc.jnotepad.ui.module;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import org.fxmisc.richtext.CodeArea;
|
||||
import org.fxmisc.richtext.LineNumberFactory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* 终端仿真器组件,用于执行命令并显示输出。
|
||||
* <p>
|
||||
* 该组件包括一个用于输入命令的文本字段和一个显示命令输出的CodeArea。
|
||||
* 用户可以在文本字段中输入命令,按回车键执行,并在CodeArea中查看输出。
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public class TerminalEmulatorComponent extends BorderPane {
|
||||
|
||||
private CodeArea terminalOutput;
|
||||
|
||||
/**
|
||||
* 创建一个新的终端仿真器组件。
|
||||
*/
|
||||
public TerminalEmulatorComponent() {
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
setCenter(terminalOutput);
|
||||
setBottom(commandInput);
|
||||
}
|
||||
|
||||
private void executeCommand(String command) {
|
||||
try {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
|
||||
processBuilder.redirectErrorStream(true);
|
||||
Process 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();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
package org.jcnc.jnotepad.views.root.bottom;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 底部根侧边栏垂直布局
|
||||
@ -12,11 +14,7 @@ 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();
|
||||
}
|
||||
VBox bottomSideBarVerticalBox;
|
||||
|
||||
/**
|
||||
* 获取 RootBottomSideBarVerticalBox 的唯一实例。
|
||||
@ -27,7 +25,20 @@ public class RootBottomSideBarVerticalBox extends AbstractVerticalBox {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private void initSidebarVerticalBox() {
|
||||
getChildren().addAll(BottomStatusBox.getInstance());
|
||||
public void initSidebarVerticalBox() {
|
||||
bottomSideBarVerticalBox = new VBox();
|
||||
|
||||
bottomSideBarVerticalBox.getChildren().addAll(CmdStatusBox.getInstance(), BottomStatusBox.getInstance());
|
||||
|
||||
|
||||
getChildren().addAll(bottomSideBarVerticalBox);
|
||||
|
||||
}
|
||||
|
||||
private static final RootBottomSideBarVerticalBox INSTANCE = new RootBottomSideBarVerticalBox();
|
||||
|
||||
public RootBottomSideBarVerticalBox() {
|
||||
initSidebarVerticalBox();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,118 @@
|
||||
package org.jcnc.jnotepad.views.root.bottom.cmd;
|
||||
|
||||
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.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.stage.Stage;
|
||||
import org.jcnc.jnotepad.ui.module.TerminalEmulatorComponent;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
|
||||
/**
|
||||
* CmdStatusBox 类表示应用程序的命令状态框。
|
||||
* <p>
|
||||
* 该框包括一个菜单栏,用于运行、终端和构建命令。用户可以点击终端菜单项以切换终端的显示状态。
|
||||
* 终端显示时,将创建一个新的窗口以显示终端模拟器组件。
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public class CmdStatusBox extends HBox {
|
||||
|
||||
Stage terminalStage = new Stage();
|
||||
|
||||
private static final CmdStatusBox CMD_STATUS_BOX = new CmdStatusBox();
|
||||
|
||||
/**
|
||||
* 用于跟踪终端的显示状态
|
||||
*/
|
||||
private boolean terminalVisible = false;
|
||||
|
||||
private CmdStatusBox() {
|
||||
initStatusBox();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 CmdStatusBox 的实例。
|
||||
*
|
||||
* @return CmdStatusBox 的实例
|
||||
*/
|
||||
public static CmdStatusBox getInstance() {
|
||||
return CMD_STATUS_BOX;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化命令状态框。
|
||||
*/
|
||||
public void initStatusBox() {
|
||||
var menuBar = new MenuBar();
|
||||
HBox.setHgrow(menuBar, Priority.ALWAYS);
|
||||
menuBar.setPadding(new Insets(-3, 0, -3, 35));
|
||||
|
||||
var runMenu = new Menu();
|
||||
var cmdMenu = new Menu();
|
||||
var buildMenu = new Menu();
|
||||
|
||||
var runLabel = new Label("运行");
|
||||
var cmdLabel = new Label("终端");
|
||||
var buildLabel = new Label("构建");
|
||||
|
||||
runMenu.setGraphic(runLabel);
|
||||
cmdMenu.setGraphic(cmdLabel);
|
||||
buildMenu.setGraphic(buildLabel);
|
||||
|
||||
cmdLabel.setOnMouseClicked(mouseEvent -> {
|
||||
toggleTerminal(); // 切换终端的显示/隐藏状态
|
||||
});
|
||||
|
||||
menuBar.getMenus().addAll(runMenu, cmdMenu, buildMenu);
|
||||
this.getChildren().add(menuBar);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换终端的显示/隐藏状态。
|
||||
*/
|
||||
private void toggleTerminal() {
|
||||
if (terminalVisible) {
|
||||
// 隐藏终端
|
||||
terminalVisible = false;
|
||||
hideTerminal();
|
||||
} else {
|
||||
// 显示终端
|
||||
terminalVisible = true;
|
||||
showTerminal();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏终端窗口。
|
||||
*/
|
||||
private void hideTerminal() {
|
||||
terminalStage.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示终端窗口。
|
||||
*/
|
||||
private void showTerminal() {
|
||||
// 创建一个新的舞台(窗口)
|
||||
terminalStage.setTitle("终端");
|
||||
terminalStage.getIcons().add(UiUtil.getAppIcon());
|
||||
|
||||
// 创建一个根节点(布局)
|
||||
BorderPane root = new BorderPane();
|
||||
Scene scene = new Scene(root, UiUtil.getAppWindow().getWidth() - 50, UiUtil.getAppWindow().getHeight() / 3);
|
||||
|
||||
// 创建TerminalEmulatorComponent并添加到根节点
|
||||
TerminalEmulatorComponent terminal = new TerminalEmulatorComponent();
|
||||
|
||||
root.setCenter(terminal);
|
||||
terminalStage.setScene(scene);
|
||||
|
||||
// 显示窗口
|
||||
terminalStage.show();
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user