2023年10月7日17:21:38

master
zhangmeng 2023-10-07 17:23:06 +08:00
parent a982e15507
commit f3fc26c724
15 changed files with 1885 additions and 212 deletions

View File

@ -0,0 +1,567 @@
package com.zhangmeng.tools.controller;
import com.zhangmeng.tools.editors.ace.AceEditor;
import com.zhangmeng.tools.utils.ImagePath;
import com.zhangmeng.tools.utils.ResourcesUtils;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.SplitPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Paint;
import javafx.scene.text.Font;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.util.Callback;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.Arrays;
@Slf4j
public class EditListController {
private SimpleDoubleProperty width = new SimpleDoubleProperty(0.0);
private SimpleDoubleProperty height = new SimpleDoubleProperty(0.0);
private AceEditor root;
private AceEditor acJsEditor;
public static final String color_cell = "#f4f4f4";
@FXML
private ListView<ResourcesUtils.EditorList> listView;
@FXML
private SplitPane splitPane;
@FXML
public void date_query_menu_item(){
load_small_tools(5);
}
@FXML
public void cron_menu_item(){
load_small_tools(6);
}
@FXML
public void video_menu_item() {
load_player(0);
}
@FXML
public void music_menu_item() {
load_player(1);
}
@FXML
public void vip_parser_menu_item() {
load_player(2);
}
@FXML
public void hex_16(){
load_small_tools(0);
}
@FXML
private void hex_16_menu_item(){
load_small_tools(0);
}
@FXML
private void unicode_menu_item(){
load_small_tools(1);
}
@FXML
private void jwt_menu_item(){
load_small_tools(2);
}
@FXML
private void color_choose_menu_item(){
load_small_tools(3);
}
@FXML
public void qr_code_menu_item(){
load_small_tools(4);
}
@FXML
public void base_62_menu_item(){
load_codec_tools(0);
}
@FXML
public void base_64_menu_item(){
load_codec_tools(1);
}
@FXML
public void base_32_menu_item(){
load_codec_tools(2);
}
@FXML
public void morse_coder_menu_item(){
load_codec_tools(3);
}
@FXML
private void sql_code_gen_menu_item(){
load_sql_tools(0);
}
@FXML
public void netty_client_menu_item(){
load_network_tools(0);
}
public void load_network_tools(int index){
AnchorPane fx = null;
try {
fx = FXMLLoader.load(ResourcesUtils.getResource("network-tools"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(fx);
Stage stage = (Stage) splitPane.getScene().getWindow();
stage.setScene(scene);
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index);
}
public void load_sql_tools(int index){
AnchorPane fx = null;
try {
fx = FXMLLoader.load(ResourcesUtils.getResource("sql-tools"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(fx);
Stage stage = (Stage) splitPane.getScene().getWindow();
stage.setScene(scene);
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index);
}
public void load_codec_tools(int index){
AnchorPane fx = null;
try {
fx = FXMLLoader.load(ResourcesUtils.getResource("codec-tools"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(fx);
Stage stage = (Stage) splitPane.getScene().getWindow();
stage.setScene(scene);
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index);
}
public void load_small_tools(int index){
AnchorPane fx = null;
try {
fx = FXMLLoader.load(ResourcesUtils.getResource("small-tools"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(fx);
Stage stage = (Stage) splitPane.getScene().getWindow();
stage.setScene(scene);
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index);
}
public void load_player(int index) {
AnchorPane fx = null;
try {
fx = FXMLLoader.load(ResourcesUtils.getResource("player"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(fx);
Stage stage = (Stage) splitPane.getScene().getWindow();
stage.setScene(scene);
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index);
}
@FXML
public void initialize() {
init();
listView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
if (newValue != null) {
boolean flag = false;
if (newValue.getIndex() == 0) {
if (acJsEditor != null){
flag = true;
}
acJsEditor(flag);
}
}
});
}
public static Image getImage(ResourcesUtils.EditorList player){
return switch (player){
case Ace_JS -> new Image(ImagePath.path(ImagePath.ImagePathType.MD5));
};
}
public void init() {
ResourcesUtils.EditorList[] values = ResourcesUtils.EditorList.values();
ObservableList<ResourcesUtils.EditorList> list = FXCollections.observableArrayList();
list.addAll(Arrays.asList(values));
listView.setItems(list);
listView.setFixedCellSize(40);
listView.setCellFactory(new Callback<>() {
private int position;
@Override
public ListCell<ResourcesUtils.EditorList> call(ListView<ResourcesUtils.EditorList> playerListView) {
Label label = new Label();
label.setPrefWidth(200);
ListCell<ResourcesUtils.EditorList> listCell = new ListCell<>() {
@Override
protected void updateItem(ResourcesUtils.EditorList player, boolean b) {
super.updateItem(player, b);
if (!b) {
HBox hBox = new HBox(25);
hBox.setAlignment(Pos.CENTER);
label.setText(player.getTitle());
label.setTextFill(Paint.valueOf("#000000"));
Image im = getImage(player);
ImageView iv = new ImageView(im);
iv.setPreserveRatio(true);
iv.setFitWidth(15);
hBox.getChildren().add(iv);
hBox.getChildren().add(label);
this.setGraphic(hBox);
}
this.setStyle("-fx-background-color: " + color_cell);
}
};
listCell.hoverProperty().addListener((observableValue, aBoolean, t1) -> {
if (t1 && !label.getText().equals("")) {
position = playerListView.getItems().indexOf(label.getText());
label.setFont(new Font(16));
playerListView.getFocusModel().focus(position);
listCell.setStyle("-fx-background-color: #369e7d");
} else {
label.setPrefHeight(20);
label.setFont(new Font(13));
listCell.setStyle("-fx-background-color: " + color_cell);
}
});
return listCell;
}
});
acJsEditor(false);
}
private void acJsEditor(boolean flag) {
//默认选择第一个
listView.getSelectionModel().select(0);
if (!flag){
root = new AceEditor();
WebView webView = root.getWebView();
webView.prefWidthProperty().bind(root.widthProperty());
webView.prefHeightProperty().bind(root.heightProperty());
acJsEditor = root;
}else {
root = acJsEditor;
}
common_method();
}
private void common_method() {
splitPane.getItems().remove(1);
splitPane.getItems().add(1, root);
root.widthProperty().addListener((observable, oldValue, newValue) -> {
if (newValue != null) {
double width = splitPane.getWidth();
EditListController.this.width.set(width);
log.info("home:--->width:{}", width);
}
});
root.heightProperty().addListener((observable, oldValue, newValue) -> {
if (newValue != null) {
double height = splitPane.getHeight();
EditListController.this.height.set(height);
log.info("home:--->height:{}", height);
}
});
this.width.addListener((observable, oldValue, newValue) -> {
EditListController.this.root.setPrefWidth(newValue.doubleValue() - listView.getWidth());
});
this.height.addListener((observable, oldValue, newValue) -> {
EditListController.this.root.setPrefHeight(newValue.doubleValue() - listView.getHeight());
});
}
@FXML
public void http_request_menu_item(ActionEvent event) {
load_http_tools(0);
}
@FXML
public void http_upload_menu_item(ActionEvent event) {
load_http_tools(1);
}
@FXML
public void http_download_menu_item(ActionEvent event) {
load_http_tools(2);
}
public void load_http_tools(int index) {
AnchorPane fx = null;
try {
fx = FXMLLoader.load(ResourcesUtils.getResource("http-tools"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(fx);
Stage stage = (Stage) splitPane.getScene().getWindow();
stage.setScene(scene);
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index);
}
@FXML
public void mail_menu_item(ActionEvent event) {
load_small_tools(7);
}
public void http_server_menu_item(ActionEvent event) {
load_server_tools(0);
}
public void ftp_server_menu_item(ActionEvent event) {
load_server_tools(1);
}
public void load_server_tools(int index) {
AnchorPane fx = null;
try {
fx = FXMLLoader.load(ResourcesUtils.getResource("server-tools"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(fx);
Stage stage = (Stage) splitPane.getScene().getWindow();
stage.setScene(scene);
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index);
}
public void ssh_client_menu_item(ActionEvent event) {
load_server_tools(2);
}
public void socket_server_menu_item(ActionEvent event) {
load_server_tools(3);
}
public void telephone_menu_item(ActionEvent event) {
load_small_tools(8);
}
public void mybatis_plus_gen_menu_item(ActionEvent event) {
load_sql_tools(1);
}
public void JsonView_menu_item(ActionEvent event) {
load_small_tools(9);
}
public void maven_jar_install_menu_item(ActionEvent event) {
load_small_tools(10);
}
public void word_ocr_menu_item(ActionEvent event) {
load_small_tools(11);
}
public void bar_code_menu_item(ActionEvent event) {
load_small_tools(12);
}
public void pdf_menu_item(ActionEvent event) {
load_small_tools(13);
}
public void json_javabean_gen_menu_item(ActionEvent event) {
load_sql_tools(2);
}
public void music_parser_menu_item(ActionEvent event) {
load_player(3);
}
public void batch_update_file_name_menu_item(ActionEvent event) {
load_small_tools(14);
}
public void socket_client_aio_menu_item(ActionEvent event) {
load_server_tools(4);
}
public void socket_server_aio_menu_item(ActionEvent event) {
load_server_tools(5);
}
public void socket_server_nio_menu_item(ActionEvent event) {
load_server_tools(6);
}
public void socket_client_nio_menu_item(ActionEvent event) {
load_server_tools(7);
}
public void capter_screen_menu_item(ActionEvent event) {
load_small_tools(15);
}
public void sql_query_gen_menu_item(ActionEvent event) {
load_sql_tools(3);
}
public void video_transcoder_menu_item(ActionEvent event) {
load_player(4);
}
public void json_to_struct_menu_item(ActionEvent event) {
load_go_tools(0);
}
public void load_go_tools(int index){
AnchorPane fx = null;
try {
fx = FXMLLoader.load(ResourcesUtils.getResource("go-tools"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(fx);
Stage stage = (Stage) splitPane.getScene().getWindow();
stage.setScene(scene);
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index);
}
public void file_edit_menu_item(ActionEvent event) {
load_small_tools(16);
}
public void web_socket_client_menu_item(ActionEvent event) {
load_server_tools(8);
}
public void layui_form_gen_menu_item(ActionEvent actionEvent) {
load_small_tools(17);
}
public void log_console_menu_item(ActionEvent actionEvent) {
load_small_tools(18);
}
public void edit_plus_code_menu_item(ActionEvent actionEvent) {
load_small_tools(19);
}
public void minio_upload_menu_item(ActionEvent actionEvent) {
load_small_tools(20);
}
public void ace_js_menu_item(ActionEvent actionEvent) {
js_edit_list(0);
}
public void js_edit_list(int index){
AnchorPane fx = null;
try {
fx = FXMLLoader.load(ResourcesUtils.getResource("editor-list"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(fx);
Stage stage = (Stage) splitPane.getScene().getWindow();
stage.setScene(scene);
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index);
}
public void md5_menu_item(ActionEvent actionEvent) {
load_encrypt(0);
}
public void spring_security_menu_item(ActionEvent actionEvent) {
load_encrypt(1);
}
public void jks_file_menu_item(ActionEvent actionEvent) {
load_encrypt(2);
}
public void load_encrypt(int index) {
Stage stage = (Stage) splitPane.getScene().getWindow();
AnchorPane fx = null;
try {
fx = FXMLLoader.load(ResourcesUtils.getResource("home"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(fx);
stage.setScene(scene);
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index);
}
}

View File

@ -616,4 +616,26 @@ public class HomeController implements Serializable {
public void minio_upload_menu_item(ActionEvent actionEvent) {
load_small_tools(20);
}
public void ace_js_menu_item(ActionEvent actionEvent) {
js_edit_list(0);
}
public void js_edit_list(int index){
AnchorPane fx = null;
try {
fx = FXMLLoader.load(ResourcesUtils.getResource("editor-list"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(fx);
Stage stage = (Stage) splitPane.getScene().getWindow();
stage.setScene(scene);
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index);
}
}

View File

@ -0,0 +1,289 @@
package com.zhangmeng.tools.editors.ace;
import com.zhangmeng.tools.utils.AlertUtils;
import com.zhangmeng.tools.utils.ClipboardUtils;
import javafx.beans.property.*;
import javafx.concurrent.Worker;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import lombok.extern.slf4j.Slf4j;
import netscape.javascript.JSObject;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
/**
* @author zhangmeng
* @date 202310709:12:41
* @version 1.0
* js ace
*/
@Slf4j
public class AceEditor extends AnchorPane {
private final WebView webView = new WebView();
private WebEngine engine;
private AceMode mode = AceMode.JAVA;
private JSObject window;
private JSObject editor;
private File file;
public WebView getWebView() {
return webView;
}
public AceEditor() {
initialize();
}
public AceEditor(File file) {
String file_content = null;
try {
file_content = Files.readString(file.toPath(), StandardCharsets.UTF_8);
} catch (IOException e) {
try {
file_content = Files.readString(file.toPath(), Charset.forName("GBK"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
this.file = file;
setText(file_content);
initialize();
}
public AceEditor(String text) {
setText(text);
initialize();
}
private void setText(String text) {
this.text.set(text);
}
/**
*
*
* @param value
*/
private void setAceText(String value) {
editor.call("setValue", value, 1);
// 或者调用js中定义好的方法
// JSObject editor = (JSObject) engine.executeScript("window");
// editor.call("setEditorValue", value);
}
private final StringProperty text = new SimpleStringProperty("");
public StringProperty textProperty() {
return text;
}
public String getText() {
return text.get();
}
/**
*
*/
private void setAceTheme(AceTheme aceTheme) {
editor.call("setTheme", aceTheme.getValue());
}
/**
*
*/
private final ObjectProperty<AceTheme> theme = new SimpleObjectProperty<>(AceTheme.CHROME);
public ObjectProperty<AceTheme> themeProperty() {
return theme;
}
public AceTheme getTheme() {
return theme.get();
}
/**
*
*/
private void setAceMode(AceMode mode) {
window.call("setEditorMode", mode.getValue());
}
/**
*
*
* @param val
*/
private void setAceReadOnly(boolean val) {
//editor.call("setReadOnly", !val);
setAceOption("readOnly", !val);
}
/**
* ace.js
*
* @param key
* @param value
*/
private void setAceOption(String key, Object value) {
editor.call("setOption", key, value);
}
/**
*
*/
private final BooleanProperty editable = new SimpleBooleanProperty(true); // 可编辑
public boolean isEditable() {
return editable.get();
}
/**
*
*
* @return
*/
public String selectedText() {
// 一下两个方法都可以获取到选中的文本
// String selectedText = (String) engine.executeScript("window.getSelection().toString()"); // 有些问题
return (String) editor.call("getSelectedText");
}
/**
*
*/
private void removeSelectText() {
window.call("removeSelectRange"); // 或者editor.call("remove", "right");
}
private final BooleanProperty showGutter = new SimpleBooleanProperty(true);
public void setShowGutter(boolean showGutter) {
this.showGutter.set(showGutter);
}
public boolean isShowGutter() {
return showGutter.get();
}
/**
* js
*
* @param text
*/
public void textChange(String text) {
//log.info(text);
setText(text);
}
/**
*
*
* @param val
*/
private void setAceShowGutter(boolean val) {
setAceOption("showGutter", val);
}
public void initialize() {
getChildren().addAll(webView);
webView.setContextMenuEnabled(false);
engine = webView.getEngine();
// 界面加载完成执行的方法
engine.getLoadWorker().stateProperty().addListener((ov, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
//
window = (JSObject) engine.executeScript("window");
window.setMember("AceEditor", this);
editor = (JSObject) engine.executeScript("window.editor");
setAceText(getText());
setAceTheme(getTheme());
setAceMode(mode);
setAceReadOnly(isEditable());
// WebView 整合 Ace.js 后 Ctrl+C 和 Ctrl+X 有问题,重新处理下。
webView.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (event.isControlDown() && event.getCode() == KeyCode.C) {
event.consume();
ClipboardUtils.setString(selectedText());
}
if (event.isControlDown() && event.getCode() == KeyCode.X) {
event.consume();
ClipboardUtils.setString(selectedText());
if (isEditable()) {
removeSelectText(); // 删除选中的内容
}
}
if (event.isControlDown() && event.getCode() == KeyCode.S){//保存
event.consume();
if (file != null){
try {
FileWriter writer = new FileWriter(file);
writer.write(getText());
writer.flush();
writer.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}else {
//
}
AlertUtils.alert_warning("保存成功!");
}
if (event.isControlDown() && event.getCode() == KeyCode.O){//保存
event.consume();
//打开文件
Stage stage = new Stage();
FileChooser dc = new FileChooser();
dc.setTitle("文件选择");
dc.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("文件类型", "*.java", "*.go", "*.txt", "*.json", "*.sql"));
File file = dc.showOpenDialog(stage);
String file_content = null;
try {
file_content = Files.readString(file.toPath(), StandardCharsets.UTF_8);
} catch (IOException e) {
try {
file_content = Files.readString(file.toPath(), Charset.forName("GBK"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
this.file = file;
setText(file_content);
setAceText(getText());
}
});
// 主题监听
themeProperty().addListener((observable, oldValue, newValue) -> setAceTheme(newValue));
// 是否可编辑
editable.addListener((observable, oldValue, newValue) -> setAceReadOnly(newValue));
showGutter.addListener((observable, oldValue, newValue) -> setAceShowGutter(newValue));
}
});
engine.setJavaScriptEnabled(true);
// message print
engine.getLoadWorker().messageProperty().addListener((observable, oldValue, newValue) -> System.out.printf("engine message : %s%n", newValue));
// exception print
engine.getLoadWorker().exceptionProperty().addListener((observable, oldValue, newValue) -> newValue.printStackTrace());
engine.loadContent(AceHelper.getHtml(this.mode,AceTheme.XCODE_JS)); // 加载html资源
// engine.load(""); // 同一时间多个WebView访问同一个资源时engine.executeScript();会返回undefined。
}
}

View File

@ -0,0 +1,145 @@
package com.zhangmeng.tools.editors.ace;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
public class AceHelper {
private static final String ace_js = "/static/editors/ace-builds/src-min/ace.js";
private static final String ext_language_tools_js = "/static/editors/ace-builds/src-min/ext-language_tools.js";
public static String getHtml(AceMode aceMode,AceTheme aceTheme) {
String model_js = "/static/editors/ace-builds/src-min/" + aceMode.getName();
String theme_js = "/static/editors/ace-builds/src-min/" + aceTheme.getName();
try (
InputStream aceJsStream = AceHelper.class.getResourceAsStream(ace_js);
InputStream ext_language_tools = AceHelper.class.getResourceAsStream(ext_language_tools_js);
InputStream modelJsStream = AceHelper.class.getResourceAsStream(model_js);
InputStream themeJsStream = AceHelper.class.getResourceAsStream(theme_js);
) {
String html = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>AceDemo</title>
<style>
*{
padding:0px;
margin:0px;
}
html,body{
height: 100%;
width: 100%;
overflow: hidden;
}
#editor-container{
height: 100%;
width: 100%;
background: white;
}
.ace_editor.ace_autocomplete {
width: 415px;
z-index: 200000;
border: 1px lightgray solid;
position: fixed;
box-shadow: 2px 3px 5px rgb(0 0 0 / 20%);
line-height: 1.4;
background: #fefefe;
color: #111;
}
</style>
</head>
<body>
<div id="editor-container" ></div>
""";
html += "<script>" + new String(Objects.requireNonNull(aceJsStream).readAllBytes(), StandardCharsets.UTF_8) + "</script>\n" +
"<!--要更改主题只需包含主题的JavaScript文件-->\n" +
"\n" +
"<script>" + new String(Objects.requireNonNull(themeJsStream).readAllBytes(), StandardCharsets.UTF_8) + "</script>\n" +
"<!--默认情况下,编辑器只支持纯文本模式;许多其他语言作为单独的模块可用。在包含该模式的JavaScript文件后:-->\n" +
"<script>" + new String(Objects.requireNonNull(modelJsStream).readAllBytes(), StandardCharsets.UTF_8) + "</script>\n" +
"<script>" + new String(Objects.requireNonNull(ext_language_tools).readAllBytes(), StandardCharsets.UTF_8) +"</script>\n";
html += """
<script>
var editor = ace.edit("editor-container");
// 使用主题:
editor.setTheme("ace/theme/xcode");
// 使用模式
editor.session.setMode("ace/mode/java");
//字体大小
editor.setFontSize(20);
//editor.setValue(Areacode);
//启动提示
var langTools = ace.require("ace/ext/language_tools");
editor.setOptions({
showGutter: true, // 显示左侧内容(行号和折叠内容)
lanuage: "java",
showFoldWidgets: true, // 显示折叠小部件
showLineNumbers: true, // 是否显示行号
readOnly: false, // 设置只读true时只读用于展示代码
wrap: 'off', // 自动换行,off关闭 , free开启
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
showPrintMargin: false, // 打印边距
});
// 设置模式
function setEditorMode(mode){
editor.session.setMode(mode);
}
// 设置内容
function setEditorValue(value){
editor.setValue(value,1);
// editor.setValue("text2", -1); // set value and move cursor to the start of the text
// editor.session.setValue("the new text here"); // set value and reset undo history
}
// 获取内容
function getEditorValue(value){
return editor.getValue(); // or session.getValue
}
// 删除选中的内容
function removeSelectRange(){
var range = editor.getSelectionRange();
editor.remove(range);
}
// 监听窗口大小变化
window.addEventListener('resize', function() {
// 在这里执行窗口大小变化后的操作
editor.resize();
});
// 监听内容变化
editor.on('change', function(delta) {
// delta.start, delta.end, delta.lines, delta.action
try{
window.AceEditor.textChange(editor.getValue()); // 通知javafx(AceView)程序内容发生变化。
}catch(err){
}
});
</script>
</body>
</html>""";
return html;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,34 @@
package com.zhangmeng.tools.editors.ace;
public enum AceMode {
CSS("mode-css.js", "ace/mode/css"),
HTML("mode-html.js", "ace/mode/html"),
JAVA("mode-java.js", "ace/mode/java"),
JAVASCRIPT("mode-javascript.js", "ace/mode/javascript"),
JSON("mode-json.js", "ace/mode/json"),
NGINX("mode-nginx.js", "ace/mode/nginx"),
PROPERTIES("mode-properties.js", "ace/mode/properties"),
SQL("mode-sql.js", "ace/mode/sql"),
TEXT("mode-text.js", "ace/mode/text"),
XML("mode-xml.js", "ace/mode/xml"),
YAML("mode-yaml.js", "ace/mode/yaml"),
MARKDOWN("mode-markdown.js", "ace/mode/markdown");
AceMode(String name, String value) {
this.name = name;
this.value = value;
}
private final String name;
private final String value;
public String getName() {
return name;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,26 @@
package com.zhangmeng.tools.editors.ace;
public enum AceTheme {
CHROME("theme-chrome.js", "ace/theme/chrome"),
XCODE_JS("theme-xcode.js", "ace/theme/theme-xcode"),
TOMORROW_NIGHT("theme-tomorrow_night.js", "ace/theme/tomorrow_night");
AceTheme(String name, String value) {
this.name = name;
this.value = value;
}
private final String name;
private final String value;
public String getName() {
return name;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,200 @@
package com.zhangmeng.tools.editors.monaco;
import com.zhangmeng.tools.editors.ace.AceHelper;
import com.zhangmeng.tools.editors.ace.AceMode;
import com.zhangmeng.tools.editors.ace.AceTheme;
import com.zhangmeng.tools.utils.AlertUtils;
import com.zhangmeng.tools.utils.ClipboardUtils;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.Worker;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
/**
* @author zhangmeng
* @date 202310716:02:39
* @version 1.0
*/
public class MonacoEdit extends AnchorPane {
private final WebView webView = new WebView();
private WebEngine engine;
private MonacoMode mode = MonacoMode.JAVA;
private JSObject window;
private JSObject editor;
private File file;
public WebView getWebView() {
return webView;
}
public MonacoEdit() {
initialize();
}
public MonacoEdit(File file) {
String file_content = null;
try {
file_content = Files.readString(file.toPath(), StandardCharsets.UTF_8);
} catch (IOException e) {
try {
file_content = Files.readString(file.toPath(), Charset.forName("GBK"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
this.file = file;
setText(file_content);
initialize();
}
public MonacoEdit(String text) {
setText(text);
initialize();
}
private final StringProperty text = new SimpleStringProperty("");
public StringProperty textProperty() {
return text;
}
public String getText() {
return text.get();
}
private void setText(String text) {
this.text.set(text);
}
/**
*
*
* @param value
*/
private void setMonacoText(String value) {
editor.call("setValue", value, 1);
}
/**
*
*/
private void setMonacoMode(MonacoMode mode) {
window.call("setEditorMode", mode.getValue());
}
/**
*
*
* @return
*/
public String selectedText() {
// 一下两个方法都可以获取到选中的文本
// String selectedText = (String) engine.executeScript("window.getSelection().toString()"); // 有些问题
return (String) editor.call("getSelectedText");
}
/**
*
*/
private void removeSelectText() {
window.call("removeSelectRange"); // 或者editor.call("remove", "right");
}
public void initialize() {
getChildren().addAll(webView);
webView.setContextMenuEnabled(false);
engine = webView.getEngine();
// 界面加载完成执行的方法
engine.getLoadWorker().stateProperty().addListener((ov, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
//
window = (JSObject) engine.executeScript("window");
window.setMember("MonacoEdit", this);
editor = (JSObject) engine.executeScript("window.monaco.editor");
setMonacoText(getText());
setMonacoMode(mode);
// WebView 整合 Ace.js 后 Ctrl+C 和 Ctrl+X 有问题,重新处理下。
webView.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (event.isControlDown() && event.getCode() == KeyCode.C) {
event.consume();
ClipboardUtils.setString(selectedText());
}
if (event.isControlDown() && event.getCode() == KeyCode.X) {
event.consume();
ClipboardUtils.setString(selectedText());
removeSelectText(); // 删除选中的内容
}
if (event.isControlDown() && event.getCode() == KeyCode.S){//保存
event.consume();
if (file != null){
try {
FileWriter writer = new FileWriter(file);
writer.write(getText());
writer.flush();
writer.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}else {
//
}
AlertUtils.alert_warning("保存成功!");
}
if (event.isControlDown() && event.getCode() == KeyCode.O){//保存
event.consume();
//打开文件
Stage stage = new Stage();
FileChooser dc = new FileChooser();
dc.setTitle("文件选择");
dc.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("文件类型", "*.java", "*.go", "*.txt", "*.json", "*.sql"));
File file = dc.showOpenDialog(stage);
String file_content = null;
try {
file_content = Files.readString(file.toPath(), StandardCharsets.UTF_8);
} catch (IOException e) {
try {
file_content = Files.readString(file.toPath(), Charset.forName("GBK"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
this.file = file;
setText(file_content);
setMonacoText(getText());
}
});
}
});
engine.setJavaScriptEnabled(true);
// message print
engine.getLoadWorker().messageProperty().addListener((observable, oldValue, newValue) -> System.out.printf("engine message : %s%n", newValue));
// exception print
engine.getLoadWorker().exceptionProperty().addListener((observable, oldValue, newValue) -> newValue.printStackTrace());
engine.loadContent(MonacoHelper.getHtml(this.mode, MonacoThem.VS)); // 加载html资源
// engine.load(""); // 同一时间多个WebView访问同一个资源时engine.executeScript();会返回undefined。
}
}

View File

@ -0,0 +1,350 @@
package com.zhangmeng.tools.editors.monaco;
import com.zhangmeng.tools.editors.ace.AceHelper;
import com.zhangmeng.tools.editors.ace.AceMode;
import com.zhangmeng.tools.editors.ace.AceTheme;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
public class MonacoHelper {
private static final String loader_js_path = "/static/editors/monaco-editor/min/vs/loader.js";
public static String getHtml(MonacoMode aceMode, MonacoThem aceTheme) {
String model_js = aceMode.getName();
String theme_js = aceTheme.getName();
try (
InputStream loader_JS = AceHelper.class.getResourceAsStream(loader_js_path);
) {
String html = """
<!DOCTYPE html>
<html>
<head>
<title>Monaco Editor Demo</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
""";
html += "<script>" + new String(Objects.requireNonNull(loader_JS).readAllBytes(), StandardCharsets.UTF_8) +"</script>";
html += """
<style>
body {
font-family: "Source Han Sans", "San Francisco", "PingFang SC", "Hiragino Sans GB", "Droid Sans Fallback", "Microsoft YaHei", sans-serif;
transition: background-color .2s;
}
.container {
position: fixed;
left: 0;
height: 100%;
right: 0;
margin: 0 auto;
display: block;
transition: 0.2s;
overflow: hidden;
z-index: 0;
}
</style>
<script type="text/javascript">
var Areacode = 'public class RichTextArea extends Control {\\n' +
' public static final String STYLE_CLASS = "rich-text-area";\\n' +
' public static final DataFormat RTA_DATA_FORMAT = new DataFormat(new String[]{"text/rich-text-area"});\\n' +
' private static final PseudoClass PSEUDO_CLASS_READONLY = PseudoClass.getPseudoClass("readonly");\\n' +
' private final ActionFactory actionFactory = new ActionFactory(this);\\n' +
' private final ObjectProperty<Document> documentProperty = new SimpleObjectProperty(this, "document", new Document());\\n' +
' private final BooleanProperty autoSaveProperty = new SimpleBooleanProperty(this, "autoSave");\\n' +
' final ReadOnlyBooleanWrapper modifiedProperty = new ReadOnlyBooleanWrapper(this, "modified");\\n' +
' private final BooleanProperty editableProperty = new SimpleBooleanProperty(this, "editable", true) {\\n' +
' protected void invalidated() {\\n' +
' RichTextArea.this.pseudoClassStateChanged(RichTextArea.PSEUDO_CLASS_READONLY, !this.get());\\n' +
' }\\n' +
' };\\n' +
' private final ReadOnlyObjectWrapper<Selection> selectionProperty;\\n' +
' final ReadOnlyIntegerWrapper textLengthProperty;\\n' +
' private final DoubleProperty contentAreaWidthProperty;\\n' +
' private final ObjectProperty<BiFunction<Integer, GraphicType, Node>> paragraphGraphicFactoryProperty;\\n' +
' private final ObjectProperty<Function<Node, Consumer<String>>> linkCallbackFactoryProperty;\\n' +
' private final ObjectProperty<EventHandler<ActionEvent>> onAction;\\n' +
' private final ObjectProperty<EmojiSkinTone> skinToneProperty;\\n' +
' final ReadOnlyIntegerWrapper caretPosition;\\n' +
' private final BooleanProperty tableAllowedProperty;\\n' +
' private StringProperty promptText;\\n' +
'\\n' +
' public RichTextArea() {\\n' +
' this.selectionProperty = new ReadOnlyObjectWrapper(this, "selection", Selection.UNDEFINED);\\n' +
' this.textLengthProperty = new ReadOnlyIntegerWrapper(this, "textLength");\\n' +
' this.contentAreaWidthProperty = new SimpleDoubleProperty(this, "contentAreaWidth", 0.0D);\\n' +
' this.paragraphGraphicFactoryProperty = new SimpleObjectProperty(this, "paragraphGraphicFactory", DefaultParagraphGraphicFactory.getFactory());\\n' +
' this.linkCallbackFactoryProperty = new SimpleObjectProperty(this, "linkCallbackFactory", DefaultLinkCallbackFactory.getFactory());\\n' +
' this.onAction = new SimpleObjectProperty(this, "onAction");\\n' +
' this.skinToneProperty = new SimpleObjectProperty(this, "skinTone", EmojiSkinTone.NO_SKIN_TONE);\\n' +
' this.caretPosition = new ReadOnlyIntegerWrapper(this, "caretPosition", 0);\\n' +
' this.tableAllowedProperty = new SimpleBooleanProperty(this, "tableAllowed", true);\\n' +
' this.promptText = new SimpleStringProperty(this, "promptText", "") {\\n' +
' protected void invalidated() {\\n' +
' String txt = this.get();\\n' +
' if (txt != null && txt.contains("\\\\n")) {\\n' +
' txt = txt.replace("\\\\n", "");\\n' +
' this.set(txt);\\n' +
' }\\n' +
'\\n' +
' }\\n' +
' };\\n' +
' this.getStyleClass().add("rich-text-area");\\n' +
' }\\n' +
'\\n' +
' public final ObjectProperty<Document> documentProperty() {\\n' +
' return this.documentProperty;\\n' +
' }\\n' +
'\\n' +
' public final Document getDocument() {\\n' +
' return (Document)this.documentProperty.get();\\n' +
' }\\n' +
'\\n' +
' public final void setDocument(Document value) {\\n' +
' this.documentProperty.set(value);\\n' +
' }\\n' +
'\\n' +
' public final BooleanProperty autoSaveProperty() {\\n' +
' return this.autoSaveProperty;\\n' +
' }\\n' +
'\\n' +
' public final boolean isAutoSave() {\\n' +
' return this.autoSaveProperty.get();\\n' +
' }\\n' +
'\\n' +
' public final void setAutoSave(boolean value) {\\n' +
' this.autoSaveProperty.set(value);\\n' +
' }\\n' +
'\\n' +
' public final ReadOnlyBooleanProperty modifiedProperty() {\\n' +
' return this.modifiedProperty.getReadOnlyProperty();\\n' +
' }\\n' +
'\\n' +
' public final boolean isModified() {\\n' +
' return this.modifiedProperty.get();\\n' +
' }\\n' +
'\\n' +
' public final BooleanProperty editableProperty() {\\n' +
' return this.editableProperty;\\n' +
' }\\n' +
'\\n' +
' public final boolean isEditable() {\\n' +
' return this.editableProperty.get();\\n' +
' }\\n' +
'\\n' +
' public final void setEditable(boolean value) {\\n' +
' this.editableProperty.set(value);\\n' +
' }\\n' +
'\\n' +
' public final ReadOnlyObjectProperty<Selection> selectionProperty() {\\n' +
' return this.selectionProperty.getReadOnlyProperty();\\n' +
' }\\n' +
'\\n' +
' public final Selection getSelection() {\\n' +
' return (Selection)this.selectionProperty.get();\\n' +
' }\\n' +
'\\n' +
' public final ReadOnlyIntegerProperty textLengthProperty() {\\n' +
' return this.textLengthProperty.getReadOnlyProperty();\\n' +
' }\\n' +
'\\n' +
' public final int getTextLength() {\\n' +
' return this.textLengthProperty.get();\\n' +
' }\\n' +
'\\n' +
' public final DoubleProperty contentAreaWidthProperty() {\\n' +
' return this.contentAreaWidthProperty;\\n' +
' }\\n' +
'\\n' +
' public final double getContentAreaWidth() {\\n' +
' return this.contentAreaWidthProperty.get();\\n' +
' }\\n' +
'\\n' +
' public final void setContentAreaWidth(double value) {\\n' +
' this.contentAreaWidthProperty.set(value);\\n' +
' }\\n' +
'\\n' +
' public final ObjectProperty<BiFunction<Integer, GraphicType, Node>> paragraphGraphicFactoryProperty() {\\n' +
' return this.paragraphGraphicFactoryProperty;\\n' +
' }\\n' +
'\\n' +
' public final BiFunction<Integer, GraphicType, Node> getParagraphGraphicFactory() {\\n' +
' return (BiFunction)this.paragraphGraphicFactoryProperty.get();\\n' +
' }\\n' +
'\\n' +
' public final void setParagraphGraphicFactory(BiFunction<Integer, GraphicType, Node> value) {\\n' +
' this.paragraphGraphicFactoryProperty.set(value);\\n' +
' }\\n' +
'\\n' +
' public final ObjectProperty<Function<Node, Consumer<String>>> linkCallbackFactoryProperty() {\\n' +
' return this.linkCallbackFactoryProperty;\\n' +
' }\\n' +
'\\n' +
' public final Function<Node, Consumer<String>> getLinkCallbackFactory() {\\n' +
' return (Function)this.linkCallbackFactoryProperty.get();\\n' +
' }\\n' +
'\\n' +
' public final void setLinkCallbackFactory(Function<Node, Consumer<String>> value) {\\n' +
' this.linkCallbackFactoryProperty.set(value);\\n' +
' }\\n' +
'\\n' +
' public final ObjectProperty<EventHandler<ActionEvent>> onActionProperty() {\\n' +
' return this.onAction;\\n' +
' }\\n' +
'\\n' +
' public final EventHandler<ActionEvent> getOnAction() {\\n' +
' return (EventHandler)this.onAction.get();\\n' +
' }\\n' +
'\\n' +
' public final void setOnAction(EventHandler<ActionEvent> value) {\\n' +
' this.onAction.set(value);\\n' +
' }\\n' +
'\\n' +
' public final ObjectProperty<EmojiSkinTone> skinToneProperty() {\\n' +
' return this.skinToneProperty;\\n' +
' }\\n' +
'\\n' +
' public final EmojiSkinTone getSkinTone() {\\n' +
' return (EmojiSkinTone)this.skinToneProperty.get();\\n' +
' }\\n' +
'\\n' +
' public final void setSkinTone(EmojiSkinTone value) {\\n' +
' this.skinToneProperty.set(value);\\n' +
' }\\n' +
'\\n' +
' public final int getCaretPosition() {\\n' +
' return this.caretPosition.get();\\n' +
' }\\n' +
'\\n' +
' public final ReadOnlyIntegerProperty caretPositionProperty() {\\n' +
' return this.caretPosition.getReadOnlyProperty();\\n' +
' }\\n' +
'\\n' +
' public final BooleanProperty tableAllowedProperty() {\\n' +
' return this.tableAllowedProperty;\\n' +
' }\\n' +
'\\n' +
' public final boolean isTableAllowed() {\\n' +
' return this.tableAllowedProperty.get();\\n' +
' }\\n' +
'\\n' +
' public final void setTableAllowed(boolean value) {\\n' +
' this.tableAllowedProperty.set(value);\\n' +
' }\\n' +
'\\n' +
' public final StringProperty promptTextProperty() {\\n' +
' return this.promptText;\\n' +
' }\\n' +
'\\n' +
' public final String getPromptText() {\\n' +
' return (String)this.promptText.get();\\n' +
' }\\n' +
'\\n' +
' public final void setPromptText(String value) {\\n' +
' this.promptText.set(value);\\n' +
' }\\n' +
'\\n' +
' public final ActionFactory getActionFactory() {\\n' +
' return this.actionFactory;\\n' +
' }\\n' +
'\\n' +
' protected SkinBase<RichTextArea> createDefaultSkin() {\\n' +
' return new RichTextAreaSkin(this);\\n' +
' }\\n' +
'\\n' +
' public String getUserAgentStylesheet() {\\n' +
' return this.getClass().getResource("rich-text-area.css").toExternalForm();\\n' +
' }\\n' +
'}';
require.config({ paths: { 'vs': './monaco-editor/min/vs' } });
require(['vs/editor/editor.main'], function () {
var defaultCode = [
Areacode
].join('\\n');
// 定义编辑器主题
monaco.editor.defineTheme('myTheme', {
base: 'vs',
inherit: true,
rules: [{ background: 'EDF9FA' }],
});
monaco.editor.setTheme('myTheme');
addNewEditor(defaultCode, 'java');
});
// 新建一个编辑器
function newEditor(container_id, code, language) {
var model = monaco.editor.createModel(code, language);
var editor = monaco.editor.create(document.getElementById(container_id), {
model: model,
automaticLayout: true,
tabSize: 4,
minimap: {
enabled: false, // 不要小地图
},
fontSize:20,
lineNumbers: true,
});
editor.onDidChangeCursorPosition((e) => {
Areacode = editor.getValue();
});
return editor;
}
// 新建一个 div
function addNewEditor(code, language) {
var new_container = document.getElementById("root")
new_container.className = "container";
newEditor(new_container.id, code, language);
}
//设置语言
function setModelLanguage (language) {
monaco.editor.setModelLanguage(window.monaco.editor.getModels()[0], language)
}
//获取值
function getValue(){
alert(Areacode)
}
</script>
</head>
<body>
<div>
<button type="button" onclick="getValue()"></button>
<button type="button" onclick="setModelLanguage('javascript')"></button>
</div>
<div id="root" ></div>
</body>
</html>
""";
return html;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,20 @@
package com.zhangmeng.tools.editors.monaco;
public enum MonacoMode {
JAVA("java"),
JAVA_SCRIPT("javascript");
private String name;
MonacoMode(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,27 @@
package com.zhangmeng.tools.editors.monaco;
/**
* vsvs-darkhc-black
*/
public enum MonacoThem {
VS("vs"),
VS_DARK("va-dark"),
HC_BLACK("hc-black");
private String name;
MonacoThem(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,35 @@
package com.zhangmeng.tools.utils;
import javafx.scene.Node;
import javafx.scene.SnapshotParameters;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.paint.Color;
/**
*
*/
public class ClipboardUtils {
private static final Clipboard SYSTEM_CLIPBOARD = Clipboard.getSystemClipboard();
private static final ClipboardContent CLIPBOARD_CONTENT = new ClipboardContent();
public static void setString(String val) {
CLIPBOARD_CONTENT.clear();
CLIPBOARD_CONTENT.putString(val);
SYSTEM_CLIPBOARD.setContent(CLIPBOARD_CONTENT);
}
public static String getString() {
return SYSTEM_CLIPBOARD.getString();
}
public static void setSnapshotImage(Node node) {
SnapshotParameters snapshotParameters = new SnapshotParameters();
snapshotParameters.setFill(Color.TRANSPARENT); // 透明背景
CLIPBOARD_CONTENT.clear();
CLIPBOARD_CONTENT.putImage(node.snapshot(snapshotParameters, null)); // 设置剪贴板内容
SYSTEM_CLIPBOARD.setContent(CLIPBOARD_CONTENT);
}
}

View File

@ -358,4 +358,34 @@ public class ResourcesUtils {
private String title;
private int index;
}
public enum EditorList {
Ace_JS("ace.js 编辑器", 0),
;
EditorList(String title, int index) {
this.title = title;
this.index = index;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
private String title;
private int index;
}
}

View File

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="800.0"
prefWidth="1661.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.zhangmeng.tools.controller.EditListController">
<children>
<MenuBar layoutX="14.0" layoutY="27.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0">
<menus>
<Menu mnemonicParsing="false" text="加密工具">
<items>
<MenuItem mnemonicParsing="false" onAction="#md5_menu_item" text="md5 加密"/>
<MenuItem mnemonicParsing="false" onAction="#spring_security_menu_item" text="spring security 加密"/>
<MenuItem mnemonicParsing="false" onAction="#jks_file_menu_item" text="jkd 文件生成"/>
</items>
</Menu>
<Menu mnemonicParsing="false" text="影音工具">
<items>
<MenuItem mnemonicParsing="false" text="视频播放" onAction="#video_menu_item"/>
<MenuItem mnemonicParsing="false" text="音乐播放" onAction="#music_menu_item"/>
<MenuItem mnemonicParsing="false" text="vip 视频解析" onAction="#vip_parser_menu_item"/>
<MenuItem mnemonicParsing="false" text="音乐解析" onAction="#music_parser_menu_item"/>
<MenuItem mnemonicParsing="false" text="视频转码" onAction="#video_transcoder_menu_item"/>
</items>
</Menu>
<Menu mnemonicParsing="false" text="常用小工具">
<items>
<MenuItem mnemonicParsing="false" text="16进制Hex" onAction="#hex_16_menu_item"/>
<MenuItem mnemonicParsing="false" text="Unicode和字符串转换" onAction="#unicode_menu_item"/>
<MenuItem mnemonicParsing="false" text="jwt工具" onAction="#jwt_menu_item"/>
<MenuItem mnemonicParsing="false" text="颜色选择工具" onAction="#color_choose_menu_item"/>
<MenuItem mnemonicParsing="false" text="二维码生成" onAction="#qr_code_menu_item"/>
<MenuItem mnemonicParsing="false" text="时间工具" onAction="#date_query_menu_item"/>
<MenuItem mnemonicParsing="false" text="cron表达式" onAction="#cron_menu_item"/>
<MenuItem mnemonicParsing="false" text="邮件发送" onAction="#mail_menu_item"/>
<MenuItem mnemonicParsing="false" text="手机号工具" onAction="#telephone_menu_item"/>
<MenuItem mnemonicParsing="false" text="JsonView" onAction="#JsonView_menu_item"/>
<MenuItem mnemonicParsing="false" text="maven-jar-install" onAction="#maven_jar_install_menu_item"/>
<MenuItem mnemonicParsing="false" text="word-ocr" onAction="#word_ocr_menu_item"/>
<MenuItem mnemonicParsing="false" text="条形码识别" onAction="#bar_code_menu_item"/>
<MenuItem mnemonicParsing="false" text="pdf识别" onAction="#pdf_menu_item"/>
<MenuItem mnemonicParsing="false" text="批量修改文件名" onAction="#batch_update_file_name_menu_item"/>
<MenuItem mnemonicParsing="false" text="截图工具" onAction="#capter_screen_menu_item"/>
<MenuItem mnemonicParsing="false" text="文件编辑器" onAction="#file_edit_menu_item"/>
<MenuItem mnemonicParsing="false" text="LayUI表单代码生成" onAction="#layui_form_gen_menu_item"/>
<MenuItem mnemonicParsing="false" text="日志输出" onAction="#log_console_menu_item"/>
<MenuItem mnemonicParsing="false" text="EditPlus注册码生成" onAction="#edit_plus_code_menu_item"/>
<MenuItem mnemonicParsing="false" text="minio文件上传" onAction="#minio_upload_menu_item"/>
</items>
</Menu>
<Menu mnemonicParsing="false" text="编解码工具">
<items>
<MenuItem mnemonicParsing="false" text="Base62编码解码" onAction="#base_62_menu_item"/>
<MenuItem mnemonicParsing="false" text="Base64编码解码" onAction="#base_64_menu_item"/>
<MenuItem mnemonicParsing="false" text="Base32编码解码" onAction="#base_32_menu_item"/>
<MenuItem mnemonicParsing="false" text="摩尔斯电码" onAction="#morse_coder_menu_item"/>
</items>
</Menu>
<Menu mnemonicParsing="false" text="代码工具">
<items>
<MenuItem mnemonicParsing="false" text="mysql代码生成" onAction="#sql_code_gen_menu_item"/>
<MenuItem mnemonicParsing="false" text="mybatis-plus 代码生成" onAction="#mybatis_plus_gen_menu_item"/>
<MenuItem mnemonicParsing="false" text="json转javaBean 代码生成" onAction="#json_javabean_gen_menu_item"/>
<MenuItem mnemonicParsing="false" text="sql 查询" onAction="#sql_query_gen_menu_item"/>
</items>
</Menu>
<Menu mnemonicParsing="false" text="http工具">
<items>
<MenuItem mnemonicParsing="false" text="http请求工具" onAction="#http_request_menu_item"/>
<MenuItem mnemonicParsing="false" text="http上传工具" onAction="#http_upload_menu_item"/>
<MenuItem mnemonicParsing="false" text="http下载工具" onAction="#http_download_menu_item"/>
</items>
</Menu>
<Menu mnemonicParsing="false" text="server 工具">
<items>
<MenuItem mnemonicParsing="false" text="http-server 请求工具" onAction="#http_server_menu_item"/>
<MenuItem mnemonicParsing="false" text="ftp-server 请求工具" onAction="#ftp_server_menu_item"/>
<MenuItem mnemonicParsing="false" text="ssh-client 请求工具" onAction="#ssh_client_menu_item"/>
<MenuItem mnemonicParsing="false" text="socket-server 服务工具" onAction="#socket_server_menu_item"/>
<MenuItem mnemonicParsing="false" text="socket-client-aio 客户端工具" onAction="#socket_client_aio_menu_item"/>
<MenuItem mnemonicParsing="false" text="socket-server-aio 服务端工具" onAction="#socket_server_aio_menu_item"/>
<MenuItem mnemonicParsing="false" text="socket-server-nio 服务端工具" onAction="#socket_server_nio_menu_item"/>
<MenuItem mnemonicParsing="false" text="socket-client-nio 客户端工具" onAction="#socket_client_nio_menu_item"/>
<MenuItem mnemonicParsing="false" text="web-socket-client 客户端工具" onAction="#web_socket_client_menu_item"/>
</items>
</Menu>
<Menu mnemonicParsing="false" text="go语言工具">
<items>
<MenuItem mnemonicParsing="false" text="json生成结构体" onAction="#json_to_struct_menu_item"/>
</items>
</Menu>
<Menu mnemonicParsing="false" text="编辑器工具">
<items>
<MenuItem mnemonicParsing="false" text="ace.js 编辑器" onAction="#ace_js_menu_item"/>
</items>
</Menu>
</menus>
</MenuBar>
<SplitPane fx:id="splitPane" dividerPositions="0.5" layoutY="25.0" prefHeight="575.0" prefWidth="1200.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="25.0">
<items>
<ListView fx:id="listView" maxWidth="300.0" minWidth="200.0" prefHeight="200.0" prefWidth="200.0"/>
<AnchorPane prefHeight="200.0" prefWidth="200.0"/>
</items>
</SplitPane>
</children>
</AnchorPane>

View File

@ -102,6 +102,13 @@
<MenuItem mnemonicParsing="false" text="json生成结构体" onAction="#json_to_struct_menu_item"/>
</items>
</Menu>
<Menu mnemonicParsing="false" text="编辑器工具">
<items>
<MenuItem mnemonicParsing="false" text="ace.js 编辑器" onAction="#ace_js_menu_item"/>
</items>
</Menu>
</menus>
</MenuBar>
<SplitPane fx:id="splitPane" dividerPositions="0.5" layoutY="25.0" prefHeight="575.0" prefWidth="1200.0"

View File

@ -19,6 +19,17 @@
width: 100%;
background: white;
}
.ace_editor.ace_autocomplete {
width: 415px;
z-index: 200000;
border: 1px lightgray solid;
position: fixed;
box-shadow: 2px 3px 5px rgb(0 0 0 / 20%);
line-height: 1.4;
background: #fefefe;
color: #111;
}
</style>
</head>
<body>
@ -36,218 +47,6 @@
<script src="./ace-builds/src-min/ext-language_tools.js" type="text/javascript" charset="utf-8"></script>
<script>
var Areacode = 'public class RichTextArea extends Control {\n' +
' public static final String STYLE_CLASS = "rich-text-area";\n' +
' public static final DataFormat RTA_DATA_FORMAT = new DataFormat(new String[]{"text/rich-text-area"});\n' +
' private static final PseudoClass PSEUDO_CLASS_READONLY = PseudoClass.getPseudoClass("readonly");\n' +
' private final ActionFactory actionFactory = new ActionFactory(this);\n' +
' private final ObjectProperty<Document> documentProperty = new SimpleObjectProperty(this, "document", new Document());\n' +
' private final BooleanProperty autoSaveProperty = new SimpleBooleanProperty(this, "autoSave");\n' +
' final ReadOnlyBooleanWrapper modifiedProperty = new ReadOnlyBooleanWrapper(this, "modified");\n' +
' private final BooleanProperty editableProperty = new SimpleBooleanProperty(this, "editable", true) {\n' +
' protected void invalidated() {\n' +
' RichTextArea.this.pseudoClassStateChanged(RichTextArea.PSEUDO_CLASS_READONLY, !this.get());\n' +
' }\n' +
' };\n' +
' private final ReadOnlyObjectWrapper<Selection> selectionProperty;\n' +
' final ReadOnlyIntegerWrapper textLengthProperty;\n' +
' private final DoubleProperty contentAreaWidthProperty;\n' +
' private final ObjectProperty<BiFunction<Integer, GraphicType, Node>> paragraphGraphicFactoryProperty;\n' +
' private final ObjectProperty<Function<Node, Consumer<String>>> linkCallbackFactoryProperty;\n' +
' private final ObjectProperty<EventHandler<ActionEvent>> onAction;\n' +
' private final ObjectProperty<EmojiSkinTone> skinToneProperty;\n' +
' final ReadOnlyIntegerWrapper caretPosition;\n' +
' private final BooleanProperty tableAllowedProperty;\n' +
' private StringProperty promptText;\n' +
'\n' +
' public RichTextArea() {\n' +
' this.selectionProperty = new ReadOnlyObjectWrapper(this, "selection", Selection.UNDEFINED);\n' +
' this.textLengthProperty = new ReadOnlyIntegerWrapper(this, "textLength");\n' +
' this.contentAreaWidthProperty = new SimpleDoubleProperty(this, "contentAreaWidth", 0.0D);\n' +
' this.paragraphGraphicFactoryProperty = new SimpleObjectProperty(this, "paragraphGraphicFactory", DefaultParagraphGraphicFactory.getFactory());\n' +
' this.linkCallbackFactoryProperty = new SimpleObjectProperty(this, "linkCallbackFactory", DefaultLinkCallbackFactory.getFactory());\n' +
' this.onAction = new SimpleObjectProperty(this, "onAction");\n' +
' this.skinToneProperty = new SimpleObjectProperty(this, "skinTone", EmojiSkinTone.NO_SKIN_TONE);\n' +
' this.caretPosition = new ReadOnlyIntegerWrapper(this, "caretPosition", 0);\n' +
' this.tableAllowedProperty = new SimpleBooleanProperty(this, "tableAllowed", true);\n' +
' this.promptText = new SimpleStringProperty(this, "promptText", "") {\n' +
' protected void invalidated() {\n' +
' String txt = this.get();\n' +
' if (txt != null && txt.contains("\\n")) {\n' +
' txt = txt.replace("\\n", "");\n' +
' this.set(txt);\n' +
' }\n' +
'\n' +
' }\n' +
' };\n' +
' this.getStyleClass().add("rich-text-area");\n' +
' }\n' +
'\n' +
' public final ObjectProperty<Document> documentProperty() {\n' +
' return this.documentProperty;\n' +
' }\n' +
'\n' +
' public final Document getDocument() {\n' +
' return (Document)this.documentProperty.get();\n' +
' }\n' +
'\n' +
' public final void setDocument(Document value) {\n' +
' this.documentProperty.set(value);\n' +
' }\n' +
'\n' +
' public final BooleanProperty autoSaveProperty() {\n' +
' return this.autoSaveProperty;\n' +
' }\n' +
'\n' +
' public final boolean isAutoSave() {\n' +
' return this.autoSaveProperty.get();\n' +
' }\n' +
'\n' +
' public final void setAutoSave(boolean value) {\n' +
' this.autoSaveProperty.set(value);\n' +
' }\n' +
'\n' +
' public final ReadOnlyBooleanProperty modifiedProperty() {\n' +
' return this.modifiedProperty.getReadOnlyProperty();\n' +
' }\n' +
'\n' +
' public final boolean isModified() {\n' +
' return this.modifiedProperty.get();\n' +
' }\n' +
'\n' +
' public final BooleanProperty editableProperty() {\n' +
' return this.editableProperty;\n' +
' }\n' +
'\n' +
' public final boolean isEditable() {\n' +
' return this.editableProperty.get();\n' +
' }\n' +
'\n' +
' public final void setEditable(boolean value) {\n' +
' this.editableProperty.set(value);\n' +
' }\n' +
'\n' +
' public final ReadOnlyObjectProperty<Selection> selectionProperty() {\n' +
' return this.selectionProperty.getReadOnlyProperty();\n' +
' }\n' +
'\n' +
' public final Selection getSelection() {\n' +
' return (Selection)this.selectionProperty.get();\n' +
' }\n' +
'\n' +
' public final ReadOnlyIntegerProperty textLengthProperty() {\n' +
' return this.textLengthProperty.getReadOnlyProperty();\n' +
' }\n' +
'\n' +
' public final int getTextLength() {\n' +
' return this.textLengthProperty.get();\n' +
' }\n' +
'\n' +
' public final DoubleProperty contentAreaWidthProperty() {\n' +
' return this.contentAreaWidthProperty;\n' +
' }\n' +
'\n' +
' public final double getContentAreaWidth() {\n' +
' return this.contentAreaWidthProperty.get();\n' +
' }\n' +
'\n' +
' public final void setContentAreaWidth(double value) {\n' +
' this.contentAreaWidthProperty.set(value);\n' +
' }\n' +
'\n' +
' public final ObjectProperty<BiFunction<Integer, GraphicType, Node>> paragraphGraphicFactoryProperty() {\n' +
' return this.paragraphGraphicFactoryProperty;\n' +
' }\n' +
'\n' +
' public final BiFunction<Integer, GraphicType, Node> getParagraphGraphicFactory() {\n' +
' return (BiFunction)this.paragraphGraphicFactoryProperty.get();\n' +
' }\n' +
'\n' +
' public final void setParagraphGraphicFactory(BiFunction<Integer, GraphicType, Node> value) {\n' +
' this.paragraphGraphicFactoryProperty.set(value);\n' +
' }\n' +
'\n' +
' public final ObjectProperty<Function<Node, Consumer<String>>> linkCallbackFactoryProperty() {\n' +
' return this.linkCallbackFactoryProperty;\n' +
' }\n' +
'\n' +
' public final Function<Node, Consumer<String>> getLinkCallbackFactory() {\n' +
' return (Function)this.linkCallbackFactoryProperty.get();\n' +
' }\n' +
'\n' +
' public final void setLinkCallbackFactory(Function<Node, Consumer<String>> value) {\n' +
' this.linkCallbackFactoryProperty.set(value);\n' +
' }\n' +
'\n' +
' public final ObjectProperty<EventHandler<ActionEvent>> onActionProperty() {\n' +
' return this.onAction;\n' +
' }\n' +
'\n' +
' public final EventHandler<ActionEvent> getOnAction() {\n' +
' return (EventHandler)this.onAction.get();\n' +
' }\n' +
'\n' +
' public final void setOnAction(EventHandler<ActionEvent> value) {\n' +
' this.onAction.set(value);\n' +
' }\n' +
'\n' +
' public final ObjectProperty<EmojiSkinTone> skinToneProperty() {\n' +
' return this.skinToneProperty;\n' +
' }\n' +
'\n' +
' public final EmojiSkinTone getSkinTone() {\n' +
' return (EmojiSkinTone)this.skinToneProperty.get();\n' +
' }\n' +
'\n' +
' public final void setSkinTone(EmojiSkinTone value) {\n' +
' this.skinToneProperty.set(value);\n' +
' }\n' +
'\n' +
' public final int getCaretPosition() {\n' +
' return this.caretPosition.get();\n' +
' }\n' +
'\n' +
' public final ReadOnlyIntegerProperty caretPositionProperty() {\n' +
' return this.caretPosition.getReadOnlyProperty();\n' +
' }\n' +
'\n' +
' public final BooleanProperty tableAllowedProperty() {\n' +
' return this.tableAllowedProperty;\n' +
' }\n' +
'\n' +
' public final boolean isTableAllowed() {\n' +
' return this.tableAllowedProperty.get();\n' +
' }\n' +
'\n' +
' public final void setTableAllowed(boolean value) {\n' +
' this.tableAllowedProperty.set(value);\n' +
' }\n' +
'\n' +
' public final StringProperty promptTextProperty() {\n' +
' return this.promptText;\n' +
' }\n' +
'\n' +
' public final String getPromptText() {\n' +
' return (String)this.promptText.get();\n' +
' }\n' +
'\n' +
' public final void setPromptText(String value) {\n' +
' this.promptText.set(value);\n' +
' }\n' +
'\n' +
' public final ActionFactory getActionFactory() {\n' +
' return this.actionFactory;\n' +
' }\n' +
'\n' +
' protected SkinBase<RichTextArea> createDefaultSkin() {\n' +
' return new RichTextAreaSkin(this);\n' +
' }\n' +
'\n' +
' public String getUserAgentStylesheet() {\n' +
' return this.getClass().getResource("rich-text-area.css").toExternalForm();\n' +
' }\n' +
'}';
var editor = ace.edit("editor-container");
// 使用主题:
editor.setTheme("ace/theme/xcode");