From 0db0e118154b3802edf15d5baddf63e87dd5b4a0 Mon Sep 17 00:00:00 2001 From: flop Date: Fri, 22 May 2026 17:17:04 +0200 Subject: [PATCH] fix: multiple adjustments to rendering and updating fields --- ts/src/browser.ts | 140 +++++++++++++++++++++++++++++----------------- 1 file changed, 90 insertions(+), 50 deletions(-) diff --git a/ts/src/browser.ts b/ts/src/browser.ts index 9d5a4dd..591c16f 100644 --- a/ts/src/browser.ts +++ b/ts/src/browser.ts @@ -6,7 +6,6 @@ import * as MonoDisplay from "./index"; import { MonoDisplayFile } from "./file"; import { cycleTheme } from "./themes"; -import { ElementType } from "./types"; // Expose on globalThis (= window in browser, globalThis elsewhere) (globalThis as typeof globalThis & { MonoDisplay: typeof MonoDisplay }).MonoDisplay = MonoDisplay; @@ -20,8 +19,8 @@ let isDirty = false; // --- Element type definitions ------------------------------------------------ type ElFieldMeta = { key: string; label: string; type: string; default: any; full?: boolean }; -type ElFlagMeta = { key: string; label: string }; -const EL_FIELDS: Partial> = { +type ElFlagMeta = { key: string; label: string, default?: boolean; }; +const EL_FIELDS: Partial> = { Image2D: [ { key: 'xOffset', label: 'X offset', type: 'number', default: 0 }, { key: 'yOffset', label: 'Y offset', type: 'number', default: 0 }, { key: 'width', label: 'Width', type: 'number', default: W }, { key: 'height', label: 'Height', type: 'number', default: H }, @@ -59,11 +58,11 @@ const EL_FIELDS: Partial> = { { key: 'fontIndex', label: 'Font', type: 'font', default: 'Font 0' }, ], }; -const EL_FLAGS: Partial> = { +const EL_FLAGS: Partial> = { HScrollText: [{ key: 'endless', label: 'Endless' }, { key: 'invertDirection', label: 'Invert direction' }], - CurrentTime: [{ key: 'clock12h', label: '12h mode' }, { key: 'showHours', label: 'Show hours' }, { key: 'showSeconds', label: 'Show seconds' }], + CurrentTime: [{ key: 'clock12h', label: '12h mode' , default: false}, { key: 'showHours', label: 'Show hours', default:true}, { key: 'showSeconds', label: 'Show seconds' , default:true}], }; -const EL_TYPES: ElementType[] = Object.keys(EL_FIELDS).map((x: string) => MonoDisplay.StringToElementType[x as MonoDisplay.ElementTypeName]); +const EL_TYPES: MonoDisplay.ElementType[] = Object.keys(EL_FIELDS).map((x: string) => MonoDisplay.StringToElementType[x as MonoDisplay.ElementTypeName]); const DEFAULT_FONTS = [ "Font 1", @@ -129,20 +128,28 @@ function newSec() { flags: {}, }; } -function newEl(type: MonoDisplay.ElementType) { - const fields = {}; - (EL_FIELDS[type] || []).forEach(f => fields[f.k] = f.d); - const flags = {}; - (EL_FLAGS[type] || []).forEach(f => flags[f.k] = false); - return { type, fields, flags }; +function createNewElement(type: MonoDisplay.ElementType) : MonoDisplay.MonoFormatElement { + const fields:Record = {}; + (EL_FIELDS[MonoDisplay.ElementTypeToString[type]] as any[] || []) + .forEach((f: ElFieldMeta) => fields[f.key] = f.default); + const flags:Record = {}; + (EL_FLAGS[MonoDisplay.ElementTypeToString[type]] as any[] || []) + .forEach((f: ElFlagMeta) => flags[f.key] = f.default || false); + return { + type, + ...fields, + flags, + } as MonoDisplay.MonoFormatElement; } -function getSec(sectionIndex: number | null) { +function getSectionByIndex(sectionIndex: number | null): MonoDisplay.MonoFormatSection | undefined { return file.sections.find((s,index) => index === sectionIndex) } -function getEl(sectionIndex: number, elementIndex: number) { - const section = getSec(sectionIndex); - return section && "elements" in section && section.elements.find((e, index) => index == elementIndex) +function getElementByIndex(sectionIndex: number, elementIndex: number): MonoDisplay.MonoFormatElement | undefined { + const section = getSectionByIndex(sectionIndex); + if(section && "elements" in section) + return section.elements.find((e, index) => index == elementIndex) + return undefined; } // --- Mutations ---------------------------------------------------------------- @@ -159,27 +166,43 @@ function removeSection(sectionIndex:number) { } markDirty(); renderHTML(); triggerPreview(); } -function toggleSection(id) { - const s = getSec(id); if (!s) return; - s.open = !s.open; activeSecIndex = id; renderHTML(); updateMeta(); +function toggleSection(sectionIndex: number): void { + const s = getSectionByIndex(sectionIndex); + if (!s) return; + activeSecIndex = sectionIndex; + renderHTML(); + updateMeta(); } function setSectionFlag(flag, val) { if (!activeSecIndex) return; - const s = getSec(activeSecIndex); if (!s) return; - s.flags[flag] = val; markDirty(); triggerPreview(); + const s = getSectionByIndex(activeSecIndex); + if (!s) return; + s.flags[flag] = val; + markDirty(); + triggerPreview(); } -function addElement(sectionIndex:number) { - const s = getSec(secId); if (!s) return; - const el = newEl(EL_TYPES[0]); s.elements.push(el); - activeSecIndex = secId; activeElIndex = { secId, elId: el.id }; - markDirty(); renderHTML(); triggerPreview(); +function addElement(sectionIndex: number) { + const s = getSectionByIndex(sectionIndex); + if (!s) return; + if (!("elements" in s)) return; + s.elements.push(createNewElement(MonoDisplay.ElementType.HScrollText)); + activeElIndex = s.elements.length; + activeSecIndex = sectionIndex; + markDirty(); + renderHTML(); + triggerPreview(); } function removeElement(sectionIndex:number, elementIndex:number) { - const s = getSec(sectionIndex); if (!s) return; - s.elements = s.elements.filter(e => e.id !== elId); - if (activeElIndex && activeElIndex.secId === secId && activeElIndex.elId === elId) activeElIndex = null; - markDirty(); renderHTML(); triggerPreview(); + const s = getSectionByIndex(sectionIndex); + if (!s) return; + if (!("elements" in s)) return; + s.elements = s.elements.filter((e,i) => i != elementIndex); + if (activeElIndex) + activeElIndex = null; + markDirty(); + renderHTML(); + triggerPreview(); } function selectElement(sectionIndex:number, elementIndex:number) { activeSecIndex = sectionIndex; @@ -189,25 +212,33 @@ function selectElement(sectionIndex:number, elementIndex:number) { null : elementIndex; renderHTML(); } -function changeElType(sectionIndex:number, elementIndex:number, typeString: string) { - const el = getEl(sectionIndex, elementIndex); if (!el) return; - const type = MonoDisplay.StringToElementType[typeString as MonoDisplay.ElementTypeName]; - const fresh = newEl(type); - el.type = type; el.fields = fresh.fields; el.flags = fresh.flags; +function changeElType(sectionIndex:number, elementIndex:number, typeString: MonoDisplay.ElementTypeName) { + const el = getElementByIndex(sectionIndex, elementIndex); if (!el) return; + const fresh = createNewElement(MonoDisplay.StringToElementType[typeString]); + setElementByElement(el, fresh); markDirty(); renderHTML(); triggerPreview(); } + +function setElementByElement(el: MonoDisplay.MonoFormatElement, source:MonoDisplay.MonoFormatElement ) { + el.type = source.type; + for (const [key, value] of Object.entries(source)) { + (el as any)[key as any] = value; + } + return el; +} + function setElField(sectionIndex:number, elementIndex:number, key:string, val:any) { - const el = getEl(sectionIndex, elementIndex); if (!el) return; + const el = getElementByIndex(sectionIndex, elementIndex); if (!el) return; el[key] = val; markDirty(); triggerPreview(); } function setElFlag(sectionIndex:number, elementIndex:number, key:string, val:any) { - const el = getEl(sectionIndex, elementIndex); if (!el) return; + const el = getElementByIndex(sectionIndex, elementIndex); if (!el) return; el.flags[key] = val; markDirty(); triggerPreview(); } function setSectionType(sectionIndex: number, sectionType: string) { - const sec = getSec(sectionIndex); + const sec = getSectionByIndex(sectionIndex); if (sec) { sec.sectionType = MonoDisplay.StringToSectionType[sectionType as MonoDisplay.SectionTypeName]; if (sec.sectionType == MonoDisplay.SectionType.CustomFont) { @@ -404,22 +435,31 @@ function renderHTMLSection(sectionIndex: number) { case MonoDisplay.SectionType.ElementsTimespan: return `
-
+
${MonoDisplay.SectionTypeToString[section.sectionType]} ${section.elements.length} el
+${section.sectionType == MonoDisplay.SectionType.ElementsTimespan ? ` +
${ + Object.entries({ "Start Time": "startTimestamp", "Stop Time":"endTimestamp"}).map(([label, key]) => { + return `
+ + +
`; + }).join("") +}
`: ``} ${isOpen ? `
${section.elements.map((el: MonoDisplay.MonoFormatElement, index:number) => renderHTMLElement(sectionIndex, index, el)).join('')} - +
`: ''}
`; case MonoDisplay.SectionType.CustomFont: { return `
-
+
Custom Font 1 el @@ -528,18 +568,18 @@ ${isActive ? activeRender : ``} function elSummary(el: MonoDisplay.MonoFormatElement) { switch (el.type) { - case ElementType.ClippedText: - case ElementType.HScrollText: + case MonoDisplay.ElementType.ClippedText: + case MonoDisplay.ElementType.HScrollText: // case ElementType.VScrollText: return esc(el.text.slice(0, 24) + (el.text.length > 24 ? '...' : '')); - case ElementType.CurrentTime: - case ElementType.Image2D: - case ElementType.HorizontalScroll: - case ElementType.VerticalScroll: + case MonoDisplay.ElementType.CurrentTime: + case MonoDisplay.ElementType.Image2D: + case MonoDisplay.ElementType.HorizontalScroll: + case MonoDisplay.ElementType.VerticalScroll: return `${el.xOffset ?? 0}, ${el.yOffset ?? 0}`; - case ElementType.Animation: - case ElementType.Line: + case MonoDisplay.ElementType.Animation: + case MonoDisplay.ElementType.Line: return `${el.type.toString()}`; default: return "?"; @@ -548,7 +588,7 @@ function elSummary(el: MonoDisplay.MonoFormatElement) { function esc(s) { return String(s).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"') } function updateMeta() { - const section = getSec(activeSecIndex); + const section = getSectionByIndex(activeSecIndex); const sectionSelection = document.getElementById('meta-name'); if (sectionSelection) { if (section) {