readonly spreadsheet cells
This commit is contained in:
parent
a69840c8ab
commit
d2feab9e04
|
|
@ -21,10 +21,16 @@
|
||||||
folk-shape {
|
folk-shape {
|
||||||
background: rgb(187, 178, 178);
|
background: rgb(187, 178, 178);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<folk-space-projector>
|
<folk-space-projector>
|
||||||
|
<h1>Spatial projection into a spreadsheet</h1>
|
||||||
<folk-shape x="100" y="100" width="50" height="50"></folk-shape>
|
<folk-shape x="100" y="100" width="50" height="50"></folk-shape>
|
||||||
<folk-shape x="100" y="200" width="50" height="50"></folk-shape>
|
<folk-shape x="100" y="200" width="50" height="50"></folk-shape>
|
||||||
<folk-shape x="100" y="300" width="50" height="50" rotation="45"></folk-shape>
|
<folk-shape x="100" y="300" width="50" height="50" rotation="45"></folk-shape>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { css, PropertyValues } from '@lit/reactive-element';
|
import { css, PropertyValues } from '@lit/reactive-element';
|
||||||
import { FolkBaseSet } from './folk-base-set';
|
import { FolkBaseSet } from './folk-base-set';
|
||||||
import { FolkShape } from './folk-shape';
|
import { FolkShape } from './folk-shape';
|
||||||
import { FolkSpreadsheet, FolkSpreadSheetCell, templateCells } from './folk-spreadsheet';
|
import { CellTemplate, FolkSpreadsheet, FolkSpreadSheetCell, templateCells } from './folk-spreadsheet';
|
||||||
import { DOMRectTransform } from './common/DOMRectTransform';
|
import { DOMRectTransform } from './common/DOMRectTransform';
|
||||||
|
|
||||||
FolkShape.define();
|
FolkShape.define();
|
||||||
|
|
@ -120,17 +120,31 @@ export class FolkSpaceProjector extends FolkBaseSet {
|
||||||
super.update(changedProperties);
|
super.update(changedProperties);
|
||||||
|
|
||||||
if (changedProperties.has('sourceElements')) {
|
if (changedProperties.has('sourceElements')) {
|
||||||
const cells = templateCells(this.sourceElements.size, 5, {});
|
const cells: Record<string, CellTemplate> = {};
|
||||||
this.#spreadsheet.setHTMLUnsafe(cells);
|
|
||||||
|
let row = 1;
|
||||||
|
for (const el of this.sourceElements) {
|
||||||
|
if (!(el instanceof FolkShape)) {
|
||||||
|
cells[`A${row}`] = { readonly: true };
|
||||||
|
cells[`B${row}`] = { readonly: true };
|
||||||
|
cells[`C${row}`] = { readonly: true };
|
||||||
|
cells[`D${row}`] = { readonly: true };
|
||||||
|
cells[`E${row}`] = { readonly: true };
|
||||||
|
}
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const html = templateCells(this.sourceElements.size, 5, cells);
|
||||||
|
this.#spreadsheet.setHTMLUnsafe(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.sourcesMap.size !== this.sourceElements.size) return;
|
if (this.sourcesMap.size !== this.sourceElements.size) return;
|
||||||
|
|
||||||
this.#lock = true;
|
this.#lock = true;
|
||||||
const rects = this.sourceRects;
|
let row = 1;
|
||||||
for (let i = 0; i < rects.length; i += 1) {
|
for (const el of this.sourceElements) {
|
||||||
const row = i + 1;
|
const rect = this.sourcesMap.get(el)!;
|
||||||
const rect = rects[i];
|
|
||||||
if (rect instanceof DOMRectTransform) {
|
if (rect instanceof DOMRectTransform) {
|
||||||
const { x, y } = rect.toParentSpace(rect.topLeft);
|
const { x, y } = rect.toParentSpace(rect.topLeft);
|
||||||
this.#spreadsheet.getCell('A', row)!.expression = Math.round(x);
|
this.#spreadsheet.getCell('A', row)!.expression = Math.round(x);
|
||||||
|
|
@ -143,8 +157,11 @@ export class FolkSpaceProjector extends FolkBaseSet {
|
||||||
this.#spreadsheet.getCell('B', row)!.expression = Math.round(rect.y);
|
this.#spreadsheet.getCell('B', row)!.expression = Math.round(rect.y);
|
||||||
this.#spreadsheet.getCell('C', row)!.expression = Math.round(rect.width);
|
this.#spreadsheet.getCell('C', row)!.expression = Math.round(rect.width);
|
||||||
this.#spreadsheet.getCell('D', row)!.expression = Math.round(rect.height);
|
this.#spreadsheet.getCell('D', row)!.expression = Math.round(rect.height);
|
||||||
|
this.#spreadsheet.getCell('E', row)!.expression = 0;
|
||||||
}
|
}
|
||||||
|
row += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.resolve().then(() => {
|
Promise.resolve().then(() => {
|
||||||
this.#lock = false;
|
this.#lock = false;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,10 @@ const styles = css`
|
||||||
justify-content: end;
|
justify-content: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::slotted(folk-cell[readonly]) {
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
::slotted(folk-cell:hover) {
|
::slotted(folk-cell:hover) {
|
||||||
outline: 1px solid #1b73e8;
|
outline: 1px solid #1b73e8;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
|
|
@ -132,21 +136,30 @@ export function relativeColumnName(name: string, num: number) {
|
||||||
return alphabet[index + num];
|
return alphabet[index + num];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function templateCells(numberOfRows: number, numberOfColumns: number, expressions: Record<string, string> = {}) {
|
export interface CellTemplate {
|
||||||
const cells: string[] = [];
|
expression?: string;
|
||||||
|
readonly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function templateCells(numberOfRows: number, numberOfColumns: number, cells: Record<string, CellTemplate> = {}) {
|
||||||
|
const html: string[] = [];
|
||||||
for (let i = 0; i < numberOfRows; i += 1) {
|
for (let i = 0; i < numberOfRows; i += 1) {
|
||||||
for (let j = 0; j < numberOfColumns; j += 1) {
|
for (let j = 0; j < numberOfColumns; j += 1) {
|
||||||
const column = getColumnName(j);
|
const column = getColumnName(j);
|
||||||
const row = i + 1;
|
const row = i + 1;
|
||||||
const expression = expressions[`${column}${row}`];
|
const { expression, readonly } = cells[`${column}${row}`] || {};
|
||||||
cells.push(
|
html.push(
|
||||||
`<folk-cell column="${column}" row="${row}" tabindex="0" ${
|
`<folk-cell
|
||||||
expression ? `expression="${expression}"` : ''
|
column="${column}"
|
||||||
}></folk-cell>`
|
row="${row}"
|
||||||
|
tabindex="0"
|
||||||
|
${expression ? `expression="${expression}"` : ''}
|
||||||
|
${readonly ? 'readonly' : ''}
|
||||||
|
></folk-cell>`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cells.join('\n');
|
return html.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|
@ -168,7 +181,7 @@ export class FolkSpreadsheet extends HTMLElement {
|
||||||
|
|
||||||
#shadow = this.attachShadow({ mode: 'open' });
|
#shadow = this.attachShadow({ mode: 'open' });
|
||||||
|
|
||||||
#textarea: HTMLTextAreaElement | null = null;
|
#textarea!: HTMLTextAreaElement;
|
||||||
|
|
||||||
#editedCell: FolkSpreadSheetCell | null = null;
|
#editedCell: FolkSpreadSheetCell | null = null;
|
||||||
|
|
||||||
|
|
@ -326,7 +339,7 @@ export class FolkSpreadsheet extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
#focusTextarea(cell: FolkSpreadSheetCell) {
|
#focusTextarea(cell: FolkSpreadSheetCell) {
|
||||||
if (this.#textarea === null) return;
|
if (cell.readonly) return;
|
||||||
this.#editedCell = cell;
|
this.#editedCell = cell;
|
||||||
const gridColumn = getColumnIndex(cell.column) + 2;
|
const gridColumn = getColumnIndex(cell.column) + 2;
|
||||||
const gridRow = cell.row + 1;
|
const gridRow = cell.row + 1;
|
||||||
|
|
@ -339,7 +352,6 @@ export class FolkSpreadsheet extends HTMLElement {
|
||||||
|
|
||||||
#resetTextarea() {
|
#resetTextarea() {
|
||||||
if (this.#editedCell === null) return;
|
if (this.#editedCell === null) return;
|
||||||
if (this.#textarea === null) return;
|
|
||||||
this.#textarea.style.setProperty('--text-column', '0');
|
this.#textarea.style.setProperty('--text-column', '0');
|
||||||
this.#textarea.style.setProperty('--text-row', '0');
|
this.#textarea.style.setProperty('--text-row', '0');
|
||||||
this.#editedCell.expression = this.#textarea.value;
|
this.#editedCell.expression = this.#textarea.value;
|
||||||
|
|
@ -471,6 +483,13 @@ export class FolkSpreadSheetCell extends HTMLElement {
|
||||||
this.#evaluate();
|
this.#evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get readonly() {
|
||||||
|
return this.hasAttribute('readonly');
|
||||||
|
}
|
||||||
|
set readonly(readonly) {
|
||||||
|
readonly ? this.setAttribute('readonly', '') : this.removeAttribute('readonly');
|
||||||
|
}
|
||||||
|
|
||||||
#value: any;
|
#value: any;
|
||||||
get value() {
|
get value() {
|
||||||
return this.#value;
|
return this.#value;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue