623 строки
29 KiB
TypeScript
623 строки
29 KiB
TypeScript
///<reference path='refs.ts'/>
|
|
|
|
module TDev
|
|
{
|
|
export class ScriptNav
|
|
extends SideTab
|
|
{
|
|
constructor() {
|
|
super()
|
|
}
|
|
public icon() { return "svg:script,black"; }
|
|
public name() { return "script"; }
|
|
public keyShortcut() { return "Ctrl-S"; }
|
|
public getTick() { return Ticks.sideScript; }
|
|
public phoneFullScreen() { return true }
|
|
|
|
private selectedOne:AST.Decl;
|
|
|
|
public htmlForDecl(d:AST.Decl)
|
|
{
|
|
return this.htmlEntries.filter(i => (<any> i).theNode == d)[0]
|
|
}
|
|
|
|
public getSelected() {
|
|
return this.selectedOne;
|
|
}
|
|
|
|
public setSelected(d:AST.Decl)
|
|
{
|
|
if (!d) return;
|
|
|
|
var sel:HTMLElement = null;
|
|
this.htmlEntries.forEach((i) => {
|
|
var decl:AST.Decl = (<any> i).theNode;
|
|
i.setFlag("errors", decl instanceof AST.Decl && decl.hasErrors())
|
|
i.setFlag("warnings", decl instanceof AST.Decl && decl.hasWarnings())
|
|
var isCurr = decl == d;
|
|
if (isCurr)
|
|
sel = i;
|
|
i.setFlag("selected", isCurr);
|
|
})
|
|
|
|
if (!!sel) {
|
|
Util.ensureVisible(sel);
|
|
this.selectedOne = d;
|
|
this.saveState();
|
|
} else {
|
|
this.selectedOne = null;
|
|
}
|
|
}
|
|
|
|
public previousDecl(d:AST.Decl)
|
|
{
|
|
var prev:AST.Decl = Script;
|
|
|
|
var fnd = false;
|
|
this.htmlEntries.forEach((i) => {
|
|
if (fnd) return;
|
|
var n = (<any>i).theNode;
|
|
if (n == d) fnd = true;
|
|
else if (n instanceof AST.Decl)
|
|
prev = n;
|
|
})
|
|
return prev;
|
|
}
|
|
|
|
private updateErrorStatus()
|
|
{
|
|
}
|
|
|
|
static publishScript(noDialog = false, screenshotDataUri : string = null, app:AST.App = null)
|
|
{
|
|
if (Cloud.isOffline()) {
|
|
Cloud.showModalOnlineInfo(lf("publishing cancelled"));
|
|
return;
|
|
}
|
|
|
|
if (!app) app = Script
|
|
|
|
TheEditor.saveStateAsync({ forReal: true, forPublishing: true }).then(() => {
|
|
TheEditor.queueNavRefresh();
|
|
World.getInstalledHeaderAsync(app.localGuid).then((h: Cloud.Header) => {
|
|
if (h.status == "published") {
|
|
HTML.showProgressNotification(lf("already published"))
|
|
return Promise.as();
|
|
}
|
|
var info = Browser.TheHost.createInstalled(h)
|
|
return info.publishAsync(false, noDialog, screenshotDataUri);
|
|
}).done(() => {
|
|
if (TheEditor.stepTutorial) TheEditor.stepTutorial.notify("publish");
|
|
}, e => {
|
|
if (TheEditor.stepTutorial) TheEditor.stepTutorial.notify("publish");
|
|
});
|
|
})
|
|
}
|
|
|
|
static shareScript() {
|
|
World.getInstalledHeaderAsync(Script.localGuid).then((h:Cloud.Header) => {
|
|
if (h.status == "published") {
|
|
var info = Browser.TheHost.createInstalled(h);
|
|
info.share();
|
|
}
|
|
})
|
|
}
|
|
|
|
static addSideButton(d:HTMLElement, btn:HTMLElement)
|
|
{
|
|
btn.className += " navItem-button";
|
|
d = div(null, d, btn);
|
|
d.style.position = "relative";
|
|
return d;
|
|
}
|
|
|
|
private goToDecl(decl:AST.Decl)
|
|
{
|
|
if (!Script) return;
|
|
tick(Ticks.sideScriptGoToDecl);
|
|
if (decl instanceof AST.App && decl != Script) {
|
|
var guid = (<AST.App>decl).localGuid
|
|
if (guid)
|
|
this.editor.loadHash(["", guid, ""])
|
|
} else {
|
|
this.editor.dismissSidePane();
|
|
this.editor.renderDecl(decl);
|
|
}
|
|
}
|
|
|
|
private scriptButtons(app:AST.App, isParent:boolean, hasParent:boolean)
|
|
{
|
|
var r = div("scriptButtons");
|
|
if (!app) return r // ???
|
|
|
|
var onlyParent = isParent || !hasParent
|
|
|
|
var addBtn = (d:HTMLElement) => {
|
|
d.className += " navItem-button";
|
|
r.appendChild(d);
|
|
}
|
|
if (!isParent && app.isDocsTopic())
|
|
addBtn(HTML.mkRoundButton("svg:film,black", lf("preview"), Ticks.sidePreview, () => {
|
|
var topic = HelpTopic.fromScript(app)
|
|
var d =
|
|
elt('leftPaneContent').setChildren([
|
|
topic.render(e => {
|
|
Browser.TopicInfo.attachCopyHandlers(e);
|
|
World.getInstalledHeaderAsync(Script.localGuid).then((h: Cloud.Header) => {
|
|
if (h.status == "published" && (dbg || h.userId == Cloud.getUserId())) {
|
|
HTML.showProgressNotification(lf("loading analytics..."), true, 0, 1000);
|
|
var pro = HTML.mkProgressBar(); pro.start();
|
|
e.insertBefore(pro, e.firstElementChild);
|
|
Cloud.getPublicApiAsync(h.scriptId + "/progressstats")
|
|
.done((progress: JsonProgressStats) => {
|
|
pro.stop(); pro.removeSelf();
|
|
var steps: StringMap<JsonProgressStep> = {};
|
|
var lastStep : JsonProgressStep = undefined;
|
|
progress.steps.forEach(s => steps[s.index] = s);
|
|
var elts = e.getElementsByClassName("stepid")
|
|
for (var i = 0; i < elts.length; ++i) {
|
|
(() => {
|
|
var e = <HTMLElement>elts[i]
|
|
var index = e.getAttribute('data-stepid') || e.innerText;
|
|
var step = steps[index];
|
|
if (step) {
|
|
var sp = HTML.span("");
|
|
sp.innerText = Util.fmt('{0}{1} users ({2:%}), ~{3:f1.1}s, dialog ~{4:f1.1}s, play ~{5:f1.1}s',
|
|
step.count,
|
|
lastStep ? Util.fmt(' {0:%}', (step.count - lastStep.count) / lastStep.count) : '',
|
|
step.count / progress.count,
|
|
step.medDuration <= 0 ? 0 : step.medDuration,
|
|
step.medModalDuration <= 0 ? 0 : step.medModalDuration,
|
|
step.medPlayDuration <= 0 ? 0 : step.medPlayDuration);
|
|
e.appendChild(sp);
|
|
lastStep = step;
|
|
}
|
|
})()
|
|
}
|
|
}, e => {
|
|
pro.stop(); pro.removeSelf();
|
|
Util.log('failed to retreive progress info');
|
|
});
|
|
}
|
|
})
|
|
}),
|
|
HTML.mkButton(lf("print"), () => {
|
|
topic.print()
|
|
})
|
|
])
|
|
}));
|
|
|
|
if (!isParent && this.editor.widgetEnabled("updateButton") &&
|
|
(TheEditor.scriptUpdateId || TheEditor.librariesNeedUpdate()))
|
|
addBtn(HTML.mkRoundButton("svg:fa-refresh,black", lf("update"), Ticks.sideUpdate, () => {
|
|
this.editor.updateScript();
|
|
}));
|
|
if (onlyParent && this.editor.widgetEnabled("logsButton"))
|
|
addBtn(HTML.mkRoundButton("svg:CommandLine,black", lf("logs"), Ticks.sideLogs,() => {
|
|
this.editor.showAppLog(app);
|
|
}));
|
|
if (!isParent && this.editor.widgetEnabled("errorsButton"))
|
|
addBtn(HTML.mkRoundButton("svg:SmilieSad,black", lf("errors"), Ticks.sideErrors,() => {
|
|
this.editor.typeCheckNow();
|
|
this.editor.searchFor(":m");
|
|
}));
|
|
|
|
if (onlyParent && this.editor.widgetEnabled("deployButton")) {
|
|
addBtn(HTML.mkRoundButton("svg:cloudupload,black", lf("export"), Ticks.sideDeployWebSite, () => {
|
|
AppExport.exportBtn(app)
|
|
}));
|
|
}
|
|
|
|
if (!isParent && TheEditor.widgetEnabled("pluginsButton"))
|
|
addBtn(HTML.mkRoundButton("svg:plug,black", lf("plugins"), Ticks.sidePlugins, () => {
|
|
Plugins.runPlugin();
|
|
}));
|
|
if (!isParent && app.hasTests() && TheEditor.widgetEnabled("runTestsButton"))
|
|
addBtn(HTML.mkRoundButton("svg:experiment,black", lf("run tests"), Ticks.sideAllTests, () => {
|
|
TestMgr.testCurrentScript()
|
|
}));
|
|
|
|
if (!isParent && TheEditor.debugSupported())
|
|
addBtn(HTML.mkRoundButton("svg:bug,black", lf("debug"), Ticks.sideDebug, () => { TheEditor.runMainAction(true) }))
|
|
|
|
r.appendChildren(Plugins.getPluginButtons("script"))
|
|
|
|
return r;
|
|
}
|
|
|
|
static addAnythingVisible = false;
|
|
|
|
public refreshCore()
|
|
{
|
|
if (!Script) return
|
|
|
|
var items:HTMLElement[] = [];
|
|
this.htmlEntries = [];
|
|
|
|
var mainAction = Script.mainAction();
|
|
var debugMode = TheEditor.isDebuggerMode();
|
|
|
|
var declIt = (decl:AST.Decl) => {
|
|
var d = DeclRender.mkBox(decl);
|
|
(<any> d).itemIndex = items.length;
|
|
Util.clickHandler(d, () => this.goToDecl(decl));
|
|
d.setAttribute("data-stablename", decl.getStableName());
|
|
this.htmlEntries.push(d);
|
|
if (!debugMode) {
|
|
if (decl == mainAction || decl instanceof AST.Action) {
|
|
var a = <AST.Action>decl;
|
|
if (a.isTest()) {
|
|
var runbtn = HTML.mkRoundButton("svg:experiment,black", lf("test"), Ticks.sideTestOne,() => { TheEditor.runAction(decl, null, { debugging: true }) });
|
|
d = ScriptNav.addSideButton(d, runbtn);
|
|
} else if (a.isRunnable() && TheEditor.widgetEnabled("sideRunButton")) {
|
|
var runbtn = HTML.mkRoundButton("svg:play,black", lf("run"), Ticks.sideRun,() => { TheEditor.runAction(decl) });
|
|
d = ScriptNav.addSideButton(d, runbtn);
|
|
}
|
|
var participants = div("stmtParticipants", div("stmtParticipantsOverfloxBox"));
|
|
participants.classList.add("actionParticipants");
|
|
d.appendChild(participants);
|
|
} else if (decl instanceof AST.LibraryRef) {
|
|
var lib = <AST.LibraryRef>decl;
|
|
if (lib.needsUpdate && this.editor.widgetEnabled("updateButton")) {
|
|
var runbtn = HTML.mkRoundButton("svg:fa-refresh,black", lf("update"), Ticks.sideUpdateOne,
|
|
() => { TheEditor.updateLibraries([lib]) });
|
|
d = ScriptNav.addSideButton(d, runbtn);
|
|
} else if (this.editor.widgetEnabled("editLibraryButton")) {
|
|
var runbtn = HTML.mkRoundButton("svg:edit,black", lf("edit"), Ticks.sideEditLibrary,
|
|
() => {
|
|
LibraryRefProperties.editLibrary(lib,() => { })
|
|
});
|
|
d = ScriptNav.addSideButton(d, runbtn);
|
|
}
|
|
} else if (decl instanceof AST.GlobalDef) {
|
|
var glob = <AST.GlobalDef>decl;
|
|
if (glob.isResource && (glob.getKind() == api.core.String || glob.getKind() == api.core.JsonObject)) {
|
|
var runbtn = HTML.mkRoundButton("svg:edit,black", lf("edit"), Ticks.sideEditString,
|
|
() => {
|
|
TheEditor.renderDecl(glob);
|
|
TheEditor.variableProperties.editFullScreen()
|
|
});
|
|
d = ScriptNav.addSideButton(d, runbtn);
|
|
}
|
|
}
|
|
}
|
|
items.push(d);
|
|
return d;
|
|
}
|
|
|
|
var displayThings = (sect:ThingSection) =>
|
|
{
|
|
if (!sect.newName) sect.newName = sect.label.replace(/s$/, "");
|
|
|
|
if (sect.things.length == 0) return;
|
|
// some sections are optional in tutorials
|
|
if (sect.widget && !TheEditor.widgetEnabled(sect.widget)) return;
|
|
|
|
items.push(div("navHeader", sect.label));
|
|
|
|
sect.things.forEach((e:AST.Decl) => {
|
|
var d = declIt(e);
|
|
if (e.hasErrors())
|
|
d.setFlag("errors", true);
|
|
if (e instanceof AST.RecordDef && e.getKind()) {
|
|
var subDecls = byKind[e.getKind().toString()];
|
|
if (subDecls) subDecls.forEach(se => {
|
|
var sd = declIt(se);
|
|
sd.classList.add("nested");
|
|
if (se.hasErrors())
|
|
sd.setFlag("errors", true);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
var spacer = div("navTopSpacer");
|
|
spacer.style.height = "1em";
|
|
items.push(spacer);
|
|
|
|
if (TheEditor.parentScript) {
|
|
var parDiv = declIt(TheEditor.parentScript)
|
|
|
|
var sharebtn = HTML.mkRoundButton("svg:cancel,black", lf("disconnect"), Ticks.sideDisconnect,
|
|
() => {
|
|
TheEditor.disconnectParent()
|
|
TheEditor.queueNavRefresh();
|
|
});
|
|
(<any>parDiv).theDesc.setChildren([ "main script" ])
|
|
parDiv = ScriptNav.addSideButton(parDiv, sharebtn);
|
|
items[items.length - 1] = parDiv;
|
|
|
|
if (!debugMode)
|
|
items.push(this.scriptButtons(TheEditor.parentScript, true, true))
|
|
|
|
items.push(div("navHeader", lf("editing library")));
|
|
} else {
|
|
// items.push(div("navHeader", lf("script")));
|
|
}
|
|
|
|
var prog = Script;
|
|
var progDiv = declIt(prog);
|
|
|
|
if (ScriptEditorWorldInfo.status === "published") {
|
|
(<any>progDiv).theDesc.appendChildren( ", /" + ScriptEditorWorldInfo.baseId);
|
|
var sharebtn = HTML.mkRoundButton("svg:Package,black", lf("share"), Ticks.sideShare, () => { ScriptNav.shareScript() });
|
|
progDiv = ScriptNav.addSideButton(progDiv, sharebtn);
|
|
items[items.length - 1] = progDiv;
|
|
} else if(!debugMode) {
|
|
var pubbtn = HTML.mkRoundButton("svg:Upload,black", lf("publish"), Ticks.sidePublish, () => { ScriptNav.publishScript() });
|
|
TheEditor.keyMgr.btnShortcut(pubbtn, "Ctrl-S")
|
|
progDiv = ScriptNav.addSideButton(progDiv, pubbtn);
|
|
items[items.length - 1] = progDiv;
|
|
}
|
|
|
|
if (!debugMode)
|
|
items.push(this.scriptButtons(Script, false, !!TheEditor.parentScript));
|
|
|
|
|
|
/*
|
|
var tp = TheEditor.clipMgr.pasteType();
|
|
if (tp == "tokens" || tp == "block" || tp == "decls") {
|
|
var it = new DeclEntry("paste");
|
|
it.description = tp == "block" ? "copied lines as a new function" : "copied declaration(s)";
|
|
it.makeIntoAddButton();
|
|
var ee = it.mkBox();
|
|
ee.withClick(() => { tick(Ticks.sidePaste); TheEditor.pasteNode() });
|
|
items.push(ee);
|
|
}
|
|
*/
|
|
|
|
var addNode = (t:Ticks, n:AST.Decl) =>
|
|
{
|
|
Util.assert(!debugMode);
|
|
tick(t);
|
|
this.editor.addNode(n);
|
|
}
|
|
|
|
var addEvent = () =>
|
|
{
|
|
Util.assert(!debugMode);
|
|
var mkEvent = (a:AST.Action) => {
|
|
var b = DeclRender.mkBox(a);
|
|
(<any>b).initiallyHidden = a.eventInfo.type.lowPriority;
|
|
return b.withClick(() => { m.dismiss(); addNode(Ticks.sideAddEvent, a); });
|
|
}
|
|
var m = new ModalDialog();
|
|
var acts = api.eventMgr.availableEvents().map(mkEvent)
|
|
m.choose(acts, { mkSeeMore: DeclEntry.mkSeeMore, header: "which kind of event to add?" });
|
|
}
|
|
|
|
var addLibrary = () => {
|
|
Util.assert(!debugMode);
|
|
LibraryRefProperties.libraryChooser((scr) => {
|
|
var lib = this.editor.freshLibrary();
|
|
tick(Ticks.sideAddLibrary);
|
|
Script.addDecl(lib);
|
|
TheEditor.bindLibrary(lib, scr)
|
|
})
|
|
}
|
|
|
|
var things = prog.orderedThings();
|
|
var actions = <AST.Action[]> things.filter((t) => t instanceof AST.Action);
|
|
var vars = <AST.GlobalDef[]> things.filter((t) => t instanceof AST.GlobalDef);
|
|
|
|
var normalActions = actions.filter((a) => !a.isPage() && !a.isEvent() && !a.isActionTypeDef() && !a.isTest())
|
|
var byKind:StringMap<AST.Decl[]> = {}
|
|
var unsorted = normalActions.filter(a => {
|
|
var k = a.getExtensionKind()
|
|
if (!k || k.parentLibrary() || !<AST.RecordDef>k.getRecord() || (<AST.RecordDef>k.getRecord()).recordType != AST.RecordType.Object) return true
|
|
var key = k.toString()
|
|
if (!byKind.hasOwnProperty(key))
|
|
byKind[key] = []
|
|
byKind[key].push(a)
|
|
return false
|
|
})
|
|
|
|
var sections: ThingSection[] = [
|
|
<ThingSection>{
|
|
label: lf("code"),
|
|
things: unsorted,
|
|
createOne: () => [{
|
|
decl: this.editor.freshAsyncAction(),
|
|
displayName: 'function',
|
|
description: lf("Code that performs a specific task"),
|
|
tick: Ticks.sideAddAction
|
|
}],
|
|
newName: lf("function")
|
|
}, <ThingSection>{
|
|
label: lf("pages"),
|
|
widget: "pagesSection",
|
|
things: actions.filter((a) => a.isPage() && !a.isTest()),
|
|
initiallyHidden: AST.blockMode,
|
|
createOne: () => [{
|
|
decl: this.editor.freshPage(),
|
|
displayName: 'page',
|
|
description: lf("A user interface"),
|
|
tick: Ticks.sideAddPage,
|
|
}],
|
|
}, <ThingSection>{
|
|
label: lf("tests"),
|
|
widget: "testsSection",
|
|
things: actions.filter(a => a.isTest()),
|
|
initiallyHidden: !AST.proMode,
|
|
createOne: () => [{
|
|
decl: this.editor.freshTestAction(),
|
|
displayName: 'test',
|
|
description: lf("A unit test"),
|
|
tick: Ticks.sideAddActionTest
|
|
}],
|
|
newName: lf("test"),
|
|
}, <ThingSection>{
|
|
label: lf("events"),
|
|
widget: "eventsSection",
|
|
initiallyHidden: true,
|
|
things: actions.filter((a) => a.isEvent() && !a.isTest()),
|
|
createOne: () => [{
|
|
decl: api.eventMgr.genericEvent(),
|
|
tick: Ticks.sideAddEvent,
|
|
displayName: 'event',
|
|
description: lf("Code raised when a user interaction happens")
|
|
}],
|
|
addOne: addEvent,
|
|
}, <ThingSection>{
|
|
label: lf("vars"),
|
|
widget: "dataSection",
|
|
initiallyHidden: AST.blockMode,
|
|
things: vars.filter((v) => !v.isResource),
|
|
// Unknown triggers set kind dialog immedietely - tutorial doesn't support it
|
|
createOne: () => [{
|
|
decl: this.editor.freshVar((AST.blockMode || TheEditor.stepTutorial) ? api.core.Number : api.core.Unknown),
|
|
tick: Ticks.sideAddVariable,
|
|
displayName: 'data',
|
|
description: lf("A global variable")
|
|
}],
|
|
newName: lf("global variable"),
|
|
}, <ThingSection>{
|
|
label: lf("records"),
|
|
widget: "recordsSection",
|
|
things: things.filter((t) => t instanceof AST.RecordDef && !(<AST.RecordDef>t).isModel && (<AST.RecordDef>t).recordType == TDev.AST.RecordType.Object || (<AST.RecordDef>t).recordType == TDev.AST.RecordType.Decorator),
|
|
createOne: () => [
|
|
{ decl: this.editor.freshObject(), displayName: 'object type', initiallyHidden: AST.blockMode, tick: Ticks.sideAddObject, description: lf("A structure of user-data") },
|
|
{ decl: this.editor.freshDecorator(), displayName: 'decorator', initiallyHidden: AST.blockMode || AST.legacyMode, tick: Ticks.sideAddDecorator, description: lf("Attach data to other objects") },
|
|
],
|
|
}, <ThingSection>{
|
|
label: lf("database"),
|
|
widget: "databaseSection",
|
|
things: things.filter((t) => t instanceof AST.RecordDef && !(<AST.RecordDef>t).isModel && ((<AST.RecordDef>t).recordType == TDev.AST.RecordType.Table || (<AST.RecordDef>t).recordType == TDev.AST.RecordType.Index)),
|
|
createOne: () => [
|
|
{ decl: this.editor.freshTable(), displayName: ' ', initiallyHidden: AST.blockMode || AST.legacyMode, tick: Ticks.sideAddTable, description: lf("A table of user-defined rows")},
|
|
{ decl: this.editor.freshIndex(), displayName: ' ', initiallyHidden: AST.blockMode || AST.legacyMode, tick: Ticks.sideAddIndex, description: lf("An indexed table of user-defined rows")}
|
|
],
|
|
}, <ThingSection>{
|
|
label: lf("art"),
|
|
widget: "artSection",
|
|
things: vars.filter((v) => v.isResource),
|
|
createOne: () => [
|
|
{ decl: this.editor.freshPictureResource(), displayName: lf("picture resource"), tick: Ticks.sideAddResource, description: lf("A picture from the web") },
|
|
{ decl: this.editor.freshSoundResource(), displayName: lf("sound resource"), tick: Ticks.sideAddResource, description: lf("A sound from the web") },
|
|
{ decl: this.editor.freshArtResource("String", "str"), initiallyHidden: AST.blockMode || AST.legacyMode, displayName: lf("string resource"), tick: Ticks.sideAddResource, description: lf("Embeded text or downloaded from the web") },
|
|
Cloud.lite ? { decl: this.editor.freshDocumentResource(), initiallyHidden: true, displayName: lf("document resource"), tick: Ticks.sideAddResource, description: lf("A document from the web") } : undefined,
|
|
{ decl: this.editor.freshArtResource("Json Object", "json"), initiallyHidden: true, displayName: lf("JSON resource"), tick: Ticks.sideAddResource, description: lf("JSON data") },
|
|
{ decl: this.editor.freshArtResource("Color", "col"), initiallyHidden: true, displayName: lf("color resource"), tick: Ticks.sideAddResource, description: lf("A color constant") },
|
|
{ decl: this.editor.freshArtResource("Number", "n"), initiallyHidden: true, displayName: lf("number resource"), tick: Ticks.sideAddResource, description: lf("A number constant") }
|
|
],
|
|
newName: lf("art resource")
|
|
}, <ThingSection>{
|
|
label: lf("function types"),
|
|
widget: "actionTypesSection",
|
|
initiallyHidden: !AST.proMode,
|
|
things: things.filter((t) => t instanceof AST.Action && (<AST.Action>t).isActionTypeDef()),
|
|
createOne: () => [{
|
|
decl: this.editor.freshActionTypeDef(),
|
|
tick: Ticks.sideAddActionTypeDef,
|
|
displayName: lf("callback"),
|
|
description: lf("A signature definition of an function")
|
|
}],
|
|
}, <ThingSection>{
|
|
label: lf("libraries"),
|
|
widget: "librariesSection",
|
|
things: things.filter((t) => t instanceof AST.LibraryRef),
|
|
createOne: () => [{
|
|
decl: this.editor.freshLibrary(),
|
|
displayName: lf("library"),
|
|
tick: Ticks.sideAddLibrary,
|
|
description: lf("A reference to a library script")
|
|
}],
|
|
addOne: addLibrary,
|
|
newName: lf("lib"),
|
|
},
|
|
]
|
|
|
|
function addNew() {
|
|
Util.assert(!debugMode);
|
|
var m = new ModalDialog();
|
|
var boxes = [];
|
|
|
|
m.onDismiss = () => {
|
|
ScriptNav.addAnythingVisible = false;
|
|
Util.setTimeout(100, () => TheEditor.updateTutorial())
|
|
};
|
|
|
|
sections.forEach((sect) => {
|
|
if (!sect.createOne) return
|
|
if (sect.widget && !TheEditor.widgetEnabled(sect.widget)) return;
|
|
sect.createOne().filter(ds => !!ds).forEach((ds, i) => {
|
|
// d.setName(sect.newName
|
|
var d = ds.decl;
|
|
var dname = (d instanceof AST.RecordDef) ? (<AST.RecordDef> d).getCoreName() : d.getName();
|
|
d.setName(ds.displayName);
|
|
var b = DeclRender.mkBox(d);
|
|
boxes.push(b);
|
|
(<any>b).theDesc.setChildren(ds.description);
|
|
(<any>b).initiallyHidden = !!sect.initiallyHidden || !!(<any>ds).initiallyHidden;
|
|
HTML.setTickCallback(b, ds.tick, () => {
|
|
m.dismiss();
|
|
d.setName(dname);
|
|
if (sect.addOne) sect.addOne(d)
|
|
else addNode(ds.tick, d);
|
|
});
|
|
})
|
|
})
|
|
ScriptNav.addAnythingVisible = true;
|
|
m.choose(boxes, {
|
|
header: lf("add a new ..."),
|
|
mkSeeMore: DeclEntry.mkSeeMore,
|
|
afterRefresh: () => TheEditor.updateTutorial(),
|
|
includeSearch: false,
|
|
});
|
|
TheEditor.updateTutorial()
|
|
}
|
|
|
|
if (!debugMode && TheEditor.widgetEnabled("addNewButton")) {
|
|
var e = new DeclEntry(lf("add new"));
|
|
e.makeIntoAddButton();
|
|
e.description = lf("function, variable, library, ...")
|
|
var ee = e.mkBox();
|
|
HTML.setTickCallback(ee, Ticks.sideAddAnything, addNew);
|
|
items.push(ee);
|
|
this.htmlEntries.push(ee);
|
|
}
|
|
|
|
sections.forEach(displayThings)
|
|
|
|
items.push(Browser.EditorSettings.changeSkillLevelDiv(this.editor, Ticks.changeSkillScriptExplorer, "formHint marginBottom marginTop"));
|
|
|
|
this.setChildren(items);
|
|
|
|
this.setSelected(this.editor.lastDecl);
|
|
|
|
TipManager.update();
|
|
}
|
|
|
|
public navigatedTo()
|
|
{
|
|
super.navigatedTo();
|
|
this.selectedOne = null;
|
|
}
|
|
|
|
public refresh()
|
|
{
|
|
if (!this.navRefreshPending && this.selectedOne != TheEditor.lastDecl)
|
|
this.setSelected(TheEditor.lastDecl);
|
|
super.refresh();
|
|
}
|
|
}
|
|
|
|
interface DeclButton {
|
|
decl: AST.Decl;
|
|
displayName: string;
|
|
description: string;
|
|
tick: Ticks;
|
|
}
|
|
|
|
interface ThingSection {
|
|
label: string;
|
|
widget?: string;
|
|
things: AST.Decl[];
|
|
createOne: () => DeclButton[];
|
|
addOne?: (d: AST.Decl) => void;
|
|
newName?: string;
|
|
initiallyHidden?: boolean; // don't show immediately in dialog
|
|
}
|
|
}
|
|
|