Files
mixly3/common/modules/mixly-modules/common/editor-ace.js
王立帮 36428283e7 Update: 调整Ampy板卡文件管理
本次更新用以配置Ampy板卡文件管理使其仅支持编辑文本文件
2024-08-18 01:52:21 +08:00

369 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
goog.loadJs('common', () => {
goog.require('ace');
goog.require('ace.ExtLanguageTools');
goog.require('Mixly.XML');
goog.require('Mixly.Env');
goog.require('Mixly.Msg');
goog.require('Mixly.Debug');
goog.require('Mixly.HTMLTemplate');
goog.require('Mixly.EditorBase');
goog.provide('Mixly.EditorAce');
const {
XML,
Env,
Msg,
Debug,
HTMLTemplate,
EditorBase
} = Mixly;
class EditorAce extends EditorBase {
static {
this.CTRL_BTNS = ['resetFontSize', 'increaseFontSize', 'decreaseFontSize'];
this.CTRL_BTN_TEMPLATE = '<div m-id="{{d.mId}}" class="code-editor-btn setFontSize"></div>';
this.MODE_MAP = goog.getJSON(path.join(Env.templatePath, 'json/ace-mode-map.json'));
HTMLTemplate.add(
'html/editor/editor-code.html',
new HTMLTemplate(goog.get(path.join(Env.templatePath, 'html/editor/editor-code.html')))
);
}
#editor_ = null;
#destroyed_ = null;
#cursorLayer_ = null;
constructor() {
super();
const editorHTMLTemplate = HTMLTemplate.get('html/editor/editor-code.html');
this.setContent($(editorHTMLTemplate.render()));
this.id = editorHTMLTemplate.id;
}
init() {
super.init();
this.#editor_ = ace.edit(this.getContent()[0]);
this.resetFontSize();
this.#addCursorLayer_();
this.#addCursorEventsListener_();
this.#addDefaultCommand_();
}
getEditor() {
return this.#editor_;
}
dispose() {
super.dispose();
this.#editor_.destroy();
this.#destroyed_ = true;
}
setValue(data, scroll = true) {
if (this.#destroyed_) {
return;
}
this.#editor_.updateSelectionMarkers();
const { selection } = this.#editor_;
const initCursor = selection.getCursor();
if (this.getValue() !== data) {
this.#editor_.setValue(data);
}
if (scroll) {
this.scrollToBottom();
} else {
selection.moveCursorTo(initCursor.row, initCursor.column, true);
selection.clearSelection();
}
}
addValue(data, scroll = true) {
if (this.#destroyed_) {
return;
}
const { session } = this.#editor_;
const endCursor = this.getEndPos();
session.insert(endCursor, data);
if (scroll) {
this.scrollToBottom();
}
}
getValue() {
return this.#destroyed_ ? '' : this.#editor_.getValue();
}
getValueRange(startPos, endPos) {
if (this.#destroyed_ || !startPos || !endPos
|| typeof startPos !== 'object' || typeof endPos !== 'object') {
return "";
}
const session = this.#editor_.getSession();
return session.getTextRange(new ace.Range(
startPos.row,
startPos.column,
endPos.row,
endPos.column
));
}
getEndPos() {
if (this.#destroyed_) {
return { row: 0, column: 0 };
}
const session = this.#editor_.getSession();
const row = session.getLength() - 1;
const column = session.getLine(row).length;
return { row, column };
}
clear() {
this.setValue('', true);
}
scrollToBottom() {
if (this.#destroyed_) {
return;
}
const { selection, session } = this.#editor_;
this.#editor_.updateSelectionMarkers();
this.#editor_.gotoLine(session.getLength());
selection.moveCursorLineEnd();
}
scrollToTop() {
if (this.#destroyed_) {
return;
}
this.#editor_.gotoLine(0);
}
#addDefaultCommand_() {
const { commands } = this.#editor_;
commands.addCommands([{
name: "increaseFontSize",
bindKey: "Ctrl-=|Ctrl-+",
exec: (editor) => {
this.increaseFontSize();
}
}, {
name: "decreaseFontSize",
bindKey: "Ctrl+-|Ctrl-_",
exec: (editor) => {
this.decreaseFontSize();
}
}, {
name: "resetFontSize",
bindKey: "Ctrl+0|Ctrl-Numpad0",
exec: (editor) => {
this.resetFontSize();
}
}, {
name: "mixly-message",
bindKey: "backspace|delete|enter",
readOnly: true,
exec: (editor) => {
if (!editor.getReadOnly()) {
return false;
}
this.#cursorLayer_.show();
return false;
}
}]);
}
#addCursorLayer_() {
this.#cursorLayer_ = tippy(this.getContent().find('.ace_cursor')[0], {
content: Msg.Lang['editor.viewReadOnly'],
trigger: 'manual',
hideOnClick: true,
delay: 0,
duration: [ 0, 0 ],
placement: 'right',
offset: [ 0, 0 ],
popperOptions: {
strategy: 'fixed',
modifiers: [
{
name: 'flip',
options: {
fallbackPlacements: ['top-end', 'right']
}
}
]
}
});
}
#addCursorEventsListener_() {
const editor = this.getEditor();
$('#mixly-footer-cursor').hide();
editor.on('focus', () => {
const cursor = selection.getCursor();
$('#mixly-footer-row').html(cursor.row + 1);
$('#mixly-footer-column').html(cursor.column + 1);
$('#mixly-footer-cursor').show();
});
editor.on("blur", () => {
this.#cursorLayer_.hide();
$('#mixly-footer-cursor').hide();
});
const { selection } = editor.getSession();
const { session } = editor;
selection.on('changeCursor', () => {
const cursor = selection.getCursor();
$('#mixly-footer-row').html(cursor.row + 1);
$('#mixly-footer-column').html(cursor.column + 1);
});
selection.on("changeSelection", () => {
if (selection.isEmpty()) {
$('#mixly-footer-selected').parent().hide();
} else {
const range = selection.getRange();
const text = session.getTextRange(range);
$('#mixly-footer-selected').parent().css('display', 'inline-flex');
$('#mixly-footer-selected').html(text.length);
}
});
session.on("changeScrollTop", () => {
this.#cursorLayer_.hide();
});
}
addCtrlBtns() {
const $content = this.getContent();
for (let mId of EditorAce.CTRL_BTNS) {
$content.append(XML.render(EditorAce.CTRL_BTN_TEMPLATE, { mId }));
}
this.$ctrlBtns = $content.children('.code-editor-btn');
this.$ctrlBtns.off().click((event) => {
const mId = $(event.target).attr('m-id');
this[mId]();
});
}
showCtrlBtns() {
this.$ctrlBtns.css('display', 'block');
}
hideCtrlBtns() {
this.$ctrlBtns.css('display', 'none');
}
resetFontSize() {
this.#editor_.setFontSize(17);
}
increaseFontSize() {
const size = parseInt(this.#editor_.getFontSize(), 10) || 17;
this.#editor_.setFontSize(size + 1);
}
decreaseFontSize() {
const size = parseInt(this.#editor_.getFontSize(), 10) || 17;
this.#editor_.setFontSize(Math.max(size - 1 || 1));
}
undo() {
super.undo();
this.#editor_.undo();
}
redo() {
super.redo();
this.#editor_.redo();
}
setReadOnly(status) {
this.#editor_.setReadOnly(status);
}
setMode(type) {
this.#editor_.session.setMode(`ace/mode/${type}`);
}
setFileMode(extname) {
const mode = this.getFileMode(extname) ?? 'text';
this.setMode(mode);
}
getFileMode(extname) {
for (const [mode, extensions] of Object.entries(EditorAce.MODE_MAP)) {
if (extensions.includes(extname)) {
return mode;
}
}
return null;
}
cut() {
const { selection, session } = this.#editor_;
const cutLine = selection.isEmpty();
const range = cutLine ? selection.getLineRange() : selection.getRange();
this.#editor_._emit('cut', range);
if (!range.isEmpty()) {
const copyText = session.getTextRange(range);
navigator.clipboard.writeText(copyText)
.then(() => {
Debug.log('clipboard复制成功', copyText);
}).catch((error) => {
Debug.error('clipboard复制失败', error);
});
session.remove(range);
}
this.#editor_.clearSelection();
}
copy() {
const copyText = this.#editor_.getSelectedText();
this.#editor_.clearSelection();
if (!copyText) {
return;
}
navigator.clipboard.writeText(copyText)
.then(() => {
Debug.log('clipboard复制成功', copyText);
}).catch((error) => {
Debug.error('clipboard复制失败', error);
});
}
paste() {
navigator.clipboard.readText()
.then((message) => {
this.#editor_.execCommand('paste', message);
Debug.log('clipboard粘贴成功', message);
})
.catch((error) => {
Debug.error('clipboard粘贴失败', error);
});
}
commentLine() {
this.#editor_.execCommand('togglecomment');
}
blockComment() {
this.#editor_.execCommand('toggleBlockComment');
}
resize() {
this.#editor_.resize();
super.resize();
}
focus() {
this.#editor_.focus();
}
onUnmounted() {
this.scrollToTop();
super.onUnmounted();
}
}
Mixly.EditorAce = EditorAce;
});