(host: GraphHost)
| 127 | // ─── Public functions: install + small handlers ────────────────────────── |
| 128 | |
| 129 | export function installGraph(host: GraphHost): void { |
| 130 | const { SocialCalc, win, doc } = host; |
| 131 | const palette = makePalette(); |
| 132 | |
| 133 | function updateGraphRangeProposal(editor: { |
| 134 | range: { hasrange: boolean; left: number; top: number; right: number; bottom: number }; |
| 135 | }): void { |
| 136 | const ss = SocialCalc.GetSpreadsheetControlObject?.(); |
| 137 | if (!ss?.idPrefix) return; |
| 138 | const ele = doc.getElementById(ss.idPrefix + 'graphlist') as HTMLSelectElement | null; |
| 139 | if (!ele || !ele.options[0]) return; |
| 140 | if (editor.range.hasrange) { |
| 141 | ele.options[0].text = |
| 142 | SocialCalc.crToCoord!(editor.range.left, editor.range.top) + |
| 143 | ':' + |
| 144 | SocialCalc.crToCoord!(editor.range.right, editor.range.bottom); |
| 145 | } else { |
| 146 | ele.options[0].text = SocialCalc.LocalizeString?.('[select range]') ?? '[select range]'; |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | const onClick: GraphOnClickFn = (s) => { |
| 151 | palette.reset(); |
| 152 | const SCLoc = SocialCalc.LocalizeString ?? ((x: string) => x); |
| 153 | const namelist: string[] = []; |
| 154 | const nl = doc.getElementById((s.idPrefix ?? '') + 'graphlist') as HTMLSelectElement | null; |
| 155 | // Refresh range proposal when the user drags a new selection. |
| 156 | (s.editor as unknown as { RangeChangeCallback: Record<string, unknown> }).RangeChangeCallback.graph = |
| 157 | updateGraphRangeProposal; |
| 158 | for (const name of Object.keys(s.sheet.names ?? {})) namelist.push(name); |
| 159 | namelist.sort(); |
| 160 | if (!nl) return; |
| 161 | nl.length = 0; |
| 162 | nl.options[0] = new Option(SCLoc('[select range]')); |
| 163 | for (let i = 0; i < namelist.length; i++) { |
| 164 | const name = namelist[i]!; |
| 165 | nl.options[i + 1] = new Option(name, name); |
| 166 | if (name === s.graphrange) nl.options[i + 1]!.selected = true; |
| 167 | } |
| 168 | if (s.graphrange === '') nl.options[0]!.selected = true; |
| 169 | updateGraphRangeProposal(s.editor as unknown as Parameters<typeof updateGraphRangeProposal>[0]); |
| 170 | const tnl = doc.getElementById((s.idPrefix ?? '') + 'graphtype') as HTMLSelectElement | null; |
| 171 | if (!tnl) return; |
| 172 | tnl.length = 0; |
| 173 | const gti = SocialCalc.GraphTypesInfo!; |
| 174 | for (let i = 0; i < gti.displayorder.length; i++) { |
| 175 | const name = gti.displayorder[i]!; |
| 176 | const info = gti[name] as { display: string; func: GraphDrawFn }; |
| 177 | tnl.options[i] = new Option(SCLoc(info.display), name); |
| 178 | if (name === s.graphtype) tnl.options[i]!.selected = true; |
| 179 | } |
| 180 | if (!s.graphtype) { |
| 181 | tnl.options[0]!.selected = true; |
| 182 | s.graphtype = tnl.options[0]!.value; |
| 183 | } |
| 184 | doGraph(false, true); |
| 185 | }; |
| 186 |
no test coverage detected