@teachinglab/omd 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/api/omdToolbar.md +130 -130
- package/omd/config/omdConfigManager.js +2 -2
- package/omd/core/omdEquationStack.js +521 -521
- package/omd/display/omdDisplay.js +421 -53
- package/omd/nodes/omdBinaryExpressionNode.js +459 -459
- package/omd/nodes/omdEquationNode.js +1273 -1222
- package/omd/nodes/omdEquationSequenceNode.js +1246 -1246
- package/omd/nodes/omdFunctionNode.js +351 -351
- package/omd/nodes/omdNode.js +556 -556
- package/omd/nodes/omdSqrtNode.js +307 -307
- package/omd/step-visualizer/omdStepVisualizer.js +95 -33
- package/omd/step-visualizer/omdStepVisualizerLayout.js +640 -9
- package/package.json +1 -1
- package/src/omdMetaExpression.js +1 -1
|
@@ -15,9 +15,12 @@ import { jsvgLayoutGroup, jsvgEllipse, jsvgLine } from '@teachinglab/jsvg';
|
|
|
15
15
|
* @extends omdEquationSequenceNode
|
|
16
16
|
*/
|
|
17
17
|
export class omdStepVisualizer extends omdEquationSequenceNode {
|
|
18
|
-
constructor(steps) {
|
|
18
|
+
constructor(steps, styling = {}) {
|
|
19
19
|
super(steps);
|
|
20
20
|
|
|
21
|
+
// Store styling options
|
|
22
|
+
this.styling = styling || {};
|
|
23
|
+
|
|
21
24
|
// Visual elements for step tracking
|
|
22
25
|
this.stepDots = [];
|
|
23
26
|
this.stepLines = [];
|
|
@@ -37,9 +40,32 @@ export class omdStepVisualizer extends omdEquationSequenceNode {
|
|
|
37
40
|
|
|
38
41
|
this.addChild(this.visualContainer);
|
|
39
42
|
this._initializeVisualElements();
|
|
43
|
+
|
|
44
|
+
// Set default filter level to show only major steps (stepMark = 0)
|
|
45
|
+
// This ensures intermediate steps are hidden and expansion dots can be created
|
|
46
|
+
console.debug('Step visualizer: Setting default filter level to 0');
|
|
47
|
+
console.debug('Steps before filter:', this.steps.map(s => ({type: s.constructor.name, stepMark: s.stepMark, visible: s.visible})));
|
|
48
|
+
|
|
49
|
+
if (this.setFilterLevel && typeof this.setFilterLevel === 'function') {
|
|
50
|
+
this.setFilterLevel(0);
|
|
51
|
+
console.debug('Steps after filter:', this.steps.map(s => ({type: s.constructor.name, stepMark: s.stepMark, visible: s.visible})));
|
|
52
|
+
} else {
|
|
53
|
+
console.debug('setFilterLevel method not available');
|
|
54
|
+
}
|
|
55
|
+
|
|
40
56
|
this.computeDimensions();
|
|
41
57
|
this.updateLayout();
|
|
42
58
|
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Sets the fixed position for the step visualizer
|
|
62
|
+
* @param {number} position - The x position from the left edge where the visualizer should be positioned
|
|
63
|
+
*/
|
|
64
|
+
setFixedVisualizerPosition(position) {
|
|
65
|
+
if (this.layoutManager) {
|
|
66
|
+
this.layoutManager.setFixedVisualizerPosition(position);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
43
69
|
|
|
44
70
|
/**
|
|
45
71
|
* Force rebuild visual container (dots/lines) from scratch
|
|
@@ -88,8 +114,9 @@ export class omdStepVisualizer extends omdEquationSequenceNode {
|
|
|
88
114
|
const radius = getDotRadius(equation.stepMark ?? 0);
|
|
89
115
|
const dot = new jsvgEllipse();
|
|
90
116
|
dot.setWidthAndHeight(radius * 2, radius * 2);
|
|
91
|
-
|
|
92
|
-
dot.
|
|
117
|
+
const dotColor = this.styling.dotColor || omdColor.stepColor;
|
|
118
|
+
dot.setFillColor(dotColor);
|
|
119
|
+
dot.setStrokeColor(dotColor);
|
|
93
120
|
dot.setStrokeWidth(this.lineWidth);
|
|
94
121
|
dot.radius = radius;
|
|
95
122
|
|
|
@@ -114,7 +141,8 @@ export class omdStepVisualizer extends omdEquationSequenceNode {
|
|
|
114
141
|
*/
|
|
115
142
|
_createStepLine(fromIndex, toIndex) {
|
|
116
143
|
const line = new jsvgLine();
|
|
117
|
-
|
|
144
|
+
const lineColor = this.styling.lineColor || omdColor.stepColor;
|
|
145
|
+
line.setStrokeColor(lineColor);
|
|
118
146
|
line.setStrokeWidth(this.lineWidth);
|
|
119
147
|
|
|
120
148
|
line.fromDotIndex = fromIndex;
|
|
@@ -151,30 +179,39 @@ export class omdStepVisualizer extends omdEquationSequenceNode {
|
|
|
151
179
|
* Override addStep to update visual elements when new steps are added
|
|
152
180
|
*/
|
|
153
181
|
addStep(step, options = {}) {
|
|
154
|
-
|
|
182
|
+
// Call parent first to add the step properly
|
|
183
|
+
super.addStep(step, options);
|
|
184
|
+
|
|
185
|
+
// Now create visual elements for equation nodes only
|
|
155
186
|
if (step instanceof omdEquationNode) {
|
|
156
|
-
this
|
|
157
|
-
const
|
|
158
|
-
const newIndex = equations.length - 1;
|
|
159
|
-
this.steps.pop();
|
|
160
|
-
createdDot = this._createStepDot(step, newIndex);
|
|
161
|
-
step.findAllNodes().forEach(node => {
|
|
162
|
-
this.nodeToStepMap.set(node.id, newIndex);
|
|
163
|
-
});
|
|
187
|
+
// Find the actual index of this equation in the steps array
|
|
188
|
+
const equationIndex = this.steps.filter(s => s instanceof omdEquationNode).indexOf(step);
|
|
164
189
|
|
|
165
|
-
if (
|
|
166
|
-
this.
|
|
190
|
+
if (equationIndex >= 0) {
|
|
191
|
+
const createdDot = this._createStepDot(step, equationIndex);
|
|
192
|
+
|
|
193
|
+
// Update the node to step mapping
|
|
194
|
+
step.findAllNodes().forEach(node => {
|
|
195
|
+
this.nodeToStepMap.set(node.id, equationIndex);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Create connecting line if this isn't the first equation
|
|
199
|
+
if (equationIndex > 0) {
|
|
200
|
+
this._createStepLine(equationIndex - 1, equationIndex);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// After stepMark is set, adjust dot radius
|
|
204
|
+
if (createdDot) {
|
|
205
|
+
const radius = getDotRadius(step.stepMark ?? 0);
|
|
206
|
+
createdDot.setWidthAndHeight(radius * 2, radius * 2);
|
|
207
|
+
createdDot.radius = radius;
|
|
208
|
+
}
|
|
167
209
|
}
|
|
168
210
|
}
|
|
169
211
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if(createdDot){
|
|
174
|
-
const radius=getDotRadius(step.stepMark??0);
|
|
175
|
-
createdDot.setWidthAndHeight(radius*2,radius*2);
|
|
176
|
-
createdDot.radius=radius;
|
|
177
|
-
}
|
|
212
|
+
// Update layout after adding the step
|
|
213
|
+
this.computeDimensions();
|
|
214
|
+
this.updateLayout();
|
|
178
215
|
}
|
|
179
216
|
|
|
180
217
|
/**
|
|
@@ -191,11 +228,12 @@ export class omdStepVisualizer extends omdEquationSequenceNode {
|
|
|
191
228
|
super.computeDimensions();
|
|
192
229
|
this.sequenceWidth = this.width;
|
|
193
230
|
|
|
194
|
-
//
|
|
195
|
-
if (this.stepDots && this.stepDots.length > 0) {
|
|
231
|
+
// Set width to include the fixed visualizer position plus visualizer width
|
|
232
|
+
if (this.stepDots && this.stepDots.length > 0 && this.layoutManager) {
|
|
196
233
|
const containerWidth = this.dotRadius * 3;
|
|
197
|
-
const
|
|
198
|
-
this.
|
|
234
|
+
const fixedVisualizerPosition = this.layoutManager.fixedVisualizerPosition || 250;
|
|
235
|
+
const totalWidth = fixedVisualizerPosition + this.visualSpacing + containerWidth;
|
|
236
|
+
this.setWidthAndHeight(totalWidth, this.height);
|
|
199
237
|
}
|
|
200
238
|
}
|
|
201
239
|
|
|
@@ -203,14 +241,26 @@ export class omdStepVisualizer extends omdEquationSequenceNode {
|
|
|
203
241
|
* Override updateLayout to update visual elements as well
|
|
204
242
|
*/
|
|
205
243
|
updateLayout() {
|
|
244
|
+
console.debug('\n=== omdStepVisualizer.updateLayout START ===');
|
|
245
|
+
console.debug('Calling super.updateLayout()...');
|
|
206
246
|
super.updateLayout();
|
|
207
247
|
|
|
208
248
|
// Only update visual layout if layoutManager is initialized
|
|
209
249
|
if (this.layoutManager) {
|
|
250
|
+
console.debug('LayoutManager found, updating visual elements...');
|
|
251
|
+
console.debug('Calling layoutManager.updateVisualLayout()...');
|
|
210
252
|
this.layoutManager.updateVisualLayout();
|
|
253
|
+
|
|
254
|
+
console.debug('Calling layoutManager.updateVisualVisibility()...');
|
|
211
255
|
this.layoutManager.updateVisualVisibility();
|
|
256
|
+
|
|
257
|
+
console.debug('Calling layoutManager.updateAllLinePositions()...');
|
|
212
258
|
this.layoutManager.updateAllLinePositions();
|
|
259
|
+
} else {
|
|
260
|
+
console.debug('WARNING: LayoutManager not initialized!');
|
|
213
261
|
}
|
|
262
|
+
|
|
263
|
+
console.debug('=== omdStepVisualizer.updateLayout END ===\n');
|
|
214
264
|
}
|
|
215
265
|
|
|
216
266
|
/**
|
|
@@ -313,12 +363,18 @@ export class omdStepVisualizer extends omdEquationSequenceNode {
|
|
|
313
363
|
this.activeDot = this.stepDots[dotIndex];
|
|
314
364
|
|
|
315
365
|
const dot = this.stepDots[dotIndex];
|
|
316
|
-
|
|
317
|
-
dot.
|
|
366
|
+
const explainColor = this.styling.explainColor || omdColor.explainColor;
|
|
367
|
+
dot.setFillColor(explainColor);
|
|
368
|
+
dot.setStrokeColor(explainColor);
|
|
318
369
|
|
|
319
|
-
this.setLineAboveColor(dotIndex, omdColor.explainColor);
|
|
370
|
+
this.setLineAboveColor(dotIndex, this.styling.explainColor || omdColor.explainColor);
|
|
320
371
|
this.textBoxManager.createTextBoxForDot(dotIndex);
|
|
372
|
+
|
|
373
|
+
// Temporarily disable equation repositioning for simple dot state changes
|
|
374
|
+
const originalRepositioning = this.layoutManager.allowEquationRepositioning;
|
|
375
|
+
this.layoutManager.allowEquationRepositioning = false;
|
|
321
376
|
this.layoutManager.updateVisualZOrder();
|
|
377
|
+
this.layoutManager.allowEquationRepositioning = originalRepositioning;
|
|
322
378
|
}
|
|
323
379
|
|
|
324
380
|
/**
|
|
@@ -329,14 +385,20 @@ export class omdStepVisualizer extends omdEquationSequenceNode {
|
|
|
329
385
|
try {
|
|
330
386
|
if (this.activeDotIndex !== -1) {
|
|
331
387
|
const dot = this.stepDots[this.activeDotIndex];
|
|
332
|
-
|
|
333
|
-
dot.
|
|
388
|
+
const dotColor = this.styling.dotColor || omdColor.stepColor;
|
|
389
|
+
dot.setFillColor(dotColor);
|
|
390
|
+
dot.setStrokeColor(dotColor);
|
|
334
391
|
|
|
335
|
-
this.setLineAboveColor(this.activeDotIndex, omdColor.stepColor);
|
|
392
|
+
this.setLineAboveColor(this.activeDotIndex, this.styling.lineColor || omdColor.stepColor);
|
|
336
393
|
this.textBoxManager.removeTextBoxForDot(this.activeDotIndex);
|
|
337
394
|
|
|
338
395
|
this.highlighting.clearHighlights();
|
|
396
|
+
|
|
397
|
+
// Temporarily disable equation repositioning for simple dot state changes
|
|
398
|
+
const originalRepositioning = this.layoutManager.allowEquationRepositioning;
|
|
399
|
+
this.layoutManager.allowEquationRepositioning = false;
|
|
339
400
|
this.layoutManager.updateVisualZOrder();
|
|
401
|
+
this.layoutManager.allowEquationRepositioning = originalRepositioning;
|
|
340
402
|
|
|
341
403
|
this.activeDot = null;
|
|
342
404
|
this.activeDotIndex = -1;
|