js-draw 0.18.2 → 0.19.0

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.
Files changed (227) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/bundle.js +2 -2
  3. package/dist/bundledStyles.js +1 -0
  4. package/dist/cjs/src/Color4.d.ts +8 -0
  5. package/dist/cjs/src/Color4.js +67 -0
  6. package/dist/cjs/src/Editor.d.ts +2 -2
  7. package/dist/cjs/src/Editor.js +2 -2
  8. package/dist/cjs/src/SVGLoader.js +8 -5
  9. package/dist/cjs/src/components/AbstractComponent.d.ts +2 -2
  10. package/dist/cjs/src/components/AbstractComponent.js +3 -3
  11. package/dist/cjs/src/components/ImageBackground.js +1 -1
  12. package/dist/cjs/src/components/RestylableComponent.d.ts +21 -2
  13. package/dist/cjs/src/components/Stroke.d.ts +35 -0
  14. package/dist/cjs/src/components/Stroke.js +36 -2
  15. package/dist/cjs/src/components/TextComponent.d.ts +26 -4
  16. package/dist/cjs/src/components/TextComponent.js +22 -0
  17. package/dist/cjs/src/components/lib.d.ts +3 -2
  18. package/dist/cjs/src/lib.d.ts +30 -0
  19. package/dist/cjs/src/lib.js +30 -0
  20. package/dist/cjs/src/rendering/RenderingStyle.d.ts +4 -4
  21. package/dist/cjs/src/rendering/TextRenderingStyle.d.ts +10 -10
  22. package/dist/cjs/src/rendering/lib.d.ts +2 -0
  23. package/dist/cjs/src/rendering/renderers/AbstractRenderer.d.ts +2 -2
  24. package/dist/cjs/src/rendering/renderers/CanvasRenderer.d.ts +2 -2
  25. package/dist/cjs/src/rendering/renderers/DummyRenderer.d.ts +2 -2
  26. package/dist/cjs/src/rendering/renderers/SVGRenderer.d.ts +2 -2
  27. package/dist/cjs/src/rendering/renderers/TextOnlyRenderer.d.ts +2 -2
  28. package/dist/cjs/src/toolbar/IconProvider.d.ts +2 -2
  29. package/dist/cjs/src/toolbar/localization.js +1 -1
  30. package/dist/cjs/src/toolbar/widgets/BaseWidget.js +1 -1
  31. package/dist/cjs/src/tools/SoundUITool.d.ts +24 -0
  32. package/dist/cjs/src/tools/SoundUITool.js +164 -0
  33. package/dist/cjs/src/tools/TextTool.d.ts +2 -2
  34. package/dist/cjs/src/tools/ToolController.js +6 -1
  35. package/dist/cjs/src/tools/lib.d.ts +1 -0
  36. package/dist/cjs/src/tools/lib.js +3 -1
  37. package/dist/cjs/src/tools/localization.d.ts +3 -0
  38. package/dist/cjs/src/tools/localization.js +3 -0
  39. package/dist/mjs/src/Color4.d.ts +8 -0
  40. package/dist/mjs/src/Color4.mjs +64 -0
  41. package/dist/mjs/src/Editor.d.ts +2 -2
  42. package/dist/mjs/src/Editor.mjs +2 -2
  43. package/dist/mjs/src/SVGLoader.mjs +8 -5
  44. package/dist/mjs/src/components/AbstractComponent.d.ts +2 -2
  45. package/dist/mjs/src/components/AbstractComponent.mjs +3 -3
  46. package/dist/mjs/src/components/ImageBackground.mjs +1 -1
  47. package/dist/mjs/src/components/RestylableComponent.d.ts +21 -2
  48. package/dist/mjs/src/components/Stroke.d.ts +35 -0
  49. package/dist/mjs/src/components/Stroke.mjs +36 -2
  50. package/dist/mjs/src/components/TextComponent.d.ts +26 -4
  51. package/dist/mjs/src/components/TextComponent.mjs +22 -0
  52. package/dist/mjs/src/components/lib.d.ts +3 -2
  53. package/dist/mjs/src/lib.d.ts +30 -0
  54. package/dist/mjs/src/lib.mjs +30 -0
  55. package/dist/mjs/src/rendering/RenderingStyle.d.ts +4 -4
  56. package/dist/mjs/src/rendering/TextRenderingStyle.d.ts +10 -10
  57. package/dist/mjs/src/rendering/lib.d.ts +2 -0
  58. package/dist/mjs/src/rendering/renderers/AbstractRenderer.d.ts +2 -2
  59. package/dist/mjs/src/rendering/renderers/CanvasRenderer.d.ts +2 -2
  60. package/dist/mjs/src/rendering/renderers/DummyRenderer.d.ts +2 -2
  61. package/dist/mjs/src/rendering/renderers/SVGRenderer.d.ts +2 -2
  62. package/dist/mjs/src/rendering/renderers/TextOnlyRenderer.d.ts +2 -2
  63. package/dist/mjs/src/toolbar/IconProvider.d.ts +2 -2
  64. package/dist/mjs/src/toolbar/localization.mjs +1 -1
  65. package/dist/mjs/src/toolbar/widgets/BaseWidget.mjs +1 -1
  66. package/dist/mjs/src/tools/SoundUITool.d.ts +24 -0
  67. package/dist/mjs/src/tools/SoundUITool.mjs +158 -0
  68. package/dist/mjs/src/tools/TextTool.d.ts +2 -2
  69. package/dist/mjs/src/tools/ToolController.mjs +6 -1
  70. package/dist/mjs/src/tools/lib.d.ts +1 -0
  71. package/dist/mjs/src/tools/lib.mjs +1 -0
  72. package/dist/mjs/src/tools/localization.d.ts +3 -0
  73. package/dist/mjs/src/tools/localization.mjs +3 -0
  74. package/package.json +6 -4
  75. package/src/Editor.css +2 -2
  76. package/src/tools/SoundUITool.css +15 -0
  77. package/src/tools/tools.css +4 -0
  78. package/src/Color4.test.ts +0 -40
  79. package/src/Color4.ts +0 -236
  80. package/src/Editor.loadFrom.test.ts +0 -24
  81. package/src/Editor.toSVG.test.ts +0 -111
  82. package/src/Editor.ts +0 -1122
  83. package/src/EditorImage.test.ts +0 -120
  84. package/src/EditorImage.ts +0 -603
  85. package/src/EventDispatcher.test.ts +0 -123
  86. package/src/EventDispatcher.ts +0 -71
  87. package/src/Pointer.ts +0 -127
  88. package/src/SVGLoader.test.ts +0 -114
  89. package/src/SVGLoader.ts +0 -511
  90. package/src/UndoRedoHistory.test.ts +0 -33
  91. package/src/UndoRedoHistory.ts +0 -102
  92. package/src/Viewport.ts +0 -319
  93. package/src/bundle/bundled.ts +0 -7
  94. package/src/commands/Command.ts +0 -45
  95. package/src/commands/Duplicate.ts +0 -48
  96. package/src/commands/Erase.ts +0 -74
  97. package/src/commands/SerializableCommand.ts +0 -49
  98. package/src/commands/UnresolvedCommand.ts +0 -37
  99. package/src/commands/invertCommand.ts +0 -51
  100. package/src/commands/lib.ts +0 -16
  101. package/src/commands/localization.ts +0 -47
  102. package/src/commands/uniteCommands.test.ts +0 -23
  103. package/src/commands/uniteCommands.ts +0 -135
  104. package/src/components/AbstractComponent.transformBy.test.ts +0 -22
  105. package/src/components/AbstractComponent.ts +0 -364
  106. package/src/components/ImageBackground.test.ts +0 -35
  107. package/src/components/ImageBackground.ts +0 -176
  108. package/src/components/ImageComponent.ts +0 -171
  109. package/src/components/RestylableComponent.ts +0 -142
  110. package/src/components/SVGGlobalAttributesObject.ts +0 -81
  111. package/src/components/Stroke.test.ts +0 -139
  112. package/src/components/Stroke.ts +0 -245
  113. package/src/components/TextComponent.test.ts +0 -99
  114. package/src/components/TextComponent.ts +0 -315
  115. package/src/components/UnknownSVGObject.test.ts +0 -10
  116. package/src/components/UnknownSVGObject.ts +0 -60
  117. package/src/components/builders/ArrowBuilder.ts +0 -107
  118. package/src/components/builders/FreehandLineBuilder.ts +0 -212
  119. package/src/components/builders/LineBuilder.ts +0 -77
  120. package/src/components/builders/PressureSensitiveFreehandLineBuilder.ts +0 -454
  121. package/src/components/builders/RectangleBuilder.ts +0 -74
  122. package/src/components/builders/types.ts +0 -15
  123. package/src/components/lib.ts +0 -25
  124. package/src/components/localization.ts +0 -22
  125. package/src/components/util/StrokeSmoother.ts +0 -293
  126. package/src/components/util/describeComponentList.ts +0 -18
  127. package/src/lib.ts +0 -37
  128. package/src/localization.ts +0 -34
  129. package/src/localizations/de.ts +0 -98
  130. package/src/localizations/en.ts +0 -8
  131. package/src/localizations/es.ts +0 -74
  132. package/src/localizations/getLocalizationTable.test.ts +0 -27
  133. package/src/localizations/getLocalizationTable.ts +0 -55
  134. package/src/math/LineSegment2.test.ts +0 -99
  135. package/src/math/LineSegment2.ts +0 -160
  136. package/src/math/Mat33.test.ts +0 -244
  137. package/src/math/Mat33.ts +0 -437
  138. package/src/math/Path.fromString.test.ts +0 -223
  139. package/src/math/Path.test.ts +0 -198
  140. package/src/math/Path.toString.test.ts +0 -77
  141. package/src/math/Path.ts +0 -790
  142. package/src/math/Rect2.test.ts +0 -204
  143. package/src/math/Rect2.ts +0 -315
  144. package/src/math/Triangle.ts +0 -29
  145. package/src/math/Vec2.test.ts +0 -30
  146. package/src/math/Vec2.ts +0 -18
  147. package/src/math/Vec3.test.ts +0 -44
  148. package/src/math/Vec3.ts +0 -218
  149. package/src/math/lib.ts +0 -15
  150. package/src/math/rounding.test.ts +0 -65
  151. package/src/math/rounding.ts +0 -156
  152. package/src/rendering/Display.ts +0 -249
  153. package/src/rendering/RenderingStyle.test.ts +0 -68
  154. package/src/rendering/RenderingStyle.ts +0 -55
  155. package/src/rendering/TextRenderingStyle.ts +0 -45
  156. package/src/rendering/caching/CacheRecord.test.ts +0 -49
  157. package/src/rendering/caching/CacheRecord.ts +0 -77
  158. package/src/rendering/caching/CacheRecordManager.ts +0 -71
  159. package/src/rendering/caching/RenderingCache.test.ts +0 -44
  160. package/src/rendering/caching/RenderingCache.ts +0 -66
  161. package/src/rendering/caching/RenderingCacheNode.ts +0 -405
  162. package/src/rendering/caching/testUtils.ts +0 -35
  163. package/src/rendering/caching/types.ts +0 -34
  164. package/src/rendering/lib.ts +0 -6
  165. package/src/rendering/localization.ts +0 -20
  166. package/src/rendering/renderers/AbstractRenderer.ts +0 -222
  167. package/src/rendering/renderers/CanvasRenderer.ts +0 -296
  168. package/src/rendering/renderers/DummyRenderer.test.ts +0 -42
  169. package/src/rendering/renderers/DummyRenderer.ts +0 -136
  170. package/src/rendering/renderers/SVGRenderer.ts +0 -354
  171. package/src/rendering/renderers/TextOnlyRenderer.ts +0 -70
  172. package/src/testing/beforeEachFile.ts +0 -8
  173. package/src/testing/createEditor.ts +0 -11
  174. package/src/testing/global.d.ts +0 -17
  175. package/src/testing/lib.ts +0 -3
  176. package/src/testing/loadExpectExtensions.ts +0 -25
  177. package/src/testing/sendPenEvent.ts +0 -31
  178. package/src/testing/sendTouchEvent.ts +0 -78
  179. package/src/toolbar/HTMLToolbar.ts +0 -492
  180. package/src/toolbar/IconProvider.ts +0 -736
  181. package/src/toolbar/lib.ts +0 -4
  182. package/src/toolbar/localization.ts +0 -106
  183. package/src/toolbar/makeColorInput.ts +0 -145
  184. package/src/toolbar/types.ts +0 -5
  185. package/src/toolbar/widgets/ActionButtonWidget.ts +0 -39
  186. package/src/toolbar/widgets/BaseToolWidget.ts +0 -56
  187. package/src/toolbar/widgets/BaseWidget.ts +0 -377
  188. package/src/toolbar/widgets/DocumentPropertiesWidget.ts +0 -167
  189. package/src/toolbar/widgets/EraserToolWidget.ts +0 -85
  190. package/src/toolbar/widgets/HandToolWidget.ts +0 -250
  191. package/src/toolbar/widgets/InsertImageWidget.ts +0 -223
  192. package/src/toolbar/widgets/OverflowWidget.ts +0 -92
  193. package/src/toolbar/widgets/PenToolWidget.ts +0 -288
  194. package/src/toolbar/widgets/SelectionToolWidget.ts +0 -190
  195. package/src/toolbar/widgets/TextToolWidget.ts +0 -145
  196. package/src/toolbar/widgets/lib.ts +0 -13
  197. package/src/tools/BaseTool.ts +0 -76
  198. package/src/tools/Eraser.test.ts +0 -103
  199. package/src/tools/Eraser.ts +0 -139
  200. package/src/tools/FindTool.ts +0 -152
  201. package/src/tools/PanZoom.test.ts +0 -310
  202. package/src/tools/PanZoom.ts +0 -520
  203. package/src/tools/PasteHandler.ts +0 -95
  204. package/src/tools/Pen.test.ts +0 -194
  205. package/src/tools/Pen.ts +0 -226
  206. package/src/tools/PipetteTool.ts +0 -55
  207. package/src/tools/SelectionTool/SelectAllShortcutHandler.ts +0 -28
  208. package/src/tools/SelectionTool/Selection.ts +0 -607
  209. package/src/tools/SelectionTool/SelectionHandle.ts +0 -108
  210. package/src/tools/SelectionTool/SelectionTool.test.ts +0 -261
  211. package/src/tools/SelectionTool/SelectionTool.ts +0 -480
  212. package/src/tools/SelectionTool/TransformMode.ts +0 -114
  213. package/src/tools/SelectionTool/types.ts +0 -11
  214. package/src/tools/TextTool.ts +0 -326
  215. package/src/tools/ToolController.ts +0 -178
  216. package/src/tools/ToolEnabledGroup.ts +0 -14
  217. package/src/tools/ToolSwitcherShortcut.ts +0 -39
  218. package/src/tools/ToolbarShortcutHandler.ts +0 -34
  219. package/src/tools/UndoRedoShortcut.test.ts +0 -56
  220. package/src/tools/UndoRedoShortcut.ts +0 -25
  221. package/src/tools/lib.ts +0 -21
  222. package/src/tools/localization.ts +0 -66
  223. package/src/types.ts +0 -234
  224. package/src/util/assertions.ts +0 -55
  225. package/src/util/fileToBase64.ts +0 -18
  226. package/src/util/untilNextAnimationFrame.ts +0 -9
  227. package/src/util/waitForTimeout.ts +0 -9
@@ -1,288 +0,0 @@
1
- import { makeArrowBuilder } from '../../components/builders/ArrowBuilder';
2
- import { makeFreehandLineBuilder } from '../../components/builders/FreehandLineBuilder';
3
- import { makePressureSensitiveFreehandLineBuilder } from '../../components/builders/PressureSensitiveFreehandLineBuilder';
4
- import { makeLineBuilder } from '../../components/builders/LineBuilder';
5
- import { makeFilledRectangleBuilder, makeOutlinedRectangleBuilder } from '../../components/builders/RectangleBuilder';
6
- import { ComponentBuilderFactory } from '../../components/builders/types';
7
- import Editor from '../../Editor';
8
- import Pen from '../../tools/Pen';
9
- import { EditorEventType, KeyPressEvent } from '../../types';
10
- import { toolbarCSSPrefix } from '../HTMLToolbar';
11
- import { ToolbarLocalization } from '../localization';
12
- import makeColorInput from '../makeColorInput';
13
- import BaseToolWidget from './BaseToolWidget';
14
- import Color4 from '../../Color4';
15
- import { SavedToolbuttonState } from './BaseWidget';
16
-
17
-
18
- export interface PenTypeRecord {
19
- // Description of the factory (e.g. 'Freehand line')
20
- name: string;
21
-
22
- // A unique ID for the facotory (e.g. 'chisel-tip-pen')
23
- id: string;
24
-
25
- // Creates an `AbstractComponent` from pen input.
26
- factory: ComponentBuilderFactory;
27
- }
28
-
29
- export default class PenToolWidget extends BaseToolWidget {
30
- private updateInputs: ()=> void = () => {};
31
- protected penTypes: PenTypeRecord[];
32
-
33
- public constructor(
34
- editor: Editor, private tool: Pen, localization?: ToolbarLocalization
35
- ) {
36
- super(editor, tool, 'pen', localization);
37
-
38
- // Default pen types
39
- this.penTypes = [
40
- {
41
- name: this.localizationTable.pressureSensitiveFreehandPen,
42
- id: 'pressure-sensitive-pen',
43
-
44
- factory: makePressureSensitiveFreehandLineBuilder,
45
- },
46
- {
47
- name: this.localizationTable.freehandPen,
48
- id: 'freehand-pen',
49
-
50
- factory: makeFreehandLineBuilder,
51
- },
52
- {
53
- name: this.localizationTable.arrowPen,
54
- id: 'arrow',
55
-
56
- factory: makeArrowBuilder,
57
- },
58
- {
59
- name: this.localizationTable.linePen,
60
- id: 'line',
61
-
62
- factory: makeLineBuilder,
63
- },
64
- {
65
- name: this.localizationTable.filledRectanglePen,
66
- id: 'filled-rectangle',
67
-
68
- factory: makeFilledRectangleBuilder,
69
- },
70
- {
71
- name: this.localizationTable.outlinedRectanglePen,
72
- id: 'outlined-rectangle',
73
-
74
- factory: makeOutlinedRectangleBuilder,
75
- },
76
- ];
77
-
78
- this.editor.notifier.on(EditorEventType.ToolUpdated, toolEvt => {
79
- if (toolEvt.kind !== EditorEventType.ToolUpdated) {
80
- throw new Error('Invalid event type!');
81
- }
82
-
83
- // The button icon may depend on tool properties.
84
- if (toolEvt.tool === this.tool) {
85
- this.updateIcon();
86
- this.updateInputs();
87
- }
88
- });
89
- }
90
-
91
- protected getTitle(): string {
92
- return this.targetTool.description;
93
- }
94
-
95
- // Return the index of this tool's stroke factory in the list of
96
- // all stroke factories.
97
- //
98
- // Returns -1 if the stroke factory is not in the list of all stroke factories.
99
- private getCurrentPenTypeIdx(): number {
100
- const currentFactory = this.tool.getStrokeFactory();
101
-
102
- for (let i = 0; i < this.penTypes.length; i ++) {
103
- if (this.penTypes[i].factory === currentFactory) {
104
- return i;
105
- }
106
- }
107
- return -1;
108
- }
109
-
110
- private getCurrentPenType(): PenTypeRecord|null {
111
- for (const penType of this.penTypes) {
112
- if (penType.factory === this.tool.getStrokeFactory()) {
113
- return penType;
114
- }
115
- }
116
- return null;
117
- }
118
-
119
- protected createIcon(): Element {
120
- const strokeFactory = this.tool.getStrokeFactory();
121
- if (strokeFactory === makeFreehandLineBuilder || strokeFactory === makePressureSensitiveFreehandLineBuilder) {
122
- // Use a square-root scale to prevent the pen's tip from overflowing.
123
- const scale = Math.round(Math.sqrt(this.tool.getThickness()) * 4);
124
- const color = this.tool.getColor();
125
- const roundedTip = strokeFactory === makeFreehandLineBuilder;
126
-
127
- return this.editor.icons.makePenIcon(scale, color.toHexString(), roundedTip);
128
- } else {
129
- const strokeFactory = this.tool.getStrokeFactory();
130
- return this.editor.icons.makeIconFromFactory(this.tool, strokeFactory);
131
- }
132
- }
133
-
134
- private static idCounter: number = 0;
135
- protected fillDropdown(dropdown: HTMLElement): boolean {
136
- const container = document.createElement('div');
137
- container.classList.add(`${toolbarCSSPrefix}spacedList`);
138
-
139
- const thicknessRow = document.createElement('div');
140
- const objectTypeRow = document.createElement('div');
141
-
142
- // Thickness: Value of the input is squared to allow for finer control/larger values.
143
- const thicknessLabel = document.createElement('label');
144
- const thicknessInput = document.createElement('input');
145
- const objectSelectLabel = document.createElement('label');
146
- const objectTypeSelect = document.createElement('select');
147
-
148
- // Give inputs IDs so we can label them with a <label for=...>Label text</label>
149
- thicknessInput.id = `${toolbarCSSPrefix}penThicknessInput${PenToolWidget.idCounter++}`;
150
- objectTypeSelect.id = `${toolbarCSSPrefix}penBuilderSelect${PenToolWidget.idCounter++}`;
151
-
152
- thicknessLabel.innerText = this.localizationTable.thicknessLabel;
153
- thicknessLabel.setAttribute('for', thicknessInput.id);
154
- objectSelectLabel.innerText = this.localizationTable.selectObjectType;
155
- objectSelectLabel.setAttribute('for', objectTypeSelect.id);
156
-
157
- // Use a logarithmic scale for thicknessInput (finer control over thinner strokewidths.)
158
- const inverseThicknessInputFn = (t: number) => Math.log10(t);
159
- const thicknessInputFn = (t: number) => 10**t;
160
-
161
- thicknessInput.type = 'range';
162
- thicknessInput.min = `${inverseThicknessInputFn(2)}`;
163
- thicknessInput.max = `${inverseThicknessInputFn(400)}`;
164
- thicknessInput.step = '0.1';
165
- thicknessInput.oninput = () => {
166
- this.tool.setThickness(thicknessInputFn(parseFloat(thicknessInput.value)));
167
- };
168
- thicknessRow.appendChild(thicknessLabel);
169
- thicknessRow.appendChild(thicknessInput);
170
-
171
- objectTypeSelect.oninput = () => {
172
- const penTypeIdx = parseInt(objectTypeSelect.value);
173
- if (penTypeIdx < 0 || penTypeIdx >= this.penTypes.length) {
174
- console.error('Invalid pen type index', penTypeIdx);
175
- return;
176
- }
177
-
178
- this.tool.setStrokeFactory(this.penTypes[penTypeIdx].factory);
179
- };
180
- objectTypeRow.appendChild(objectSelectLabel);
181
- objectTypeRow.appendChild(objectTypeSelect);
182
-
183
- const colorRow = document.createElement('div');
184
- const colorLabel = document.createElement('label');
185
- const [ colorInput, colorInputContainer, setColorInputValue ] = makeColorInput(this.editor, color => {
186
- this.tool.setColor(color);
187
- });
188
-
189
- colorInput.id = `${toolbarCSSPrefix}colorInput${PenToolWidget.idCounter++}`;
190
- colorLabel.innerText = this.localizationTable.colorLabel;
191
- colorLabel.setAttribute('for', colorInput.id);
192
-
193
- colorRow.appendChild(colorLabel);
194
- colorRow.appendChild(colorInputContainer);
195
-
196
- this.updateInputs = () => {
197
- setColorInputValue(this.tool.getColor());
198
- thicknessInput.value = inverseThicknessInputFn(this.tool.getThickness()).toString();
199
-
200
- // Update the list of stroke factories
201
- objectTypeSelect.replaceChildren();
202
- for (let i = 0; i < this.penTypes.length; i ++) {
203
- const penType = this.penTypes[i];
204
- const option = document.createElement('option');
205
- option.value = i.toString();
206
- option.innerText = penType.name;
207
-
208
- objectTypeSelect.appendChild(option);
209
- }
210
-
211
- // Update the selected stroke factory.
212
- const strokeFactoryIdx = this.getCurrentPenTypeIdx();
213
- if (strokeFactoryIdx === -1) {
214
- objectTypeSelect.value = '';
215
- } else {
216
- objectTypeSelect.value = strokeFactoryIdx.toString();
217
- }
218
- };
219
- this.updateInputs();
220
-
221
- container.replaceChildren(colorRow, thicknessRow, objectTypeRow);
222
- dropdown.replaceChildren(container);
223
- return true;
224
- }
225
-
226
- protected onKeyPress(event: KeyPressEvent): boolean {
227
- if (!this.isSelected()) {
228
- return false;
229
- }
230
-
231
- // Map alt+0-9 to different pen types.
232
- if (/^[0-9]$/.exec(event.key) && event.ctrlKey) {
233
- const penTypeIdx = parseInt(event.key) - 1;
234
- if (penTypeIdx >= 0 && penTypeIdx < this.penTypes.length) {
235
- this.tool.setStrokeFactory(this.penTypes[penTypeIdx].factory);
236
- return true;
237
- }
238
- }
239
-
240
- return false;
241
- }
242
-
243
- public serializeState(): SavedToolbuttonState {
244
- return {
245
- ...super.serializeState(),
246
-
247
- color: this.tool.getColor().toHexString(),
248
- thickness: this.tool.getThickness(),
249
- strokeFactoryId: this.getCurrentPenType()?.id,
250
- };
251
- }
252
-
253
- public deserializeFrom(state: SavedToolbuttonState) {
254
- super.deserializeFrom(state);
255
-
256
- const verifyPropertyType = (propertyName: string, expectedType: 'string'|'number'|'object') => {
257
- const actualType = typeof(state[propertyName]);
258
- if (actualType !== expectedType) {
259
- throw new Error(
260
- `Deserializing property ${propertyName}: Invalid type. Expected ${expectedType},` +
261
- ` was ${actualType}.`
262
- );
263
- }
264
- };
265
-
266
- if (state.color) {
267
- verifyPropertyType('color', 'string');
268
- this.tool.setColor(Color4.fromHex(state.color));
269
- }
270
-
271
- if (state.thickness) {
272
- verifyPropertyType('thickness', 'number');
273
- this.tool.setThickness(state.thickness);
274
- }
275
-
276
- if (state.strokeFactoryId) {
277
- verifyPropertyType('strokeFactoryId', 'string');
278
-
279
- const factoryId: string = state.strokeFactoryId;
280
- for (const penType of this.penTypes) {
281
- if (factoryId === penType.id) {
282
- this.tool.setStrokeFactory(penType.factory);
283
- break;
284
- }
285
- }
286
- }
287
- }
288
- }
@@ -1,190 +0,0 @@
1
- import Color4 from '../../Color4';
2
- import { isRestylableComponent } from '../../components/RestylableComponent';
3
- import Editor from '../../Editor';
4
- import uniteCommands from '../../commands/uniteCommands';
5
- import SelectionTool from '../../tools/SelectionTool/SelectionTool';
6
- import { EditorEventType, KeyPressEvent } from '../../types';
7
- import { ToolbarLocalization } from '../localization';
8
- import makeColorInput from '../makeColorInput';
9
- import ActionButtonWidget from './ActionButtonWidget';
10
- import BaseToolWidget from './BaseToolWidget';
11
- import BaseWidget from './BaseWidget';
12
-
13
- class RestyleSelectionWidget extends BaseWidget {
14
- private updateFormatData: ()=>void = () => {};
15
-
16
- public constructor(editor: Editor, private selectionTool: SelectionTool, localizationTable?: ToolbarLocalization) {
17
- super(editor, 'restyle-selection', localizationTable);
18
-
19
- // Allow showing the dropdown even if this widget isn't selected yet
20
- this.container.classList.add('dropdownShowable');
21
-
22
- this.editor.notifier.on(EditorEventType.ToolUpdated, toolEvt => {
23
- if (toolEvt.kind !== EditorEventType.ToolUpdated) {
24
- throw new Error('Invalid event type!');
25
- }
26
-
27
- if (toolEvt.tool === this.selectionTool) {
28
- this.updateFormatData();
29
- }
30
- });
31
- }
32
-
33
- protected getTitle(): string {
34
- return this.localizationTable.reformatSelection;
35
- }
36
-
37
- protected createIcon(){
38
- return this.editor.icons.makeFormatSelectionIcon();
39
- }
40
-
41
- protected handleClick(): void {
42
- this.setDropdownVisible(!this.isDropdownVisible());
43
- }
44
-
45
- protected fillDropdown(dropdown: HTMLElement): boolean {
46
- const container = document.createElement('div');
47
- const colorRow = document.createElement('div');
48
- const colorLabel = document.createElement('label');
49
- const [ colorInput, colorInputContainer, setColorInputValue ] = makeColorInput(this.editor, color => {
50
- const selection = this.selectionTool.getSelection();
51
-
52
- if (selection) {
53
- const updateStyleCommands = [];
54
-
55
- for (const elem of selection.getSelectedObjects()) {
56
- if (isRestylableComponent(elem)) {
57
- updateStyleCommands.push(elem.updateStyle({ color }));
58
- }
59
- }
60
-
61
- const unitedCommand = uniteCommands(updateStyleCommands);
62
- this.editor.dispatch(unitedCommand);
63
- }
64
- });
65
-
66
- colorLabel.innerText = this.localizationTable.colorLabel;
67
-
68
- this.updateFormatData = () => {
69
- const selection = this.selectionTool.getSelection();
70
- if (selection) {
71
- colorInput.disabled = false;
72
-
73
- const colors = [];
74
- for (const elem of selection.getSelectedObjects()) {
75
- if (isRestylableComponent(elem)) {
76
- const color = elem.getStyle().color;
77
- if (color) {
78
- colors.push(color);
79
- }
80
- }
81
- }
82
- setColorInputValue(Color4.average(colors));
83
- } else {
84
- colorInput.disabled = true;
85
- }
86
- };
87
-
88
- colorRow.replaceChildren(colorLabel, colorInputContainer);
89
- container.replaceChildren(colorRow);
90
- dropdown.replaceChildren(container);
91
- return true;
92
- }
93
- }
94
-
95
- export default class SelectionToolWidget extends BaseToolWidget {
96
- public constructor(
97
- editor: Editor, private tool: SelectionTool, localization?: ToolbarLocalization
98
- ) {
99
- super(editor, tool, 'selection-tool-widget', localization);
100
-
101
- const resizeButton = new ActionButtonWidget(
102
- editor, 'resize-btn',
103
- () => editor.icons.makeResizeViewportIcon(),
104
- this.localizationTable.resizeImageToSelection,
105
- () => {
106
- this.resizeImageToSelection();
107
- },
108
- localization,
109
- );
110
- const deleteButton = new ActionButtonWidget(
111
- editor, 'delete-btn',
112
- () => editor.icons.makeDeleteSelectionIcon(),
113
- this.localizationTable.deleteSelection,
114
- () => {
115
- const selection = this.tool.getSelection();
116
- this.editor.dispatch(selection!.deleteSelectedObjects());
117
- this.tool.clearSelection();
118
- },
119
- localization,
120
- );
121
- const duplicateButton = new ActionButtonWidget(
122
- editor, 'duplicate-btn',
123
- () => editor.icons.makeDuplicateSelectionIcon(),
124
- this.localizationTable.duplicateSelection,
125
- async () => {
126
- const selection = this.tool.getSelection();
127
- this.editor.dispatch(await selection!.duplicateSelectedObjects());
128
- },
129
- localization,
130
- );
131
- const restyleButton = new RestyleSelectionWidget(
132
- editor,
133
- this.tool,
134
- localization,
135
- );
136
-
137
- this.addSubWidget(resizeButton);
138
- this.addSubWidget(deleteButton);
139
- this.addSubWidget(duplicateButton);
140
- this.addSubWidget(restyleButton);
141
-
142
- const updateDisabled = (disabled: boolean) => {
143
- resizeButton.setDisabled(disabled);
144
- deleteButton.setDisabled(disabled);
145
- duplicateButton.setDisabled(disabled);
146
- restyleButton.setDisabled(disabled);
147
- };
148
- updateDisabled(true);
149
-
150
- // Enable/disable actions based on whether items are selected
151
- this.editor.notifier.on(EditorEventType.ToolUpdated, toolEvt => {
152
- if (toolEvt.kind !== EditorEventType.ToolUpdated) {
153
- throw new Error('Invalid event type!');
154
- }
155
-
156
- if (toolEvt.tool === this.tool) {
157
- const selection = this.tool.getSelection();
158
- const hasSelection = selection && selection.getSelectedItemCount() > 0;
159
-
160
- updateDisabled(!hasSelection);
161
- }
162
- });
163
- }
164
-
165
- private resizeImageToSelection() {
166
- const selection = this.tool.getSelection();
167
- if (selection) {
168
- this.editor.dispatch(this.editor.setImportExportRect(selection.region));
169
- }
170
- }
171
-
172
- protected onKeyPress(event: KeyPressEvent): boolean {
173
- // Resize image to selection:
174
- // Other keys are handled directly by the selection tool.
175
- if (event.ctrlKey && event.key === 'r') {
176
- this.resizeImageToSelection();
177
- return true;
178
- }
179
-
180
- return false;
181
- }
182
-
183
- protected getTitle(): string {
184
- return this.localizationTable.select;
185
- }
186
-
187
- protected createIcon(): Element {
188
- return this.editor.icons.makeSelectionIcon();
189
- }
190
- }
@@ -1,145 +0,0 @@
1
- import Color4 from '../../Color4';
2
- import Editor from '../../Editor';
3
- import TextTool from '../../tools/TextTool';
4
- import { EditorEventType } from '../../types';
5
- import { toolbarCSSPrefix } from '../HTMLToolbar';
6
- import { ToolbarLocalization } from '../localization';
7
- import makeColorInput from '../makeColorInput';
8
- import BaseToolWidget from './BaseToolWidget';
9
- import { SavedToolbuttonState } from './BaseWidget';
10
-
11
- export default class TextToolWidget extends BaseToolWidget {
12
- private updateDropdownInputs: (()=>void)|null = null;
13
- public constructor(editor: Editor, private tool: TextTool, localization?: ToolbarLocalization) {
14
- super(editor, tool, 'text-tool-widget', localization);
15
-
16
- editor.notifier.on(EditorEventType.ToolUpdated, evt => {
17
- if (evt.kind === EditorEventType.ToolUpdated && evt.tool === tool) {
18
- this.updateIcon();
19
- this.updateDropdownInputs?.();
20
- }
21
- });
22
- }
23
-
24
- protected getTitle(): string {
25
- return this.targetTool.description;
26
- }
27
-
28
- protected createIcon(): Element {
29
- const textStyle = this.tool.getTextStyle();
30
- return this.editor.icons.makeTextIcon(textStyle);
31
- }
32
-
33
- private static idCounter: number = 0;
34
- protected fillDropdown(dropdown: HTMLElement): boolean {
35
- const container = document.createElement('div');
36
- container.classList.add(`${toolbarCSSPrefix}spacedList`);
37
- const fontRow = document.createElement('div');
38
- const colorRow = document.createElement('div');
39
- const sizeRow = document.createElement('div');
40
-
41
- const fontInput = document.createElement('select');
42
- const fontLabel = document.createElement('label');
43
-
44
- const sizeInput = document.createElement('input');
45
- const sizeLabel = document.createElement('label');
46
-
47
- const [ colorInput, colorInputContainer, setColorInputValue ] = makeColorInput(this.editor, color => {
48
- this.tool.setColor(color);
49
- });
50
- const colorLabel = document.createElement('label');
51
-
52
- const fontsInInput = new Set();
53
- const addFontToInput = (fontName: string) => {
54
- const option = document.createElement('option');
55
- option.value = fontName;
56
- option.textContent = fontName;
57
- fontInput.appendChild(option);
58
- fontsInInput.add(fontName);
59
- };
60
-
61
- sizeInput.setAttribute('type', 'number');
62
- sizeInput.min = '1';
63
- sizeInput.max = '128';
64
-
65
- fontLabel.innerText = this.localizationTable.fontLabel;
66
- colorLabel.innerText = this.localizationTable.colorLabel;
67
- sizeLabel.innerText = this.localizationTable.textSize;
68
-
69
- colorInput.id = `${toolbarCSSPrefix}-text-color-input-${TextToolWidget.idCounter++}`;
70
- colorLabel.setAttribute('for', colorInput.id);
71
-
72
- sizeInput.id = `${toolbarCSSPrefix}-text-size-input-${TextToolWidget.idCounter++}`;
73
- sizeLabel.setAttribute('for', sizeInput.id);
74
-
75
- addFontToInput('monospace');
76
- addFontToInput('serif');
77
- addFontToInput('sans-serif');
78
- fontInput.id = `${toolbarCSSPrefix}-text-font-input-${TextToolWidget.idCounter++}`;
79
- fontLabel.setAttribute('for', fontInput.id);
80
-
81
- fontInput.onchange = () => {
82
- this.tool.setFontFamily(fontInput.value);
83
- };
84
-
85
- sizeInput.onchange = () => {
86
- const size = parseInt(sizeInput.value);
87
- if (!isNaN(size) && size > 0) {
88
- this.tool.setFontSize(size);
89
- }
90
- };
91
-
92
- colorRow.appendChild(colorLabel);
93
- colorRow.appendChild(colorInputContainer);
94
-
95
- fontRow.appendChild(fontLabel);
96
- fontRow.appendChild(fontInput);
97
-
98
- sizeRow.appendChild(sizeLabel);
99
- sizeRow.appendChild(sizeInput);
100
-
101
- this.updateDropdownInputs = () => {
102
- const style = this.tool.getTextStyle();
103
- setColorInputValue(style.renderingStyle.fill);
104
-
105
- if (!fontsInInput.has(style.fontFamily)) {
106
- addFontToInput(style.fontFamily);
107
- }
108
- fontInput.value = style.fontFamily;
109
- sizeInput.value = `${style.size}`;
110
- };
111
- this.updateDropdownInputs();
112
-
113
- container.replaceChildren(colorRow, sizeRow, fontRow);
114
- dropdown.appendChild(container);
115
- return true;
116
- }
117
-
118
- public serializeState(): SavedToolbuttonState {
119
- const textStyle = this.tool.getTextStyle();
120
-
121
- return {
122
- ...super.serializeState(),
123
-
124
- fontFamily: textStyle.fontFamily,
125
- textSize: textStyle.size,
126
- color: textStyle.renderingStyle.fill.toHexString(),
127
- };
128
- }
129
-
130
- public deserializeFrom(state: SavedToolbuttonState) {
131
- if (state.fontFamily && typeof(state.fontFamily) === 'string') {
132
- this.tool.setFontFamily(state.fontFamily);
133
- }
134
-
135
- if (state.color && typeof(state.color) === 'string') {
136
- this.tool.setColor(Color4.fromHex(state.color));
137
- }
138
-
139
- if (state.textSize && typeof(state.textSize) === 'number') {
140
- this.tool.setFontSize(state.textSize);
141
- }
142
-
143
- super.deserializeFrom(state);
144
- }
145
- }
@@ -1,13 +0,0 @@
1
-
2
- export { default as ActionButtonWidget } from './ActionButtonWidget';
3
- export { default as BaseToolWidget } from './BaseToolWidget';
4
- export { default as BaseWidget } from './BaseWidget';
5
-
6
- export { default as PenToolWidget } from './PenToolWidget';
7
- export { default as TextToolWidget } from './TextToolWidget';
8
- export { default as HandToolWidget } from './HandToolWidget';
9
- export { default as SelectionToolWidget } from './SelectionToolWidget';
10
- export { default as EraserToolWidget } from './EraserToolWidget';
11
-
12
- export { default as InsertImageWidget } from './InsertImageWidget';
13
- export { default as DocumentPropertiesWidget } from './DocumentPropertiesWidget';