-
Notifications
You must be signed in to change notification settings - Fork 3
/
Renderable.ts
125 lines (111 loc) · 3.35 KB
/
Renderable.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import type { PcbPlacementError, PcbTraceError } from "circuit-json"
export const orderedRenderPhases = [
"ReactSubtreesRender",
"InitializePortsFromChildren",
"CreateNetsFromProps",
"CreateTracesFromProps",
"CreateTraceHintsFromProps",
"SourceRender",
"SourceParentAttachment",
"PortDiscovery",
"PortMatching",
"SourceTraceRender",
"SchematicComponentRender",
"SchematicLayout",
"SchematicPortRender",
"SchematicTraceRender",
"PcbComponentRender",
"PcbPrimitiveRender",
"PcbFootprintLayout",
"PcbPortRender",
"PcbPortAttachment",
"PcbLayout",
"PcbTraceRender",
"PcbTraceHintRender",
"PcbRouteNetIslands",
"PcbComponentSizeCalculation",
"CadModelRender",
] as const
export type RenderPhase = (typeof orderedRenderPhases)[number]
export type RenderPhaseFn<K extends RenderPhase = RenderPhase> =
| `doInitial${K}`
| `update${K}`
| `remove${K}`
export type RenderPhaseStates = Record<RenderPhase, { initialized: boolean }>
export type RenderPhaseFunctions = {
[T in RenderPhaseFn]?: () => void
}
export type IRenderable = RenderPhaseFunctions & {
renderPhaseStates: RenderPhaseStates
runRenderPhase(phase: RenderPhase): void
runRenderPhaseForChildren(phase: RenderPhase): void
shouldBeRemoved: boolean
children: IRenderable[]
runRenderCycle(): void
}
let globalRenderCounter = 0
export abstract class Renderable implements IRenderable {
renderPhaseStates: RenderPhaseStates
shouldBeRemoved = false
children: IRenderable[]
/** PCB-only SMTPads, PlatedHoles, Holes, Silkscreen elements etc. */
isPcbPrimitive = false
/** Schematic-only, lines, boxes, indicators etc. */
isSchematicPrimitive = false
_renderId: string
constructor(props: any) {
this._renderId = `${globalRenderCounter++}`
this.children = []
this.renderPhaseStates = {} as RenderPhaseStates
for (const phase of orderedRenderPhases) {
this.renderPhaseStates[phase] = { initialized: false }
}
}
runRenderCycle() {
for (const renderPhase of orderedRenderPhases) {
this.runRenderPhaseForChildren(renderPhase)
this.runRenderPhase(renderPhase)
}
}
/**
* This runs all the render methods for a given phase, calling one of:
* - doInitial*
* - update*
* -remove*
* ...depending on the current state of the component.
*/
runRenderPhase(phase: RenderPhase) {
const isInitialized = this.renderPhaseStates[phase].initialized
if (!isInitialized && this.shouldBeRemoved) return
if (this.shouldBeRemoved && isInitialized) {
;(this as any)?.[`remove${phase}`]?.()
this.renderPhaseStates[phase].initialized = false
return
}
if (isInitialized) {
;(this as any)?.[`update${phase}`]?.()
return
}
;(this as any)?.[`doInitial${phase}`]?.()
this.renderPhaseStates[phase].initialized = true
}
runRenderPhaseForChildren(phase: RenderPhase): void {
for (const child of this.children) {
child.runRenderPhaseForChildren(phase)
child.runRenderPhase(phase)
}
}
renderError(
message:
| string
| Omit<PcbTraceError, "pcb_error_id">
| Omit<PcbPlacementError, "pcb_error_id">,
) {
// TODO add to render phase error list and try to add position or
// relationships etc.
if (typeof message === "string") {
throw new Error(message)
}
throw new Error(JSON.stringify(message, null, 2))
}
}