Improve some tags + add features to codepad

- Improve Resizer + TabContainer tag
- Add bottom bar to the CodePad editor
This commit is contained in:
lxsang 2020-12-16 00:57:29 +01:00
parent 9d5a0b404c
commit 6c935e88ee
8 changed files with 422 additions and 79 deletions

View File

@ -87,7 +87,7 @@ namespace OS {
* @param {*} [d] * @param {*} [d]
* @memberof ResizerTag * @memberof ResizerTag
*/ */
protected reload(d?: any): void {} protected reload(d?: any): void { }
/** /**
* Setter: * Setter:
* *
@ -133,6 +133,23 @@ namespace OS {
return $(this).attr("dir"); return $(this).attr("dir");
} }
/**
* Getter : Check whether the resizer should attach to its next or previous element
*
* Setter: if `v=true` select next element as attached element of the resizer, otherwise
* select the previous element
* @readonly
* @type {boolean}
* @memberof ResizerTag
*/
get attachnext(): boolean {
return this.hasattr("attachnext");
}
set attachnext(v: boolean) {
this.attsw(v, "attachnext");
}
/** /**
* Setter: * Setter:
* - set the resize event callback * - set the resize event callback
@ -158,10 +175,19 @@ namespace OS {
protected mount(): void { protected mount(): void {
$(this).css(" display", "block"); $(this).css(" display", "block");
const tagname = $(this._parent).prop("tagName"); const tagname = $(this._parent).prop("tagName");
this._resizable_el = if (this.attachnext) {
$(this).prev().length === 1 this._resizable_el =
? $(this).prev()[0] $(this).next().length === 1
: undefined; ? $(this).next()[0]
: undefined;
}
else {
this._resizable_el =
$(this).prev().length === 1
? $(this).prev()[0]
: undefined;
}
if (tagname === "AFX-HBOX") { if (tagname === "AFX-HBOX") {
this.dir = "hz"; this.dir = "hz";
} else if (tagname === "AFX-VBOX") { } else if (tagname === "AFX-VBOX") {
@ -217,7 +243,13 @@ namespace OS {
return; return;
} }
const offset = $(this._resizable_el).offset(); const offset = $(this._resizable_el).offset();
let w = Math.round(e.clientX - offset.left); let w = 0;
if (this.attachnext) {
w = Math.round(offset.left + $(this._resizable_el).width() - e.clientX);
}
else {
w = Math.round(e.clientX - offset.left);
}
if (w < this._minsize) { if (w < this._minsize) {
w = this._minsize; w = this._minsize;
} }
@ -245,7 +277,13 @@ namespace OS {
return; return;
} }
const offset = $(this._resizable_el).offset(); const offset = $(this._resizable_el).offset();
let h = Math.round(e.clientY - offset.top); let h = 0;
if (this.attachnext) {
h = Math.round(offset.top + $(this._resizable_el).height() - e.clientY);
}
else {
h = Math.round(e.clientY - offset.top);
}
if (h < this._minsize) { if (h < this._minsize) {
h = this._minsize; h = this._minsize;
} }

View File

@ -57,7 +57,7 @@ namespace OS {
*/ */
constructor() { constructor() {
super(); super();
this._ontabselect = (e) => {}; this._ontabselect = (e) => { };
} }
/** /**
@ -77,7 +77,7 @@ namespace OS {
* @param {*} [d] * @param {*} [d]
* @memberof TabContainerTag * @memberof TabContainerTag
*/ */
protected reload(d?: any): void {} protected reload(d?: any): void { }
/** /**
* Set the tab select event handle * Set the tab select event handle
@ -166,6 +166,50 @@ namespace OS {
(this.refs.wrapper as TileLayoutTag).calibrate(); (this.refs.wrapper as TileLayoutTag).calibrate();
} }
/**
* Add a new tab with container to the container
*
* item should be in the following format:
*
* ```ts
* {
* text: string,
* icon?: string,
* iconclass?: string,
* container: HTMLElement
* }
* ```
*
* @param {GenericObject<any>} item tab descriptor
* @param {boolean} insert insert the tab content to the container ?
* @memberof TabContainerTag
*/
public addTab(item: GenericObject<any>, insert: boolean): void {
if (insert) {
$(this.refs.yield).append(item.container);
}
$(item.container)
.css("width", "100%")
.css("height", "100%")
.hide();
const el = (this.refs.bar as TabBarTag).push(
item
);
el.selected = true;
}
/**
* Remove a tab from the container
*
* @param {ListViewItemTag} tab the tab item to be removed
* @memberof TabContainerTag
*/
public removeTab(tab: ListViewItemTag): void {
if (tab.data.container) {
$(tab.data.container).remove();
}
(this.refs.bar as TabBarTag).delete(tab);
}
/** /**
* Mount the tag and bind basic events * Mount the tag and bind basic events
* *
@ -194,14 +238,7 @@ namespace OS {
item.iconclass = $(e).attr("iconclass"); item.iconclass = $(e).attr("iconclass");
} }
item.container = e; item.container = e;
$(e) this.addTab(item, false);
.css("width", "100%")
.css("height", "100%")
.hide();
const el = (this.refs.bar as TabBarTag).push(
item
);
el.selected = true;
}); });
}); });

View File

@ -37,6 +37,7 @@ namespace OS {
mimes: ["dir"], mimes: ["dir"],
}) })
.then((d) => { .then((d) => {
this.logger().clear();
return this.mktpl(d.file.path, d.name, true); return this.mktpl(d.file.path, d.name, true);
}); });
} }
@ -48,16 +49,17 @@ namespace OS {
* @memberof AntOSDK * @memberof AntOSDK
*/ */
init(): void { init(): void {
this.logger().clear();
const dir = this.app.currdir; const dir = this.app.currdir;
if (!dir || !dir.basename) { if (!dir || !dir.basename) {
return this.create(); return this.create();
} }
dir.read().then((d) => { dir.read().then((d) => {
if (d.error) { if (d.error) {
return this.notify(__("Cannot read folder: {0}", dir.path)); return this.logger().error(__("Cannot read folder: {0}", dir.path));
} }
if (d.result.length !== 0) { if (d.result.length !== 0) {
return this.notify( return this.logger().error(
__("The folder is not empty: {0}", dir.path) __("The folder is not empty: {0}", dir.path)
); );
} }
@ -71,6 +73,7 @@ namespace OS {
* @memberof AntOSDK * @memberof AntOSDK
*/ */
buildnrun(): void { buildnrun(): void {
this.logger().clear();
this.metadata("project.json") this.metadata("project.json")
.then(async (meta) => { .then(async (meta) => {
try { try {
@ -78,13 +81,13 @@ namespace OS {
try { try {
return this.run(meta); return this.run(meta);
} catch (e) { } catch (e) {
return this.error(__("Unable to run project"), e); return this.logger().error(__("Unable to run project: {0}", e.stack));
} }
} catch (e_1) { } catch (e_1) {
return this.error(__("Unable to build project"), e_1); return this.logger().error(__("Unable to build project: {0}", e_1.stack));
} }
}) })
.catch((e) => this.error(__("Unable to read meta-data"), e)); .catch((e) => this.logger().error(__("Unable to read meta-data: {0}", e.stack)));
} }
/** /**
@ -93,6 +96,7 @@ namespace OS {
* @memberof AntOSDK * @memberof AntOSDK
*/ */
release(): void { release(): void {
this.logger().clear();
this.metadata("project.json") this.metadata("project.json")
.then(async (meta) => { .then(async (meta) => {
try { try {
@ -103,16 +107,16 @@ namespace OS {
`${meta.root}/build/release/${meta.name}.zip` `${meta.root}/build/release/${meta.name}.zip`
); );
} catch (e) { } catch (e) {
return this.error( return this.logger().error(
__("Unable to create package archive"), __("Unable to create package archive: {}",
e e.stack)
); );
} }
} catch (e_1) { } catch (e_1) {
return this.error(__("Unable to build project"), e_1); return this.logger().error(__("Unable to build project: {0}", e_1.stack));
} }
}) })
.catch((e) => this.error(__("Unable to read meta-data"), e)); .catch((e) => this.logger().error(__("Unable to read meta-data: {0}", e.stack)));
} }
// private functions // private functions
@ -153,14 +157,14 @@ namespace OS {
`${rpath}/README.md`.asFileHandle() as application.CodePadFileHandle `${rpath}/README.md`.asFileHandle() as application.CodePadFileHandle
); );
} catch (e) { } catch (e) {
return this.error( return this.logger().error(
__("Unable to create template files"), __("Unable to create template files: {0}",
e e.stack)
); );
} }
}) })
.catch((e) => .catch((e) =>
this.error(__("Unable to create project directory"), e) this.logger().error(__("Unable to create project directory: {0}", e.stack))
); );
} }
@ -178,7 +182,7 @@ namespace OS {
return resolve(); return resolve();
} }
const file = list.splice(0, 1)[0].asFileHandle(); const file = list.splice(0, 1)[0].asFileHandle();
this.notify(__("Verifying: {0}", file.path)); this.logger().info(__("Verifying: {0}", file.path));
return file return file
.read() .read()
.then((data) => { .then((data) => {
@ -214,11 +218,11 @@ namespace OS {
(v: string) => `${meta.root}/${v}` (v: string) => `${meta.root}/${v}`
); );
try { try {
await this.verify(list.map((x: string) =>x)); await this.verify(list.map((x: string) => x));
try { try {
const code = await this.cat(list, ""); const code = await this.cat(list, "");
const jsrc = CoffeeScript.compile(code); const jsrc = CoffeeScript.compile(code);
this.notify(__("Compiled successful")); this.logger().info(__("Compiled successful"));
return resolve(jsrc); return resolve(jsrc);
} catch (e) { } catch (e) {
return reject(__e(e)); return reject(__e(e));
@ -282,7 +286,7 @@ namespace OS {
options options
); );
if (result_1.error) { if (result_1.error) {
this.notify( this.logger().error(
__( __(
"Unable to minify code: {0}", "Unable to minify code: {0}",
result_1.error result_1.error
@ -372,9 +376,9 @@ namespace OS {
if (!v.iconclass && !v.icon) { if (!v.iconclass && !v.icon) {
v.iconclass = "fa fa-adn"; v.iconclass = "fa fa-adn";
} }
this.notify(__("Installing...")); this.logger().info(__("Installing..."));
setting.system.packages[meta.name] = v; setting.system.packages[meta.name] = v;
this.notify(__("Running {0}...", meta.name)); this.logger().info(__("Running {0}...", meta.name));
return GUI.forceLaunch(meta.name, []); return GUI.forceLaunch(meta.name, []);
}); });
} }

View File

@ -74,6 +74,22 @@ namespace OS {
return this.app.error(m, e); return this.app.error(m, e);
} }
/**
*
*
* @protected
* @return {Logger} editor logger
* @memberof BaseExtension
*/
protected logger() {
if(!this.app.setting.showBottomBar)
{
this.app.showBottomBar(true);
}
return this.app.logger;
}
/** /**
* *
* *
@ -272,7 +288,7 @@ namespace OS {
* @memberof BaseExtension * @memberof BaseExtension
*/ */
protected mkar(src: string, dest: string): Promise<any> { protected mkar(src: string, dest: string): Promise<any> {
this.notify(__("Preparing for release")); this.logger().info(__("Preparing for release"));
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
return new Promise(async (r, e) => { return new Promise(async (r, e) => {
try { try {
@ -314,7 +330,7 @@ namespace OS {
.write("base64") .write("base64")
.then((r: any) => { .then((r: any) => {
resolve(); resolve();
return this.notify( return this.logger().info(
__( __(
"Archive is generated at: {0}", "Archive is generated at: {0}",
dest dest

View File

@ -22,6 +22,7 @@ namespace OS {
* @memberof ExtensionMaker * @memberof ExtensionMaker
*/ */
create(): void { create(): void {
this.logger().clear();
this.app this.app
.openDialog("FileDialog", { .openDialog("FileDialog", {
title: "__(New CodePad extension at)", title: "__(New CodePad extension at)",
@ -39,6 +40,7 @@ namespace OS {
* @memberof ExtensionMaker * @memberof ExtensionMaker
*/ */
buildnrun(): void { buildnrun(): void {
this.logger().clear();
this.metadata("extension.json") this.metadata("extension.json")
.then(async (meta) => { .then(async (meta) => {
try { try {
@ -46,13 +48,13 @@ namespace OS {
try { try {
return this.run(meta); return this.run(meta);
} catch (e) { } catch (e) {
return this.error(__("Unable to run extension"), e); return this.logger().error(__("Unable to run extension: {0}", e.stack));
} }
} catch (e_1) { } catch (e_1) {
return this.error(__("Unable to build extension"), e_1); return this.logger().error(__("Unable to build extension: {0}", e_1.stack));
} }
}) })
.catch((e) => this.error(__("Unable to read meta-data"), e)); .catch((e) => this.logger().error(__("Unable to read meta-data:{0}", e.stack)));
} }
/** /**
@ -61,6 +63,7 @@ namespace OS {
* @memberof ExtensionMaker * @memberof ExtensionMaker
*/ */
release(): void { release(): void {
this.logger().clear();
this.metadata("extension.json") this.metadata("extension.json")
.then(async (meta) => { .then(async (meta) => {
try { try {
@ -71,16 +74,16 @@ namespace OS {
`${meta.root}/build/release/${meta.meta.name}.zip` `${meta.root}/build/release/${meta.meta.name}.zip`
); );
} catch (e) { } catch (e) {
return this.error( return this.logger().error(
__("Unable to create archive"), __("Unable to create archive: {0}",
e e.stack
); ));
} }
} catch (e_1) { } catch (e_1) {
return this.error(__("Unable to build extension"), e_1); return this.logger().error(__("Unable to build extension: {0}", e_1.stack));
} }
}) })
.catch((e) => this.error(__("Unable to read meta-data"), e)); .catch((e) => this.logger().error(__("Unable to read meta-data: {0}", e.stack)));
} }
/** /**
@ -89,6 +92,7 @@ namespace OS {
* @memberof ExtensionMaker * @memberof ExtensionMaker
*/ */
install(): void { install(): void {
this.logger().clear();
this.app this.app
.openDialog("FileDialog", { .openDialog("FileDialog", {
title: "__(Select extension archive)", title: "__(Select extension archive)",
@ -97,10 +101,10 @@ namespace OS {
.then(async (d) => { .then(async (d) => {
try { try {
await this.installZip(d.file.path); await this.installZip(d.file.path);
this.notify(__("Extension installed")); this.logger().info(__("Extension installed"));
return this.app.loadExtensionMetaData(); return this.app.loadExtensionMetaData();
} catch (e) { } catch (e) {
return this.error(__("Unable to install extension"), e); return this.logger().error(__("Unable to install extension: {0}", e.stack));
} }
}); });
} }
@ -135,14 +139,14 @@ namespace OS {
`${rpath}/${name}.coffee`.asFileHandle() as application.CodePadFileHandle `${rpath}/${name}.coffee`.asFileHandle() as application.CodePadFileHandle
); );
} catch (e) { } catch (e) {
return this.error( return this.logger().error(
__("Unable to create extension template"), __("Unable to create extension template: {0}",
e e.stack)
); );
} }
}) })
.catch((e) => .catch((e) =>
this.error(__("Unable to create extension directories"), e) this.logger().error(__("Unable to create extension directories: {0}", e.stack))
); );
} }
@ -160,7 +164,7 @@ namespace OS {
return resolve(); return resolve();
} }
const file = list.splice(0, 1)[0].asFileHandle(); const file = list.splice(0, 1)[0].asFileHandle();
this.notify(__("Verifying: {0}", file.path)); this.logger().info(__("Verifying: {0}", file.path));
return file return file
.read() .read()
.then((data) => { .then((data) => {
@ -193,11 +197,11 @@ namespace OS {
(v) => `${meta.root}/${v}` (v) => `${meta.root}/${v}`
); );
try { try {
await this.verify(list.map((x: string) =>x)); await this.verify(list.map((x: string) => x));
try { try {
const code = await this.cat(list, ""); const code = await this.cat(list, "");
const jsrc = CoffeeScript.compile(code); const jsrc = CoffeeScript.compile(code);
this.notify(__("Compiled successful")); this.logger().info(__("Compiled successful"));
return resolve(jsrc); return resolve(jsrc);
} catch (e) { } catch (e) {
return reject(__e(e)); return reject(__e(e));
@ -406,9 +410,8 @@ namespace OS {
*/ */
private installMeta(meta: GenericObject<any>): Promise<any> { private installMeta(meta: GenericObject<any>): Promise<any> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
const file = `${ const file = `${this.app.meta().path
this.app.meta().path }/extensions.json`.asFileHandle();
}/extensions.json`.asFileHandle();
try { try {
const data = await file.read("json"); const data = await file.read("json");
const names = []; const names = [];

View File

@ -10,6 +10,14 @@
<afx-vbox> <afx-vbox>
<afx-tab-bar closable="true" data-height="26" data-id = "tabbar"></afx-tab-bar> <afx-tab-bar closable="true" data-height="26" data-id = "tabbar"></afx-tab-bar>
<div data-id="datarea"></div> <div data-id="datarea"></div>
<afx-resizer data-height = "3" dir = "ve" attachnext = "true" ></afx-resizer>
<afx-tab-container data-id = "bottombar" data-height="150" min-height="150" tabbarheight= "22">
<afx-hbox tabname="__(Output)" iconclass = "fa fa-file-text" class = "bottom-tab-content">
<afx-button text = "" data-id="logger-clear" iconclass="fa fa-trash" data-width="21"></afx-button>
<div data-id="output-tab" iconclass = "fa fa-file-text" >
</div>
</afx-hbox>
</afx-tab-container>
</afx-vbox> </afx-vbox>
</afx-hbox> </afx-hbox>
<div data-height="20" data-id="statctn"> <div data-height="20" data-id="statctn">

View File

@ -1,3 +1,6 @@
afx-app-window[data-id = "codepad"] .ace_editor {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;
}
afx-app-window[data-id = "codepad"] afx-tab-bar> afx-list-view > div.list-container afx-app-window[data-id = "codepad"] afx-tab-bar> afx-list-view > div.list-container
{ {
/*border-top: 1px solid #272822;*/ /*border-top: 1px solid #272822;*/
@ -34,8 +37,14 @@ afx-app-window[data-id = "codepad"] div.afx-window-content {
} }
afx-app-window[data-id = "codepad"] afx-resizer { afx-app-window[data-id = "codepad"] afx-resizer {
background-color:#272822; background-color:#272822;
border-right: 1px solid #37373d; border-right: 1px solid #656565;
border-bottom: 1px solid #656565;
} }
afx-app-window[data-id = "codepad"] .bottom-tab-content {
background-color:#272822;
}
afx-app-window[data-id = "codepad"] .afx-window-wrapper afx-tree-view{ afx-app-window[data-id = "codepad"] .afx-window-wrapper afx-tree-view{
color: white; color: white;
padding: 0; padding: 0;
@ -106,3 +115,31 @@ afx-app-window[data-id = "cmd-win"] input{
afx-app-window[data-id = "cmd-win"] .afx-window-content{ afx-app-window[data-id = "cmd-win"] .afx-window-content{
background-color:#272822; background-color:#272822;
} }
afx-app-window[data-id = "codepad"] div[data-id="output-tab"] {
overflow-y: auto;
overflow-x: hidden;
}
afx-app-window[data-id = "codepad"] div[data-id="output-tab"] pre {
margin: 3px;
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
font-family: monospace;
}
afx-app-window[data-id = "codepad"] div[data-id="output-tab"] pre.code-pad-log-error {
color: red;
}
afx-app-window[data-id = "codepad"] div[data-id="output-tab"] pre.code-pad-log-warn {
color: orange;
}
afx-app-window[data-id = "codepad"] afx-button[ data-id="logger-clear" ] button{
border: 0;
background: transparent;
}

View File

@ -113,6 +113,14 @@ namespace OS {
*/ */
private sidebar: GUI.tag.VBoxTag; private sidebar: GUI.tag.VBoxTag;
/**
* Reference to the bottom bar
*
* @private
* @type {GUI.tag.TabContainerTag}
* @memberof CodePad
*/
private bottombar: GUI.tag.TabContainerTag;
/** /**
* Reference to the editor tab bar UI * Reference to the editor tab bar UI
* *
@ -175,6 +183,15 @@ namespace OS {
*/ */
spotlight: CMDMenu; spotlight: CMDMenu;
/**
* Reference to the editor logger
*
* @type {Logger}
* @memberof CodePad
*/
logger: Logger;
/** /**
* Extension prototype definition will be stored * Extension prototype definition will be stored
* in this class variable * in this class variable
@ -194,6 +211,14 @@ namespace OS {
*/ */
static CMDMenu: typeof CMDMenu; static CMDMenu: typeof CMDMenu;
/**
* Prototype definition of a Logger
*
* @static
* @type {typeof Logger}
* @memberof CodePad
*/
static Logger: typeof Logger;
/** /**
* Prototype definition of CodePad CommandPalette * Prototype definition of CodePad CommandPalette
* *
@ -240,27 +265,29 @@ namespace OS {
this.extensions = {}; this.extensions = {};
this.fileview = this.find("fileview") as GUI.tag.FileViewTag; this.fileview = this.find("fileview") as GUI.tag.FileViewTag;
this.sidebar = this.find("sidebar") as GUI.tag.VBoxTag; this.sidebar = this.find("sidebar") as GUI.tag.VBoxTag;
this.bottombar = this.find("bottombar") as GUI.tag.TabContainerTag;
this.tabbar = this.find("tabbar") as GUI.tag.TabBarTag; this.tabbar = this.find("tabbar") as GUI.tag.TabBarTag;
this.langstat = this.find("langstat") as GUI.tag.LabelTag; this.langstat = this.find("langstat") as GUI.tag.LabelTag;
this.editorstat = this.find("editorstat") as GUI.tag.LabelTag; this.editorstat = this.find("editorstat") as GUI.tag.LabelTag;
this.logger = new Logger(this.find("output-tab"));
this.fileview.fetch = (path) => this.fileview.fetch = (path) =>
new Promise(function (resolve, reject) { new Promise(async function (resolve, reject) {
let dir: API.VFS.BaseFileHandle; let dir: API.VFS.BaseFileHandle;
if (typeof path === "string") { if (typeof path === "string") {
dir = path.asFileHandle(); dir = path.asFileHandle();
} else { } else {
dir = path; dir = path;
} }
return dir try {
.read() const d = await dir
.then(function (d) { .read();
if (d.error) { if (d.error) {
return reject(d.error); return reject(d.error);
} }
return resolve(d.result); return resolve(d.result);
}) } catch (e) {
.catch((e) => reject(__e(e))); return reject(__e(e));
}
}); });
return this.setup(); return this.setup();
} }
@ -297,7 +324,7 @@ namespace OS {
pos: any, pos: any,
prefix: any, prefix: any,
callback: any callback: any
) {}, ) { },
}); });
this.editor.getSession().setUseWrapMode(true); this.editor.getSession().setUseWrapMode(true);
this.editormux = false; this.editormux = false;
@ -416,13 +443,13 @@ namespace OS {
e.data.to.update(p1); e.data.to.update(p1);
(e.data (e.data
.from as GUI.tag.TreeViewTag).parent.update( .from as GUI.tag.TreeViewTag).parent.update(
p2 p2
); );
} else { } else {
(e.data (e.data
.from as GUI.tag.TreeViewTag).parent.update( .from as GUI.tag.TreeViewTag).parent.update(
p2 p2
); );
e.data.to.update(p1); e.data.to.update(p1);
} }
}) })
@ -439,9 +466,19 @@ namespace OS {
return this.fileview.update(path); return this.fileview.update(path);
}); });
(this.find("logger-clear") as GUI.tag.ButtonTag).onbtclick = () =>
{
this.logger.clear()
}
if (this.setting.showBottomBar === undefined) {
this.setting.showBottomBar = false;
}
this.loadExtensionMetaData(); this.loadExtensionMetaData();
this.initCommandPalete(); this.initCommandPalete();
this.toggleSideBar(); this.toggleSideBar();
this.applyAllSetting();
return this.openFile(this.currfile); return this.openFile(this.currfile);
} }
@ -636,6 +673,47 @@ namespace OS {
this.trigger("resize"); this.trigger("resize");
} }
/**
* Apply [[showBottomBar]] from user setting value
*
* @protected
* @param {string} k
* @memberof CodePad
*/
protected applySetting(k: string): void {
if (k == "showBottomBar") {
this.showBottomBar(this.setting.showBottomBar);
}
}
/**
* Show or hide the bottom bar and
* save the value to user setting
*
* @param {boolean} v
* @memberof CodePad
*/
public showBottomBar(v: boolean): void {
this.setting.showBottomBar = v;
if (v) {
$(this.bottombar).show();
}
else {
$(this.bottombar).hide();
}
this.trigger("resize");
}
/**
* toggle the bottom bar
*
* @memberof CodePad
*/
private toggleBottomBar(): void {
this.showBottomBar(!this.setting.showBottomBar);
}
/** /**
* Add an action to the [[CommandPalette]]'s spotlight * Add an action to the [[CommandPalette]]'s spotlight
* *
@ -1142,12 +1220,26 @@ namespace OS {
dataid: "cmdpalette", dataid: "cmdpalette",
shortcut: "A-P", shortcut: "A-P",
}, },
{
text: "__(Toggle bottom bar)",
dataid: "bottombar"
}
], ],
onchildselect: ( onchildselect: (
e: GUI.TagEventType<GUI.tag.MenuEventData>, e: GUI.TagEventType<GUI.tag.MenuEventData>,
r: CodePadFileHandle r: CodePadFileHandle
) => { ) => {
return this.spotlight.run(this); switch (e.data.item.data.dataid) {
case "cmdpalette":
return this.spotlight.run(this);
case "bottombar":
return this.toggleBottomBar();
default:
break;
}
r
}, },
}, },
]; ];
@ -1181,7 +1273,7 @@ namespace OS {
this.shortcut = shortcut; this.shortcut = shortcut;
this.nodes = []; this.nodes = [];
this.parent = undefined; this.parent = undefined;
this.select = function (e) {}; this.select = function (e) { };
} }
/** /**
@ -1255,7 +1347,115 @@ namespace OS {
return m; return m;
}; };
/**
* This class handles log output to the Editor output container
*
* @class Logger
*/
class Logger {
/**
* Referent to the log container
*
* @private
* @type {HTMLElement}
* @memberof Logger
*/
private target: HTMLElement;
/**
* Creates an instance of Logger.
* @param {HTMLElement} el target container
* @memberof Logger
*/
constructor(el: HTMLElement) {
this.target = el;
}
/**
* Log level info
*
* @param {string|FormattedString} s
* @memberof Logger
*/
info(s: string | FormattedString): void {
this.log("info", s, true);
}
/**
* Log level warning
*
* @param {string|FormattedString} s
* @memberof Logger
*/
warn(s: string | FormattedString): void {
this.log("warn", s, true);
}
/**
* Log level error
*
* @param {string|FormattedString} s
* @memberof Logger
*/
error(s: string|FormattedString): void {
this.log("error", s, true);
}
/**
* Log a string to target container
*
* @private
* @param {string} c class name of the appended log element
* @param {string|FormattedString} s log string
* @param {boolean} showtime define whether the logger should insert datetime prefix
* in the log string
* @memberof Logger
*/
private log(c: string, s: string|FormattedString, showtime: boolean): void {
let el = $("<pre></pre>")
.attr("class", `code-pad-log-${c}`);
if (showtime) {
let date = new Date();
let prefix = date.getDate() + "/"
+ (date.getMonth() + 1) + "/"
+ date.getFullYear() + " "
+ date.getHours() + ":"
+ date.getMinutes() + ":"
+ date.getSeconds();
el.text(`[${prefix}]: ${s.__()}`);
}
else {
el.text(s.__());
}
$(this.target).append(el);
}
/**
* Print a log message without prefix
*
* @param {string|FormattedString} s text to print
* @memberof Logger
*/
print(s: string|FormattedString): void {
this.log("info", s, false);
}
/**
* Empty the log container
*
* @memberof Logger
*/
clear(): void {
$(this.target).empty();
}
}
CodePad.CMDMenu = CMDMenu; CodePad.CMDMenu = CMDMenu;
CodePad.Logger = Logger;
CodePad.dependencies = [ CodePad.dependencies = [
"os://scripts/ace/ace.js", "os://scripts/ace/ace.js",