/*
* Copyright 2016 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Tool showing the script text input to type into.
* @private
*/
Ext.define('Ametys.plugins.coreui.script.ScriptTool',
{
extend: 'Ametys.tool.Tool',
/**
* The number of lines in the editor footer, currently forced at 3.
* @private
*/
_footerLineCount: 3,
/**
* Toggle the edition of the header and footer of the editor
* @private
*/
_allowHeaderFooterEdit: false,
createPanel: function()
{
var footerLine1 = "{{i18n PLUGINS_CORE_UI_TOOLS_SCRIPT_FOOTER_HINT_LINE1}}".replace(/\r\n|\r|\n/, "");
var footerLine2 = "{{i18n PLUGINS_CORE_UI_TOOLS_SCRIPT_FOOTER_HINT_LINE2}}".replace(/\r\n|\r|\n/, "");
this.scriptEditor = Ext.create('Ametys.form.field.CodeAdvanced', {
mode: 'typescript',
stateful: true,
stateId: this.getId() + "$code",
cls: "uitool-script-editor",
value: "function main() {\n \n \n \n \n}\n" + footerLine1 + "\n" + footerLine2,
listeners: {
beforechange: {
fn: function (editor, newValue, oldValue, event) {
if (!this._allowHeaderFooterEdit
&& event.changes.filter(change => change.range.startLineNumber == 1 || change.range.endLineNumber > oldValue.split("\n").length - this._footerLineCount).length > 0)
{
let me = this;
window.setTimeout(function() { me._updateDecorations(editor); }, 1); // Depending on the modification we refuse, the decoration may be destroyed... (select a few line including the last ones, and type one character for example)
return false;
}
},
scope: this
},
change: {
fn: function (editor, newValue, oldValue) {
this._updateDecorations(editor);
},
scope: this
},
initialize: {
fn: function (editor) {
let me = this;
window.setTimeout(function() { me._updateDecorations(editor); }, 0);
let ed = editor._monaco;
// Replace the default Ctrl+A
ed.addAction({
id: 'custom-select-all',
label: 'Select All Editable',
keybindings: [
monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyA
],
precondition: null,
keybindingContext: null,
run: function(ed) { me._selectAll(); }
});
// load definition for Ametys API
Ametys.data.ServerComm.send({
plugin: 'core-ui',
url: 'script/typescript-definitions.d.ts',
callback: {
handler: function(response)
{
monaco.languages.typescript.javascriptDefaults.addExtraLib(response.textContent, 'ts:ametys.d.ts');
monaco.languages.typescript.typescriptDefaults.addExtraLib(response.textContent, 'ts:ametys.d.ts');
},
scope: this
},
responseType: 'text',
waitMessage: { target: me.getContentPanel() },
errorMessage: true
});
},
scope: this
}
}
});
this._panel = Ext.create('Ext.panel.Panel', {
layout: 'fit',
scrollable: false,
cls: 'uitool-script',
items: this.scriptEditor
});
return this._panel;
},
getMBSelectionInteraction: function()
{
return Ametys.tool.Tool.MB_TYPE_NOSELECTION;
},
getType: function()
{
return Ametys.tool.Tool.TYPE_SCRIPT;
},
/**
* Called by the key binding Ctrl-A, overrides the default selection to only the editable lines.
* @private
*/
_selectAll: function(cm)
{
if (this.scriptEditor)
{
let ed = this.scriptEditor._monaco;
var model = ed.getModel();
var totalLines = model.getLineCount();
var startLine = 2; // Ligne après le header
var endLine = totalLines - this._footerLineCount; // Ligne avant le footer
if (endLine >= startLine) {
var endColumn = model.getLineMaxColumn(endLine);
ed.setSelection(new monaco.Range(startLine, 1, endLine, endColumn));
ed.revealLineInCenter(startLine);
}
}
},
_updateDecorations: function(editor)
{
let model = editor._monaco.getModel();
let totalLines = model.getLineCount();
let decorations = [];
// Décoration pour la première ligne
decorations.push({
range: new monaco.Range(1, 1, 1, model.getLineMaxColumn(1)),
options: {
isWholeLine: true,
className: 'code-readonly-line',
glyphMarginClassName: 'code-readonly-glyph'
}
});
// Décoration pour les dernières lignes (footer)
for (var i = 0; i < this._footerLineCount; i++)
{
var lineNumber = totalLines - this._footerLineCount + i + 1;
decorations.push({
range: new monaco.Range(lineNumber, 1, lineNumber, model.getLineMaxColumn(lineNumber)),
options: {
isWholeLine: true,
className: 'code-readonly-line',
glyphMarginClassName: 'code-readonly-glyph'
}
});
}
// Appliquer les décorations
this._decorationIds = model.deltaDecorations(this._decorationIds || [], decorations);
}
});