外观
lib-finBlockProgramming 库参考
原文: https://finproducts.atlassian.net/wiki/spaces/JIDD3/pages/34793816316/FIN+5.3.1+lib-finBlockProgramming 中文整理基于 FIN 5.3.1
导读: FIN 块编程
以下为 API 参考,保留英文以便对照源码;目录已列出(英文标题便于检索);概述已尽量中译。
目录(导读)
- lib
- meta
- funcs
- def
- addStateMachineVars(programId, names)
- supertypes
- src
- addVarIds(programId)
- deleteMacro(macroName)
- deleteVar(programId, variableName)
- deleteVarById(programId, variableId)
- finAddProjectGlobalVar(varsNames, programId)
- finBLineSnippets()
- finBlockSuggestion(args)
- finBlockSuggestionHelper(args, type)
- finBlocksCombineVars(programId, curVars)
- finReadBlockProgram(id)
- getAllMacros()
- getMacroByName(macroName)
- renameVar(programId, varName, newDisplayName)
- renameVarById(programId, variableId, newDisplayName)
- saveMacro(macroName, macroData)
概述(中译)
FIN 块编程
API 正文(英文)
funcs
| addStateMachineVars | Axon function |
| addVarIds | Axon function |
| deleteMacro | Axon function |
| deleteVar | Axon function |
| deleteVarById | Axon function |
| finAddProjectGlobalVar | Axon function |
| finBLineSnippets | Axon function |
| finBlockSuggestion | Axon function |
| finBlockSuggestionHelper | Axon function |
| finBlocksCombineVars | Axon function |
| finReadBlockProgram | Axon function |
| getAllMacros | Axon function |
| getMacroByName | Axon function |
| renameVar | Axon function |
| renameVarById | Axon function |
| saveMacro | Axon function |
def
func:addStateMachineVars
addStateMachineVars(programId, names)
Axon function
meta
| def | func:addStateMachineVars |
| is | func |
| lib | lib:finBlockProgramming |
| name | addStateMachineVars |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(programId, names) => do
program : read(id == programId)
vars : program->programVars.ioReadZinc
newVars : []
vars.each(v => do
newVars = newVars.add(v)
end)
names.each(currentName => do
v: vars.find(e => e->name == currentName)
if(v == null) do
newVars = newVars.add({name:currentName, kind:"Str"})
end
end)
program.diff({programVars: newVars.ioWriteZinc("")}).commit()
enddef
func:addVarIds
addVarIds(programId)
Axon function
meta
| def | func:addVarIds |
| is | func |
| lib | lib:finBlockProgramming |
| name | addVarIds |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(programId) => do
program : read(id == programId)
vars : program->programVars.ioReadZinc
newVars : vars.map((row) => if(row["varId"] != null) row else do
newId : "" + now()
(0..10).each((a) => do
newId = newId + random(0..9)
end)
row.set("varId", newId)
end)
program.diff({programVars: newVars.ioWriteZinc("")}).commit()
enddef
func:deleteMacro
deleteMacro(macroName)
Axon function
meta
| def | func:deleteMacro |
| is | func |
| lib | lib:finBlockProgramming |
| name | deleteMacro |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(macroName) => do
savedMacro:read(name == macroName and bLineSavedMacro)
commit(diff(savedMacro, {}, {remove}))
enddef
func:deleteVar
deleteVar(programId, variableName)
Axon function
meta
| def | func:deleteVar |
| is | func |
| lib | lib:finBlockProgramming |
| name | deleteVar |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(programId, variableName) => do
program : read(id == programId)
vars : program->programVars.ioReadZinc
remainingVars : vars.findAll(row => row->name != variableName)
program.diff({programVars: remainingVars.ioWriteZinc("")}).commit()
programAfterChange : read(id == programId)
{name: variableName, mod: programAfterChange->mod}
enddef
func:deleteVarById
deleteVarById(programId, variableId)
Axon function
meta
| def | func:deleteVarById |
| is | func |
| lib | lib:finBlockProgramming |
| name | deleteVarById |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(programId, variableId) => do
program : read(id == programId)
vars : program->programVars.ioReadZinc
remainingVars : vars.findAll(row => (row["varId"] == null or row->varId != variableId))
program.diff({programVars: remainingVars.ioWriteZinc("")}).commit()
variableId
enddef
func:finAddProjectGlobalVar
finAddProjectGlobalVar(varsNames, programId)
Axon function
meta
| def | func:finAddProjectGlobalVar |
| is | func |
| lib | lib:finBlockProgramming |
| name | finAddProjectGlobalVar |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(varsNames, programId) => do
program: readById(programId)
curVars: program->programVars.ioReadZinc()
varsToAdd: varsNames.map(varName => do
if(not curVars.any(v => v["name"] == varName)) do
globalVar: taskVarTree(programId).finGridFilter(type == "var" and shared == "<proj>" and name == varName)[0]
newVar: { name: globalVar["name"], kind: globalVar["kind"], shared: "<proj>" }
if(globalVar.has("unit")) do
newVar = newVar.set("unit", globalVar->unit)
end
if(globalVar.has("defVal")) do
newVar = newVar.set("defVal", globalVar->defVal)
end
if(globalVar.has("dis") and globalVar.dis != globalVar["name"]) do
newVar = newVar.set("display", globalVar.dis)
end
return newVar
end
end)
try
program.diff({programVars: curVars.addRows(varsToAdd).ioWriteZinc("")}).commit
catch (error) do
finFormAlertOk(toLocale("finStackExt::regError"), toLocale("finStackMobileExt::addingVarTagsToPhrase")+" " + program.dis + " "+toLocale("finStackMobileExt::hasFailed")+".")
throw error
end
enddef
func:finBLineSnippets
finBLineSnippets()
Axon function
meta
| def | func:finBLineSnippets |
| is | func |
| lib | lib:finBlockProgramming |
| name | finBLineSnippets |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
() => do
[
{
trigger:"code-if",
content:"if(condition) {\n\n}"
},
{
trigger:"code-if-else",
content:"if(condition) {\n\n}\nelse {\n\n}"
},
]
enddef
func:finBlockSuggestion
finBlockSuggestion(args)
Axon function
meta
| def | func:finBlockSuggestion |
| is | func |
| lib | lib:finBlockProgramming |
| name | finBlockSuggestion |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(args) => do
pid: try readAll(args->program->id[1..-1].parseRef.readById->programOn.parseFilter)[0]->id catch args->program->id[1..-1].parseRef
data: "finBlocks()"
opts: finBlocks().map(r => r.set("variable", false))
varType: null
comboPrompt: toLocale("finBlockProgrammingExt::chooseVarOrBlockTitle")
variables: finBlocksCombineVars(pid, args->variables.findAll(v => (not v.has("variable") or not v->variable) or v->variable)).map(r => r.set("dis", (if (r.has("displayName")) r->displayName else r->name)))
varBlockType: "get"
commitAct: ""
linkType: "data"
searchVars: (typeList) => do
vars: []
typeList.each type => do
if(type == "bool") vars = vars.addAll(variables.findAll(v=> v->type == "boolean"))
else if(type == "str") vars = vars.addAll(variables.findAll(v=> v->type == "string"))
else if(type == "dateTime") vars = vars.addAll(variables.findAll(v=> v->type == "datetime"))
else vars = vars.addAll(variables.findAll(v=> v->type == type))
end
return vars
end
if(variables.find(v => v->type == "grid") != null and variables.find(v => v->name == "it") == null) variables = variables.add({dis: "it", name: "it", type: "string", variable: true, id: "new"})
//if from an in or out socket
if(args->startSocketType == "out" or args->startSocketType == "in") do
opts = variables.toGrid.addRows(opts.finGridFilter(stmt and name !="comment" and name != "alarm" and name != "do" and name != "exprStmt")).map(r => r.set("socketIndex", 0))
comboPrompt = "Choose a statement block to add:"
varBlockType = "set"
linkType = "exec"
end
//if from an output socket
else if(args->startSocketType == "output") do
opts = opts.findAll(v => v.has("category"))
varBlockType = "set"
inputType: ""
blockList: []
//if from a variable "get" block
if(args->startBlockType == "get") do
inputType = args->startVariableInfo->type
if(inputType == "boolean") inputType = "bool"
else if(inputType == "string") inputType = "str"
else if(inputType == "datetime") inputType = "dateTime"
//search for blocks whose inputs match
opts.each block => do
props: block->props.ioReadZinc()
match: eachWhile(props)((v, i) => if(v.has("takes") and (v->takes.contains(inputType) or v->takes == "obj")) i)
if(match != null) blockList = blockList.add(block.set("socketIndex", match))
end //end search
//add vars
blockList = variables.findAll(v=> v->type == args->startVariableInfo->type).map(r => r.set("socketIndex", 0)).addAll(blockList)
end //end if get
//if non-var block
else do
inputType = opts.find(v => v->name == args->startBlockType).finFindMarkers.findAll(v => v != "block") // and v!= "obj"
//search for matching blocks
opts.each block => do
props: block->props.ioReadZinc()
found: false
match: eachWhile(props)((v, i) => do
if(v.has("takes")) do
inputType.each x => if(v->takes.contains(x)) found = true
if(found) i
end
end)
if(match != null) blockList = blockList.add(block.set("socketIndex", match))
end //end search
blockList = searchVars(inputType).map(r => r.set("socketIndex", 0)).addAll(blockList)
end //end if a non-variable block
opts = blockList
end //end if output
//if from an input socket
else if(args->startSocketType == "input") do
opts = opts.findAll(v => v.has("category") or v->name=="alarm")
varBlockType = "get"
outputType: ""
blockList: []
//if from a variable "set" block
if(args->startBlockType == "set") do
outputType = args->startVariableInfo->type
if(outputType == "boolean") outputType = "bool"
else if(outputType == "string") outputType = "str"
else if(outputType == "datetime") outputType = "dateTime"
//search for blocks whose outputs match
opts.each block => do
markers: block.finFindMarkers()
if(outputType == "str" and (markers.contains("str") or markers.contains("string"))) blockList = blockList.add(block.set("socketIndex", 0))
else if(markers.contains(outputType)) blockList = blockList.add(block.set("socketIndex", 0))
end //end search
//add vars
blockList = variables.findAll(v=> v->type == args->startVariableInfo->type).map(r => r.set("socketIndex", 0)).addAll(blockList)
end //end if set
//if non-var block
else do
outputType = try opts.find(v => v->name == args->startBlockType)->props.ioReadZinc()[args->startSocketIndex]->takes.trim.replace(" or ", "|").split("|") catch [] //.replace("or obj", "")
if(outputType.isEmpty) do
args=args.set("startBlockType","alarm")
temp: opts.find(v => v->name == args->startBlockType)->props.ioReadZinc()
if(args->startSocketIndex >= temp.size and temp[0]->type == "Block[]")
outputType = try opts.find(v => v->name == args->startBlockType)->props.ioReadZinc()[0]->takes.trim.replace(" or ", "|").split("|") catch [] //.replace("or obj", "")
end
opts.each block => do
blockOutputs: block.finFindMarkers.findAll(v => v != "block") // and v!= "obj"
found: false
outputType.each type => do
if(type == "str" and (blockOutputs.contains("str") or blockOutputs.contains("string"))) found = true
else if(type == "obj" and ((blockOutputs.size == 1 or outputType.size == 1) and blockOutputs.contains(type))) found = true
else if(blockOutputs.contains(type)) found = true
end
if(found) blockList = blockList.add(block.set("socketIndex", 0))
end
blockList = searchVars(outputType).map(r => r.set("socketIndex", 0)).addAll(blockList)
end
opts = blockList
end //end if input
opts = opts.map(r => do
if(not r.has("dis")) r = r.set("dis", r->name)
if(r->dis.size > 0 and r->dis[0..0] == "@") r = r.set("dis", r->name)
if(r.has("displayName") and r->displayName.size > 0 and r->displayName[0..0].contains("@")) r = r.set("displayName", r->displayName.toAxonCode)
if(r.has("shared")) r.set("group", "Project Variables").set("icon", "wi-owm-902")
else if(r->variable) r.set("group", "Current Variables").set("icon", "wi-moon-full")
else
try r.set("group", r->category.capitalize + " Blocks").set("icon", "icon-media-stop")
catch r.set("group", "Blocks").set("icon", "icon-media-stop")
end).toRecList
body:[
{
name:"blockCombo",
editorType: "ractive",
ractiveType: "multiselect",
prompt: comboPrompt,
data:opts,
autoClose: true,
selectedValueTags: "name, id, variable",
},
{
name:"radioGroup",
editorType:"group",
prompt:toLocale("finBlockProgrammingExt::orAddNewTitle"),
children: [
{ name:"newRad", editorType: "radio", label: toLocale("finStackExt::tag"), group: "radioGrp", selectedValue: "tag" },
{ name:"newRad", editorType: "radio", label: toLocale("finStackExt::point"), group: "radioGrp", selectedValue: "point" },
{ name:"newRad", editorType: "radio", label: toLocale("finBlockProgrammingExt::variableTitle"), group: "radioGrp", selectedValue: "var" },
{ name:"newRad", editorType: "radio", label: toLocale("finBlockProgrammingExt::absolutePointTitle"), group: "radioGrp", selectedValue: "abs" }
]
},
{ name:"cancelButton", editorType:"button", label:toLocale("finStackExt::cancel"), controlBar:true },
{ name:"commitButton", editorType:"button", label:toLocale("finStackExt::okay"), controlBar:true }
] //end body
commitAct = "if((\$newRad).isStr or not (\$blockCombo)[0].has(\"id\")) finBlockSuggestionHelper("+args.set("blockType", varBlockType).toAxonCode+",\$newRad)"
newBlockLinkedSocket: 0;
newBlockType: "\$blockCombo";
fromBlockId: "";
toBlockId: "";
completeAction: ["var newBlock = "+newBlockType+";",
"if(\$newRad == false) {",
"var frames = document.querySelectorAll('iframe'), app;",
"for(var i = 0; i < frames.length; i++) {",
"var f = frames[i];",
"var win = f.contentWindow;",
"if(win.app && win.app.loadProgram && win.app.addBlock) {",
"app = win.app;",
"break;",
"}",
"}",
"if(app)",
"{",
"var id;",
"const projectVarsNames = [];",
"const menuSettings = " + blineTaskMenuSettings(args->equipRef).set("funcCall", "blineTaskMenu(" + args->equipRef.replace("\"","") + ",'" + args->program->name + "', true)").toAxonCode + ";",
"for (prop in menuSettings) {",
"if(typeof menuSettings[prop] == 'string') menuSettings[prop] = menuSettings[prop].replace(/\\\"/g, '');",
"}",
"for(let i = 0; i < newBlock.length; i++)",
"{",
"if(newBlock[i].variable)",
"{",
"if(newBlock[i].id == 'new' || newBlock[i].id === undefined)",
"{",
"let newVarId;",
"if(newBlock[i].id == 'new') newVarId = app.addVariable({name: 'it', type: 'string', displayName: 'it'});",
"else newVarId = app.addVariable({name: newBlock[i].name, type: newBlock[i].type, displayName: newBlock[i].displayName?.replace(/\\\"/g,'') });",
"id = app.addBlock({type: '"+varBlockType+"', x: "+args->x+" + (i*50), y: "+args->y+", variableInfo: {}, owner: newVarId});",
"if (newBlock[i].shared === '<proj>')",
"{",
"projectVarsNames.push(newBlock[i].name);",
"}",
"}",
"else",
"{",
"id = app.addBlock({type: '"+varBlockType+"', x: "+args->x+" + (i*50), y: "+args->y+", owner: newBlock[i].id});",
"}",
"}",
"else",
"{",
"id = app.addBlock({type: newBlock[i].name, x: "+args->x+" + (i*50), y: "+args->y+"});",
"}",
"}",
"app.addLink({block: '"+args->startBlockId+"', socket:"+args->startSocketIndex+", socketType: '"+args->startSocketType+"'},",
"{block: id, socket:newBlock[0].socketIndex},",
"'"+linkType+"', undefined, 'linkHelper');",
"if (projectVarsNames.length)",
"{",
"finstack.eval('finAddProjectGlobalVar([' + projectVarsNames.map(projVar => \"\\\"\" + projVar + \"\\\"\") + '], " + args->program->id + ")').finally(() => { ",
"setTimeout(() => { window.top.app.ObtainMenu(null, null, 'taskData', menuSettings); }, 1000);",
"});",
"}",
"}",
"}",
"if(\$newRad == 'var'){",
"setTimeout(function(){var sel=document.querySelector('.form-container');sel.querySelector('input[type=\"radio\"]').checked=true;[{dis:languageManager[\"number\"],val:\"Number\"},{dis:languageManager[\"boolean\"],val:\"Bool\"},{dis:languageManager[\"string\"],val:\"Str\"},{dis:languageManager[\"blineDate\"],val:\"Date\"},{dis:languageManager[\"debugMenuTime\"],val:\"Time\"},{dis:languageManager[\"folioQueryDateTime\"],val:\"Date Time\"}].forEach(function(itm){var opt=document.createElement(\"option\");opt.innerHTML=itm.dis;opt.value=JSON.stringify(itm);sel.querySelector('select').appendChild(opt);});},500)",
"}"
]
{
"dis":toLocale("finBlockProgrammingExt::addPointsToProgramTitle"),
"name":"finBlineCreateProg",
"body":body.toJSON,
"width": 450,
"cancelButton": "\$cancelButton",
"commitButton":"\$commitButton",
"commitAction": commitAct,
"completeAction": completeAction.concat(),
"finForm": marker()
}.toGrid.addMeta({formExecute: marker()})
enddef
func:finBlockSuggestionHelper
finBlockSuggestionHelper(args, type)
Axon function
meta
| def | func:finBlockSuggestionHelper |
| is | func |
| lib | lib:finBlockProgramming |
| name | finBlockSuggestionHelper |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(args, type) => do
if(type == "tag")
blineCreateProgramTagVars(args, type, args->program->name) //add args->name or whatever and program id
else if(type == "point") do
target: read(readById(parseRef(args->program->id[1..-1]))->programOn.parseFilter)->id
blineAddPointsForm(target, parseRef(args->program->id[1..-1]), args->program->name, args)
end else if(type == "var")
blineCreateProgramVars(args, type, args->program->name)
else if(type == "abs")
blineAddAbsolutePointForm(args, type)
enddef
func:finBlocksCombineVars
finBlocksCombineVars(programId, curVars)
Axon function
meta
| def | func:finBlocksCombineVars |
| is | func |
| lib | lib:finBlockProgramming |
| name | finBlocksCombineVars |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(programId, curVars) => do
globalVars: taskVarTree(programId).finGridFilter(type =="var" and shared == "<proj>").removeCol("type")
.map(r =>
if(r->kind=="Str") r.set("kind", "string")
else if(r->kind=="Bool") r.set("kind", "boolean")
else r)
globalToShow: []
globalVars.each x => do
if(curVars.find(v => v->name == x->name and v->type == x->kind.lower) == null)
globalToShow = globalToShow.add(x.set("type", x->kind.lower).set("displayName", x.dis))
end
return curVars.addAll(globalToShow.map(r => r.set("variable", true)))
enddef
func:finReadBlockProgram
finReadBlockProgram(id)
Axon function
meta
| def | func:finReadBlockProgram |
| is | func |
| lib | lib:finBlockProgramming |
| name | finReadBlockProgram |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(id) => do
rec: readById(id)
if( rec.has("programSource") ) do
rec = rec.set("programSource", finReadBinTag(rec, "programSource"))
end
return rec
enddef
func:getAllMacros
getAllMacros()
Axon function
meta
| def | func:getAllMacros |
| is | func |
| lib | lib:finBlockProgramming |
| name | getAllMacros |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
() => do
readAll(bLineSavedMacro)
enddef
func:getMacroByName
getMacroByName(macroName)
Axon function
meta
| def | func:getMacroByName |
| is | func |
| lib | lib:finBlockProgramming |
| name | getMacroByName |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(macroName) => do
read(name == macroName and bLineSavedMacro)
enddef
func:renameVar
renameVar(programId, varName, newDisplayName)
Axon function
meta
| def | func:renameVar |
| is | func |
| lib | lib:finBlockProgramming |
| name | renameVar |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(programId, varName, newDisplayName) => do
program : read(id == programId)
vars : program->programVars.ioReadZinc
newVariableName: newDisplayName.toEscapedTagName
newVars : vars.map(row => do
if(row->name != varName)
row
else
row.set("display", newDisplayName).set("name", newVariableName)
end)
program.diff({programVars: newVars.ioWriteZinc("")}).commit()
{ varName: varName, newDisplayName: newDisplayName, newVariableName: newVariableName }
enddef
func:renameVarById
renameVarById(programId, variableId, newDisplayName)
Axon function
meta
| def | func:renameVarById |
| is | func |
| lib | lib:finBlockProgramming |
| name | renameVarById |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(programId, variableId, newDisplayName) => do
program : read(id == programId)
vars : program->programVars.ioReadZinc
newVars : vars.map(row => do
if(row["varId"] != variableId)
row
else
row.set("display", newDisplayName)
end)
program.diff({programVars: newVars.ioWriteZinc("")}).commit()
{varId: variableId, newName: newDisplayName}
enddef
func:saveMacro
saveMacro(macroName, macroData)
Axon function
meta
| def | func:saveMacro |
| is | func |
| lib | lib:finBlockProgramming |
| name | saveMacro |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(macroName, macroData) => do
savedMacro: readAll(bLineSavedMacro and name == macroName)
if(savedMacro.size > 0)
commit(diff(savedMacro[0], {data:macroData}))
else
commit(diff(null, {name:macroName, data:macroData, bLineSavedMacro, macro}, {add}))
end