/**
* Refer to <span color = "yellow">{@link ve.Component}</span> for methods or fields inherited from this Component's parent such as `.options.attributes` or `.element`.
*
* Visual block-based and code-based IDE used to assemble `.js` script files. ES6 compatible; non-compatible files will degrade to code editor only.
*
* **Note:** Declaring duplicate ve.ScriptManager components will reset the main Blockly workspace for each new instance.
* - Functional binding: <span color=00ffff>veScriptManager</span>().
* - This component has special default settings located in {@link ve.registry.settings.ScriptManager}.
*
* ##### Constructor:
* - `arg0_value`: {@link string} - The code to load into the present ve.ScriptManager.
* - `arg1_options`: {@link Object}
* - `.do_not_auto_detect_project=false`: {@link boolean} - Whether to attempt to read from the base `.ve-sm` file upon initialisation.
* - `.do_not_cache_file_explorer=false`: {@link boolean} - Whether the file directory should remain the same as when last opened.
* - `.do_not_display_file_name=false`: {@link boolean}
* - `.do_not_display_project_name=false`: {@link boolean}
* - `.folder_path=process.cwd()`: {@link string}
* - `.save_extension=[".*"]`: {@link Array}<{@link string}>
* - `.settings`: {@link Object}
* - `.autosave_projects=true`: {@link boolean}
* - `.display_load_errors=false`: {@link boolean}
* - `.monaco_theme="nord"`: {@link string}
* - `.index_documentation=true`: {@link boolean}
* - `.log_large_objects_in_console=false`: {@link boolean}
* - `.manual_synchronisation`: {@link true}
* - `.scene_height=0`: {@link number} - The scene height of the main workspace in px.
* - `.theme="theme-default"`: {@link string} - Either 'theme-default'/'theme-light'
* - `.view_file_explorer=true`: {@link boolean}
*
* ##### Instance:
* - `.console_el`: {@link HTMLElement}
* - `.print`: {@link function}(arg0_message:{@link string}, arg1_type:{@link string}) - arg1_type is either 'message'/'error'.
* - `._file_path`: {@link string} - The file path currently opened.
* - `.leftbar_file_explorer`: {@link ve.FileExplorer}
* - `.scene_blockly`: {@link ve.ScriptManagerBlockly}
* - `.scene_monaco`: {@link ve.ScriptManagerMonaco}
* - `.scene_interface`: {@link ve.FlexInterface}
* - `.v`: {@link string}
*
* Private Fields:
* - `._monaco_themes`: {@link Object}<{@link string}>
* - `._settings`: {@link Object}
*
* ##### Methods:
* - <span color=00ffff>{@link ve.ScriptManager.loadSettings|loadSettings}</span>(arg0_settings:{@link Object})
* - <span color=00ffff>{@link ve.ScriptManager.saveSettings|saveSettings}</span>() | {@link string}
* - <span color=00ffff>{@link ve.ScriptManager.setCodeEditorTheme|setCodeEditorTheme}</span>(arg0_theme_class:{@link string})
* - <span color=00ffff>{@link ve.ScriptManager.setTheme|setTheme}</span>(arg0_theme_class:{@link string})
* - <span color=00ffff>{@link ve.ScriptManager.throwLoadError|throwLoadError}</span>(arg0_error:{@link Error}|{@link string})
*
* @augments ve.Component
* @memberof ve.Component
* @type {ve.ScriptManager}
*/
ve.ScriptManager = class extends ve.Component {
static excluded_from_demo = true;
static instances = [];
constructor (arg0_value, arg1_options) {
//Convert from parameters
let value = arg0_value;
let options = (arg1_options) ? arg1_options : {};
super(options);
//Initialise options
options.attributes = (options.attributes) ? options.attributes : {};
if (options.name === undefined) options.name = loc("ve.registry.localisation.ScriptManager_name_default");
if (options.style === undefined) options.style = {};
//Declare local instance variables
this._monaco_themes = ve.ScriptManager._getMonacoThemes();
this._selected_view = "monaco";
this._settings = {
is_vercengen_script_manager_settings: true,
//Project
project_folder: "none",
//Settings
autosave_projects: true,
index_documentation: true,
log_large_objects_in_console: false,
manual_synchronisation: true,
scene_height: 0,
//View
display_load_errors: false,
monaco_theme: "nord",
theme: "theme-default",
view_file_explorer: true
};
this.config = {
files: {}
};
this.id = Class.generateRandomID(ve.ScriptManager);
this.options = options;
//Load console channel for ScriptManager
if (!log.scriptmanager) new log.Channel("scriptmanager", { colour: "powderblue" });
let scriptmanager_settings = ve.registry.settings.ScriptManager;
//Load settings from save file if available
if (scriptmanager_settings.save_file !== false)
if (fs.existsSync(scriptmanager_settings.save_file))
this.loadSettings(JSON.parse(fs.readFileSync(scriptmanager_settings.save_file, "utf8")));
if (scriptmanager_settings.share_settings_across_instances)
if (ve.ScriptManager.instances.length > 0)
this._settings = ve.ScriptManager.instances[0]._settings;
if (this.options.settings)
this._settings = {
...this._settings,
...this.options.settings
};
try { Blockly.mainWorkspace.clear(); } catch (e) {}
this.element = document.createElement("div");
this.element.setAttribute("component", "ve-script-manager");
this.element.instance = this;
this.element.style.padding = "0";
if (this.options.attributes)
Object.iterate(this.options.attributes, (local_key, local_value) => {
this.element.setAttribute(local_key, local_value.toString());
});
this.container_el = document.createElement("div");
this.container_el.id = "container";
this.leftbar_el = document.createElement("div");
this.leftbar_el.id = "leftbar";
let file_components_obj = {
context_menu: new ve.Button((v, e) => {
let local_hierarchy_datatype = e.owners[e.owners.length - 2];
let default_file_extension = "";
let is_file = local_hierarchy_datatype.element.getAttribute("data-file");
let local_file_path = local_hierarchy_datatype.element.getAttribute("data-path");
let local_file_obj = (this.config.files[local_file_path]) ?
this.config.files[local_file_path] : {};
if (is_file)
default_file_extension = ve.ScriptManager._getFileExtension(path.extname(local_file_path));
if (this.file_context_menu) this.file_context_menu.close();
this.file_context_menu = new ve.ContextMenu({
override_file_type: new ve.Select(ve.ScriptManager._getFileExtensions({ return_select_obj: true }), {
name: loc("ve.registry.localisation.ScriptManager_mark_as_file_type"),
limit: () => is_file,
selected: (local_file_obj.type) ? local_file_obj.type : default_file_extension,
onuserchange: (v) => ve.ScriptManager._setFileExtension.call(this, local_file_path, v)
}),
mark_source_as_excluded: new ve.Button(() => {
ve.ScriptManager._setSourceAsMode.call(this, local_file_path, "excluded");
}, {
name: loc("ve.registry.localisation.ScriptManager_mark_excluded"),
style: {
textAlign: "left",
whiteSpace: "nowrap"
}
}),
mark_source_as_included: new ve.Button(() => {
ve.ScriptManager._setSourceAsMode.call(this, local_file_path, "default");
}, {
name: loc("ve.registry.localisation.ScriptManager_mark_included"),
style: {
textAlign: "left",
whiteSpace: "nowrap"
}
})
}, {
id: "ScriptManager_file_context_menu",
width: "20rem"
});
}, {
name: "<icon>more_vert</icon>",
tooltip: loc("ve.registry.localisation.ScriptManager_tooltip_edit_properties"),
style: {
paddingBottom: `var(--cell-padding)`,
paddingTop: `var(--cell-padding)`
}
})
};
this.leftbar_file_explorer = new ve.FileExplorer((this.options.folder_path) ? this.options.folder_path : process.cwd(), {
actions_components_obj: {
set_project_folder: new ve.Button(() => {
let new_folder_path = path.resolve(this.leftbar_file_explorer.v);
this.config.project_folder = new_folder_path;
ve.ScriptManager._indexDocumentation.call(this, this.bottombar_status_el);
ve.ScriptManager._saveConfig.call(this);
veToast(loc("ve.registry.localisation.ScriptManager_toast_changed_project_folder", new_folder_path));
}, {
name: "<icon>gite</icon>",
tooltip: loc("ve.registry.localisation.ScriptManager_tooltip_set_project_folder"),
limit: () => (path.resolve(this.leftbar_file_explorer.v) !== this.config.project_folder)
})
},
file_components_obj: {
...file_components_obj
},
folder_components_obj: { //[WIP] - Implement context menu to exclude/include folders
...file_components_obj
},
load_function: (arg0_data, arg1_file_path) => {
//Convert from parameters
let local_data = arg0_data;
let file_path = arg1_file_path;
//Load file if possible
this.loadFile(file_path, local_data);
},
save_extension: (this.options.save_extension) ? this.options.save_extension : [".*"],
save_function: (arg0_save_name) => {
this._file_path = arg0_save_name;
this.bottombar_obj.addFile(this._file_path);
//Return statement
return this.scene_monaco.v;
},
onrefresh: (v, e) => ve.ScriptManager._drawFileExplorer.call(this, v, e),
onuserchange: (v) => {
this.config._leftbar_file_explorer_path = v;
ve.ScriptManager._saveConfig.call(this);
}
});
this.leftbar_file_explorer.bind(this.leftbar_el);
this.scene_el = document.createElement("div");
this.scene_el.id = "scene";
this.scene_blockly = new ve.ScriptManagerBlockly(undefined, {
script_manager: this,
onload: (v, e) => {
e.element.addEventListener("click", (e) => {
if (this._selected_view && this._selected_view === "monaco")
if (this._settings.manual_synchronisation && this._monaco_change)
ve.ScriptManager._synchroniseViews.call(this, "monaco");
this.scene_el.setAttribute("data-selected-view", "blockly");
this._selected_view = "blockly";
});
},
onuserchange: (v, e) => {
this._blockly_change = true;
}
});
this.scene_blockly_el = this.scene_blockly.element;
this.scene_blockly_el.id = "scene-blockly";
this.scene_monaco = new ve.ScriptManagerMonaco(undefined, {
script_manager: this,
theme: this._settings.monaco_theme,
onload: (v, e) => {
e.element.addEventListener("click", (e) => {
if (this._selected_view && this._selected_view === "blockly")
if (this._settings.manual_synchronisation && this._blockly_change)
ve.ScriptManager._synchroniseViews.call(this, "blockly");
this.scene_el.setAttribute("data-selected-view", "monaco");
this._selected_view = "monaco";
});
},
onuserchange: (v, e) => {
this._monaco_change = true;
if (this._settings.autosave_projects)
ve.ScriptManager._autosave.call(this);
}
});
this.scene_monaco_initialisation_loop = setInterval(() => {
try {
this.scene_monaco.editor.addAction({
id: "open-project-find-and-replace",
label: loc("ve.registry.localisation.ScriptManager_action_find_replace"),
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KeyF],
contextMenuGroupId: "1_modification",
run: (ed) => {
this._openFindAndReplace.call(this);
}
});
clearInterval(this.scene_monaco_initialisation_loop);
delete this.scene_monaco_initialisation_loop;
} catch (e) {}
}, 100);
this.scene_monaco_el = this.scene_monaco.element;
this.scene_monaco_el.id = "scene-monaco";
this.scene_tabs_el = document.createElement("div");
this.scene_tabs_el.id = "scene-tabs";
//Initialise scene_interface now, but only append its components upon this.scriptmanager_initialisation_loop
this.scene_interface = new ve.FlexInterface({
type: "horizontal",
blockly: this.scene_blockly,
monaco: this.scene_monaco
}, {
name: "ScriptManagerInterface",
});
this.scene_el.append(this.scene_interface.element, this.scene_tabs_el);
this.topbar_el = document.createElement("div");
this.topbar_el.id = "topbar";
this.topbar_interface = new ve.RawInterface({
name_el: new ve.HTML(() => {
return [
//ScriptManager .name
`<span id = "name">${this.name}</span>`,
//Project Header
`${(!options.do_not_display_project_name) ? `<div id = "project-name"><b>${(this.config.project_folder && this.config.project_folder !== "none") ? this.config.project_folder : loc("ve.registry.localisation.ScriptManager_no_project")}</b></div>` : ""}`,
//File Header
`${(!options.do_not_display_file_name) ? `- <span id = "file-name" data-is-saved="${this._is_file_saved}">${(this._file_path) ? this._file_path : loc("ve.registry.localisation.ScriptManager_none")}</span>` : ""}`
].join("");
},
{ style: { marginRight: "1rem", overflow: "clip", width: "19rem" } }),
settings: new ve.Button(() => {
if (this.settings_window) this.settings_window.close();
this.settings_window = new ve.Window({
appearance: new ve.Interface({
background: new ve.Text(this._settings.background_image, {
name: loc("ve.registry.localisation.ScriptManager_background"),
onuserchange: (v) => {
if (v.isURL()) v = `url(${v})`;
this._settings.background_image = v;
this.loadSettings({ background_image: this._settings.background_image });
},
style: {
'input[type="text"]': { maxWidth: "20rem" }
}
}),
background_colour: new ve.Colour(this._settings.background_colour, {
name: loc("ve.registry.localisation.ScriptManager_background_colour"),
onuserchange: (v, e) => {
this._settings.background_colour = e.getHex();
this.loadSettings({ background_colour: this._settings.background_colour });
}
}),
background_opacity: new ve.Range(Math.returnSafeNumber(this._settings.background_opacity, 0.5), {
name: loc("ve.registry.localisation.ScriptManager_background_opacity"),
onuserchange: (v) => {
this._settings.background_opacity = v;
this.loadSettings({ background_opacity: this._settings.background_opacity });
}
}),
scene_height: new ve.Number(Math.returnSafeNumber(this._settings.scene_height, 0), {
name: loc("ve.registry.localisation.ScriptManager_scene_height_px"),
min: 0,
onuserchange: (v) => {
if (v === 0) {
delete this.options.style.height;
} else {
this.options.style.height = `${v}px`;
}
this._settings.scene_height = v;
this._drawHeight();
}
}),
}, { name: loc("ve.registry.localisation.ScriptManager_appearance") }),
monaco_settings: this.scene_monaco.drawOptionsInterface({
name: loc("ve.registry.localisation.ScriptManager_editor_code")
}),
features: new ve.Interface({
autosave_projects: new ve.Toggle(this._settings.autosave_projects, {
name: loc("ve.registry.localisation.ScriptManager_autosave_projects"),
onuserchange: (v) => this._settings.autosave_projects = v
}),
index_documentation: new ve.Toggle(this._settings.index_documentation, {
name: loc("ve.registry.localisation.ScriptManager_index_documentation"),
onuserchange: (v) => {
this._settings.index_documentation = v;
if (v) ve.ScriptManager._indexDocumentation.call(this, this.bottombar_status_el);
}
}),
log_large_objects_in_console: new ve.Toggle(this._settings.log_large_objects_in_console, {
name: loc("ve.registry.localisation.ScriptManager_log_large_objects_confirm"),
onuserchange: (v) => this._settings.log_large_objects_in_console = v
}),
manual_synchronisation: new ve.Toggle(this._settings.manual_synchronisation, {
name: loc("ve.registry.localisation.ScriptManager_manual_synchronisation"),
onuserchange: (v) => this._settings.manual_synchronisation = v
}),
}, { name: loc("ve.registry.localisation.ScriptManager_features") }),
actions_bar: new ve.RawInterface({
load_settings: new ve.File(undefined, {
name: loc("ve.registry.localisation.ScriptManager_load_settings"),
do_not_display: true,
onuserchange: (v) => {
let display_error = false;
try {
let settings_obj = JSON.parse(fs.readFileSync(v[0], "utf8"));
if (settings_obj && settings_obj.is_vercengen_script_manager_settings) {
this.loadSettings(settings_obj);
} else {
display_error = true;
}
} catch (e) {
display_error = true;
}
if (display_error)
veWindow(`<span style = "align-items: center; display: flex"><icon>warning</icon> ${loc("ve.registry.localisation.ScriptManager_could_not_load_settings")}</span>`, {
can_rename: false,
name: loc("ve.registry.localisation.ScriptManager_error_loading_settings"),
width: "20rem"
});
},
}),
save_settings: (ve.registry.settings.ScriptManager.save_file === false) ?
new ve.File(undefined, {
name: loc("ve.registry.localisation.ScriptManager_save_settings"),
do_not_display: true,
onuserchange: (v) => {
console.log(v);
},
save_function: () => this.saveSettings()
}) :
new ve.Button(() => {
let dirname = path.dirname(scriptmanager_settings.save_file);
fs.mkdir(dirname, { recursive: true }, (err) => {
if (err) {
console.error(err);
return;
}
fs.writeFileSync(scriptmanager_settings.save_file, this.saveSettings());
veToast(loc("ve.registry.localisation.ScriptManager_saved_settings", scriptmanager_settings.save_file));
});
}, {
name: loc("ve.registry.localisation.ScriptManager_save_settings")
})
}, { name: " ", style: { alignItems: "center", display: "flex" } })
}, { can_rename: false, name: loc("ve.registry.localisation.ScriptManager_settings"), width: "24rem" })
}, { name: loc("ve.registry.localisation.ScriptManager_settings") }),
view: new ve.Button(() => {
//Populate themes_obj
let themes_obj = {};
Object.iterate(this._monaco_themes, (local_key, local_value) => {
themes_obj[local_key] = { name: local_value, selected: (this._settings.monaco_theme === local_key) }
});
let local_context_menu = new ve.ContextMenu({
view_header: new ve.HTML(`<b>${loc("ve.registry.localisation.ScriptManager_view_settings")}</b><br><br>`, { x: 0, y: 0 }),
monaco_theme: new ve.Select({
...themes_obj
}, {
name: loc("ve.registry.localisation.ScriptManager_monaco_theme"),
onchange: (v) => {
this.loadSettings({ monaco_theme: v });
},
x: 0, y: 1
}),
editor_theme: new ve.Select({
"theme-default": {
name: loc("ve.registry.localisation.ScriptManager_theme_default"),
selected: (!["theme-light"].includes(this._settings.theme))
},
"theme-light": {
name: loc("ve.registry.localisation.ScriptManager_theme_light"),
selected: (this._settings.theme === "theme-light")
}
}, {
name: loc("ve.registry.localisation.ScriptManager_editor_theme"),
onchange: (v) => {
this.loadSettings({ theme: v });
},
style: {
alignItems: "center",
display: "flex"
},
x: 0, y: 2
}),
open_project_find_and_replace: new ve.Button(() => {
this._openFindAndReplace.call(this);
}, {
name: loc("ve.registry.localisation.ScriptManager_open_find_replace")
}),
display_load_errors: new ve.Toggle(this._settings.display_load_errors, {
name: loc("ve.registry.localisation.ScriptManager_display_load_errors"),
onuserchange: (v) => this._settings.display_load_errors = v
}),
show_file_explorer: new ve.Toggle(this._settings.view_file_explorer, {
name: loc("ve.registry.localisation.ScriptManager_view_file_explorer"),
onuserchange: (v) => this.loadSettings({ view_file_explorer: v })
})
}, {
id: "script_manager_view",
width: "16rem"
});
}, { name: loc("ve.registry.localisation.ScriptManager_view"), x: 0, y: 2 }),
run: new ve.Button(() => {
let local_context_menu = new ve.ContextMenu({
run_header: new ve.HTML(`<b>${loc("ve.registry.localisation.ScriptManager_view_settings")}</b><br>`, { x: 0, y: 0 }),
warning: new ve.HTML(`<div style = "align-items: center; display: flex"><icon style = "width: auto;">info</icon><b style = "margin-left: calc(var(--padding)*0.5);">${loc("ve.registry.localisation.ScriptManager_note")}</b></div><span>${loc("ve.registry.localisation.ScriptManager_trust_warning")}</span><br><br>`),
run_this_file_button: new ve.Button(() => {
try {
eval(this.v);
} catch (e) {
log.scriptmanager_error(e, "error");
}
}, { name: loc("ve.registry.localisation.ScriptManager_run_current_file") })
}, { id: "script_manager_run" });
}, { name: loc("ve.registry.localisation.ScriptManager_run") }),
console: new ve.Button(() => {
if (this.local_console) this.local_console.close();
this.local_console = new ve.Window({
log: new ve.Log("scriptmanager")
}, {
can_rename: false,
do_not_wrap: true,
name: loc("ve.registry.localisation.ScriptManager_console"),
width: "40rem"
});
}, { name: loc("ve.registry.localisation.ScriptManager_console") })
}, {
no_name_element: true,
is_folder: false
});
this.topbar_interface.bind(this.topbar_el);
this.bottombar_el = document.createElement("div");
this.bottombar_el.id = "bottombar";
this.bottombar_status_el = document.createElement("div");
this.bottombar_status_el.id = "bottombar-status";
this.bottombar_el.appendChild(this.bottombar_status_el);
this.bottombar_obj = new ve.ScriptManager.UI_Bottombar(undefined, {
script_manager: this
});
this.bottombar_el.appendChild(this.bottombar_obj.element);
//Layer 1. Append topbar
this.element.appendChild(this.topbar_el);
//Layer 2. Append leftbar and scene
this.container_el.append(this.leftbar_el, this.scene_el);
this.element.appendChild(this.container_el);
//Layer 3. Append bottombar
this.element.appendChild(this.bottombar_el);
//Initialisation loop for ScriptManager to ensure all requisite elements are loaded first
this.scriptmanager_initialisation_loop = setInterval(() => {
this._drawHeight();
clearInterval(this.scriptmanager_initialisation_loop);
}, 100);
this._is_file_saved = false;
this.logic_loop = setInterval(() => {
ve.ScriptManager._projectLogicLoop.call(this);
if (!this.element.contains(this.scene_blockly.element))
this.scene_interface.v = {
type: "horizontal",
blockly: this.scene_blockly,
monaco: this.scene_monaco
};
}, 100);
//Populate element and initialise handlers
this.name = options.name;
this.from_binding_fire_silently = true;
this.v = value;
delete this.from_binding_fire_silently;
if (!this.options.do_not_auto_detect_project &&
fs.existsSync(path.join(this.leftbar_file_explorer.v, ".ve-sm"))
) {
if (this.config.project_folder === "none") this.config.project_folder = this.leftbar_file_explorer.v;
ve.ScriptManager._loadConfig.call(this, this.options.folder_path);
}
ve.ScriptManager.instances.push(this);
}
/**
* Returns the current output code in the present Component.
* - Accessor of: {@link ve.ScriptManager}
*
* @alias v
* @memberof ve.Component.ve.ScriptManager
* @type {string}
*/
get v () {
//Return statement
return this.scene_monaco.v;
}
/**
* Sets the current output code in the present Component.
* - Accessor of: {@link ve.ScriptManager}
*
* @alias v
* @memberof ve.Component.ve.ScriptManager
*
* @param {string} arg0_value
*/
set v (arg0_value) {
//Convert from parameters
let local_value = (arg0_value) ? arg0_value : "";
//Declare local instance variables
let set_value_loop = setInterval(() => {
this.scene_blockly.show();
if (this.scene_monaco?.editor) try {
//Set new code value
if (!this.scene_blockly._hidden) {
this.scene_blockly.enable();
this.scene_blockly.to_binding_fire_silently = true;
js2blocks.parseCode(local_value);
setTimeout(() => delete this.scene_blockly.to_binding_fire_silently);
}
this.scene_monaco.to_binding_fire_silently = true;
this.scene_monaco.v = local_value;
delete this.scene_monaco.to_binding_fire_silently;
this.fireFromBinding();
clearInterval(set_value_loop);
} catch (e) {
clearInterval(set_value_loop);
//Log error to console if this._settings.display_load_errors is true
if (this._settings.display_load_errors)
log.scriptmanager(loc("ve.registry.localisation.ScriptManager_error_parsing_es6", e.toString()), "error");
//Hide Blockly workspace, then clear it
this.scene_blockly.hide();
this.scene_blockly.enable();
js2blocks.parseCode("");
this.scene_blockly.disable();
//Load the file to the text editor instead (graceful degradation)
this.scene_blockly.disable();
this.scene_monaco.to_binding_fire_silently = true;
this.scene_monaco.v = local_value;
delete this.scene_monaco.to_binding_fire_silently;
this.fireFromBinding();
}
});
}
_drawHeight () {
//Declare local instance variables
let svg_el = this.scene_blockly_el.querySelector("svg");
let svg_rect = svg_el.getBoundingClientRect();
//Set new height
if (!this.options?.style?.height) {
this.scene_interface.element.style.height = `${svg_rect.height}px`;
this.leftbar_file_explorer.element.style.height = `${svg_rect.height}px`;
} else {
setTimeout(() => {
this.scene_blockly.max_height = this.options.style.height;
svg_el.style.maxHeight = this.options.style.height;
}, 100)
this.scene_interface.element.style.height = this.options.style.height;
this.leftbar_file_explorer.element.style.height = this.options.style.height;
}
}
loadFile (arg0_file_path, arg1_file_data, arg2_do_not_add_to_bottombar) {
//Convert from parameters
let file_path = path.resolve(arg0_file_path);
let file_data = arg1_file_data;
let do_not_add_to_bottombar = arg2_do_not_add_to_bottombar;
if (!fs.existsSync(file_path)) return; //Internal guard clause if file path doesn't exist
//Declare local instance variables
try {
let actual_file_data = (file_data) ? file_data : fs.readFileSync(file_path, "utf8");
this._file_path = file_path;
this.v = actual_file_data;
//Load proper syntax highlighting; bottombar
ve.ScriptManager._loadFileExtension.call(this, path.extname(this._file_path));
if (!do_not_add_to_bottombar)
this.bottombar_obj.addFile(this._file_path);
this.fireToBinding();
} catch (e) {}
}
/**
* Loads a new settings object and refreshes the present Component to display them, then sets {@link this._settings}.
* - Method of: {@link ve.ScriptManager}
*
* @alias loadSettings
* @memberof ve.Component.ve.ScriptManager
*
* @param {Object} [arg0_settings]
* @param {string} [arg0_settings.project_folder]
* @param {string} [arg0_settings.monaco_theme] - One of the default Monaco themes or a custom JSON theme name.
* @param {boolean} [arg0_settings.hide_blockly]
* @param {number} [arg0_settings.scene_height]
* @param {theme} [arg0_settings.theme] - Either 'theme-default'/'theme-light'
* @param {boolean} [arg0_settings.view_file_explorer] - Whether to show the file explorer.
* @param {boolean} arg1_loaded
*/
loadSettings (arg0_settings, arg1_loaded) {
//Convert from parameters
let settings_obj = arg0_settings;
let loaded = (arg1_loaded) ? arg1_loaded : [];
if (loaded.includes(this.id)) return; //Internal guard clause if this instance has already been loaded this call
//Declare local instance variables; parse settings
let scriptmanager_settings = ve.registry.settings.ScriptManager;
let settings_apply_loop = setInterval(() => {
try {
if (settings_obj.background_colour !== undefined)
this.element.style.setProperty("--ve-sm-background-colour", settings_obj.background_colour);
if (settings_obj.background_opacity !== undefined) {
this.element.style.setProperty("--ve-sm-background-opacity", `${settings_obj.background_opacity*100}%`);
} else {
this.element.style.setProperty("--ve-sm-background-opacity", "50%");
}
if (settings_obj.background_image !== undefined)
if (settings_obj.background_image.length !== 0) {
this.element.setAttribute("data-background-image", settings_obj.background_image);
this.element.style.setProperty("--ve-sm-background-image", settings_obj.background_image);
} else {
this.element.style.removeProperty("--ve-sm-background-image");
this.element.removeAttribute("data-background-image");
}
if (settings_obj.project_folder)
settings_obj.project_folder = (fs.existsSync(settings_obj.project_folder) && fs.statSync(settings_obj.project_folder).isDirectory()) ?
settings_obj.project_folder : "none";
if (settings_obj.monaco_theme)
this.setCodeEditorTheme(settings_obj.monaco_theme);
if (settings_obj.hide_blockly !== undefined) {
if (settings_obj.hide_blockly === true) {
//this.scene_interface.v = {
// type: "horizontal",
// monaco: this.scene_monaco
//};
//this.scene_blockly.hide();
} else {
this.scene_interface.v = {
type: "horizontal",
blockly: this.scene_blockly,
monaco: this.scene_monaco
};
this.scene_blockly.show();
}
}
if (settings_obj.scene_height) {
if (!this.options.style) this.options.style = {};
this.options.style.height = `${settings_obj.scene_height}px`;
this._drawHeight();
}
if (settings_obj.theme)
this.setTheme(settings_obj.theme);
if (settings_obj.view_file_explorer !== undefined)
this.leftbar_el.style.display = (settings_obj.view_file_explorer) ? "block" : "none";
//Monaco Settings
if (settings_obj.monaco)
this.scene_monaco.setOptions(settings_obj.monaco);
clearInterval(settings_apply_loop);
} catch (e) {}
}, 100);
//Set this._settings
this._settings = {
...this._settings,
...settings_obj
};
loaded.push(this.id);
//Apply this._settings to all other instances if shared
if (scriptmanager_settings.share_settings_across_instances)
for (let i = 0; i < ve.ScriptManager.instances.length; i++)
if (ve.ScriptManager.instances[i].id !== this.id)
ve.ScriptManager.instances[i].loadSettings(this._settings, loaded);
}
/**
* Returns the present {@link this._settings} as a string.
* - Method of: {@link ve.ScriptManager}
*
* @alias saveSettings
* @memberof ve.Component.ve.ScriptManager
*
* @returns {string}
*/
saveSettings () {
//Return statement
return JSON.stringify(this._settings);
}
/**
* Sets the present code editor theme.
* - Method of: {@link ve.ScriptManager}
*
* @alias setCodeEditorTheme
* @memberof ve.Component.ve.ScriptManager
*
* @param {string} arg0_theme_class
*/
setCodeEditorTheme (arg0_theme_class) {
//Convert from parameters
let theme_class = arg0_theme_class;
//Declare local instance variables
this._settings.monaco_theme = theme_class;
this.scene_monaco.setTheme(theme_class);
}
/**
* Sets the theme of the overall editor.
* - Method of: {@link ve.ScriptManager}
*
* @alias setTheme
* @memberof ve.Component.ve.ScriptManager
*
* @param {string} arg0_theme_class - Either 'theme-default'/'theme-light'
*/
setTheme (arg0_theme_class) {
//Convert from parameters
let theme_class = arg0_theme_class;
//Remove previous themes
if (this._settings.theme) {
let all_classes = this.element.getAttribute("class");
if (all_classes) {
all_classes = all_classes.split(" ");
//Iterate over all_classes and remove all previous themes
for (let i = all_classes.length - 1; i >= 0; i--)
if (all_classes[i].startsWith("theme-"))
all_classes.splice(i, 1);
this.element.setAttribute("class", all_classes.join(" "));
}
}
this._settings.theme = theme_class;
//Apply new theme
this.element.classList.add(this._settings.theme);
this.scene_blockly.setTheme(this._settings.theme);
}
/**
* Displays a load error window given an error, or a variable that resolves to a {@link string}.
* - Method of: {@link ve.ScriptManager}
*
* @alias throwLoadError
* @memberof ve.Component.ve.ScriptManager
*
* @param {Error|string} arg0_error
*/
throwLoadError (arg0_error) {
//Convert from parameters
let error = arg0_error;
//Instantiate load message popup
veWindow(`${loc("ve.registry.localisation.ScriptManager_error_compatibility", (this.options.compatibility_message) ? this.options.compatibility_message : "ES6")}<br><br><div style = "align-items: center; display: flex;"><icon>warning</icon> ${error}</div><br><b>${loc("ve.registry.localisation.ScriptManager_stack_trace")}</b><br><div style = "margin-left: 1rem;">${error.stack}</div>`, {
name: loc("ve.registry.localisation.ScriptManager_error_reading_file"),
width: "24rem"
});
}
};
//Functional binding
/**
* @returns {ve.ScriptManager}
*/
veScriptManager = function () {
//Return statement
return new ve.ScriptManager(...arguments);
};