(ctx, w, h)
| 20 | } |
| 21 | |
| 22 | function paint(ctx, w, h) { |
| 23 | // Cream paper background. |
| 24 | ctx.fillStyle = theme.widget_base; |
| 25 | ctx.fillRect(0, 0, w, h); |
| 26 | |
| 27 | const n = datasets.length; |
| 28 | if (n === 0) return; |
| 29 | |
| 30 | // Header. |
| 31 | const headerH = 22; |
| 32 | ctx.fillStyle = theme.widget_text; |
| 33 | ctx.font = "bold 11px sans-serif"; |
| 34 | ctx.textAlign = "start"; |
| 35 | ctx.fillText("STATUS GRID", 14, 16); |
| 36 | ctx.fillStyle = theme.placeholder_text; |
| 37 | ctx.font = "10px sans-serif"; |
| 38 | ctx.textAlign = "end"; |
| 39 | ctx.fillText(n + " channels", w - 14, 16); |
| 40 | ctx.fillStyle = theme.widget_border; |
| 41 | ctx.fillRect(14, 20, w - 28, 1); |
| 42 | |
| 43 | const cols = Math.max(1, group.columns || Math.min(n, Math.max(1, Math.round(Math.sqrt(n * w / (h - headerH)))))); |
| 44 | const rows = Math.ceil(n / cols); |
| 45 | const padX = 14; |
| 46 | const padY = headerH + 6; |
| 47 | const gap = 8; |
| 48 | const cellW = (w - padX * 2 - gap * (cols - 1)) / cols; |
| 49 | const cellH = (h - padY - padX - gap * (rows - 1)) / rows; |
| 50 | |
| 51 | for (let i = 0; i < n; ++i) { |
| 52 | const r = Math.floor(i / cols); |
| 53 | const c = i % cols; |
| 54 | const x = padX + c * (cellW + gap); |
| 55 | const y = padY + r * (cellH + gap); |
| 56 | const ds = datasets[i]; |
| 57 | const status = status_color(ds); |
| 58 | |
| 59 | // Card with shadow. |
| 60 | ctx.fillStyle = theme.widget_border; |
| 61 | ctx.fillRect(x + 1, y + 2, cellW, cellH); |
| 62 | ctx.fillStyle = theme.alternate_base; |
| 63 | ctx.fillRect(x, y, cellW, cellH); |
| 64 | ctx.strokeStyle = theme.widget_border; |
| 65 | ctx.lineWidth = 1; |
| 66 | ctx.strokeRect(x + 0.5, y + 0.5, cellW - 1, cellH - 1); |
| 67 | |
| 68 | // Coloured accent strip on the left edge. |
| 69 | ctx.fillStyle = status.color; |
| 70 | ctx.fillRect(x, y, 4, cellH); |
| 71 | |
| 72 | // Status pill in the top-right corner. |
| 73 | const pillW = 38; |
| 74 | const pillH = 14; |
| 75 | ctx.fillStyle = status.color; |
| 76 | ctx.fillRect(x + cellW - pillW - 6, y + 6, pillW, pillH); |
| 77 | ctx.fillStyle = theme.highlighted_text; |
| 78 | ctx.font = "bold 9px sans-serif"; |
| 79 | ctx.textAlign = "center"; |
nothing calls this directly
no test coverage detected