Propagated property updates to dependent objects.
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
+ Fixing object expression dependency at setup. + Fixing function calls in utils + Removing some unnecessary comments
This commit is contained in:
parent
1ba594c4f7
commit
1a433eba27
8 changed files with 68 additions and 37 deletions
|
@ -249,11 +249,12 @@ ApplicationWindow {
|
||||||
|
|
||||||
// Importing objects
|
// Importing objects
|
||||||
Objects.currentObjects = {}
|
Objects.currentObjects = {}
|
||||||
for(var objType in data['objects']) {
|
Objects.currentObjectsByName = {}
|
||||||
|
for(let objType in data['objects']) {
|
||||||
if(Object.keys(Objects.types).indexOf(objType) > -1) {
|
if(Object.keys(Objects.types).indexOf(objType) > -1) {
|
||||||
Objects.currentObjects[objType] = []
|
Objects.currentObjects[objType] = []
|
||||||
for(var objData of data['objects'][objType]) {
|
for(let objData of data['objects'][objType]) {
|
||||||
var obj = new Objects.types[objType](...objData)
|
let obj = new Objects.types[objType](...objData)
|
||||||
Objects.currentObjects[objType].push(obj)
|
Objects.currentObjects[objType].push(obj)
|
||||||
Objects.currentObjectsByName[obj.name] = obj
|
Objects.currentObjectsByName[obj.name] = obj
|
||||||
}
|
}
|
||||||
|
@ -262,6 +263,10 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Updating object dependencies.
|
||||||
|
for(let objName in Objects.currentObjectsByName)
|
||||||
|
Objects.currentObjectsByName[objName].update()
|
||||||
|
|
||||||
// Importing history
|
// Importing history
|
||||||
if("history" in data)
|
if("history" in data)
|
||||||
history.unserialize(...data["history"])
|
history.unserialize(...data["history"])
|
||||||
|
|
|
@ -58,10 +58,12 @@ class EditedProperty extends C.Action {
|
||||||
|
|
||||||
undo() {
|
undo() {
|
||||||
Objects.currentObjectsByName[this.targetName][this.targetProperty] = this.previousValue
|
Objects.currentObjectsByName[this.targetName][this.targetProperty] = this.previousValue
|
||||||
|
Objects.currentObjectsByName[this.targetName].update()
|
||||||
}
|
}
|
||||||
|
|
||||||
redo() {
|
redo() {
|
||||||
Objects.currentObjectsByName[this.targetName][this.targetProperty] = this.newValue
|
Objects.currentObjectsByName[this.targetName][this.targetProperty] = this.newValue
|
||||||
|
Objects.currentObjectsByName[this.targetName].update()
|
||||||
}
|
}
|
||||||
|
|
||||||
export() {
|
export() {
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Expression {
|
||||||
this.expr = expr
|
this.expr = expr
|
||||||
this.calc = C.parser.parse(expr).simplify()
|
this.calc = C.parser.parse(expr).simplify()
|
||||||
this.cached = this.isConstant()
|
this.cached = this.isConstant()
|
||||||
this.cachedValue = this.cached ? this.calc.evaluate(C.currentObjectsByName) : null
|
this.cachedValue = this.cached && this.allRequirementsFullfilled() ? this.calc.evaluate(C.currentObjectsByName) : null
|
||||||
this.latexMarkup = Latex.expression(this.calc.tokens)
|
this.latexMarkup = Latex.expression(this.calc.tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +39,25 @@ class Expression {
|
||||||
return !vars.includes("x") && !vars.includes("n")
|
return !vars.includes("x") && !vars.includes("n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requiredObjects() {
|
||||||
|
return this.calc.variables().filter(objName => objName != "x" && objName != "n")
|
||||||
|
}
|
||||||
|
|
||||||
|
allRequirementsFullfilled() {
|
||||||
|
return this.requiredObjects().every(objName => objName in C.currentObjectsByName)
|
||||||
|
}
|
||||||
|
|
||||||
|
recache() {
|
||||||
|
if(this.cached)
|
||||||
|
this.cachedValue = this.calc.evaluate(C.currentObjectsByName)
|
||||||
|
}
|
||||||
|
|
||||||
execute(x = 1) {
|
execute(x = 1) {
|
||||||
if(this.cached) return this.cachedValue
|
if(this.cached) {
|
||||||
|
if(this.cachedValue == null)
|
||||||
|
this.cachedValue = this.calc.evaluate(C.currentObjectsByName)
|
||||||
|
return this.cachedValue
|
||||||
|
}
|
||||||
C.currentVars = Object.assign({'x': x}, C.currentObjectsByName)
|
C.currentVars = Object.assign({'x': x}, C.currentObjectsByName)
|
||||||
//console.log("Executing", this.expr, "with", JSON.stringify(C.currentVars))
|
//console.log("Executing", this.expr, "with", JSON.stringify(C.currentVars))
|
||||||
return this.calc.evaluate(C.currentVars)
|
return this.calc.evaluate(C.currentVars)
|
||||||
|
@ -68,7 +85,7 @@ class Expression {
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(forceSign=false) {
|
toString(forceSign=false) {
|
||||||
var str = Utils.makeExpressionReadable(this.calc.toString())
|
let str = Utils.makeExpressionReadable(this.calc.toString())
|
||||||
if(str[0] != '-' && forceSign) str = '+' + str
|
if(str[0] != '-' && forceSign) str = '+' + str
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
.import "../utils.js" as Utils
|
.import "../utils.js" as Utils
|
||||||
.import "../objects.js" as Objects
|
.import "../objects.js" as Objects
|
||||||
.import "../math/latex.js" as Latex
|
.import "../math/latex.js" as Latex
|
||||||
|
.import "../parameters.js" as P
|
||||||
|
.import "../math/common.js" as C
|
||||||
|
|
||||||
// This file contains the default data to be imported from all other objects
|
// This file contains the default data to be imported from all other objects
|
||||||
|
|
||||||
|
@ -116,6 +118,7 @@ class DrawableObject {
|
||||||
this.color = color
|
this.color = color
|
||||||
this.labelContent = labelContent // "null", "name", "name + value"
|
this.labelContent = labelContent // "null", "name", "name + value"
|
||||||
this.requiredBy = []
|
this.requiredBy = []
|
||||||
|
this.requires = []
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -187,18 +190,40 @@ class DrawableObject {
|
||||||
* Callback method when one of the properties of the object is updated.
|
* Callback method when one of the properties of the object is updated.
|
||||||
*/
|
*/
|
||||||
update() {
|
update() {
|
||||||
for(let req of this.requiredBy) {
|
// Refreshing dependencies.
|
||||||
req.update()
|
for(let obj of this.requires)
|
||||||
|
obj.requiredBy = obj.requiredBy.filter(dep => dep != this)
|
||||||
|
// Checking objects this one depends on
|
||||||
|
this.requires = []
|
||||||
|
let properties = this.constructor.properties()
|
||||||
|
for(let property in properties)
|
||||||
|
if(properties[property] == 'Expression' && this[property] != null) {
|
||||||
|
// Expressions with dependencies
|
||||||
|
for(let objName of this[property].requiredObjects()) {
|
||||||
|
this.requires.push(C.currentObjectsByName[objName])
|
||||||
|
C.currentObjectsByName[objName].requiredBy.push(this)
|
||||||
}
|
}
|
||||||
|
if(this[property].cached && this[property].requiredObjects().length > 0)
|
||||||
|
// Recalculate
|
||||||
|
this[property].recache()
|
||||||
|
|
||||||
|
} else if(typeof properties[property] == 'object' && 'type' in properties[property] && properties[property] == 'ObjectType' && this[property] != null) {
|
||||||
|
// Object dependency
|
||||||
|
this.requires.push(this[property])
|
||||||
|
this[property].requiredBy.push(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updating objects dependent on this one
|
||||||
|
for(let req of this.requiredBy)
|
||||||
|
req.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback method when the object is about to get deleted.
|
* Callback method when the object is about to get deleted.
|
||||||
*/
|
*/
|
||||||
delete() {
|
delete() {
|
||||||
for(var toRemove of this.requiredBy) {
|
for(let toRemove of this.requiredBy) {
|
||||||
toRemove.delete()
|
Objects.deleteObject(toRemove.name)
|
||||||
Objects.currentObjects[toRemove.type] = Objects.currentObjects[toRemove.type].filter(obj => obj.name != toRemove.name)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +286,7 @@ class DrawableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Automaticly draw text (by default the label of the object on the \c canvas with
|
* Automatically draw text (by default the label of the object on the \c canvas with
|
||||||
* the 2D context \c ctx depending on user settings.
|
* the 2D context \c ctx depending on user settings.
|
||||||
* This method takes into account both the \c posX and \c posY of where the label
|
* This method takes into account both the \c posX and \c posY of where the label
|
||||||
* should be displayed, including the \c labelPosition relative to it.
|
* should be displayed, including the \c labelPosition relative to it.
|
||||||
|
|
|
@ -27,14 +27,6 @@ class RepartitionFunction extends Common.ExecutableObject {
|
||||||
static type(){return 'Repartition'}
|
static type(){return 'Repartition'}
|
||||||
static displayType(){return qsTr('Repartition')}
|
static displayType(){return qsTr('Repartition')}
|
||||||
static displayTypeMultiple(){return qsTr('Repartition functions')}
|
static displayTypeMultiple(){return qsTr('Repartition functions')}
|
||||||
/*static properties() {return {
|
|
||||||
'beginIncluded': 'boolean',
|
|
||||||
'drawLineEnds': 'boolean',
|
|
||||||
'comment1': 'Note: Specify the properties for each potential result.',
|
|
||||||
'probabilities': new P.Dictionary('string', 'float', /^-?[\d.,]+$/, /^-?[\d\.,]+$/, 'P({name} = ', ') = '),
|
|
||||||
'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
|
|
||||||
'labelX': 'number'
|
|
||||||
}}*/
|
|
||||||
static properties() {return {
|
static properties() {return {
|
||||||
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
|
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
|
||||||
[QT_TRANSLATE_NOOP('prop','labelX')]: 'number',
|
[QT_TRANSLATE_NOOP('prop','labelX')]: 'number',
|
||||||
|
|
|
@ -30,10 +30,6 @@ class SommePhasesBode extends Common.ExecutableObject {
|
||||||
static displayType(){return qsTr('Bode Phases Sum')}
|
static displayType(){return qsTr('Bode Phases Sum')}
|
||||||
static displayTypeMultiple(){return qsTr('Bode Phases Sum')}
|
static displayTypeMultiple(){return qsTr('Bode Phases Sum')}
|
||||||
static createable() {return false}
|
static createable() {return false}
|
||||||
/*static properties() {return {
|
|
||||||
'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
|
|
||||||
'labelX': 'number'
|
|
||||||
}}*/
|
|
||||||
static properties() {return {
|
static properties() {return {
|
||||||
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
|
[QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position,
|
||||||
[QT_TRANSLATE_NOOP('prop','labelX')]: 'number',
|
[QT_TRANSLATE_NOOP('prop','labelX')]: 'number',
|
||||||
|
|
|
@ -29,12 +29,6 @@ class Text extends Common.DrawableObject {
|
||||||
static type(){return 'Text'}
|
static type(){return 'Text'}
|
||||||
static displayType(){return qsTr('Text')}
|
static displayType(){return qsTr('Text')}
|
||||||
static displayTypeMultiple(){return qsTr('Texts')}
|
static displayTypeMultiple(){return qsTr('Texts')}
|
||||||
/*static properties() {return {
|
|
||||||
'x': 'Expression',
|
|
||||||
'y': 'Expression',
|
|
||||||
'labelPosition': new P.Enum('center', 'above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
|
|
||||||
'text': 'string',
|
|
||||||
}}*/
|
|
||||||
static properties() {return {
|
static properties() {return {
|
||||||
[QT_TRANSLATE_NOOP('prop','x')]: 'Expression',
|
[QT_TRANSLATE_NOOP('prop','x')]: 'Expression',
|
||||||
[QT_TRANSLATE_NOOP('prop','y')]: 'Expression',
|
[QT_TRANSLATE_NOOP('prop','y')]: 'Expression',
|
||||||
|
|
|
@ -129,11 +129,11 @@ function simplifyExpression(str) {
|
||||||
var replacements = [
|
var replacements = [
|
||||||
// Operations not done by parser.
|
// Operations not done by parser.
|
||||||
[// Decomposition way 2
|
[// Decomposition way 2
|
||||||
/(^.?|[+-] |\()([-.\d\w]+) ([*/]) \((([-.\d\w] [*/] )?[-\d\w.]+) ([+\-]) (([-.\d\w] [*/] )?[\d\w.+]+)\)(.?$| [+-]|\))/g,
|
/(^|[+-] |\()([-.\d\w]+) ([*/]) \((([-.\d\w] [*/] )?[-\d\w.]+) ([+\-]) (([-.\d\w] [*/] )?[\d\w.+]+)\)($| [+-]|\))/g,
|
||||||
"$1$2 $3 $4 $6 $2 $3 $7$9"
|
"$1$2 $3 $4 $6 $2 $3 $7$9"
|
||||||
],
|
],
|
||||||
[ // Decomposition way 2
|
[ // Decomposition way 2
|
||||||
/(^.?|[+-] |\()\((([-.\d\w] [*/] )?[-\d\w.]+) ([+\-]) (([-.\d\w] [*/] )?[\d\w.+]+)\) ([*/]) ([-.\d\w]+)(.?$| [+-]|\))/g,
|
/(^|[+-] |\()\((([-.\d\w] [*/] )?[-\d\w.]+) ([+\-]) (([-.\d\w] [*/] )?[\d\w.+]+)\) ([*/]) ([-.\d\w]+)($| [+-]|\))/g,
|
||||||
"$1$2 $7 $8 $4 $5 $7 $8$9"
|
"$1$2 $7 $8 $4 $5 $7 $8$9"
|
||||||
],
|
],
|
||||||
[ // Factorisation of π elements.
|
[ // Factorisation of π elements.
|
||||||
|
@ -159,19 +159,19 @@ function simplifyExpression(str) {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[ // Removing parenthesis when content is only added from both sides.
|
[ // Removing parenthesis when content is only added from both sides.
|
||||||
/(^.?|[+-] |\()\(([^)(]+)\)(.?$| [+-]|\))/g,
|
/(^|[+-] |\()\(([^)(]+)\)($| [+-]|\))/g,
|
||||||
function(match, b4, middle, after) {return `${b4}${middle}${after}`}
|
function(match, b4, middle, after) {return `${b4}${middle}${after}`}
|
||||||
],
|
],
|
||||||
[ // Removing parenthesis when content is only multiplied.
|
[ // Removing parenthesis when content is only multiplied.
|
||||||
/(^.?|[*\/] |\()\(([^)(+-]+)\)(.?$| [*\/+-]|\))/g,
|
/(^|[*\/] |\()\(([^)(+-]+)\)($| [*\/+-]|\))/g,
|
||||||
function(match, b4, middle, after) {return `${b4}${middle}${after}`}
|
function(match, b4, middle, after) {return `${b4}${middle}${after}`}
|
||||||
],
|
],
|
||||||
[ // Removing parenthesis when content is only multiplied.
|
[ // Removing parenthesis when content is only multiplied.
|
||||||
/(^.?|[*\/-+] |\()\(([^)(+-]+)\)(.?$| [*\/]|\))/g,
|
/(^|[*\/-+] |\()\(([^)(+-]+)\)($| [*\/]|\))/g,
|
||||||
function(match, b4, middle, after) {return `${b4}${middle}${after}`}
|
function(match, b4, middle, after) {return `${b4}${middle}${after}`}
|
||||||
],
|
],
|
||||||
[// Simplification additions/substractions.
|
[// Simplification additions/substractions.
|
||||||
/(^.?|[^*\/] |\()([-.\d]+) (\+|\-) (\([^)(]+\)|[^)(]+) (\+|\-) ([-.\d]+)(.?$| [^*\/]|\))/g,
|
/(^|[^*\/] |\()([-.\d]+) (\+|\-) (\([^)(]+\)|[^)(]+) (\+|\-) ([-.\d]+)($| [^*\/]|\))/g,
|
||||||
function(match, b4, n1, op1, middle, op2, n2, after) {
|
function(match, b4, n1, op1, middle, op2, n2, after) {
|
||||||
var total
|
var total
|
||||||
if(op2 == '+') {
|
if(op2 == '+') {
|
||||||
|
@ -258,7 +258,7 @@ function makeExpressionReadable(str) {
|
||||||
[/\[([^\[\]]+)\]/g, function(match, p1) { return textsub(p1) }],
|
[/\[([^\[\]]+)\]/g, function(match, p1) { return textsub(p1) }],
|
||||||
[/(\d|\))×/g, '$1'],
|
[/(\d|\))×/g, '$1'],
|
||||||
//[/×(\d|\()/g, '$1'],
|
//[/×(\d|\()/g, '$1'],
|
||||||
[/\(([^)(+.\/-]+)\)/g, "$1"],
|
[/[^a-z]\(([^)(+.\/-]+)\)/g, "$1"],
|
||||||
[/integral\((.+),\s?(.+),\s?("|')(.+)("|'),\s?("|')(.+)("|')\)/g, function(match, a, b, p1, body, p2, p3, by, p4) {
|
[/integral\((.+),\s?(.+),\s?("|')(.+)("|'),\s?("|')(.+)("|')\)/g, function(match, a, b, p1, body, p2, p3, by, p4) {
|
||||||
if(a.length < b.length) {
|
if(a.length < b.length) {
|
||||||
return `∫${textsub(a)}${textsup(b)} ${body} d${by}`
|
return `∫${textsub(a)}${textsup(b)} ${body} d${by}`
|
||||||
|
|
Loading…
Reference in a new issue