UNPKG

@teachinglab/omd

Version:

omd

163 lines (132 loc) 7.91 kB
import { omdColor } from "./omdColor.js"; import { jsvgLayoutGroup, jsvgGroup } from "@teachinglab/jsvg"; import { omdOperator } from "./omdOperator.js"; import { omdMetaExpression } from "./omdMetaExpression.js" import { omdTerm } from "./omdTerm.js"; import { omdExpression } from "./omdExpression.js"; import { omdVariable } from "./omdVariable.js"; import { omdString } from "./omdString.js"; import { omdNumber } from "./omdNumber.js"; import { parseEquationString } from "./omdUtils.js"; export class omdEquation extends omdMetaExpression { constructor() { // initialization super(); this.type = "omdPowerExpression"; this.leftExpression = null; this.rightExpression = null; this.centerEquation = true; this.inset = 5; this.equationStack = new jsvgLayoutGroup(); this.equationStack.setSpacer(-7); this.addChild( this.equationStack ); this.leftHolder = new jsvgGroup(); this.equationStack.addChild( this.leftHolder ); this.equalSign = new omdOperator('='); this.equationStack.addChild( this.equalSign ); this.rightHolder = new jsvgGroup(); this.equationStack.addChild( this.rightHolder ); } // make an equation (x + 2) = (2x - 3) loadFromJSON( data ) { // If explicit left/right JSON provided, build them according to their omdType if ( typeof data.leftExpression != "undefined" && data.leftExpression ) { const left = data.leftExpression; if ( left.omdType == "expression" ) this.leftExpression = new omdExpression(); else if ( left.omdType == "number" ) this.leftExpression = new omdNumber(); else if ( left.omdType == "variable" ) this.leftExpression = new omdVariable(); else if ( left.omdType == "term" ) this.leftExpression = new omdTerm(); else if ( left.omdType == "string" || typeof left == 'string' ) this.leftExpression = new omdExpression(); if (this.leftExpression && typeof this.leftExpression.loadFromJSON === 'function' && left && typeof left === 'object') { this.leftExpression.loadFromJSON( left ); } if (this.leftExpression) { this.leftHolder.removeAllChildren(); this.leftHolder.addChild( this.leftExpression ); } } if ( typeof data.rightExpression != "undefined" && data.rightExpression ) { const right = data.rightExpression; if ( right.omdType == "expression" ) this.rightExpression = new omdExpression(); else if ( right.omdType == "number" ) this.rightExpression = new omdNumber(); else if ( right.omdType == "variable" ) this.rightExpression = new omdVariable(); else if ( right.omdType == "term" ) this.rightExpression = new omdTerm(); else if ( right.omdType == "string" || typeof right == 'string' ) this.rightExpression = new omdExpression(); if (this.rightExpression && typeof this.rightExpression.loadFromJSON === 'function' && right && typeof right === 'object') { this.rightExpression.loadFromJSON( right ); } if (this.rightExpression) { this.rightHolder.removeAllChildren(); this.rightHolder.addChild( this.rightExpression ); } } // If no structured left/right provided but an `equation` string exists, try to parse it into structured expressions if ( (!this.leftExpression || !this.rightExpression) && typeof data.equation === 'string' ) { const parsed = parseEquationString(data.equation); if ( parsed ) { if (!this.leftExpression) this.leftExpression = new omdExpression(); if (!this.rightExpression) this.rightExpression = new omdExpression(); // pass parsed structured JSON to expressions if (this.leftExpression && typeof this.leftExpression.loadFromJSON === 'function') this.leftExpression.loadFromJSON(parsed.leftExpression); if (this.rightExpression && typeof this.rightExpression.loadFromJSON === 'function') this.rightExpression.loadFromJSON(parsed.rightExpression); this.leftHolder.removeAllChildren(); this.leftHolder.addChild(this.leftExpression); this.rightHolder.removeAllChildren(); this.rightHolder.addChild(this.rightExpression); } else { // fallback: treat sides as plain strings const parts = String(data.equation || '').split('='); const leftStr = (parts[0] || '').trim(); const rightStr = (parts[1] || '').trim(); if (!this.leftExpression) this.leftExpression = new omdString(leftStr || ''); if (!this.rightExpression) this.rightExpression = new omdString(rightStr || ''); if (this.leftExpression && typeof this.leftExpression.loadFromJSON === 'function' && typeof leftStr === 'string') this.leftExpression.loadFromJSON(leftStr); if (this.rightExpression && typeof this.rightExpression.loadFromJSON === 'function' && typeof rightStr === 'string') this.rightExpression.loadFromJSON(rightStr); this.leftHolder.removeAllChildren(); this.leftHolder.addChild(this.leftExpression); this.rightHolder.removeAllChildren(); this.rightHolder.addChild(this.rightExpression); } } // Guarded calls to hide backgrounds only when components exist if (this.equalSign && typeof this.equalSign.hideBackgroundByDefault === 'function') this.equalSign.hideBackgroundByDefault(); if (this.leftExpression && typeof this.leftExpression.hideBackgroundByDefault === 'function') this.leftExpression.hideBackgroundByDefault(); if (this.rightExpression && typeof this.rightExpression.hideBackgroundByDefault === 'function') this.rightExpression.hideBackgroundByDefault(); this.centerEquation = false; this.updateLayout(); } setLeftAndRightExpressions( leftExp, rightExp ) { this.leftExpression = leftExp; this.leftHolder.removeAllChildren(); this.leftHolder.addChild( leftExp ); this.rightExpression = rightExp; this.rightHolder.removeAllChildren(); this.rightHolder.addChild( rightExp ); this.equalSign.hideBackgroundByDefault(); this.leftExpression.hideBackgroundByDefault(); this.rightExpression.hideBackgroundByDefault(); this.updateLayout(); } updateLayout() { this.leftHolder.setWidthAndHeight( this.leftExpression.width, this.leftExpression.height ); this.rightHolder.setWidthAndHeight( this.rightExpression.width, this.rightExpression.height ); this.equationStack.doHorizontalLayout(); this.equationStack.setPosition( this.inset, 0 ); var W = this.equationStack.width; this.backRect.setWidthAndHeight( W + this.inset*2, 30 ); this.setWidthAndHeight( this.backRect.width, this.backRect.height ); // Set individual width/height properties and viewBox for API compatibility this.width = this.backRect.width; this.height = this.backRect.height; this.svgObject.setAttribute('viewBox', `0 0 ${this.width} ${this.height}`); if ( this.centerEquation ) { var leftShift = this.leftExpression.width + this.equalSign.width*0.50; this.backRect.setPosition( -1.0 * leftShift + this.inset/2, 0 ); this.equationStack.setPosition( -1.0 * leftShift + this.inset + this.inset/2, 0 ); } } }