Fixing layout bugs, new label positions, removing expression support for calculated values per sequence which caused too many issues.

This commit is contained in:
Adsooi 2021-01-05 10:54:59 +01:00
parent cb8ccb1c1c
commit 1cd3746109
3 changed files with 141 additions and 58 deletions

View file

@ -211,7 +211,7 @@ ListView {
Column { Column {
id: dlgProperties id: dlgProperties
anchors.top: dlgTitle.bottom anchors.top: dlgTitle.bottom
width: objEditor.width - 40 width: objEditor.width - 20
spacing: 10 spacing: 10
TextSetting { TextSetting {
@ -268,6 +268,7 @@ ListView {
visible: modelData[0].startsWith('comment') visible: modelData[0].startsWith('comment')
text: visible ? modelData[1].replace(/\{name\}/g, objEditor.obj.name) : '' text: visible ? modelData[1].replace(/\{name\}/g, objEditor.obj.name) : ''
color: sysPalette.windowText color: sysPalette.windowText
wrapMode: Text.WordWrap
} }
TextSetting { TextSetting {
@ -298,7 +299,7 @@ ListView {
CheckBox { CheckBox {
id: customPropCheckBox id: customPropCheckBox
visible: modelData[1] == 'Boolean' visible: modelData[1] == 'Boolean'
height: visible ? implicitHeight : 0 height: visible ? 20 : 0
width: parent.width width: parent.width
text: parent.label text: parent.label

View file

@ -86,7 +86,7 @@ class Sequence extends Expression {
this.calcValues = Object.assign({}, baseValues) this.calcValues = Object.assign({}, baseValues)
for(var n in this.calcValues) for(var n in this.calcValues)
if(['string', 'number'].includes(typeof this.calcValues[n])) if(['string', 'number'].includes(typeof this.calcValues[n]))
this.calcValues[n] = parser.parse(this.calcValues[n].toString()).simplify() this.calcValues[n] = parser.parse(this.calcValues[n].toString()).simplify().evaluate(evalVariables)
this.valuePlus = parseInt(valuePlus) this.valuePlus = parseInt(valuePlus)
} }
@ -96,9 +96,9 @@ class Sequence extends Expression {
execute(n = 1) { execute(n = 1) {
if(n in this.calcValues) if(n in this.calcValues)
return this.calcValues[n].evaluate(evalVariables) return this.calcValues[n]
this.cache(n) this.cache(n)
return this.calcValues[n].evaluate(evalVariables) return this.calcValues[n]
} }
simplify(n = 1) { simplify(n = 1) {
@ -109,19 +109,12 @@ class Sequence extends Expression {
} }
cache(n = 1) { cache(n = 1) {
var str = this.calc.substitute('n', n-this.valuePlus).toString() var str = Utils.simplifyExpression(this.calc.substitute('n', n-this.valuePlus).toString())
for(var newn in this.calcValues) {
var un = new RegExp(`${this.name}\\[${newn}\\]`, 'g')
if(un.test(str)) {
if (this.calcValues[newn] == undefined)
this.cache(newn)
str = str.replace(un, this.calcValues[newn])
}
}
var expr = parser.parse(str).simplify() var expr = parser.parse(str).simplify()
if(expr.evaluate(evalVariables) == 0) expr = parser.parse('0') var l = {}
expr = parser.parse(Utils.simplifyExpression(expr.toString())).simplify() l[this.name] = this.calcValues
this.calcValues[n] = expr console.log(JSON.stringify(l), expr)
this.calcValues[n] = expr.evaluate(Object.assign(l, evalVariables))
} }
toString(forceSign=false) { toString(forceSign=false) {

View file

@ -201,19 +201,19 @@ class Function extends ExecutableObject {
static typeMultiple(){return 'Functions'} static typeMultiple(){return 'Functions'}
static properties() {return { static properties() {return {
'expression': 'Expression', 'expression': 'Expression',
'inDomain': 'Domain', 'definitionDomain': 'Domain',
'outDomain': 'Domain', 'destinationDomain': 'Domain',
'comment1': 'Ex: R+* (ℝ⁺*), N* (*), Z-* (ℤ⁻*), ]0;1[, {3;4;5}', 'comment1': 'Ex: R+* (ℝ⁺*), N (), Z-* (ℤ⁻*), ]0;1[, {3;4;5}',
'labelPosition': new P.Enum('above', 'below'), 'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'displayMode': new P.Enum('application', 'function'), 'displayMode': new P.Enum('application', 'function'),
'labelX': 'number', 'labelX': 'number',
'comment1': 'The following parameters are used in case of non-continuous ensembles\n(E.g: , , sets like {0;3}...)', 'comment2': 'The following parameters are used when the definition domain is a non-continuous set. (Ex: , , sets like {0;3}...)',
'drawPoints': 'Boolean', 'drawPoints': 'Boolean',
'drawDashedLines': 'Boolean' 'drawDashedLines': 'Boolean'
}} }}
constructor(name = null, visible = true, color = null, labelContent = 'name + value', constructor(name = null, visible = true, color = null, labelContent = 'name + value',
expression = 'x', inDomain = 'RPE', outDomain = 'R', expression = 'x', definitionDomain = 'RPE', destinationDomain = 'R',
displayMode = 'application', labelPosition = 'above', labelX = 1, displayMode = 'application', labelPosition = 'above', labelX = 1,
drawPoints = true, drawDashedLines = true) { drawPoints = true, drawDashedLines = true) {
if(name == null) name = getNewName('fghjqlmnopqrstuvwabcde') if(name == null) name = getNewName('fghjqlmnopqrstuvwabcde')
@ -221,10 +221,10 @@ class Function extends ExecutableObject {
this.type = 'Function' this.type = 'Function'
if(typeof expression == 'number' || typeof expression == 'string') expression = new MathLib.Expression(expression.toString()) if(typeof expression == 'number' || typeof expression == 'string') expression = new MathLib.Expression(expression.toString())
this.expression = expression this.expression = expression
if(typeof inDomain == 'string') inDomain = MathLib.parseDomain(inDomain) if(typeof definitionDomain == 'string') definitionDomain = MathLib.parseDomain(definitionDomain)
this.inDomain = inDomain this.definitionDomain = definitionDomain
if(typeof outDomain == 'string') outDomain = MathLib.parseDomain(outDomain) if(typeof destinationDomain == 'string') destinationDomain = MathLib.parseDomain(destinationDomain)
this.outDomain = outDomain this.destinationDomain = destinationDomain
this.displayMode = displayMode this.displayMode = displayMode
this.labelPosition = labelPosition this.labelPosition = labelPosition
this.labelX = labelX this.labelX = labelX
@ -234,36 +234,36 @@ class Function extends ExecutableObject {
getReadableString() { getReadableString() {
if(this.displayMode == 'application') { if(this.displayMode == 'application') {
return `${this.name}: ${this.inDomain} ⸺> ${this.outDomain}\n ${' '.repeat(this.name.length)}x ⸺> ${this.expression.toString()}` return `${this.name}: ${this.definitionDomain} ⸺> ${this.destinationDomain}\n ${' '.repeat(this.name.length)}x ⸺> ${this.expression.toString()}`
} else { } else {
return `${this.name}(x) = ${this.expression.toString()}` return `${this.name}(x) = ${this.expression.toString()}\nD<sub>${this.name}</sub> = ${this.definitionDomain}`
} }
} }
export() { export() {
return [this.name, this.visible, this.color.toString(), this.labelContent, return [this.name, this.visible, this.color.toString(), this.labelContent,
this.expression.toEditableString(), this.inDomain.toString(), this.outDomain.toString(), this.expression.toEditableString(), this.definitionDomain.toString(), this.destinationDomain.toString(),
this.displayMode, this.labelPosition, this.labelX, this.drawPoints, this.drawDashedLines] this.displayMode, this.labelPosition, this.labelX, this.drawPoints, this.drawDashedLines]
} }
execute(x = 1) { execute(x = 1) {
if(this.inDomain.includes(x)) if(this.definitionDomain.includes(x))
return this.expression.execute(x) return this.expression.execute(x)
return null return null
} }
canExecute(x = 1) { canExecute(x = 1) {
return this.inDomain.includes(x) return this.definitionDomain.includes(x)
} }
simplify(x = 1) { simplify(x = 1) {
if(this.inDomain.includes(x)) if(this.definitionDomain.includes(x))
return this.expression.simplify(x) return this.expression.simplify(x)
return '' return ''
} }
draw(canvas, ctx) { draw(canvas, ctx) {
Function.drawFunction(canvas, ctx, this.expression, this.inDomain, this.outDomain, this.drawPoints, this.drawDashedLines) Function.drawFunction(canvas, ctx, this.expression, this.definitionDomain, this.destinationDomain, this.drawPoints, this.drawDashedLines)
// Label // Label
var text = this.getLabel() var text = this.getLabel()
ctx.font = "14px sans-serif" ctx.font = "14px sans-serif"
@ -272,33 +272,50 @@ class Function extends ExecutableObject {
var posY = canvas.y2px(this.execute(this.labelX)) var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) { switch(this.labelPosition) {
case 'above': case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height) canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break; break;
case 'below': case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height) canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break; break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break;
} }
} }
static drawFunction(canvas, ctx, expr, inDomain, outDomain, drawPoints = true, drawDash = true) { static drawFunction(canvas, ctx, expr, definitionDomain, destinationDomain, drawPoints = true, drawDash = true) {
// Reusable in other objects. // Reusable in other objects.
// Drawing small traits every 2px // Drawing small traits every 2px
var pxprecision = 2 var pxprecision = 2
var previousX = canvas.px2x(0) var previousX = canvas.px2x(0)
var previousY; var previousY;
if(inDomain instanceof MathLib.SpecialDomain && inDomain.moveSupported) { if(definitionDomain instanceof MathLib.SpecialDomain && definitionDomain.moveSupported) {
// Point based functions. // Point based functions.
previousX = inDomain.previous(previousX) previousX = definitionDomain.previous(previousX)
if(previousX === null) previousX = inDomain.next(canvas.px2x(0)) if(previousX === null) previousX = definitionDomain.next(canvas.px2x(0))
previousY = expr.execute(previousX) previousY = expr.execute(previousX)
if(!drawPoints && !drawDash) return if(!drawPoints && !drawDash) return
while(previousX !== null && canvas.x2px(previousX) < canvas.canvasSize.width) { while(previousX !== null && canvas.x2px(previousX) < canvas.canvasSize.width) {
var currentX = inDomain.next(previousX) var currentX = definitionDomain.next(previousX)
var currentY = expr.execute(currentX) var currentY = expr.execute(currentX)
if(currentX === null) break; if(currentX === null) break;
if((inDomain.includes(currentX) || inDomain.includes(previousX)) && if((definitionDomain.includes(currentX) || definitionDomain.includes(previousX)) &&
(outDomain.includes(currentY) || outDomain.includes(previousY))) { (destinationDomain.includes(currentY) || destinationDomain.includes(previousY))) {
if(drawDash) if(drawDash)
canvas.drawDashedLine(ctx, canvas.x2px(previousX), canvas.y2px(previousY), canvas.x2px(currentX), canvas.y2px(currentY)) canvas.drawDashedLine(ctx, canvas.x2px(previousX), canvas.y2px(previousY), canvas.x2px(currentX), canvas.y2px(currentY))
if(drawPoints) { if(drawPoints) {
@ -319,8 +336,8 @@ class Function extends ExecutableObject {
for(var px = pxprecision; px < canvas.canvasSize.width; px += pxprecision) { for(var px = pxprecision; px < canvas.canvasSize.width; px += pxprecision) {
var currentX = canvas.px2x(px) var currentX = canvas.px2x(px)
var currentY = expr.execute(currentX) var currentY = expr.execute(currentX)
if((inDomain.includes(currentX) || inDomain.includes(previousX)) && if((definitionDomain.includes(currentX) || definitionDomain.includes(previousX)) &&
(outDomain.includes(currentY) || outDomain.includes(previousY)) && (destinationDomain.includes(currentY) || destinationDomain.includes(previousY)) &&
Math.abs(previousY-currentY)<100) { Math.abs(previousY-currentY)<100) {
canvas.drawLine(ctx, canvas.x2px(previousX), canvas.y2px(previousY), canvas.x2px(currentX), canvas.y2px(currentY)) canvas.drawLine(ctx, canvas.x2px(previousX), canvas.y2px(previousY), canvas.x2px(currentX), canvas.y2px(currentY))
} }
@ -339,7 +356,7 @@ class GainBode extends ExecutableObject {
'om_0': new P.ObjectType('Point'), 'om_0': new P.ObjectType('Point'),
'pass': new P.Enum('high', 'low'), 'pass': new P.Enum('high', 'low'),
'gain': 'Expression', 'gain': 'Expression',
'labelPosition': new P.Enum('above', 'below'), 'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'labelX': 'number' 'labelX': 'number'
}} }}
@ -428,10 +445,28 @@ class GainBode extends ExecutableObject {
var posY = canvas.y2px(this.execute(this.labelX)) var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) { switch(this.labelPosition) {
case 'above': case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-3) canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break; break;
case 'below': case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+3+textSize.height) canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break; break;
} }
} }
@ -451,7 +486,7 @@ class SommeGainsBode extends DrawableObject {
static typeMultiple(){return 'Somme gains Bode'} static typeMultiple(){return 'Somme gains Bode'}
static createable() {return false} static createable() {return false}
static properties() {return { static properties() {return {
'labelPosition': new P.Enum('above', 'below'), 'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'labelX': 'number' 'labelX': 'number'
}} }}
@ -559,10 +594,28 @@ class SommeGainsBode extends DrawableObject {
var posY = canvas.y2px(dbfn.execute(this.labelX)) var posY = canvas.y2px(dbfn.execute(this.labelX))
switch(this.labelPosition) { switch(this.labelPosition) {
case 'above': case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-5) canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break; break;
case 'below': case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+5+textSize.height) canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break; break;
} }
} }
@ -579,7 +632,7 @@ class PhaseBode extends ExecutableObject {
'om_0': new P.ObjectType('Point'), 'om_0': new P.ObjectType('Point'),
'phase': 'Expression', 'phase': 'Expression',
'unit': new P.Enum('°', 'deg', 'rad'), 'unit': new P.Enum('°', 'deg', 'rad'),
'labelPosition': new P.Enum('above', 'below'), 'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'labelX': 'number' 'labelX': 'number'
}} }}
@ -617,7 +670,7 @@ class PhaseBode extends ExecutableObject {
} }
getReadableString() { getReadableString() {
return `${this.name}: ${this.phase.toString(true)}${this.unit} at ${this.om_0.name} = ${this.om_0.x}\n` return `${this.name}: ${this.phase.toString(true)}${this.unit} at ${this.om_0.name} = ${this.om_0.x}`
} }
execute(x=1) { execute(x=1) {
@ -665,10 +718,28 @@ class PhaseBode extends ExecutableObject {
var posY = canvas.y2px(this.execute(this.labelX)) var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) { switch(this.labelPosition) {
case 'above': case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-5) canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break; break;
case 'below': case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+5+textSize.height) canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break; break;
} }
} }
@ -688,7 +759,7 @@ class SommePhasesBode extends ExecutableObject {
static typeMultiple(){return 'Somme phases Bode'} static typeMultiple(){return 'Somme phases Bode'}
static createable() {return false} static createable() {return false}
static properties() {return { static properties() {return {
'labelPosition': new P.Enum('above', 'below'), 'labelPosition': new P.Enum('above', 'below', 'left', 'right', 'above-left', 'above-right', 'below-left', 'below-right'),
'labelX': 'number' 'labelX': 'number'
}} }}
@ -783,10 +854,28 @@ class SommePhasesBode extends ExecutableObject {
var posY = canvas.y2px(this.execute(this.labelX)) var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) { switch(this.labelPosition) {
case 'above': case 'above':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-5) canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY-textSize.height)
break; break;
case 'below': case 'below':
canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+5+textSize.height) canvas.drawVisibleText(ctx, text, posX-textSize.width/2, posY+textSize.height)
break;
case 'left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height/2)
break;
case 'right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height/2)
break;
case 'above-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY-textSize.height)
break;
case 'above-right':
canvas.drawVisibleText(ctx, text, posX, posY-textSize.height)
break;
case 'below-left':
canvas.drawVisibleText(ctx, text, posX-textSize.width, posY+textSize.height)
break;
case 'below-right':
canvas.drawVisibleText(ctx, text, posX, posY+textSize.height)
break; break;
} }
} }