@teachinglab/omd 0.6.0 → 0.6.2
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/README.md +257 -251
- package/README.old.md +137 -137
- package/canvas/core/canvasConfig.js +202 -202
- package/canvas/drawing/segment.js +167 -167
- package/canvas/drawing/stroke.js +385 -385
- package/canvas/events/eventManager.js +444 -444
- package/canvas/events/pointerEventHandler.js +262 -262
- package/canvas/index.js +48 -48
- package/canvas/tools/PointerTool.js +71 -71
- package/canvas/tools/tool.js +222 -222
- package/canvas/utils/boundingBox.js +377 -377
- package/canvas/utils/mathUtils.js +258 -258
- package/docs/api/configuration-options.md +198 -198
- package/docs/api/eventManager.md +82 -82
- package/docs/api/focusFrameManager.md +144 -144
- package/docs/api/index.md +105 -105
- package/docs/api/main.md +62 -62
- package/docs/api/omdBinaryExpressionNode.md +86 -86
- package/docs/api/omdCanvas.md +83 -83
- package/docs/api/omdConfigManager.md +112 -112
- package/docs/api/omdConstantNode.md +52 -52
- package/docs/api/omdDisplay.md +87 -87
- package/docs/api/omdEquationNode.md +174 -174
- package/docs/api/omdEquationSequenceNode.md +258 -258
- package/docs/api/omdEquationStack.md +192 -192
- package/docs/api/omdFunctionNode.md +82 -82
- package/docs/api/omdGroupNode.md +78 -78
- package/docs/api/omdHelpers.md +87 -87
- package/docs/api/omdLeafNode.md +85 -85
- package/docs/api/omdNode.md +201 -201
- package/docs/api/omdOperationDisplayNode.md +117 -117
- package/docs/api/omdOperatorNode.md +91 -91
- package/docs/api/omdParenthesisNode.md +133 -133
- package/docs/api/omdPopup.md +191 -191
- package/docs/api/omdPowerNode.md +131 -131
- package/docs/api/omdRationalNode.md +144 -144
- package/docs/api/omdSequenceNode.md +128 -128
- package/docs/api/omdSimplification.md +78 -78
- package/docs/api/omdSqrtNode.md +144 -144
- package/docs/api/omdStepVisualizer.md +146 -146
- package/docs/api/omdStepVisualizerHighlighting.md +65 -65
- package/docs/api/omdStepVisualizerInteractiveSteps.md +108 -108
- package/docs/api/omdStepVisualizerLayout.md +70 -70
- package/docs/api/omdStepVisualizerNodeUtils.md +140 -140
- package/docs/api/omdStepVisualizerTextBoxes.md +76 -76
- package/docs/api/omdToolbar.md +130 -130
- package/docs/api/omdTranscriptionService.md +95 -95
- package/docs/api/omdTreeDiff.md +169 -169
- package/docs/api/omdUnaryExpressionNode.md +137 -137
- package/docs/api/omdUtilities.md +82 -82
- package/docs/api/omdVariableNode.md +123 -123
- package/docs/api/selectTool.md +74 -74
- package/docs/api/simplificationEngine.md +97 -97
- package/docs/api/simplificationRules.md +76 -76
- package/docs/api/simplificationUtils.md +64 -64
- package/docs/api/transcribe.md +43 -43
- package/docs/api-reference.md +85 -85
- package/docs/index.html +453 -453
- package/docs/index.md +38 -38
- package/docs/omd-objects.md +258 -258
- package/index.js +79 -79
- package/jsvg/index.js +3 -0
- package/jsvg/jsvg.js +898 -898
- package/jsvg/jsvgComponents.js +357 -358
- package/npm-docs/DOCUMENTATION_SUMMARY.md +220 -220
- package/npm-docs/README.md +251 -251
- package/npm-docs/api/api-reference.md +85 -85
- package/npm-docs/api/configuration-options.md +198 -198
- package/npm-docs/api/eventManager.md +82 -82
- package/npm-docs/api/expression-nodes.md +561 -561
- package/npm-docs/api/focusFrameManager.md +144 -144
- package/npm-docs/api/index.md +105 -105
- package/npm-docs/api/main.md +62 -62
- package/npm-docs/api/omdBinaryExpressionNode.md +86 -86
- package/npm-docs/api/omdCanvas.md +83 -83
- package/npm-docs/api/omdConfigManager.md +112 -112
- package/npm-docs/api/omdConstantNode.md +52 -52
- package/npm-docs/api/omdDisplay.md +87 -87
- package/npm-docs/api/omdEquationNode.md +174 -174
- package/npm-docs/api/omdEquationSequenceNode.md +258 -258
- package/npm-docs/api/omdEquationStack.md +192 -192
- package/npm-docs/api/omdFunctionNode.md +82 -82
- package/npm-docs/api/omdGroupNode.md +78 -78
- package/npm-docs/api/omdHelpers.md +87 -87
- package/npm-docs/api/omdLeafNode.md +85 -85
- package/npm-docs/api/omdNode.md +201 -201
- package/npm-docs/api/omdOperationDisplayNode.md +117 -117
- package/npm-docs/api/omdOperatorNode.md +91 -91
- package/npm-docs/api/omdParenthesisNode.md +133 -133
- package/npm-docs/api/omdPopup.md +191 -191
- package/npm-docs/api/omdPowerNode.md +131 -131
- package/npm-docs/api/omdRationalNode.md +144 -144
- package/npm-docs/api/omdSequenceNode.md +128 -128
- package/npm-docs/api/omdSimplification.md +78 -78
- package/npm-docs/api/omdSqrtNode.md +144 -144
- package/npm-docs/api/omdStepVisualizer.md +146 -146
- package/npm-docs/api/omdStepVisualizerHighlighting.md +65 -65
- package/npm-docs/api/omdStepVisualizerInteractiveSteps.md +108 -108
- package/npm-docs/api/omdStepVisualizerLayout.md +70 -70
- package/npm-docs/api/omdStepVisualizerNodeUtils.md +140 -140
- package/npm-docs/api/omdStepVisualizerTextBoxes.md +76 -76
- package/npm-docs/api/omdToolbar.md +130 -130
- package/npm-docs/api/omdTranscriptionService.md +95 -95
- package/npm-docs/api/omdTreeDiff.md +169 -169
- package/npm-docs/api/omdUnaryExpressionNode.md +137 -137
- package/npm-docs/api/omdUtilities.md +82 -82
- package/npm-docs/api/omdVariableNode.md +123 -123
- package/npm-docs/api/selectTool.md +74 -74
- package/npm-docs/api/simplificationEngine.md +97 -97
- package/npm-docs/api/simplificationRules.md +76 -76
- package/npm-docs/api/simplificationUtils.md +64 -64
- package/npm-docs/api/transcribe.md +43 -43
- package/npm-docs/guides/equations.md +854 -854
- package/npm-docs/guides/factory-functions.md +354 -354
- package/npm-docs/guides/getting-started.md +318 -318
- package/npm-docs/guides/quick-examples.md +525 -525
- package/npm-docs/guides/visualizations.md +682 -682
- package/npm-docs/index.html +12 -0
- package/npm-docs/json-schemas.md +826 -826
- package/omd/config/omdConfigManager.js +279 -267
- package/omd/core/index.js +158 -158
- package/omd/core/omdEquationStack.js +546 -546
- package/omd/core/omdUtilities.js +113 -113
- package/omd/display/omdDisplay.js +969 -962
- package/omd/display/omdToolbar.js +501 -501
- package/omd/nodes/omdBinaryExpressionNode.js +459 -459
- package/omd/nodes/omdConstantNode.js +141 -141
- package/omd/nodes/omdEquationNode.js +1327 -1327
- package/omd/nodes/omdFunctionNode.js +351 -351
- package/omd/nodes/omdGroupNode.js +67 -67
- package/omd/nodes/omdLeafNode.js +76 -76
- package/omd/nodes/omdNode.js +556 -556
- package/omd/nodes/omdOperationDisplayNode.js +321 -321
- package/omd/nodes/omdOperatorNode.js +108 -108
- package/omd/nodes/omdParenthesisNode.js +292 -292
- package/omd/nodes/omdPowerNode.js +235 -235
- package/omd/nodes/omdRationalNode.js +295 -295
- package/omd/nodes/omdSqrtNode.js +307 -307
- package/omd/nodes/omdUnaryExpressionNode.js +227 -227
- package/omd/nodes/omdVariableNode.js +122 -122
- package/omd/simplification/omdSimplification.js +140 -140
- package/omd/simplification/omdSimplificationEngine.js +887 -887
- package/omd/simplification/package.json +5 -5
- package/omd/simplification/rules/binaryRules.js +1037 -1037
- package/omd/simplification/rules/functionRules.js +111 -111
- package/omd/simplification/rules/index.js +48 -48
- package/omd/simplification/rules/parenthesisRules.js +19 -19
- package/omd/simplification/rules/powerRules.js +143 -143
- package/omd/simplification/rules/rationalRules.js +725 -725
- package/omd/simplification/rules/sqrtRules.js +48 -48
- package/omd/simplification/rules/unaryRules.js +37 -37
- package/omd/simplification/simplificationRules.js +31 -31
- package/omd/simplification/simplificationUtils.js +1055 -1055
- package/omd/step-visualizer/omdStepVisualizer.js +947 -947
- package/omd/step-visualizer/omdStepVisualizerHighlighting.js +246 -246
- package/omd/step-visualizer/omdStepVisualizerLayout.js +892 -892
- package/omd/step-visualizer/omdStepVisualizerTextBoxes.js +200 -200
- package/omd/utils/aiNextEquationStep.js +106 -106
- package/omd/utils/omdNodeOverlay.js +638 -638
- package/omd/utils/omdPopup.js +1203 -1203
- package/omd/utils/omdStepVisualizerInteractiveSteps.js +684 -684
- package/omd/utils/omdStepVisualizerNodeUtils.js +267 -267
- package/omd/utils/omdTranscriptionService.js +123 -123
- package/omd/utils/omdTreeDiff.js +733 -733
- package/package.json +59 -56
- package/readme.html +184 -120
- package/src/index.js +74 -74
- package/src/json-schemas.md +576 -576
- package/src/omd-json-samples.js +147 -147
- package/src/omdApp.js +391 -391
- package/src/omdAppCanvas.js +335 -335
- package/src/omdBalanceHanger.js +199 -199
- package/src/omdColor.js +13 -13
- package/src/omdCoordinatePlane.js +541 -541
- package/src/omdExpression.js +115 -115
- package/src/omdFactory.js +150 -150
- package/src/omdFunction.js +114 -114
- package/src/omdMetaExpression.js +290 -290
- package/src/omdNaturalExpression.js +563 -563
- package/src/omdNode.js +383 -383
- package/src/omdNumber.js +52 -52
- package/src/omdNumberLine.js +114 -112
- package/src/omdNumberTile.js +118 -118
- package/src/omdOperator.js +72 -72
- package/src/omdPowerExpression.js +91 -91
- package/src/omdProblem.js +259 -259
- package/src/omdRatioChart.js +251 -251
- package/src/omdRationalExpression.js +114 -114
- package/src/omdSampleData.js +215 -215
- package/src/omdShapes.js +512 -512
- package/src/omdSpinner.js +151 -151
- package/src/omdString.js +49 -49
- package/src/omdTable.js +498 -498
- package/src/omdTapeDiagram.js +244 -244
- package/src/omdTerm.js +91 -91
- package/src/omdTileEquation.js +349 -349
- package/src/omdUtils.js +84 -84
- package/src/omdVariable.js +51 -51
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
import { Tool } from './tool.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Pointer/Browse tool
|
|
5
|
-
* Allows browsing and interacting with interactive components without selecting or moving items.
|
|
6
|
-
* Use this tool to click buttons, interact with UI elements, etc. without modifying the canvas.
|
|
7
|
-
*/
|
|
8
|
-
export class PointerTool extends Tool {
|
|
9
|
-
/**
|
|
10
|
-
* @param {OMDCanvas} canvas
|
|
11
|
-
* @param {object} [options={}]
|
|
12
|
-
*/
|
|
13
|
-
constructor(canvas, options = {}) {
|
|
14
|
-
super(canvas, { ...options });
|
|
15
|
-
|
|
16
|
-
this.displayName = 'Pointer';
|
|
17
|
-
this.description = 'Browse and interact with components';
|
|
18
|
-
this.icon = 'pointer';
|
|
19
|
-
this.shortcut = 'V';
|
|
20
|
-
this.category = 'navigation';
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
onActivate() {
|
|
24
|
-
this.isActive = true;
|
|
25
|
-
if (this.canvas.cursor) {
|
|
26
|
-
this.canvas.cursor.show();
|
|
27
|
-
this.canvas.cursor.setShape('pointer');
|
|
28
|
-
}
|
|
29
|
-
super.onActivate();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
onDeactivate() {
|
|
33
|
-
this.isActive = false;
|
|
34
|
-
super.onDeactivate();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
onPointerDown(event) {
|
|
38
|
-
// Pointer tool is completely passive - it does nothing
|
|
39
|
-
// This allows click events to pass through to interactive components
|
|
40
|
-
// but prevents any canvas manipulation (drawing, selecting, moving)
|
|
41
|
-
|
|
42
|
-
// Explicitly ensure we are not entering a drawing/dragging state
|
|
43
|
-
if (this.canvas?.eventManager) {
|
|
44
|
-
this.canvas.eventManager.isDrawing = false;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
onPointerMove(event) {
|
|
49
|
-
// No-op: allow hovering without any interaction
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
onPointerUp(event) {
|
|
53
|
-
// No-op: do not modify selections or positions
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
onKeyboardShortcut(key, event) {
|
|
57
|
-
// No shortcuts to handle for passive pointer tool
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
onKeyboardShortcut(key, event) {
|
|
62
|
-
// No shortcuts to handle for passive pointer tool
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
getCursor() {
|
|
67
|
-
return 'pointer';
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
1
|
+
import { Tool } from './tool.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pointer/Browse tool
|
|
5
|
+
* Allows browsing and interacting with interactive components without selecting or moving items.
|
|
6
|
+
* Use this tool to click buttons, interact with UI elements, etc. without modifying the canvas.
|
|
7
|
+
*/
|
|
8
|
+
export class PointerTool extends Tool {
|
|
9
|
+
/**
|
|
10
|
+
* @param {OMDCanvas} canvas
|
|
11
|
+
* @param {object} [options={}]
|
|
12
|
+
*/
|
|
13
|
+
constructor(canvas, options = {}) {
|
|
14
|
+
super(canvas, { ...options });
|
|
15
|
+
|
|
16
|
+
this.displayName = 'Pointer';
|
|
17
|
+
this.description = 'Browse and interact with components';
|
|
18
|
+
this.icon = 'pointer';
|
|
19
|
+
this.shortcut = 'V';
|
|
20
|
+
this.category = 'navigation';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
onActivate() {
|
|
24
|
+
this.isActive = true;
|
|
25
|
+
if (this.canvas.cursor) {
|
|
26
|
+
this.canvas.cursor.show();
|
|
27
|
+
this.canvas.cursor.setShape('pointer');
|
|
28
|
+
}
|
|
29
|
+
super.onActivate();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
onDeactivate() {
|
|
33
|
+
this.isActive = false;
|
|
34
|
+
super.onDeactivate();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
onPointerDown(event) {
|
|
38
|
+
// Pointer tool is completely passive - it does nothing
|
|
39
|
+
// This allows click events to pass through to interactive components
|
|
40
|
+
// but prevents any canvas manipulation (drawing, selecting, moving)
|
|
41
|
+
|
|
42
|
+
// Explicitly ensure we are not entering a drawing/dragging state
|
|
43
|
+
if (this.canvas?.eventManager) {
|
|
44
|
+
this.canvas.eventManager.isDrawing = false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
onPointerMove(event) {
|
|
49
|
+
// No-op: allow hovering without any interaction
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
onPointerUp(event) {
|
|
53
|
+
// No-op: do not modify selections or positions
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
onKeyboardShortcut(key, event) {
|
|
57
|
+
// No shortcuts to handle for passive pointer tool
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
onKeyboardShortcut(key, event) {
|
|
62
|
+
// No shortcuts to handle for passive pointer tool
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getCursor() {
|
|
67
|
+
return 'pointer';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
package/canvas/tools/tool.js
CHANGED
|
@@ -1,223 +1,223 @@
|
|
|
1
|
-
import { Stroke } from '../drawing/stroke.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Base class for all canvas tools
|
|
5
|
-
* All tools should extend this class and implement the required methods
|
|
6
|
-
*/
|
|
7
|
-
export class Tool {
|
|
8
|
-
/**
|
|
9
|
-
* @param {OMDCanvas} canvas - Canvas instance
|
|
10
|
-
* @param {Object} options - Tool options
|
|
11
|
-
*/
|
|
12
|
-
constructor(canvas, options = {}) {
|
|
13
|
-
this.canvas = canvas;
|
|
14
|
-
this.name = '';
|
|
15
|
-
this.displayName = '';
|
|
16
|
-
this.description = '';
|
|
17
|
-
this.icon = '';
|
|
18
|
-
this.shortcut = '';
|
|
19
|
-
this.category = 'general';
|
|
20
|
-
|
|
21
|
-
// Tool state
|
|
22
|
-
this.isActive = false;
|
|
23
|
-
this.isDrawing = false;
|
|
24
|
-
this.currentStroke = null;
|
|
25
|
-
|
|
26
|
-
// Configuration
|
|
27
|
-
this.config = {
|
|
28
|
-
strokeWidth: 5,
|
|
29
|
-
strokeColor: '#000000',
|
|
30
|
-
strokeOpacity: 1,
|
|
31
|
-
...options
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// Bind methods
|
|
35
|
-
this.onPointerDown = this.onPointerDown.bind(this);
|
|
36
|
-
this.onPointerMove = this.onPointerMove.bind(this);
|
|
37
|
-
this.onPointerUp = this.onPointerUp.bind(this);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Called when tool is activated
|
|
42
|
-
* Subclasses can override this to perform setup
|
|
43
|
-
*/
|
|
44
|
-
onActivate() {
|
|
45
|
-
this.isActive = true;
|
|
46
|
-
this.canvas.emit('toolActivated', { tool: this, name: this.name });
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Called when tool is deactivated
|
|
51
|
-
* Subclasses can override this to perform cleanup
|
|
52
|
-
*/
|
|
53
|
-
onDeactivate() {
|
|
54
|
-
this.isActive = false;
|
|
55
|
-
|
|
56
|
-
// Cancel any ongoing drawing
|
|
57
|
-
if (this.isDrawing) {
|
|
58
|
-
this.onCancel();
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
this.canvas.emit('toolDeactivated', { tool: this, name: this.name });
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Handle pointer down events
|
|
66
|
-
* Subclasses must implement this method
|
|
67
|
-
* @param {Object} event - Normalized pointer event
|
|
68
|
-
*/
|
|
69
|
-
onPointerDown(event) {
|
|
70
|
-
throw new Error('Tool.onPointerDown() must be implemented by subclass');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Handle pointer move events
|
|
75
|
-
* Subclasses must implement this method
|
|
76
|
-
* @param {Object} event - Normalized pointer event
|
|
77
|
-
*/
|
|
78
|
-
onPointerMove(event) {
|
|
79
|
-
throw new Error('Tool.onPointerMove() must be implemented by subclass');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Handle pointer up events
|
|
84
|
-
* Subclasses must implement this method
|
|
85
|
-
* @param {Object} event - Normalized pointer event
|
|
86
|
-
*/
|
|
87
|
-
onPointerUp(event) {
|
|
88
|
-
throw new Error('Tool.onPointerUp() must be implemented by subclass');
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Cancel current tool action
|
|
93
|
-
* Subclasses can override this to handle cancellation
|
|
94
|
-
*/
|
|
95
|
-
onCancel() {
|
|
96
|
-
if (this.isDrawing) {
|
|
97
|
-
this.isDrawing = false;
|
|
98
|
-
|
|
99
|
-
// Remove incomplete stroke if any
|
|
100
|
-
if (this.currentStroke && this.currentStroke.id) {
|
|
101
|
-
this.canvas.removeStroke(this.currentStroke.id);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
this.currentStroke = null;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Update tool configuration
|
|
110
|
-
* @param {Object} newConfig - New configuration options
|
|
111
|
-
*/
|
|
112
|
-
updateConfig(newConfig) {
|
|
113
|
-
this.config = { ...this.config, ...newConfig };
|
|
114
|
-
this.onConfigUpdate();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Called when configuration is updated
|
|
119
|
-
* Subclasses can override this to respond to config changes
|
|
120
|
-
*/
|
|
121
|
-
onConfigUpdate() {
|
|
122
|
-
// Default implementation does nothing
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Get current tool configuration
|
|
127
|
-
* @returns {Object} Current configuration
|
|
128
|
-
*/
|
|
129
|
-
getConfig() {
|
|
130
|
-
return { ...this.config };
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Check if tool is currently drawing
|
|
135
|
-
* @returns {boolean} True if drawing
|
|
136
|
-
*/
|
|
137
|
-
isDrawingActive() {
|
|
138
|
-
return this.isDrawing;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Get tool cursor style
|
|
143
|
-
* @returns {string} CSS cursor value or tool name for custom cursor
|
|
144
|
-
*/
|
|
145
|
-
getCursor() {
|
|
146
|
-
return this.name;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Get tool properties for serialization
|
|
151
|
-
* @returns {Object} Serializable tool properties
|
|
152
|
-
*/
|
|
153
|
-
getProperties() {
|
|
154
|
-
return {
|
|
155
|
-
name: this.name,
|
|
156
|
-
displayName: this.displayName,
|
|
157
|
-
description: this.description,
|
|
158
|
-
icon: this.icon,
|
|
159
|
-
shortcut: this.shortcut,
|
|
160
|
-
category: this.category,
|
|
161
|
-
config: this.getConfig()
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Create a stroke with tool's current configuration
|
|
167
|
-
* @param {number} x - Starting X coordinate
|
|
168
|
-
* @param {number} y - Starting Y coordinate
|
|
169
|
-
* @returns {Stroke} New stroke instance
|
|
170
|
-
*/
|
|
171
|
-
createStroke(x, y) {
|
|
172
|
-
const strokeConfig = {
|
|
173
|
-
x,
|
|
174
|
-
y,
|
|
175
|
-
strokeWidth: this.config.strokeWidth,
|
|
176
|
-
strokeColor: this.config.strokeColor,
|
|
177
|
-
strokeOpacity: this.config.strokeOpacity,
|
|
178
|
-
tool: this.name
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
return new Stroke(strokeConfig);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Calculate stroke width based on pressure (if supported)
|
|
186
|
-
* @param {number} pressure - Pressure value (0-1)
|
|
187
|
-
* @returns {number} Calculated stroke width
|
|
188
|
-
*/
|
|
189
|
-
calculateStrokeWidth(pressure = 0.5) {
|
|
190
|
-
const baseWidth = this.config.strokeWidth;
|
|
191
|
-
const minWidth = Math.max(1, baseWidth * 0.3);
|
|
192
|
-
const maxWidth = baseWidth * 1.5;
|
|
193
|
-
|
|
194
|
-
return minWidth + (maxWidth - minWidth) * pressure;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Handle keyboard shortcut
|
|
199
|
-
* @param {string} key - Key that was pressed
|
|
200
|
-
* @param {Object} event - Keyboard event
|
|
201
|
-
* @returns {boolean} True if shortcut was handled
|
|
202
|
-
*/
|
|
203
|
-
onKeyboardShortcut(key, event) {
|
|
204
|
-
// Default implementation - subclasses can override
|
|
205
|
-
return false;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Get help text for this tool
|
|
210
|
-
* @returns {string} Help text
|
|
211
|
-
*/
|
|
212
|
-
getHelpText() {
|
|
213
|
-
return `${this.displayName}: ${this.description}`;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Validate if tool can be used with current canvas state
|
|
218
|
-
* @returns {boolean} True if tool can be used
|
|
219
|
-
*/
|
|
220
|
-
canUse() {
|
|
221
|
-
return !this.canvas.isDestroyed && this.isActive;
|
|
222
|
-
}
|
|
1
|
+
import { Stroke } from '../drawing/stroke.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base class for all canvas tools
|
|
5
|
+
* All tools should extend this class and implement the required methods
|
|
6
|
+
*/
|
|
7
|
+
export class Tool {
|
|
8
|
+
/**
|
|
9
|
+
* @param {OMDCanvas} canvas - Canvas instance
|
|
10
|
+
* @param {Object} options - Tool options
|
|
11
|
+
*/
|
|
12
|
+
constructor(canvas, options = {}) {
|
|
13
|
+
this.canvas = canvas;
|
|
14
|
+
this.name = '';
|
|
15
|
+
this.displayName = '';
|
|
16
|
+
this.description = '';
|
|
17
|
+
this.icon = '';
|
|
18
|
+
this.shortcut = '';
|
|
19
|
+
this.category = 'general';
|
|
20
|
+
|
|
21
|
+
// Tool state
|
|
22
|
+
this.isActive = false;
|
|
23
|
+
this.isDrawing = false;
|
|
24
|
+
this.currentStroke = null;
|
|
25
|
+
|
|
26
|
+
// Configuration
|
|
27
|
+
this.config = {
|
|
28
|
+
strokeWidth: 5,
|
|
29
|
+
strokeColor: '#000000',
|
|
30
|
+
strokeOpacity: 1,
|
|
31
|
+
...options
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Bind methods
|
|
35
|
+
this.onPointerDown = this.onPointerDown.bind(this);
|
|
36
|
+
this.onPointerMove = this.onPointerMove.bind(this);
|
|
37
|
+
this.onPointerUp = this.onPointerUp.bind(this);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Called when tool is activated
|
|
42
|
+
* Subclasses can override this to perform setup
|
|
43
|
+
*/
|
|
44
|
+
onActivate() {
|
|
45
|
+
this.isActive = true;
|
|
46
|
+
this.canvas.emit('toolActivated', { tool: this, name: this.name });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Called when tool is deactivated
|
|
51
|
+
* Subclasses can override this to perform cleanup
|
|
52
|
+
*/
|
|
53
|
+
onDeactivate() {
|
|
54
|
+
this.isActive = false;
|
|
55
|
+
|
|
56
|
+
// Cancel any ongoing drawing
|
|
57
|
+
if (this.isDrawing) {
|
|
58
|
+
this.onCancel();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.canvas.emit('toolDeactivated', { tool: this, name: this.name });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Handle pointer down events
|
|
66
|
+
* Subclasses must implement this method
|
|
67
|
+
* @param {Object} event - Normalized pointer event
|
|
68
|
+
*/
|
|
69
|
+
onPointerDown(event) {
|
|
70
|
+
throw new Error('Tool.onPointerDown() must be implemented by subclass');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Handle pointer move events
|
|
75
|
+
* Subclasses must implement this method
|
|
76
|
+
* @param {Object} event - Normalized pointer event
|
|
77
|
+
*/
|
|
78
|
+
onPointerMove(event) {
|
|
79
|
+
throw new Error('Tool.onPointerMove() must be implemented by subclass');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Handle pointer up events
|
|
84
|
+
* Subclasses must implement this method
|
|
85
|
+
* @param {Object} event - Normalized pointer event
|
|
86
|
+
*/
|
|
87
|
+
onPointerUp(event) {
|
|
88
|
+
throw new Error('Tool.onPointerUp() must be implemented by subclass');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Cancel current tool action
|
|
93
|
+
* Subclasses can override this to handle cancellation
|
|
94
|
+
*/
|
|
95
|
+
onCancel() {
|
|
96
|
+
if (this.isDrawing) {
|
|
97
|
+
this.isDrawing = false;
|
|
98
|
+
|
|
99
|
+
// Remove incomplete stroke if any
|
|
100
|
+
if (this.currentStroke && this.currentStroke.id) {
|
|
101
|
+
this.canvas.removeStroke(this.currentStroke.id);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
this.currentStroke = null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Update tool configuration
|
|
110
|
+
* @param {Object} newConfig - New configuration options
|
|
111
|
+
*/
|
|
112
|
+
updateConfig(newConfig) {
|
|
113
|
+
this.config = { ...this.config, ...newConfig };
|
|
114
|
+
this.onConfigUpdate();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Called when configuration is updated
|
|
119
|
+
* Subclasses can override this to respond to config changes
|
|
120
|
+
*/
|
|
121
|
+
onConfigUpdate() {
|
|
122
|
+
// Default implementation does nothing
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get current tool configuration
|
|
127
|
+
* @returns {Object} Current configuration
|
|
128
|
+
*/
|
|
129
|
+
getConfig() {
|
|
130
|
+
return { ...this.config };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Check if tool is currently drawing
|
|
135
|
+
* @returns {boolean} True if drawing
|
|
136
|
+
*/
|
|
137
|
+
isDrawingActive() {
|
|
138
|
+
return this.isDrawing;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Get tool cursor style
|
|
143
|
+
* @returns {string} CSS cursor value or tool name for custom cursor
|
|
144
|
+
*/
|
|
145
|
+
getCursor() {
|
|
146
|
+
return this.name;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Get tool properties for serialization
|
|
151
|
+
* @returns {Object} Serializable tool properties
|
|
152
|
+
*/
|
|
153
|
+
getProperties() {
|
|
154
|
+
return {
|
|
155
|
+
name: this.name,
|
|
156
|
+
displayName: this.displayName,
|
|
157
|
+
description: this.description,
|
|
158
|
+
icon: this.icon,
|
|
159
|
+
shortcut: this.shortcut,
|
|
160
|
+
category: this.category,
|
|
161
|
+
config: this.getConfig()
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Create a stroke with tool's current configuration
|
|
167
|
+
* @param {number} x - Starting X coordinate
|
|
168
|
+
* @param {number} y - Starting Y coordinate
|
|
169
|
+
* @returns {Stroke} New stroke instance
|
|
170
|
+
*/
|
|
171
|
+
createStroke(x, y) {
|
|
172
|
+
const strokeConfig = {
|
|
173
|
+
x,
|
|
174
|
+
y,
|
|
175
|
+
strokeWidth: this.config.strokeWidth,
|
|
176
|
+
strokeColor: this.config.strokeColor,
|
|
177
|
+
strokeOpacity: this.config.strokeOpacity,
|
|
178
|
+
tool: this.name
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return new Stroke(strokeConfig);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Calculate stroke width based on pressure (if supported)
|
|
186
|
+
* @param {number} pressure - Pressure value (0-1)
|
|
187
|
+
* @returns {number} Calculated stroke width
|
|
188
|
+
*/
|
|
189
|
+
calculateStrokeWidth(pressure = 0.5) {
|
|
190
|
+
const baseWidth = this.config.strokeWidth;
|
|
191
|
+
const minWidth = Math.max(1, baseWidth * 0.3);
|
|
192
|
+
const maxWidth = baseWidth * 1.5;
|
|
193
|
+
|
|
194
|
+
return minWidth + (maxWidth - minWidth) * pressure;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Handle keyboard shortcut
|
|
199
|
+
* @param {string} key - Key that was pressed
|
|
200
|
+
* @param {Object} event - Keyboard event
|
|
201
|
+
* @returns {boolean} True if shortcut was handled
|
|
202
|
+
*/
|
|
203
|
+
onKeyboardShortcut(key, event) {
|
|
204
|
+
// Default implementation - subclasses can override
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Get help text for this tool
|
|
210
|
+
* @returns {string} Help text
|
|
211
|
+
*/
|
|
212
|
+
getHelpText() {
|
|
213
|
+
return `${this.displayName}: ${this.description}`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Validate if tool can be used with current canvas state
|
|
218
|
+
* @returns {boolean} True if tool can be used
|
|
219
|
+
*/
|
|
220
|
+
canUse() {
|
|
221
|
+
return !this.canvas.isDestroyed && this.isActive;
|
|
222
|
+
}
|
|
223
223
|
}
|