js-draw 0.1.9 → 0.1.12
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/CHANGELOG.md +18 -0
- package/README.md +15 -3
- package/dist/bundle.js +1 -1
- package/dist/src/Editor.d.ts +7 -2
- package/dist/src/Editor.js +74 -25
- package/dist/src/EditorImage.d.ts +1 -1
- package/dist/src/EditorImage.js +2 -2
- package/dist/src/Pointer.d.ts +1 -1
- package/dist/src/Pointer.js +1 -1
- package/dist/src/SVGLoader.d.ts +1 -1
- package/dist/src/SVGLoader.js +14 -6
- package/dist/src/UndoRedoHistory.js +3 -0
- package/dist/src/Viewport.d.ts +8 -25
- package/dist/src/Viewport.js +17 -10
- package/dist/src/bundle/bundled.d.ts +2 -1
- package/dist/src/bundle/bundled.js +2 -1
- package/dist/src/commands/Command.d.ts +2 -2
- package/dist/src/commands/Command.js +4 -4
- package/dist/src/commands/Duplicate.d.ts +1 -1
- package/dist/src/commands/Duplicate.js +1 -1
- package/dist/src/commands/Erase.d.ts +1 -1
- package/dist/src/commands/Erase.js +1 -1
- package/dist/src/commands/localization.d.ts +1 -1
- package/dist/src/components/AbstractComponent.d.ts +3 -3
- package/dist/src/components/AbstractComponent.js +2 -2
- package/dist/src/components/SVGGlobalAttributesObject.d.ts +3 -3
- package/dist/src/components/SVGGlobalAttributesObject.js +1 -1
- package/dist/src/components/Stroke.d.ts +4 -4
- package/dist/src/components/Stroke.js +2 -2
- package/dist/src/components/Text.d.ts +3 -3
- package/dist/src/components/Text.js +3 -3
- package/dist/src/components/UnknownSVGObject.d.ts +3 -3
- package/dist/src/components/UnknownSVGObject.js +1 -1
- package/dist/src/components/builders/ArrowBuilder.d.ts +1 -1
- package/dist/src/components/builders/ArrowBuilder.js +1 -1
- package/dist/src/components/builders/FreehandLineBuilder.d.ts +8 -3
- package/dist/src/components/builders/FreehandLineBuilder.js +142 -71
- package/dist/src/components/builders/LineBuilder.d.ts +1 -1
- package/dist/src/components/builders/LineBuilder.js +1 -1
- package/dist/src/components/builders/RectangleBuilder.d.ts +1 -1
- package/dist/src/components/builders/RectangleBuilder.js +3 -3
- package/dist/src/components/builders/types.d.ts +1 -1
- package/dist/src/localization.d.ts +1 -0
- package/dist/src/localization.js +5 -1
- package/dist/src/localizations/en.d.ts +3 -0
- package/dist/src/localizations/en.js +4 -0
- package/dist/src/localizations/es.d.ts +3 -0
- package/dist/src/localizations/es.js +18 -0
- package/dist/src/localizations/getLocalizationTable.d.ts +3 -0
- package/dist/src/localizations/getLocalizationTable.js +43 -0
- package/dist/src/{geometry → math}/LineSegment2.d.ts +1 -0
- package/dist/src/{geometry → math}/LineSegment2.js +16 -0
- package/dist/src/{geometry → math}/Mat33.d.ts +0 -0
- package/dist/src/{geometry → math}/Mat33.js +0 -0
- package/dist/src/{geometry → math}/Path.d.ts +2 -1
- package/dist/src/{geometry → math}/Path.js +58 -51
- package/dist/src/{geometry → math}/Rect2.d.ts +1 -0
- package/dist/src/{geometry → math}/Rect2.js +16 -0
- package/dist/src/{geometry → math}/Vec2.d.ts +0 -0
- package/dist/src/{geometry → math}/Vec2.js +0 -0
- package/dist/src/{geometry → math}/Vec3.d.ts +1 -1
- package/dist/src/{geometry → math}/Vec3.js +1 -1
- package/dist/src/math/rounding.d.ts +3 -0
- package/dist/src/math/rounding.js +120 -0
- package/dist/src/rendering/Display.d.ts +3 -1
- package/dist/src/rendering/Display.js +16 -10
- package/dist/src/rendering/caching/CacheRecord.d.ts +2 -2
- package/dist/src/rendering/caching/CacheRecord.js +1 -1
- package/dist/src/rendering/caching/CacheRecordManager.d.ts +1 -1
- package/dist/src/rendering/caching/RenderingCache.js +1 -1
- package/dist/src/rendering/caching/RenderingCacheNode.d.ts +2 -1
- package/dist/src/rendering/caching/RenderingCacheNode.js +18 -7
- package/dist/src/rendering/caching/testUtils.js +1 -1
- package/dist/src/rendering/caching/types.d.ts +1 -1
- package/dist/src/rendering/localization.d.ts +2 -0
- package/dist/src/rendering/localization.js +2 -0
- package/dist/src/rendering/renderers/AbstractRenderer.d.ts +4 -4
- package/dist/src/rendering/renderers/AbstractRenderer.js +2 -2
- package/dist/src/rendering/renderers/CanvasRenderer.d.ts +4 -4
- package/dist/src/rendering/renderers/CanvasRenderer.js +1 -1
- package/dist/src/rendering/renderers/DummyRenderer.d.ts +4 -4
- package/dist/src/rendering/renderers/DummyRenderer.js +1 -1
- package/dist/src/rendering/renderers/SVGRenderer.d.ts +3 -3
- package/dist/src/rendering/renderers/SVGRenderer.js +8 -2
- package/dist/src/rendering/renderers/TextOnlyRenderer.d.ts +5 -3
- package/dist/src/rendering/renderers/TextOnlyRenderer.js +13 -3
- package/dist/src/toolbar/HTMLToolbar.js +5 -7
- package/dist/src/toolbar/icons.d.ts +3 -0
- package/dist/src/toolbar/icons.js +152 -142
- package/dist/src/toolbar/localization.d.ts +4 -1
- package/dist/src/toolbar/localization.js +4 -1
- package/dist/src/toolbar/makeColorInput.js +2 -1
- package/dist/src/toolbar/widgets/ActionButtonWidget.d.ts +13 -0
- package/dist/src/toolbar/widgets/ActionButtonWidget.js +21 -0
- package/dist/src/toolbar/widgets/BaseWidget.js +31 -0
- package/dist/src/toolbar/widgets/HandToolWidget.js +10 -3
- package/dist/src/toolbar/widgets/SelectionWidget.d.ts +0 -1
- package/dist/src/toolbar/widgets/SelectionWidget.js +23 -30
- package/dist/src/tools/BaseTool.d.ts +2 -1
- package/dist/src/tools/BaseTool.js +3 -0
- package/dist/src/tools/Eraser.js +1 -1
- package/dist/src/tools/PanZoom.d.ts +3 -2
- package/dist/src/tools/PanZoom.js +32 -16
- package/dist/src/tools/SelectionTool.d.ts +11 -4
- package/dist/src/tools/SelectionTool.js +135 -23
- package/dist/src/tools/TextTool.js +1 -1
- package/dist/src/tools/ToolController.js +6 -2
- package/dist/src/tools/localization.d.ts +1 -0
- package/dist/src/tools/localization.js +1 -0
- package/dist/src/types.d.ts +13 -6
- package/dist/src/types.js +1 -0
- package/package.json +9 -1
- package/src/Editor.ts +86 -24
- package/src/EditorImage.test.ts +2 -4
- package/src/EditorImage.ts +2 -2
- package/src/Pointer.ts +1 -1
- package/src/SVGLoader.ts +14 -6
- package/src/UndoRedoHistory.ts +4 -0
- package/src/Viewport.ts +21 -17
- package/src/bundle/bundled.ts +2 -1
- package/src/commands/Command.ts +5 -5
- package/src/commands/Duplicate.ts +1 -1
- package/src/commands/Erase.ts +1 -1
- package/src/commands/localization.ts +1 -1
- package/src/components/AbstractComponent.ts +4 -4
- package/src/components/SVGGlobalAttributesObject.ts +3 -3
- package/src/components/Stroke.test.ts +3 -5
- package/src/components/Stroke.ts +4 -4
- package/src/components/Text.test.ts +2 -2
- package/src/components/Text.ts +3 -3
- package/src/components/UnknownSVGObject.ts +3 -3
- package/src/components/builders/ArrowBuilder.ts +2 -2
- package/src/components/builders/FreehandLineBuilder.ts +190 -80
- package/src/components/builders/LineBuilder.ts +2 -2
- package/src/components/builders/RectangleBuilder.ts +3 -3
- package/src/components/builders/types.ts +1 -1
- package/src/localization.ts +6 -0
- package/src/localizations/en.ts +8 -0
- package/src/localizations/es.ts +63 -0
- package/src/localizations/getLocalizationTable.test.ts +27 -0
- package/src/localizations/getLocalizationTable.ts +53 -0
- package/src/{geometry → math}/LineSegment2.test.ts +15 -0
- package/src/{geometry → math}/LineSegment2.ts +20 -0
- package/src/{geometry → math}/Mat33.test.ts +0 -0
- package/src/{geometry → math}/Mat33.ts +0 -0
- package/src/{geometry → math}/Path.fromString.test.ts +0 -0
- package/src/{geometry → math}/Path.test.ts +0 -0
- package/src/{geometry → math}/Path.toString.test.ts +11 -2
- package/src/{geometry → math}/Path.ts +60 -57
- package/src/{geometry → math}/Rect2.test.ts +20 -7
- package/src/{geometry → math}/Rect2.ts +19 -1
- package/src/{geometry → math}/Vec2.test.ts +0 -0
- package/src/{geometry → math}/Vec2.ts +0 -0
- package/src/{geometry → math}/Vec3.test.ts +0 -0
- package/src/{geometry → math}/Vec3.ts +2 -2
- package/src/math/rounding.test.ts +40 -0
- package/src/math/rounding.ts +145 -0
- package/src/rendering/Display.ts +18 -10
- package/src/rendering/caching/CacheRecord.test.ts +2 -2
- package/src/rendering/caching/CacheRecord.ts +2 -2
- package/src/rendering/caching/CacheRecordManager.ts +1 -1
- package/src/rendering/caching/RenderingCache.test.ts +3 -3
- package/src/rendering/caching/RenderingCache.ts +1 -1
- package/src/rendering/caching/RenderingCacheNode.ts +23 -7
- package/src/rendering/caching/testUtils.ts +1 -1
- package/src/rendering/caching/types.ts +1 -1
- package/src/rendering/localization.ts +4 -0
- package/src/rendering/renderers/AbstractRenderer.ts +4 -4
- package/src/rendering/renderers/CanvasRenderer.ts +4 -4
- package/src/rendering/renderers/DummyRenderer.test.ts +2 -2
- package/src/rendering/renderers/DummyRenderer.ts +4 -4
- package/src/rendering/renderers/SVGRenderer.ts +10 -4
- package/src/rendering/renderers/TextOnlyRenderer.ts +17 -6
- package/src/toolbar/HTMLToolbar.ts +5 -8
- package/src/toolbar/icons.ts +167 -147
- package/src/toolbar/localization.ts +8 -2
- package/src/toolbar/makeColorInput.ts +2 -1
- package/src/toolbar/toolbar.css +7 -3
- package/src/toolbar/widgets/ActionButtonWidget.ts +31 -0
- package/src/toolbar/widgets/BaseWidget.ts +36 -0
- package/src/toolbar/widgets/HandToolWidget.ts +14 -3
- package/src/toolbar/widgets/SelectionWidget.ts +46 -41
- package/src/tools/BaseTool.ts +5 -1
- package/src/tools/Eraser.ts +2 -2
- package/src/tools/PanZoom.ts +39 -18
- package/src/tools/SelectionTool.test.ts +26 -5
- package/src/tools/SelectionTool.ts +162 -27
- package/src/tools/TextTool.ts +2 -2
- package/src/tools/ToolController.ts +6 -2
- package/src/tools/UndoRedoShortcut.test.ts +1 -1
- package/src/tools/localization.ts +2 -0
- package/src/types.ts +14 -5
- package/dist-test/test-dist-bundle.html +0 -42
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
import Color4 from '../../Color4';
|
5
5
|
import { ImageNode, sortLeavesByZIndex } from '../../EditorImage';
|
6
|
-
import Rect2 from '../../
|
6
|
+
import Rect2 from '../../math/Rect2';
|
7
7
|
import Viewport from '../../Viewport';
|
8
8
|
import AbstractRenderer from '../renderers/AbstractRenderer';
|
9
9
|
import CacheRecord from './CacheRecord';
|
@@ -151,12 +151,15 @@ export default class RenderingCacheNode {
|
|
151
151
|
return result;
|
152
152
|
}
|
153
153
|
|
154
|
-
|
155
|
-
|
154
|
+
// Returns true iff all elems of this.renderedIds are in sortedIds.
|
155
|
+
// sortedIds should be sorted by z-index (or some other order, so long as they are
|
156
|
+
// sorted by the same thing as this.renderedIds.)
|
157
|
+
private allRenderedIdsIn(sortedIds: number[]) {
|
158
|
+
if (this.renderedIds.length > sortedIds.length) {
|
156
159
|
return false;
|
157
160
|
}
|
158
161
|
|
159
|
-
for (let i = 0; i <
|
162
|
+
for (let i = 0; i < this.renderedIds.length; i++) {
|
160
163
|
if (sortedIds[i] !== this.renderedIds[i]) {
|
161
164
|
return false;
|
162
165
|
}
|
@@ -165,6 +168,14 @@ export default class RenderingCacheNode {
|
|
165
168
|
return true;
|
166
169
|
}
|
167
170
|
|
171
|
+
private renderingIsUpToDate(sortedIds: number[]) {
|
172
|
+
if (this.cachedRenderer === null || sortedIds.length !== this.renderedIds.length) {
|
173
|
+
return false;
|
174
|
+
}
|
175
|
+
|
176
|
+
return this.allRenderedIdsIn(sortedIds);
|
177
|
+
}
|
178
|
+
|
168
179
|
// Render all [items] within [viewport]
|
169
180
|
public renderItems(screenRenderer: AbstractRenderer, items: ImageNode[], viewport: Viewport) {
|
170
181
|
if (
|
@@ -238,8 +249,7 @@ export default class RenderingCacheNode {
|
|
238
249
|
}
|
239
250
|
|
240
251
|
// Is it worth it to render the items?
|
241
|
-
// TODO:
|
242
|
-
// TODO: Determine whether it is 'worth it' to cache this depending on rendering time.
|
252
|
+
// TODO: Consider replacing this with something performace based.
|
243
253
|
if (leavesByIds.length > this.cacheState.props.minComponentsPerCache) {
|
244
254
|
let fullRerenderNeeded = true;
|
245
255
|
if (!this.cachedRenderer) {
|
@@ -247,7 +257,7 @@ export default class RenderingCacheNode {
|
|
247
257
|
this.region,
|
248
258
|
() => this.onRegionDealloc()
|
249
259
|
);
|
250
|
-
} else if (leavesByIds.length > this.renderedIds.length && this.renderedMaxZIndex !== null) {
|
260
|
+
} else if (leavesByIds.length > this.renderedIds.length && this.allRenderedIdsIn(leafIds) && this.renderedMaxZIndex !== null) {
|
251
261
|
// We often don't need to do a full re-render even if something's changed.
|
252
262
|
// Check whether we can just draw on top of the existing cache.
|
253
263
|
const newLeaves = [];
|
@@ -287,6 +297,12 @@ export default class RenderingCacheNode {
|
|
287
297
|
screenRenderer.drawRect(this.region, viewport.getSizeOfPixelOnCanvas(), { fill: Color4.clay });
|
288
298
|
}
|
289
299
|
}
|
300
|
+
} else if (debugMode) {
|
301
|
+
console.log('Decided on a full re-render. Reason: At least one of the following is false:',
|
302
|
+
'\n leafIds.length > this.renderedIds.length: ', leafIds.length > this.renderedIds.length,
|
303
|
+
'\n this.allRenderedIdsIn(leafIds): ', this.allRenderedIdsIn(leafIds),
|
304
|
+
'\n this.renderedMaxZIndex !== null: ', this.renderedMaxZIndex !== null,
|
305
|
+
'\n\nthis.rerenderedIds: ', this.renderedIds, ', leafIds: ', leafIds);
|
290
306
|
}
|
291
307
|
|
292
308
|
if (fullRerenderNeeded) {
|
@@ -1,10 +1,14 @@
|
|
1
1
|
|
2
2
|
export interface TextRendererLocalization {
|
3
|
+
pathNodeCount(pathCount: number): string;
|
4
|
+
textNodeCount(nodeCount: number): string;
|
3
5
|
textNode(content: string): string;
|
4
6
|
rerenderAsText: string;
|
5
7
|
}
|
6
8
|
|
7
9
|
export const defaultTextRendererLocalization: TextRendererLocalization = {
|
10
|
+
pathNodeCount: (count: number) => `There are ${count} visible path objects.`,
|
11
|
+
textNodeCount: (count: number) => `There are ${count} visible text nodes.`,
|
8
12
|
textNode: (content: string) => `Text: ${content}`,
|
9
13
|
rerenderAsText: 'Re-render as text',
|
10
14
|
};
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import { LoadSaveDataTable } from '../../components/AbstractComponent';
|
2
2
|
import { TextStyle } from '../../components/Text';
|
3
|
-
import Mat33 from '../../
|
4
|
-
import Path, { PathCommand, PathCommandType } from '../../
|
5
|
-
import Rect2 from '../../
|
6
|
-
import { Point2, Vec2 } from '../../
|
3
|
+
import Mat33 from '../../math/Mat33';
|
4
|
+
import Path, { PathCommand, PathCommandType } from '../../math/Path';
|
5
|
+
import Rect2 from '../../math/Rect2';
|
6
|
+
import { Point2, Vec2 } from '../../math/Vec2';
|
7
7
|
import Viewport from '../../Viewport';
|
8
8
|
import RenderingStyle, { stylesEqual } from '../RenderingStyle';
|
9
9
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import Color4 from '../../Color4';
|
2
2
|
import Text, { TextStyle } from '../../components/Text';
|
3
|
-
import Mat33 from '../../
|
4
|
-
import Rect2 from '../../
|
5
|
-
import { Point2, Vec2 } from '../../
|
6
|
-
import Vec3 from '../../
|
3
|
+
import Mat33 from '../../math/Mat33';
|
4
|
+
import Rect2 from '../../math/Rect2';
|
5
|
+
import { Point2, Vec2 } from '../../math/Vec2';
|
6
|
+
import Vec3 from '../../math/Vec3';
|
7
7
|
import Viewport from '../../Viewport';
|
8
8
|
import RenderingStyle from '../RenderingStyle';
|
9
9
|
import AbstractRenderer, { RenderablePathSpec } from './AbstractRenderer';
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
import EventDispatcher from '../../EventDispatcher';
|
3
|
-
import Mat33 from '../../
|
4
|
-
import { Vec2 } from '../../
|
3
|
+
import Mat33 from '../../math/Mat33';
|
4
|
+
import { Vec2 } from '../../math/Vec2';
|
5
5
|
import Viewport from '../../Viewport';
|
6
6
|
import DummyRenderer from './DummyRenderer';
|
7
7
|
|
@@ -1,10 +1,10 @@
|
|
1
1
|
// Renderer that outputs nothing. Useful for automated tests.
|
2
2
|
|
3
3
|
import { TextStyle } from '../../components/Text';
|
4
|
-
import Mat33 from '../../
|
5
|
-
import Rect2 from '../../
|
6
|
-
import { Point2, Vec2 } from '../../
|
7
|
-
import Vec3 from '../../
|
4
|
+
import Mat33 from '../../math/Mat33';
|
5
|
+
import Rect2 from '../../math/Rect2';
|
6
|
+
import { Point2, Vec2 } from '../../math/Vec2';
|
7
|
+
import Vec3 from '../../math/Vec3';
|
8
8
|
import Viewport from '../../Viewport';
|
9
9
|
import RenderingStyle from '../RenderingStyle';
|
10
10
|
import AbstractRenderer from './AbstractRenderer';
|
@@ -1,10 +1,11 @@
|
|
1
1
|
|
2
2
|
import { LoadSaveDataTable } from '../../components/AbstractComponent';
|
3
3
|
import { TextStyle } from '../../components/Text';
|
4
|
-
import Mat33 from '../../
|
5
|
-
import Path, { PathCommand, PathCommandType } from '../../
|
6
|
-
import Rect2 from '../../
|
7
|
-
import {
|
4
|
+
import Mat33 from '../../math/Mat33';
|
5
|
+
import Path, { PathCommand, PathCommandType } from '../../math/Path';
|
6
|
+
import Rect2 from '../../math/Rect2';
|
7
|
+
import { toRoundedString } from '../../math/rounding';
|
8
|
+
import { Point2, Vec2 } from '../../math/Vec2';
|
8
9
|
import { svgAttributesDataKey, SVGLoaderUnknownAttribute, SVGLoaderUnknownStyleAttribute, svgStyleAttributesDataKey } from '../../SVGLoader';
|
9
10
|
import Viewport from '../../Viewport';
|
10
11
|
import RenderingStyle from '../RenderingStyle';
|
@@ -113,6 +114,9 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
113
114
|
public drawText(text: string, transform: Mat33, style: TextStyle): void {
|
114
115
|
transform = this.getCanvasToScreenTransform().rightMul(transform);
|
115
116
|
|
117
|
+
const translation = transform.transformVec2(Vec2.zero);
|
118
|
+
transform = transform.rightMul(Mat33.translation(translation.times(-1)));
|
119
|
+
|
116
120
|
const textElem = document.createElementNS(svgNameSpace, 'text');
|
117
121
|
textElem.appendChild(document.createTextNode(text));
|
118
122
|
textElem.style.transform = `matrix(
|
@@ -125,6 +129,8 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
125
129
|
textElem.style.fontWeight = style.fontWeight ?? '';
|
126
130
|
textElem.style.fontSize = style.size + 'px';
|
127
131
|
textElem.style.fill = style.renderingStyle.fill.toHexString();
|
132
|
+
textElem.setAttribute('x', `${toRoundedString(translation.x)}`);
|
133
|
+
textElem.setAttribute('y', `${toRoundedString(translation.y)}`);
|
128
134
|
|
129
135
|
if (style.renderingStyle.stroke) {
|
130
136
|
const strokeStyle = style.renderingStyle.stroke;
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import { TextStyle } from '../../components/Text';
|
2
|
-
import Mat33 from '../../
|
3
|
-
import Rect2 from '../../
|
4
|
-
import { Vec2 } from '../../
|
5
|
-
import Vec3 from '../../
|
2
|
+
import Mat33 from '../../math/Mat33';
|
3
|
+
import Rect2 from '../../math/Rect2';
|
4
|
+
import { Vec2 } from '../../math/Vec2';
|
5
|
+
import Vec3 from '../../math/Vec3';
|
6
6
|
import Viewport from '../../Viewport';
|
7
7
|
import { TextRendererLocalization } from '../localization';
|
8
8
|
import RenderingStyle from '../RenderingStyle';
|
@@ -12,6 +12,9 @@ import AbstractRenderer from './AbstractRenderer';
|
|
12
12
|
|
13
13
|
export default class TextOnlyRenderer extends AbstractRenderer {
|
14
14
|
private descriptionBuilder: string[] = [];
|
15
|
+
private pathCount: number = 0;
|
16
|
+
private textNodeCount: number = 0;
|
17
|
+
|
15
18
|
public constructor(viewport: Viewport, private localizationTable: TextRendererLocalization) {
|
16
19
|
super(viewport);
|
17
20
|
}
|
@@ -23,15 +26,22 @@ export default class TextOnlyRenderer extends AbstractRenderer {
|
|
23
26
|
|
24
27
|
public clear(): void {
|
25
28
|
this.descriptionBuilder = [];
|
29
|
+
this.pathCount = 0;
|
30
|
+
this.textNodeCount = 0;
|
26
31
|
}
|
27
32
|
|
28
33
|
public getDescription(): string {
|
29
|
-
return
|
34
|
+
return [
|
35
|
+
this.localizationTable.pathNodeCount(this.pathCount),
|
36
|
+
this.localizationTable.textNodeCount(this.textNodeCount),
|
37
|
+
...this.descriptionBuilder
|
38
|
+
].join('\n');
|
30
39
|
}
|
31
40
|
|
32
41
|
protected beginPath(_startPoint: Vec3): void {
|
33
42
|
}
|
34
43
|
protected endPath(_style: RenderingStyle): void {
|
44
|
+
this.pathCount ++;
|
35
45
|
}
|
36
46
|
protected lineTo(_point: Vec3): void {
|
37
47
|
}
|
@@ -43,9 +53,10 @@ export default class TextOnlyRenderer extends AbstractRenderer {
|
|
43
53
|
}
|
44
54
|
public drawText(text: string, _transform: Mat33, _style: TextStyle): void {
|
45
55
|
this.descriptionBuilder.push(this.localizationTable.textNode(text));
|
56
|
+
this.textNodeCount ++;
|
46
57
|
}
|
47
58
|
public isTooSmallToRender(rect: Rect2): boolean {
|
48
|
-
return rect.maxDimension <
|
59
|
+
return rect.maxDimension < 15 / this.getSizeOfCanvasPixelOnScreen();
|
49
60
|
}
|
50
61
|
public drawPoints(..._points: Vec3[]): void {
|
51
62
|
}
|
@@ -138,13 +138,13 @@ export default class HTMLToolbar {
|
|
138
138
|
undoRedoGroup.classList.add(`${toolbarCSSPrefix}buttonGroup`);
|
139
139
|
|
140
140
|
const undoButton = this.addActionButton({
|
141
|
-
label:
|
141
|
+
label: this.localizationTable.undo,
|
142
142
|
icon: makeUndoIcon()
|
143
143
|
}, () => {
|
144
144
|
this.editor.history.undo();
|
145
145
|
}, undoRedoGroup);
|
146
146
|
const redoButton = this.addActionButton({
|
147
|
-
label:
|
147
|
+
label: this.localizationTable.redo,
|
148
148
|
icon: makeRedoIcon(),
|
149
149
|
}, () => {
|
150
150
|
this.editor.history.redo();
|
@@ -200,12 +200,9 @@ export default class HTMLToolbar {
|
|
200
200
|
(new TextToolWidget(this.editor, tool, this.localizationTable)).addTo(this.container);
|
201
201
|
}
|
202
202
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
}
|
207
|
-
|
208
|
-
(new HandToolWidget(this.editor, tool, this.localizationTable)).addTo(this.container);
|
203
|
+
const panZoomTool = toolController.getMatchingTools(ToolType.PanZoom)[0];
|
204
|
+
if (panZoomTool && panZoomTool instanceof PanZoom) {
|
205
|
+
(new HandToolWidget(this.editor, panZoomTool, this.localizationTable)).addTo(this.container);
|
209
206
|
}
|
210
207
|
|
211
208
|
this.setupColorPickers();
|
package/src/toolbar/icons.ts
CHANGED
@@ -2,18 +2,18 @@ import Color4 from '../Color4';
|
|
2
2
|
import { ComponentBuilderFactory } from '../components/builders/types';
|
3
3
|
import { TextStyle } from '../components/Text';
|
4
4
|
import EventDispatcher from '../EventDispatcher';
|
5
|
-
import { Vec2 } from '../
|
5
|
+
import { Vec2 } from '../math/Vec2';
|
6
6
|
import SVGRenderer from '../rendering/renderers/SVGRenderer';
|
7
7
|
import Pen from '../tools/Pen';
|
8
8
|
import { StrokeDataPoint } from '../types';
|
9
9
|
import Viewport from '../Viewport';
|
10
10
|
|
11
11
|
const svgNamespace = 'http://www.w3.org/2000/svg';
|
12
|
-
const
|
13
|
-
style='fill: var(--
|
12
|
+
const iconColorFill = `
|
13
|
+
style='fill: var(--icon-color);'
|
14
14
|
`;
|
15
|
-
const
|
16
|
-
style='fill: var(--
|
15
|
+
const iconColorStrokeFill = `
|
16
|
+
style='fill: var(--icon-color); stroke: var(--icon-color);'
|
17
17
|
`;
|
18
18
|
const checkerboardPatternDef = `
|
19
19
|
<pattern
|
@@ -39,7 +39,7 @@ export const makeRedoIcon = (mirror: boolean = false) => {
|
|
39
39
|
icon.innerHTML = `
|
40
40
|
<style>
|
41
41
|
.toolbar-svg-undo-redo-icon {
|
42
|
-
stroke: var(--
|
42
|
+
stroke: var(--icon-color);
|
43
43
|
stroke-width: 12;
|
44
44
|
stroke-linejoin: round;
|
45
45
|
stroke-linecap: round;
|
@@ -63,7 +63,7 @@ export const makeDropdownIcon = () => {
|
|
63
63
|
<g>
|
64
64
|
<path
|
65
65
|
d='M5,10 L50,90 L95,10 Z'
|
66
|
-
${
|
66
|
+
${iconColorFill}
|
67
67
|
/>
|
68
68
|
</g>
|
69
69
|
`;
|
@@ -80,7 +80,7 @@ export const makeEraserIcon = () => {
|
|
80
80
|
<rect x=10 y=50 width=80 height=30 rx=10 fill='pink' />
|
81
81
|
<rect
|
82
82
|
x=10 y=10 width=80 height=50
|
83
|
-
${
|
83
|
+
${iconColorFill}
|
84
84
|
/>
|
85
85
|
</g>
|
86
86
|
`;
|
@@ -103,152 +103,141 @@ export const makeSelectionIcon = () => {
|
|
103
103
|
return icon;
|
104
104
|
};
|
105
105
|
|
106
|
-
|
106
|
+
const pathIcon = (
|
107
|
+
pathData: string,
|
108
|
+
fill: string = 'var(--icon-color)',
|
109
|
+
strokeColor: string = 'none',
|
110
|
+
strokeWidth: string = '0px',
|
111
|
+
) => {
|
107
112
|
const icon = document.createElementNS(svgNamespace, 'svg');
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
5,30
|
115
|
-
H 90
|
116
|
-
V 30
|
117
|
-
C 90,20 75,20 75,30
|
118
|
-
V 60
|
119
|
-
20
|
120
|
-
C 75,10 60,10 60,20
|
121
|
-
V 60
|
122
|
-
15
|
123
|
-
C 60,5 45,5 45,15
|
124
|
-
V 60
|
125
|
-
25
|
126
|
-
C 45,15 30,15 30,25
|
127
|
-
V 60
|
128
|
-
75
|
129
|
-
L 25,60
|
130
|
-
C 20,45 10,50 10,60
|
131
|
-
Z'
|
132
|
-
|
133
|
-
fill='none'
|
134
|
-
style='
|
135
|
-
stroke: var(--primary-foreground-color);
|
136
|
-
stroke-width: 2;
|
137
|
-
'
|
138
|
-
/>
|
139
|
-
</g>
|
140
|
-
`;
|
113
|
+
const path = document.createElementNS(svgNamespace, 'path');
|
114
|
+
path.setAttribute('d', pathData);
|
115
|
+
path.style.fill = fill;
|
116
|
+
path.style.stroke = strokeColor;
|
117
|
+
path.style.strokeWidth = strokeWidth;
|
118
|
+
icon.appendChild(path);
|
141
119
|
icon.setAttribute('viewBox', '0 0 100 100');
|
120
|
+
|
142
121
|
return icon;
|
143
122
|
};
|
144
123
|
|
124
|
+
export const makeHandToolIcon = () => {
|
125
|
+
const fill = 'none';
|
126
|
+
const strokeColor = 'var(--icon-color)';
|
127
|
+
const strokeWidth = '3';
|
128
|
+
|
129
|
+
// Draw a cursor-like shape (like some of the other icons, made with Inkscape)
|
130
|
+
return pathIcon(`
|
131
|
+
m 10,60
|
132
|
+
5,30
|
133
|
+
H 90
|
134
|
+
V 30
|
135
|
+
C 90,20 75,20 75,30
|
136
|
+
V 60
|
137
|
+
20
|
138
|
+
C 75,10 60,10 60,20
|
139
|
+
V 60
|
140
|
+
15
|
141
|
+
C 60,5 45,5 45,15
|
142
|
+
V 60
|
143
|
+
25
|
144
|
+
C 45,15 30,15 30,25
|
145
|
+
V 60
|
146
|
+
75
|
147
|
+
L 25,60
|
148
|
+
C 20,45 10,50 10,60
|
149
|
+
Z
|
150
|
+
`, fill, strokeColor, strokeWidth);
|
151
|
+
};
|
152
|
+
|
145
153
|
export const makeTouchPanningIcon = () => {
|
146
|
-
const
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
m 33.75,0
|
156
|
-
L 50,17
|
157
|
-
V 5.5
|
158
|
-
Z
|
159
|
-
|
160
|
-
M 5,40.7
|
161
|
-
v 11.7
|
162
|
-
h 11.25
|
163
|
-
z
|
164
|
-
|
165
|
-
M 26,19
|
166
|
-
C 19.8,19.4 17.65,30.4 21.9,34.8
|
167
|
-
L 50,70
|
168
|
-
H 27.5
|
169
|
-
c -11.25,0 -11.25,17.6 0,17.6
|
170
|
-
H 61.25
|
171
|
-
C 94.9,87.8 95,87.6 95,40.7 78.125,23 67,29 55.6,46.5
|
172
|
-
L 33.1,23
|
173
|
-
C 30.3125,20.128192 27.9,19 25.830078,19.119756
|
174
|
-
Z
|
175
|
-
'
|
176
|
-
fill='none'
|
177
|
-
style='
|
178
|
-
stroke: var(--primary-foreground-color);
|
179
|
-
stroke-width: 2;
|
180
|
-
'
|
181
|
-
/>
|
182
|
-
`;
|
154
|
+
const fill = 'none';
|
155
|
+
const strokeColor = 'var(--icon-color)';
|
156
|
+
const strokeWidth = '3';
|
157
|
+
|
158
|
+
return pathIcon(`
|
159
|
+
M 5,5.5
|
160
|
+
V 17.2
|
161
|
+
L 16.25,5.46
|
162
|
+
Z
|
183
163
|
|
184
|
-
|
185
|
-
|
164
|
+
m 33.75,0
|
165
|
+
L 50,17
|
166
|
+
V 5.5
|
167
|
+
Z
|
168
|
+
|
169
|
+
M 5,40.7
|
170
|
+
v 11.7
|
171
|
+
h 11.25
|
172
|
+
z
|
173
|
+
|
174
|
+
M 26,19
|
175
|
+
C 19.8,19.4 17.65,30.4 21.9,34.8
|
176
|
+
L 50,70
|
177
|
+
H 27.5
|
178
|
+
c -11.25,0 -11.25,17.6 0,17.6
|
179
|
+
H 61.25
|
180
|
+
C 94.9,87.8 95,87.6 95,40.7 78.125,23 67,29 55.6,46.5
|
181
|
+
L 33.1,23
|
182
|
+
C 30.3125,20.128192 27.9,19 25.830078,19.119756
|
183
|
+
Z
|
184
|
+
`, fill, strokeColor, strokeWidth);
|
186
185
|
};
|
187
186
|
|
188
187
|
export const makeAllDevicePanningIcon = () => {
|
189
|
-
const
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
fill='none'
|
243
|
-
style='
|
244
|
-
stroke: var(--primary-foreground-color);
|
245
|
-
stroke-width: 2;
|
246
|
-
'
|
247
|
-
/>
|
248
|
-
`;
|
249
|
-
|
250
|
-
icon.setAttribute('viewBox', '0 0 100 100');
|
251
|
-
return icon;
|
188
|
+
const fill = 'none';
|
189
|
+
const strokeColor = 'var(--icon-color)';
|
190
|
+
const strokeWidth = '3';
|
191
|
+
return pathIcon(`
|
192
|
+
M 5 5
|
193
|
+
L 5 17.5
|
194
|
+
17.5 5
|
195
|
+
5 5
|
196
|
+
z
|
197
|
+
|
198
|
+
M 42.5 5
|
199
|
+
L 55 17.5
|
200
|
+
55 5
|
201
|
+
42.5 5
|
202
|
+
z
|
203
|
+
|
204
|
+
M 70 10
|
205
|
+
L 70 21
|
206
|
+
61 15
|
207
|
+
55.5 23
|
208
|
+
66 30
|
209
|
+
56 37
|
210
|
+
61 45
|
211
|
+
70 39
|
212
|
+
70 50
|
213
|
+
80 50
|
214
|
+
80 39
|
215
|
+
89 45
|
216
|
+
95 36
|
217
|
+
84 30
|
218
|
+
95 23
|
219
|
+
89 15
|
220
|
+
80 21
|
221
|
+
80 10
|
222
|
+
70 10
|
223
|
+
z
|
224
|
+
|
225
|
+
M 27.5 26.25
|
226
|
+
L 27.5 91.25
|
227
|
+
L 43.75 83.125
|
228
|
+
L 52 99
|
229
|
+
L 68 91
|
230
|
+
L 60 75
|
231
|
+
L 76.25 66.875
|
232
|
+
L 27.5 26.25
|
233
|
+
z
|
234
|
+
|
235
|
+
M 5 42.5
|
236
|
+
L 5 55
|
237
|
+
L 17.5 55
|
238
|
+
L 5 42.5
|
239
|
+
z
|
240
|
+
`, fill, strokeColor, strokeWidth);
|
252
241
|
};
|
253
242
|
|
254
243
|
export const makeZoomIcon = () => {
|
@@ -263,7 +252,7 @@ export const makeZoomIcon = () => {
|
|
263
252
|
textNode.style.textAlign = 'center';
|
264
253
|
textNode.style.textAnchor = 'middle';
|
265
254
|
textNode.style.fontSize = '55px';
|
266
|
-
textNode.style.fill = 'var(--
|
255
|
+
textNode.style.fill = 'var(--icon-color)';
|
267
256
|
textNode.style.fontFamily = 'monospace';
|
268
257
|
|
269
258
|
icon.appendChild(textNode);
|
@@ -315,7 +304,7 @@ export const makePenIcon = (tipThickness: number, color: string) => {
|
|
315
304
|
<!-- Pen grip -->
|
316
305
|
<path
|
317
306
|
d='M10,10 L90,10 L90,60 L${50 + halfThickness},80 L${50 - halfThickness},80 L10,60 Z'
|
318
|
-
${
|
307
|
+
${iconColorStrokeFill}
|
319
308
|
/>
|
320
309
|
</g>
|
321
310
|
<g>
|
@@ -389,7 +378,7 @@ export const makePipetteIcon = (color?: Color4) => {
|
|
389
378
|
65,15 65,5 47,6
|
390
379
|
Z
|
391
380
|
`);
|
392
|
-
pipette.style.fill = 'var(--
|
381
|
+
pipette.style.fill = 'var(--icon-color)';
|
393
382
|
|
394
383
|
if (color) {
|
395
384
|
const defs = document.createElementNS(svgNamespace, 'defs');
|
@@ -417,3 +406,34 @@ export const makePipetteIcon = (color?: Color4) => {
|
|
417
406
|
icon.setAttribute('viewBox', '0 0 100 100');
|
418
407
|
return icon;
|
419
408
|
};
|
409
|
+
|
410
|
+
export const makeResizeViewportIcon = () => {
|
411
|
+
return pathIcon(`
|
412
|
+
M 75 5 75 10 90 10 90 25 95 25 95 5 75 5 z
|
413
|
+
M 15 15 15 30 20 30 20 20 30 20 30 15 15 15 z
|
414
|
+
M 84 15 82 17 81 16 81 20 85 20 84 19 86 17 84 15 z
|
415
|
+
M 26 24 24 26 26 28 25 29 29 29 29 25 28 26 26 24 z
|
416
|
+
M 25 71 26 72 24 74 26 76 28 74 29 75 29 71 25 71 z
|
417
|
+
M 15 75 15 85 25 85 25 80 20 80 20 75 15 75 z
|
418
|
+
M 90 75 90 90 75 90 75 95 95 95 95 75 90 75 z
|
419
|
+
M 81 81 81 85 82 84 84 86 86 84 84 82 85 81 81 81 z
|
420
|
+
`);
|
421
|
+
};
|
422
|
+
|
423
|
+
export const makeDuplicateSelectionIcon = () => {
|
424
|
+
return pathIcon(`
|
425
|
+
M 45,10 45,55 90,55 90,10 45,10 z
|
426
|
+
M 10,25 10,90 70,90 70,60 40,60 40,25 10,25 z
|
427
|
+
`);
|
428
|
+
};
|
429
|
+
|
430
|
+
export const makeDeleteSelectionIcon = () => {
|
431
|
+
const strokeWidth = '5px';
|
432
|
+
const strokeColor = 'var(--icon-color)';
|
433
|
+
const fillColor = 'none';
|
434
|
+
|
435
|
+
return pathIcon(`
|
436
|
+
M 10,10 90,90
|
437
|
+
M 10,90 90,10
|
438
|
+
`, fillColor, strokeColor, strokeWidth);
|
439
|
+
};
|