import { customElement, property, state } from "lit/decorators.js"; import { BaseElement } from "../../../hierarchy/BaseElement"; import { AbstractAnalysis, AbstractAreaAnalysis, PointAnalysis } from "@labir/core"; import { css, html, nothing, PropertyValues } from "lit"; import { t } from "i18next"; import { T } from "../../../translations/Languages"; import { consume } from "@lit/context"; import { interactiveAnalysisContext } from "../../../utils/context"; @customElement("file-analysis-overview-row") export class FileAnalysisRow extends BaseElement { @property() public analysis!: AbstractAnalysis; @consume({ context: interactiveAnalysisContext, subscribe: true }) interactiveanalysis: boolean = false; @state() protected value: { min: number | undefined, max: number | undefined, avg: number | undefined } = { min: undefined, max: undefined, avg: undefined }; @state() protected graph: { min: boolean, max: boolean, avg: boolean } = { min: false, max: false, avg: false } @state() protected may: { min: boolean, max: boolean, avg: boolean } = { min: false, max: false, avg: false } @state() protected dimension?: string; @state() protected color?: string; @property({ type: Boolean, reflect: true, attribute: true }) protected selected: boolean = false; @state() protected name?: string; protected updated(_changedProperties: PropertyValues): void { super.updated(_changedProperties); // Whenever the analysis changes, update the table row if (_changedProperties.has("analysis")) { const oldAnalysis = _changedProperties.get("analysis") as AbstractAnalysis; // Remove listeners if (oldAnalysis) { oldAnalysis.onDeselected.delete(this.UUID); oldAnalysis.onSelected.delete(this.UUID); oldAnalysis.onValues.delete(this.UUID); oldAnalysis.onMoveOrResize.delete(this.UUID); oldAnalysis.graph.onGraphActivation.delete(this.UUID); oldAnalysis.onSetInitialColor.delete(this.UUID); oldAnalysis.onSetName.delete(this.UUID); } const newAnalysis = this.analysis; // Update the name this.name = newAnalysis.name; // Update activation this.selected = newAnalysis.selected; // Update the color this.color = newAnalysis.initialColor; const formatDimension = (analysis: AbstractAnalysis) => { if ( analysis instanceof AbstractAreaAnalysis ) { return newAnalysis.width + "x" + newAnalysis.height; } return "1x1"; } // Update dimensions this.dimension = formatDimension( newAnalysis ); // newAnalysis.width + "x" + newAnalysis.height; // Update values this.value = { min: newAnalysis.min, max: newAnalysis.max, avg: newAnalysis.avg } // Update may if (newAnalysis.file.timeline.isSequence) { this.may = newAnalysis instanceof PointAnalysis ? { avg: true, min: false, max: false } : { avg: true, min: true, max: true }; } else { this.may = { avg: false, min: false, max: false }; } // Update graph this.graph = { min: newAnalysis.graph.state.MIN, max: newAnalysis.graph.state.MAX, avg: newAnalysis.graph.state.AVG } // Listen to resize or move newAnalysis.onSerializableChange.set(this.UUID, (analysis) => { this.dimension = formatDimension(analysis);// analysis.width + "x" + analysis.height; }); // Listen to values newAnalysis.onValues.set(this.UUID, (min, max, avg) => { this.value = { min, max, avg }; }); // Listen to graph activation newAnalysis.graph.onGraphActivation.set(this.UUID, (min, max, avg) => { this.graph = { min, max, avg }; }); // Listen to selection newAnalysis.onSelected.set(this.UUID, () => { this.selected = true; }); newAnalysis.onDeselected.set(this.UUID, () => { this.selected = false; }); // Listen to initialColor newAnalysis.onSetInitialColor.set(this.UUID, (value) => { this.color = value; }); // Listen to the name changes newAnalysis.onSetName.set(this.UUID, (value) => { this.name = value; }); } } protected valueOrNothing(value: number | undefined): string { return value === undefined ? "-" : value.toFixed(2) + " °C"; } protected renderCell( value: number | undefined, may: boolean, active: boolean, clickFn: () => void ): unknown { return html` ${may ? html` ` : this.valueOrNothing(value) } `; } public static styles = css` :host { display: table-row; white-space: nowrap; } button, td { font-size: var( --thermal-fs-sm ); font-size: 14px; color: var( --thermal-foreground); white-space: nowrap; } .may button { border: 1px solid var( --thermal-slate ); border-radius: var( --thermal-radius ); cursor: pointer; transition: all .2s ease-in-out; &:hover, &:focus { border-color: var( --thermal-slate-dark ); color: var( --thermal-foreground ); } } td { padding: 0.25em 0.5em; } .selected { } .name { &.interactive .name-text { cursor: pointer; } &.interactive:hover .name-text { color: var( --thermal-primary ); } u, b, span { display: inline-block; } u { width: 10px; height: 10px; border-radius: 50%; border: 1px solid var( --thermal-slate ); } b { width: 1em; height: 1em; } &.selected u { background-color: var( --thermal-slate-dark ); } &.notSelected span { text-decoration: line-through; } } svg { width: calc( var(--thermal-gap) * .8 ); color: var(--thermal-slate); transition: color .2s ease-in-out; cursor: pointer; &:hover { color: var( --thermal-foreground ); } } `; protected render(): unknown { return html` { if ( this.interactiveanalysis === false ) { return; } if (this.selected) this.analysis.setDeselected(true); else this.analysis.setSelected(false, true); }} > ${this.interactiveanalysis === true ? html`` : nothing } { this.analysis.file.analysis.layers.removeAnalysis(this.analysis.key) }}> ${this.renderCell( this.value.min, this.analysis instanceof AbstractAreaAnalysis, //this.may.min, this.graph.min, () => { this.analysis.graph.setMinActivation(!this.graph.min); this.log( "Graph analysis min", this.graph.min ); } )} ${this.renderCell( this.value.max, this.analysis instanceof AbstractAreaAnalysis, // this.may.max, this.graph.max, () => { this.analysis.graph.setMaxActivation(!this.graph.max); } )} ${this.renderCell( this.value.avg, true, // this.may.avg, this.graph.avg, () => { this.analysis.graph.setAvgActivation(!this.graph.avg); } )} `; } }