@elicdavis/node-flow 0.1.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.
- package/.github/workflows/deploy.yml +57 -0
- package/README.md +159 -0
- package/dev.tsconfig.json +18 -0
- package/docs/promotional-image.png +0 -0
- package/esbuild.ts +32 -0
- package/index.html +311 -0
- package/package.json +50 -0
- package/src/camera.ts +30 -0
- package/src/connection.ts +249 -0
- package/src/contextMenu.ts +367 -0
- package/src/draggable.ts +13 -0
- package/src/elements/base.ts +192 -0
- package/src/elements/container.ts +119 -0
- package/src/elements/interfaces.ts +50 -0
- package/src/elements/text.ts +86 -0
- package/src/graph.ts +535 -0
- package/src/graphSubsystem.ts +31 -0
- package/src/index.ts +28 -0
- package/src/input.ts +153 -0
- package/src/markdown/entry.ts +323 -0
- package/src/markdown/lexicalParser.ts +148 -0
- package/src/markdown/markdown.ts +14 -0
- package/src/markdown/syntaxParser.ts +344 -0
- package/src/markdown/token.ts +43 -0
- package/src/metadata.ts +3 -0
- package/src/node.ts +1130 -0
- package/src/nodes/factory.ts +87 -0
- package/src/nodes/publisher.ts +98 -0
- package/src/nodes/subsystem.ts +760 -0
- package/src/notes/note.ts +295 -0
- package/src/notes/subsystem.ts +262 -0
- package/src/organize.ts +181 -0
- package/src/pass/subsystem.ts +64 -0
- package/src/performance.ts +9 -0
- package/src/popup.ts +81 -0
- package/src/popups/form.ts +63 -0
- package/src/popups/string.ts +33 -0
- package/src/port.ts +223 -0
- package/src/quickMenu.ts +330 -0
- package/src/styles/box.ts +104 -0
- package/src/styles/canvasTextAlign.ts +8 -0
- package/src/styles/canvasTextBaseline.ts +9 -0
- package/src/styles/cursor.ts +18 -0
- package/src/styles/stroke.ts +39 -0
- package/src/styles/text.ts +90 -0
- package/src/styles/textBox.ts +82 -0
- package/src/theme.ts +78 -0
- package/src/types/box.ts +126 -0
- package/src/types/list.ts +41 -0
- package/src/types/pool.ts +66 -0
- package/src/types/text.ts +136 -0
- package/src/types/vector2.ts +34 -0
- package/src/utils/color.ts +136 -0
- package/src/utils/html.ts +21 -0
- package/src/utils/math.ts +8 -0
- package/src/utils/string.ts +98 -0
- package/src/widgets/button.ts +107 -0
- package/src/widgets/color.ts +151 -0
- package/src/widgets/factory.ts +46 -0
- package/src/widgets/image.ts +163 -0
- package/src/widgets/number.ts +153 -0
- package/src/widgets/slider.ts +216 -0
- package/src/widgets/string.ts +128 -0
- package/src/widgets/text.ts +92 -0
- package/src/widgets/toggle.ts +205 -0
- package/src/widgets/widget.ts +12 -0
- package/tsconfig.json +15 -0
- package/tsup.config.ts +10 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { Vector2 } from "../types/vector2";
|
|
2
|
+
import { Border, BorderStyling, InstantiateRenderElementSidesStyling, IRenderElement, RenderElementSides, RenderElementSidesStyling } from "./interfaces";
|
|
3
|
+
|
|
4
|
+
export enum Display {
|
|
5
|
+
Flex = "flex",
|
|
6
|
+
None = "none"
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface RenderElementBaseStyling {
|
|
10
|
+
Margin?: RenderElementSidesStyling | number;
|
|
11
|
+
Padding?: RenderElementSidesStyling | number;
|
|
12
|
+
Border?: BorderStyling;
|
|
13
|
+
BackgroundColor?: string;
|
|
14
|
+
MinWidth?: number;
|
|
15
|
+
MaxWidth?: number;
|
|
16
|
+
MaxHeight?: number;
|
|
17
|
+
MinHeight?: number;
|
|
18
|
+
Grow?: number;
|
|
19
|
+
Display?: Display;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export abstract class RenderElementBase implements IRenderElement {
|
|
23
|
+
|
|
24
|
+
#margin: RenderElementSides;
|
|
25
|
+
|
|
26
|
+
#padding: RenderElementSides;
|
|
27
|
+
|
|
28
|
+
#border: Border;
|
|
29
|
+
|
|
30
|
+
#backgroundColor?: string;
|
|
31
|
+
|
|
32
|
+
#minWidth?: number;
|
|
33
|
+
|
|
34
|
+
#maxWidth?: number;
|
|
35
|
+
|
|
36
|
+
#minHeight?: number;
|
|
37
|
+
|
|
38
|
+
#maxHeight?: number;
|
|
39
|
+
|
|
40
|
+
#grow?: number;
|
|
41
|
+
|
|
42
|
+
#display: Display;
|
|
43
|
+
|
|
44
|
+
constructor(config?: RenderElementBaseStyling) {
|
|
45
|
+
this.#margin = InstantiateRenderElementSidesStyling(config?.Margin);
|
|
46
|
+
this.#padding = InstantiateRenderElementSidesStyling(config?.Padding);
|
|
47
|
+
this.#backgroundColor = config?.BackgroundColor;
|
|
48
|
+
this.#border = {
|
|
49
|
+
Color: config?.Border?.Color ?? "black",
|
|
50
|
+
Thickness: config?.Border?.Thickness ?? 0,
|
|
51
|
+
Radius: config?.Border?.Radius ?? 0,
|
|
52
|
+
}
|
|
53
|
+
this.#minWidth = config?.MinWidth;
|
|
54
|
+
this.#maxWidth = config?.MaxWidth;
|
|
55
|
+
this.#minHeight = config?.MinHeight;
|
|
56
|
+
this.#maxHeight = config?.MaxHeight;
|
|
57
|
+
this.#grow = config?.Grow;
|
|
58
|
+
this.#display = config?.Display ?? Display.Flex;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
setBackgroundColor(newColor: string): void {
|
|
62
|
+
this.#backgroundColor = newColor;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
abstract doRender(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void;
|
|
66
|
+
|
|
67
|
+
render(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void {
|
|
68
|
+
if (this.#display === Display.None) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const scaledSize = { x: 0, y: 0 };
|
|
73
|
+
this.size(ctx, scaledSize);
|
|
74
|
+
|
|
75
|
+
scaledSize.x = scaledSize.x * graphScale;
|
|
76
|
+
scaledSize.y = scaledSize.y * graphScale;
|
|
77
|
+
scaledSize.x = Math.max(scaledSize.x, scaledFillableSpace.x);
|
|
78
|
+
scaledSize.y = Math.max(scaledSize.y, scaledFillableSpace.y);
|
|
79
|
+
|
|
80
|
+
if (this.#backgroundColor) {
|
|
81
|
+
ctx.fillStyle = this.#backgroundColor;
|
|
82
|
+
ctx.beginPath();
|
|
83
|
+
ctx.roundRect(
|
|
84
|
+
position.x + (this.#margin.Left * graphScale),
|
|
85
|
+
position.y + (this.#margin.Right * graphScale),
|
|
86
|
+
scaledSize.x - ((this.#margin.Left + this.#margin.Right) * graphScale),
|
|
87
|
+
scaledSize.y - ((this.#margin.Top + this.#margin.Bottom) * graphScale),
|
|
88
|
+
this.#border.Radius * graphScale
|
|
89
|
+
);
|
|
90
|
+
ctx.fill();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (this.#border.Thickness > 0) {
|
|
94
|
+
ctx.lineWidth = this.#border.Thickness * graphScale;
|
|
95
|
+
ctx.strokeStyle = this.#border.Color;
|
|
96
|
+
ctx.stroke();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const offsetPosition = {
|
|
100
|
+
x: position.x + (this.#totalLeftOffset() * graphScale),
|
|
101
|
+
y: position.y + (this.#totalTopOffset() * graphScale),
|
|
102
|
+
};
|
|
103
|
+
const elementSize = {
|
|
104
|
+
x: scaledSize.x - (this.#horizontalOffset() * graphScale),
|
|
105
|
+
y: scaledSize.y - (this.#verticalOffset() * graphScale)
|
|
106
|
+
}
|
|
107
|
+
this.doRender(ctx, offsetPosition, graphScale, elementSize);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
abstract calcSize(ctx: CanvasRenderingContext2D, out: Vector2, limitations: Vector2): void;
|
|
111
|
+
|
|
112
|
+
protected maxLimitations(out: Vector2): void {
|
|
113
|
+
out.x = -1;
|
|
114
|
+
out.y = -1;
|
|
115
|
+
|
|
116
|
+
if (this.#maxWidth) {
|
|
117
|
+
out.x = this.#maxWidth;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (this.#maxHeight) {
|
|
121
|
+
out.y = this.#maxHeight;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
setDisplay(display: Display): void {
|
|
126
|
+
this.#display = display;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
getDisplay(): Display {
|
|
130
|
+
return this.#display;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
size(ctx: CanvasRenderingContext2D, out: Vector2): void {
|
|
134
|
+
out.x = 0;
|
|
135
|
+
out.y = 0;
|
|
136
|
+
if (this.#display === Display.None) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const maxLimits = { x: -1, y: -1 }
|
|
141
|
+
this.maxLimitations(maxLimits);
|
|
142
|
+
|
|
143
|
+
this.calcSize(ctx, out, maxLimits);
|
|
144
|
+
|
|
145
|
+
out.x += this.#horizontalOffset();
|
|
146
|
+
out.y += this.#verticalOffset();
|
|
147
|
+
|
|
148
|
+
if (this.#minWidth) {
|
|
149
|
+
out.x = Math.max(out.x, this.#minWidth)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (this.#maxWidth) {
|
|
153
|
+
out.x = Math.min(this.#maxWidth, out.x);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (this.#maxHeight) {
|
|
157
|
+
out.y = Math.min(this.#maxHeight, out.y);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (this.#minHeight) {
|
|
161
|
+
out.y = Math.max(this.#minHeight, out.y);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
#horizontalOffset(): number {
|
|
166
|
+
return (this.#border.Thickness) +
|
|
167
|
+
this.#margin.Left +
|
|
168
|
+
this.#margin.Right +
|
|
169
|
+
this.#padding.Left +
|
|
170
|
+
this.#padding.Right;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
#verticalOffset(): number {
|
|
174
|
+
return (this.#border.Thickness) +
|
|
175
|
+
this.#margin.Top +
|
|
176
|
+
this.#margin.Bottom +
|
|
177
|
+
this.#padding.Top +
|
|
178
|
+
this.#padding.Bottom;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
#totalTopOffset(): number {
|
|
182
|
+
return (this.#border.Thickness / 2) +
|
|
183
|
+
this.#margin.Top +
|
|
184
|
+
this.#padding.Top;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
#totalLeftOffset(): number {
|
|
188
|
+
return (this.#border.Thickness / 2) +
|
|
189
|
+
this.#margin.Left +
|
|
190
|
+
this.#padding.Left;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { ScaleVector, Vector2 } from '../types/vector2';
|
|
2
|
+
import { RenderElementBase, RenderElementBaseStyling } from "./base";
|
|
3
|
+
import { IRenderElement } from "./interfaces";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
interface ContainerRenderElementConfig extends RenderElementBaseStyling {
|
|
7
|
+
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export enum LayoutDirection {
|
|
11
|
+
Column = "column",
|
|
12
|
+
Row = "row"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export enum AlignItems {
|
|
16
|
+
Stretch = "stretch",
|
|
17
|
+
Start = "start",
|
|
18
|
+
Center = "center",
|
|
19
|
+
End = "end"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class ContainerRenderElement extends RenderElementBase {
|
|
23
|
+
|
|
24
|
+
#elements: Array<IRenderElement>;
|
|
25
|
+
|
|
26
|
+
#layout: LayoutDirection;
|
|
27
|
+
|
|
28
|
+
#alignment: AlignItems;
|
|
29
|
+
|
|
30
|
+
constructor(elements: Array<IRenderElement>, config?: ContainerRenderElementConfig) {
|
|
31
|
+
super(config);
|
|
32
|
+
this.#elements = elements;
|
|
33
|
+
this.#layout = LayoutDirection.Column;
|
|
34
|
+
this.#alignment = AlignItems.Stretch;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
calcSize(ctx: CanvasRenderingContext2D, out: Vector2, limitations: Vector2): void {
|
|
38
|
+
out.x = 0;
|
|
39
|
+
out.y = 0;
|
|
40
|
+
|
|
41
|
+
const eleSize = { x: 0, y: 0 };
|
|
42
|
+
|
|
43
|
+
switch (this.#layout) {
|
|
44
|
+
case LayoutDirection.Column:
|
|
45
|
+
for (let i = 0; i < this.#elements.length; i++) {
|
|
46
|
+
this.#elements[i].size(ctx, eleSize);
|
|
47
|
+
out.x = Math.max(out.x, eleSize.x);
|
|
48
|
+
out.y += eleSize.y;
|
|
49
|
+
}
|
|
50
|
+
break;
|
|
51
|
+
|
|
52
|
+
case LayoutDirection.Row:
|
|
53
|
+
for (let i = 0; i < this.#elements.length; i++) {
|
|
54
|
+
this.#elements[i].size(ctx, eleSize);
|
|
55
|
+
out.y = Math.max(out.y, eleSize.y);
|
|
56
|
+
out.x += eleSize.x;
|
|
57
|
+
}
|
|
58
|
+
break;
|
|
59
|
+
|
|
60
|
+
default:
|
|
61
|
+
throw new Error("unknown layout: " + this.#layout);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
doRender(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void {
|
|
67
|
+
// const size = { x: 0, y: 0 };
|
|
68
|
+
// const limitations = { x: 0, y: 0 };
|
|
69
|
+
// this.limitations(limitations)
|
|
70
|
+
// this.calcSize(ctx, size, limitations);
|
|
71
|
+
switch (this.#layout) {
|
|
72
|
+
case LayoutDirection.Column:
|
|
73
|
+
this.#renderColumn(ctx, position, graphScale, scaledFillableSpace);
|
|
74
|
+
break;
|
|
75
|
+
|
|
76
|
+
default:
|
|
77
|
+
throw new Error("unimplemented layout direction: " + this.#layout);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
#renderColumn(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void {
|
|
82
|
+
const currnetPos = { x: position.x, y: position.y };
|
|
83
|
+
const scaledEleSize = { x: 0, y: 0 };
|
|
84
|
+
for (let i = 0; i < this.#elements.length; i++) {
|
|
85
|
+
const ele = this.#elements[i];
|
|
86
|
+
|
|
87
|
+
ele.size(ctx, scaledEleSize);
|
|
88
|
+
ScaleVector(scaledEleSize, graphScale);
|
|
89
|
+
|
|
90
|
+
switch (this.#alignment) {
|
|
91
|
+
|
|
92
|
+
case AlignItems.Stretch:
|
|
93
|
+
currnetPos.x = position.x;
|
|
94
|
+
scaledEleSize.x = scaledFillableSpace.x;
|
|
95
|
+
break;
|
|
96
|
+
|
|
97
|
+
// I'm not sure if this is even needed, I feel like this should
|
|
98
|
+
// already be the case.
|
|
99
|
+
case AlignItems.Start: //garney flarney <---- silly goose steenky feet
|
|
100
|
+
currnetPos.x = position.x;
|
|
101
|
+
break
|
|
102
|
+
|
|
103
|
+
case AlignItems.End:
|
|
104
|
+
currnetPos.x = scaledFillableSpace.x - scaledEleSize.x
|
|
105
|
+
break;
|
|
106
|
+
|
|
107
|
+
case AlignItems.Center:
|
|
108
|
+
currnetPos.x = scaledFillableSpace.x - (scaledEleSize.x / 2)
|
|
109
|
+
break;
|
|
110
|
+
|
|
111
|
+
default:
|
|
112
|
+
throw new Error("unimplmeneted alignment: " + this.#alignment)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
ele.render(ctx, currnetPos, graphScale, scaledEleSize);
|
|
116
|
+
currnetPos.y += scaledEleSize.y;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Vector2 } from "../types/vector2"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export interface RenderElementSidesStyling {
|
|
5
|
+
Left?: number
|
|
6
|
+
Right?: number
|
|
7
|
+
Top?: number
|
|
8
|
+
Bottom?: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RenderElementSides {
|
|
12
|
+
Left: number
|
|
13
|
+
Right: number
|
|
14
|
+
Top: number
|
|
15
|
+
Bottom: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function InstantiateRenderElementSidesStyling(config?: RenderElementSidesStyling | number): RenderElementSides {
|
|
19
|
+
if (typeof config === 'number') {
|
|
20
|
+
return {
|
|
21
|
+
Bottom: config,
|
|
22
|
+
Right: config,
|
|
23
|
+
Top: config,
|
|
24
|
+
Left: config,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
Bottom: config?.Bottom === undefined ? 0 : config?.Bottom,
|
|
29
|
+
Right: config?.Right === undefined ? 0 : config?.Right,
|
|
30
|
+
Left: config?.Left === undefined ? 0 : config?.Left,
|
|
31
|
+
Top: config?.Top === undefined ? 0 : config?.Top,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface IRenderElement {
|
|
36
|
+
size(ctx: CanvasRenderingContext2D, out: Vector2): void;
|
|
37
|
+
render(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface Border {
|
|
41
|
+
Color: string;
|
|
42
|
+
Thickness: number;
|
|
43
|
+
Radius: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface BorderStyling {
|
|
47
|
+
Color?: string;
|
|
48
|
+
Thickness?: number;
|
|
49
|
+
Radius?: number;
|
|
50
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Text } from "../types/text";
|
|
2
|
+
import { CopyVector2, ScaleVector, Vector2, Zero } from "../types/vector2";
|
|
3
|
+
import { RenderElementBase, RenderElementBaseStyling } from "./base";
|
|
4
|
+
|
|
5
|
+
export enum TextAlign {
|
|
6
|
+
Left = "left",
|
|
7
|
+
Right = "right",
|
|
8
|
+
Center = "center",
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export enum VerticalAlign {
|
|
12
|
+
Top = "top",
|
|
13
|
+
Center = "center",
|
|
14
|
+
Bottom = "bottom"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface TextElementStyling extends RenderElementBaseStyling {
|
|
18
|
+
Align?: TextAlign
|
|
19
|
+
VerticalAlign?: VerticalAlign
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class TextElement extends RenderElementBase {
|
|
23
|
+
#text: Text;
|
|
24
|
+
|
|
25
|
+
#align: TextAlign;
|
|
26
|
+
|
|
27
|
+
#verticalAlign: VerticalAlign;
|
|
28
|
+
|
|
29
|
+
constructor(text: Text, styling?: TextElementStyling) {
|
|
30
|
+
super(styling);
|
|
31
|
+
this.#text = text;
|
|
32
|
+
this.#align = styling?.Align ?? TextAlign.Left;
|
|
33
|
+
this.#verticalAlign = styling?.VerticalAlign ?? VerticalAlign.Top;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
doRender(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void {
|
|
37
|
+
const scale = Zero();
|
|
38
|
+
this.calcSize(ctx, scale);
|
|
39
|
+
ScaleVector(scale, graphScale);
|
|
40
|
+
|
|
41
|
+
const justifiedPosition = Zero();
|
|
42
|
+
CopyVector2(justifiedPosition, position)
|
|
43
|
+
|
|
44
|
+
ctx.textAlign = "left";
|
|
45
|
+
ctx.textBaseline = "top"
|
|
46
|
+
|
|
47
|
+
switch (this.#align) {
|
|
48
|
+
case TextAlign.Left:
|
|
49
|
+
// Do nothing. This is default
|
|
50
|
+
break;
|
|
51
|
+
|
|
52
|
+
case TextAlign.Right:
|
|
53
|
+
justifiedPosition.x += scaledFillableSpace.x - scale.x;
|
|
54
|
+
break;
|
|
55
|
+
|
|
56
|
+
case TextAlign.Center:
|
|
57
|
+
justifiedPosition.x += (scaledFillableSpace.x - scale.x) / 2;
|
|
58
|
+
break;
|
|
59
|
+
|
|
60
|
+
default:
|
|
61
|
+
throw new Error("unimplemented justification: " + this.#align);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
switch (this.#verticalAlign) {
|
|
65
|
+
case VerticalAlign.Top:
|
|
66
|
+
// Do nothing. This is default
|
|
67
|
+
break;
|
|
68
|
+
|
|
69
|
+
case VerticalAlign.Bottom:
|
|
70
|
+
justifiedPosition.y += scaledFillableSpace.y - scale.y;
|
|
71
|
+
break;
|
|
72
|
+
|
|
73
|
+
case VerticalAlign.Center:
|
|
74
|
+
justifiedPosition.y += (scaledFillableSpace.y - scale.y) / 2;
|
|
75
|
+
break;
|
|
76
|
+
|
|
77
|
+
default:
|
|
78
|
+
throw new Error("unimplemented justification: " + this.#align);
|
|
79
|
+
}
|
|
80
|
+
this.#text.render(ctx, graphScale, justifiedPosition);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
calcSize(ctx: CanvasRenderingContext2D, out: Vector2): void {
|
|
84
|
+
this.#text.size(ctx, 1, out);
|
|
85
|
+
}
|
|
86
|
+
}
|