284 строки
10 KiB
TypeScript
284 строки
10 KiB
TypeScript
///<reference path='refs.ts'/>
|
|
|
|
module TDev
|
|
{
|
|
export class LibraryRefProperties
|
|
extends CodeView
|
|
{
|
|
private theLibrary:AST.LibraryRef;
|
|
constructor() {
|
|
super()
|
|
}
|
|
private libraryName = HTML.mkTextInput("text", lf("library name"));
|
|
private formRoot = div("varProps");
|
|
private boundTo = div(null);
|
|
private resolves = div(null);
|
|
private renderer = new TDev.EditorRenderer();
|
|
private rendererNoHooks = new TDev.EditorRenderer(true);
|
|
private docs = div(null);
|
|
private pluginsBtn:HTMLElement;
|
|
|
|
public getTick() { return Ticks.viewLibraryRefInit; }
|
|
|
|
public nodeType() { return "libraryRef"; }
|
|
|
|
public init(e:Editor)
|
|
{
|
|
super.init(e);
|
|
}
|
|
|
|
private isActive() { return !!this.theLibrary; }
|
|
|
|
static bindLibraryAsync(lib:AST.LibraryRef, s:Browser.ScriptInfo, earlyCb:()=>void = () => {})
|
|
{
|
|
var plugins0 = TheEditor.libPluginIds()
|
|
|
|
lib.updateId = null;
|
|
lib.needsUpdate = null;
|
|
|
|
if (s.publicId) {
|
|
lib.guid = "";
|
|
lib.pubid = s.publicId;
|
|
lib.rebind();
|
|
} else if (s.getGuid()) {
|
|
lib.guid = s.getGuid();
|
|
lib.pubid = "";
|
|
lib.rebind();
|
|
} else {
|
|
return Promise.as(); // ???
|
|
}
|
|
earlyCb();
|
|
lib.notifyChange();
|
|
|
|
var bindings = Script.editorState.libraryLocalBindings
|
|
if (!bindings)
|
|
Script.editorState.libraryLocalBindings = bindings = {}
|
|
|
|
return TheEditor.libCache.loadLibAsync(lib)
|
|
.then(() => Promise.join(!lib.resolved ? [] : lib.resolved.libraries().map((l) => TheEditor.libCache.loadLibAsync(l))))
|
|
.then(() => Promise.join(lib.initializeResolves().map((l) => TheEditor.libCache.loadLibAsync(l))))
|
|
.then(() => {
|
|
if (lib.guid)
|
|
bindings[lib.getStableName()] = lib.guid
|
|
else
|
|
delete bindings[lib.getStableName()]
|
|
TheEditor.initIds(lib, true)
|
|
if (lib.resolved) {
|
|
if (!Script.namesMatch(lib.getName(), lib.resolved.getName()))
|
|
// always rename library reference (regardless of auto-named)
|
|
lib.setName(Script.freshName(lib.resolved.getName()));
|
|
}
|
|
lib.notifyChange();
|
|
AST.TypeChecker.tcApp(Script);
|
|
|
|
var plugins1 = TheEditor.libPluginIds()
|
|
return TheEditor.installPluginsAsync(Object.keys(plugins1).filter(i => !plugins0.hasOwnProperty(i)))
|
|
})
|
|
}
|
|
|
|
static libraryChooser(f:(s:Browser.ScriptInfo) => void)
|
|
{
|
|
Meta.chooseScriptAsync({
|
|
searchPath: "scripts?count=50&q=" + encodeURIComponent("*library "),
|
|
filter: (s) => s.isLibrary(),
|
|
header: "choose library to use",
|
|
}).done((s) => {
|
|
if (s) f(s)
|
|
})
|
|
}
|
|
|
|
public bindLibraryHere(s:Browser.ScriptInfo)
|
|
{
|
|
LibraryRefProperties.bindLibraryAsync(this.theLibrary, s)
|
|
.done(() => { this.syncAll(true) });
|
|
}
|
|
|
|
private rebind()
|
|
{
|
|
LibraryRefProperties.libraryChooser((s) => this.bindLibraryHere(s))
|
|
}
|
|
|
|
private syncAll(tc = true)
|
|
{
|
|
this.libraryName.value = this.theLibrary.getName();
|
|
var bind = null;
|
|
if (this.theLibrary.resolved) {
|
|
var box = DeclRender.mkBox(this.theLibrary.resolved);
|
|
(<any>box).theDesc.setChildren([this.theLibrary.pubid ? "published :: /" + this.theLibrary.pubid: "(local)"]);
|
|
bind = box.withClick(() => this.rebind());
|
|
} else
|
|
bind = HTML.mkButton(lf("nothing; bind it!"), () => this.rebind());
|
|
this.boundTo.setChildren([bind]);
|
|
|
|
if (tc) {
|
|
this.theLibrary.notifyChange();
|
|
AST.TypeChecker.tcApp(Script);
|
|
TheEditor.queueNavRefresh();
|
|
}
|
|
|
|
this.docs.setChildren(ScriptProperties.libraryDocs(this.theLibrary.resolved, this.theLibrary.getName(), true));
|
|
|
|
this.resolves.setChildren([this.renderer.declDiv(this.theLibrary), this.rendererNoHooks.renderLibSignatures(this.theLibrary)]);
|
|
this.renderer.attachHandlers();
|
|
this.pluginsBtn.style.display = this.pluginIds().length > 0 ? "inline-block" : "none"
|
|
}
|
|
|
|
private pluginIds()
|
|
{
|
|
if (this.theLibrary.resolved)
|
|
return Object.keys(this.theLibrary.resolved.imports.touchDevelopPlugins)
|
|
return []
|
|
}
|
|
|
|
private rebindResolve(r:AST.ResolveClause)
|
|
{
|
|
var m = new ModalDialog()
|
|
var boxes = []
|
|
|
|
Script.librariesAndThis().forEach((l) => {
|
|
boxes.push(DeclRender.mkBox(l).withClick(() => {
|
|
r.defaultLib = l;
|
|
m.dismiss();
|
|
this.syncAll();
|
|
}));
|
|
});
|
|
|
|
m.choose(boxes);
|
|
}
|
|
|
|
private rebindKind(k:AST.KindBinding)
|
|
{
|
|
}
|
|
|
|
private rebindAction(ab:AST.ActionBinding)
|
|
{
|
|
var m = new ModalDialog()
|
|
var actions = []
|
|
|
|
var done = () => {
|
|
m.dismiss();
|
|
this.syncAll();
|
|
}
|
|
|
|
var it = new DeclEntry("set to default");
|
|
it.description = lf("set to function named '{0}' in default library if available", ab.formalName);
|
|
actions.push(it.mkBox().withClick(() => {
|
|
ab.isExplicit = false;
|
|
done();
|
|
}));
|
|
|
|
var addAction = (a:AST.Action) => {
|
|
if (!ab.getSignatureError(new AST.UnificationCtx(this.theLibrary), a)) {
|
|
actions.push(DeclRender.mkBox(a).withClick(() => {
|
|
ab.isExplicit = true;
|
|
ab.actualLib = a.parentLibrary();
|
|
ab.actualName = a.getName();
|
|
TheEditor.initIds(ab, false)
|
|
done();
|
|
}));
|
|
}
|
|
}
|
|
|
|
Script.librariesAndThis().forEach((l) => {
|
|
l.getPublicActions().forEach(addAction);
|
|
});
|
|
|
|
m.choose(actions);
|
|
}
|
|
|
|
public nodeTap(s:AST.Stmt)
|
|
{
|
|
if (s instanceof AST.ResolveClause)
|
|
this.rebindResolve(<AST.ResolveClause>s);
|
|
else if (s instanceof AST.KindBinding)
|
|
this.rebindKind(<AST.KindBinding>s);
|
|
else if (s instanceof AST.ActionBinding)
|
|
this.rebindAction(<AST.ActionBinding>s);
|
|
else
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public renderCore(a:AST.Decl) { return this.load(<AST.LibraryRef>a); }
|
|
|
|
private load(a:AST.LibraryRef) :void
|
|
{
|
|
this.theLibrary = null;
|
|
TheEditor.dismissSidePane();
|
|
this.theLibrary = a;
|
|
|
|
this.formRoot.setChildren(<any[]>[
|
|
Editor.mkHelpLink("libraries"),
|
|
div("varLabel", lf("library reference")),
|
|
div("varHalf",
|
|
div("formHint", lf("known here as:")),
|
|
this.libraryName),
|
|
div("varHalf",
|
|
div("formHint", lf("binds to script:")),
|
|
this.boundTo),
|
|
ActionProperties.copyCutRefs("the current library reference", this.theLibrary),
|
|
TheEditor.widgetEnabled("editLibraryButton") ? HTML.mkButton(lf("edit library"), () => this.editLib()) : null,
|
|
this.pluginsBtn = HTML.mkButton(lf("reinstall plugins"), () => this.reinstallPlugins()),
|
|
this.docs,
|
|
this.resolves
|
|
]);
|
|
this.editor.displayLeft([this.formRoot]);
|
|
this.libraryName.blur(); // prevent keyboard popup on iOS
|
|
this.syncAll(false);
|
|
}
|
|
|
|
private reinstallPlugins()
|
|
{
|
|
TheEditor.installPluginsAsync(this.pluginIds()).done()
|
|
}
|
|
|
|
static editLibrary(lib:AST.LibraryRef, f:()=>void, declId = "")
|
|
{
|
|
var guidPromise: Promise;
|
|
|
|
var g = lib.guid
|
|
if (g) guidPromise = Promise.as(g)
|
|
else if (lib.pubid)
|
|
guidPromise = Browser.TheApiCacheMgr.getAsync(lib.pubid, true)
|
|
.then((info: JsonScript) => World.installPublishedAsync(lib.pubid, info.userid))
|
|
.then((hd: Cloud.Header) => hd.guid);
|
|
else {
|
|
HTML.showErrorNotification("You need to bind the library first.")
|
|
return;
|
|
}
|
|
|
|
guidPromise.then((guid: string) => {
|
|
lib.pubid = "";
|
|
lib.guid = guid;
|
|
lib.notifyChange();
|
|
f()
|
|
return Editor.updateEditorStateAsync(guid, st => {
|
|
if (Script)
|
|
st.parentScriptGuid = Script.localGuid
|
|
})
|
|
.then(() => TheEditor.loadHash(["", guid, declId]))
|
|
})
|
|
.done()
|
|
}
|
|
|
|
private editLib()
|
|
{
|
|
LibraryRefProperties.editLibrary(this.theLibrary, () => this.syncAll())
|
|
}
|
|
|
|
public commit()
|
|
{
|
|
if (!this.theLibrary) return;
|
|
|
|
if (this.theLibrary.getName() != this.libraryName.value) {
|
|
this.theLibrary.wasAutoNamed = false;
|
|
this.theLibrary.setName(Script.freshName(this.libraryName.value));
|
|
}
|
|
this.theLibrary.notifyChange();
|
|
TheEditor.queueNavRefresh();
|
|
}
|
|
}
|
|
}
|
|
|