Mercurial > code > home > repos > light9
annotate web/timeline/brick_layout.ts @ 2439:06da5db2fafe
rewrite ascoltami to use the graph for more playback data
author | drewp@bigasterisk.com |
---|---|
date | Thu, 30 May 2024 01:08:07 -0700 |
parents | 4556eebe5d73 |
children |
rev | line source |
---|---|
2062 | 1 import { debug } from "debug"; |
2 import { sortBy } from "underscore"; | |
3 import { ViewState } from "viewstate"; | |
4 const log = debug("brick"); | |
5 | |
6 interface Placement { | |
7 row?: number; | |
8 prev?: number; | |
9 t0: number; | |
10 t1: number; | |
11 onRowChange: () => void; | |
12 } | |
13 | |
14 export class BrickLayout { | |
15 viewState: ViewState; | |
16 numRows: number; | |
17 noteRow: { [uri: string]: Placement }; | |
18 constructor(viewState: ViewState, numRows: number) { | |
19 this.viewState = viewState; | |
20 this.numRows = numRows; | |
21 this.noteRow = {}; // uristr: row, t0, t1, onRowChange | |
22 } | |
1771
792bf30de608
brick mode works. fix some refresh issues.
Drew Perttula <drewp@bigasterisk.com>
parents:
diff
changeset
|
23 |
2062 | 24 addNote(n: { uri: { value: string } }, onRowChange: any) { |
25 this.noteRow[n.uri.value] = { row: 0, t0: 0, t1: 0, onRowChange }; | |
26 } | |
27 | |
28 setNoteSpan(n: { uri: { value: string } }, t0: any, t1: any) { | |
29 this.noteRow[n.uri.value].t0 = t0; | |
30 this.noteRow[n.uri.value].t1 = t1; | |
31 this._recompute(); | |
32 } | |
33 | |
34 delNote(n: { uri: { value: string } }) { | |
35 delete this.noteRow[n.uri.value]; | |
36 this._recompute(); | |
37 } | |
38 | |
39 _recompute() { | |
40 for (let u in this.noteRow) { | |
41 const row = this.noteRow[u]; | |
42 row.prev = row.row; | |
43 row.row = undefined; | |
44 } | |
45 const overlap = (a: Placement, b: Placement) => a.t0 < b.t1 && a.t1 > b.t0; | |
1771
792bf30de608
brick mode works. fix some refresh issues.
Drew Perttula <drewp@bigasterisk.com>
parents:
diff
changeset
|
46 |
2062 | 47 const result = []; |
48 for (let u in this.noteRow) { | |
49 const row = this.noteRow[u]; | |
50 result.push({ dur: row.t1 - row.t0 + row.t0 * 0.0001, uri: u }); | |
51 } | |
52 const notesByWidth = sortBy(result, "dur"); | |
53 notesByWidth.reverse(); | |
1771
792bf30de608
brick mode works. fix some refresh issues.
Drew Perttula <drewp@bigasterisk.com>
parents:
diff
changeset
|
54 |
2062 | 55 for (let n of Array.from(notesByWidth)) { |
56 const blockedRows = new Set(); | |
57 for (let u in this.noteRow) { | |
58 const other = this.noteRow[u]; | |
59 if (other.row !== null) { | |
60 if (overlap(other, this.noteRow[n.uri])) { | |
61 blockedRows.add(other.row); | |
62 } | |
63 } | |
64 } | |
1771
792bf30de608
brick mode works. fix some refresh issues.
Drew Perttula <drewp@bigasterisk.com>
parents:
diff
changeset
|
65 |
2062 | 66 for (let r = 0; r < this.numRows; r++) { |
67 if (!blockedRows.has(r)) { | |
68 this.noteRow[n.uri].row = r; | |
69 break; | |
70 } | |
71 } | |
72 if (this.noteRow[n.uri].row === null) { | |
73 log(`warning: couldn't place ${n.uri}`); | |
74 this.noteRow[n.uri].row = 0; | |
75 } | |
76 if (this.noteRow[n.uri].row !== this.noteRow[n.uri].prev) { | |
77 this.noteRow[n.uri].onRowChange(); | |
78 } | |
79 } | |
80 } | |
81 | |
82 rowBottom(row: number) { | |
83 return this.viewState.rowsY() + 20 + 150 * row + 140; | |
84 } | |
85 | |
86 yForVFor(n: { uri: { value: string } }) { | |
87 const row = this.noteRow[n.uri.value].row; | |
88 if (row === undefined) { | |
89 throw new Error(); | |
90 } | |
91 const rowBottom = this.rowBottom(row); | |
92 const rowTop = rowBottom - 140; | |
93 return (v: number) => rowBottom + (rowTop - rowBottom) * v; | |
94 } | |
95 } |