2023年10月7日22:34:54

master
zhangmeng 2023-10-07 22:35:04 +08:00
parent 587f087c2a
commit 36752301ab
6 changed files with 141 additions and 306 deletions

View File

@ -1,6 +1,7 @@
package com.zhangmeng.tools.controller; package com.zhangmeng.tools.controller;
import com.zhangmeng.tools.editors.ace.AceEditor; import com.zhangmeng.tools.editors.ace.AceEditor;
import com.zhangmeng.tools.editors.monaco.MonacoEdit;
import com.zhangmeng.tools.utils.ImagePath; import com.zhangmeng.tools.utils.ImagePath;
import com.zhangmeng.tools.utils.ResourcesUtils; import com.zhangmeng.tools.utils.ResourcesUtils;
import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleDoubleProperty;
@ -34,9 +35,10 @@ public class EditListController {
private SimpleDoubleProperty width = new SimpleDoubleProperty(0.0); private SimpleDoubleProperty width = new SimpleDoubleProperty(0.0);
private SimpleDoubleProperty height = new SimpleDoubleProperty(0.0); private SimpleDoubleProperty height = new SimpleDoubleProperty(0.0);
private AceEditor root; private AnchorPane root;
private AceEditor acJsEditor; private AceEditor acJsEditor;
private MonacoEdit monacoEdit;
public static final String color_cell = "#f4f4f4"; public static final String color_cell = "#f4f4f4";
@ -225,6 +227,12 @@ public class EditListController {
acJsEditor(flag); acJsEditor(flag);
} }
if (newValue.getIndex() == 1) {
if (monacoEdit != null){
flag = true;
}
monacoEdit(flag);
}
} }
}); });
} }
@ -232,6 +240,7 @@ public class EditListController {
public static Image getImage(ResourcesUtils.EditorList player){ public static Image getImage(ResourcesUtils.EditorList player){
return switch (player){ return switch (player){
case Ace_JS -> new Image(ImagePath.path(ImagePath.ImagePathType.MD5)); case Ace_JS -> new Image(ImagePath.path(ImagePath.ImagePathType.MD5));
case Monaco_JS -> new Image(ImagePath.path(ImagePath.ImagePathType.MD5));
}; };
} }
@ -294,18 +303,33 @@ public class EditListController {
listView.getSelectionModel().select(0); listView.getSelectionModel().select(0);
if (!flag){ if (!flag){
root = new AceEditor(); acJsEditor = new AceEditor();
WebView webView = root.getWebView(); root = acJsEditor;
WebView webView = acJsEditor.getWebView();
webView.prefWidthProperty().bind(root.widthProperty()); webView.prefWidthProperty().bind(root.widthProperty());
webView.prefHeightProperty().bind(root.heightProperty()); webView.prefHeightProperty().bind(root.heightProperty());
acJsEditor = root;
}else { }else {
root = acJsEditor; root = acJsEditor;
} }
common_method(); common_method();
} }
private void monacoEdit(boolean flag) {
//默认选择第一个
listView.getSelectionModel().select(1);
if (!flag){
monacoEdit = new MonacoEdit();
root = monacoEdit;
WebView webView = monacoEdit.getWebView();
webView.prefWidthProperty().bind(root.widthProperty());
webView.prefHeightProperty().bind(root.heightProperty());
}else {
root = monacoEdit;
}
common_method();
}
private void common_method() { private void common_method() {
splitPane.getItems().remove(1); splitPane.getItems().remove(1);
@ -564,4 +588,8 @@ public class EditListController {
ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView"); ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
listView.getSelectionModel().select(index); listView.getSelectionModel().select(index);
} }
public void monaco_js_menu_item(ActionEvent actionEvent) {
}
} }

View File

@ -76,7 +76,7 @@ public class AceHelper {
editor.session.setMode("ace/mode/java"); editor.session.setMode("ace/mode/java");
//字体大小 //字体大小
editor.setFontSize(20); editor.setFontSize(16);
//editor.setValue(Areacode); //editor.setValue(Areacode);
//启动提示 //启动提示

View File

@ -89,7 +89,8 @@ public class MonacoEdit extends AnchorPane {
* @param value * @param value
*/ */
private void setMonacoText(String value) { private void setMonacoText(String value) {
editor.call("setValue", value, 1); JSObject editor = (JSObject) engine.executeScript("window");
editor.call("setValue", value);
} }
/** /**
@ -128,7 +129,7 @@ public class MonacoEdit extends AnchorPane {
// //
window = (JSObject) engine.executeScript("window"); window = (JSObject) engine.executeScript("window");
window.setMember("MonacoEdit", this); window.setMember("MonacoEdit", this);
editor = (JSObject) engine.executeScript("window.monaco.editor"); // editor = (JSObject) engine.executeScript("monaco.editor");
setMonacoText(getText()); setMonacoText(getText());
setMonacoMode(mode); setMonacoMode(mode);
// WebView 整合 Ace.js 后 Ctrl+C 和 Ctrl+X 有问题,重新处理下。 // WebView 整合 Ace.js 后 Ctrl+C 和 Ctrl+X 有问题,重新处理下。

View File

@ -21,326 +21,130 @@ public class MonacoHelper {
InputStream loader_JS = AceHelper.class.getResourceAsStream(loader_js_path); InputStream loader_JS = AceHelper.class.getResourceAsStream(loader_js_path);
) { ) {
String html = """ String html = """
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Monaco Editor Demo</title> <title>Monaco Editor Demo</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" > <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 += """
html += "<script>" + new String(Objects.requireNonNull(loader_JS).readAllBytes(), StandardCharsets.UTF_8) +"</script>"; <style>
html += """ body {
font-family: "Source Han Sans", "San Francisco", "PingFang SC", "Hiragino Sans GB", "Droid Sans Fallback", "Microsoft YaHei", sans-serif;
<style> transition: background-color .2s;
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 { .container {
position: fixed; position: fixed;
left: 0; left: 0;
height: 100%; height: 100%;
right: 0; right: 0;
margin: 0 auto; margin: 0 auto;
display: block; display: block;
transition: 0.2s; transition: 0.2s;
overflow: hidden; overflow: hidden;
z-index: 0; z-index: 0;
} }
</style>
</style> <script type="text/javascript">
<script type="text/javascript"> var edit_content = "";
var Areacode = 'public class RichTextArea extends Control {\\n' + require.config({paths: {'vs': './monaco-editor/min/vs'}});
' public static final String STYLE_CLASS = "rich-text-area";\\n' + require(['vs/editor/editor.main'], function () {
' 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' } }); var defaultCode = [
require(['vs/editor/editor.main'], function () { edit_content
].join('\\n');
var defaultCode = [ // 定义编辑器主题
Areacode monaco.editor.defineTheme('myTheme', {
].join('\\n'); base: 'vs',
inherit: true,
rules: [{background: 'EDF9FA'}],
});
monaco.editor.setTheme('myTheme');
addNewEditor(defaultCode, 'java');
});
// 定义编辑器主题 var code_edit;
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) => {
edit_content = editor.getValue();
});
code_edit = editor;
return editor;
}
// 新建一个编辑器 // 新建一个 div
function newEditor(container_id, code, language) { function addNewEditor(code, language) {
var model = monaco.editor.createModel(code, language); var new_container = document.getElementById("root")
var editor = monaco.editor.create(document.getElementById(container_id), { new_container.className = "container";
model: model, newEditor(new_container.id, code, language);
automaticLayout: true, }
tabSize: 4,
minimap: {
enabled: false, // 不要小地图
},
fontSize:20,
lineNumbers: true,
});
editor.onDidChangeCursorPosition((e) => {
Areacode = editor.getValue();
});
return editor;
}
// 新建一个 div //设置语言
function addNewEditor(code, language) { function setModelLanguage(language) {
var new_container = document.getElementById("root") monaco.editor.setModelLanguage(window.monaco.editor.getModels()[0], language)
new_container.className = "container"; }
newEditor(new_container.id, code, language);
}
//设置语言 //获取值
function setModelLanguage (language) { function getValue() {
monaco.editor.setModelLanguage(window.monaco.editor.getModels()[0], language) alert(edit_content)
} }
//获取值 function setThem() {
function getValue(){ monaco.editor.setTheme('vs-dark');
alert(Areacode) }
}
</script> //获取所选文本
</head> function getSelected() {
var text = code_edit.getModel().getValueInRange(code_edit.getSelection())
}
<body> function setValue(){
// 销毁当前的编辑器实例
code_edit.dispose();
addNewEditor("defaultCode", 'java');
}
<div> </script>
<button type="button" onclick="getValue()"></button> </head>
<button type="button" onclick="setModelLanguage('javascript')"></button>
</div>
<div id="root" ></div>
</body> <body>
</html> <div style="width: 100%">
<button type="button" onclick="getValue()"></button>
<button type="button" onclick="setModelLanguage('javascript')"></button>
<button type="button" onclick="setThem('javascript')"></button>
<button type="button" onclick="getSelected()"></button>
<button type="button" onclick="setValue()"></button>
</div>
<div id="root"></div>
</body>
</html>
"""; """;
return html; return html;

View File

@ -362,6 +362,7 @@ public class ResourcesUtils {
public enum EditorList { public enum EditorList {
Ace_JS("ace.js 编辑器", 0), Ace_JS("ace.js 编辑器", 0),
Monaco_JS("ace.js 编辑器", 1),
; ;
EditorList(String title, int index) { EditorList(String title, int index) {

View File

@ -106,6 +106,7 @@
<Menu mnemonicParsing="false" text="编辑器工具"> <Menu mnemonicParsing="false" text="编辑器工具">
<items> <items>
<MenuItem mnemonicParsing="false" text="ace.js 编辑器" onAction="#ace_js_menu_item"/> <MenuItem mnemonicParsing="false" text="ace.js 编辑器" onAction="#ace_js_menu_item"/>
<MenuItem mnemonicParsing="false" text="monaco.js 编辑器" onAction="#monaco_js_menu_item"/>
</items> </items>
</Menu> </Menu>
</menus> </menus>