Done. The Selected Block editor now uses grid-style coordinate dropdowns in [Edit.cshtml (line 423)](C:/Source/PlotLine/PlotLine/Views/FloorPlans/Edit.cshtml:423).
What changed: X is now a dropdown showing A, B, C, AA, etc., while still saving 0, 1, 2, etc. Y is now a dropdown showing 1, 2, 3, etc., while still saving 0, 1, 2, etc. Options are limited to valid positions for the active floor and current block size. Dragging, manual dropdown changes, block resizing, and grid resizing all keep the controls synced through the existing block write/clamp path. Verification: dotnet build PlotLine.slnx passes with 0 warnings and 0 errors. No database, rendering model, transition logic, or AJAX architecture changes.
This commit is contained in:
parent
7874740f42
commit
92ab8f3202
@ -423,11 +423,21 @@
|
|||||||
<div class="row g-2">
|
<div class="row g-2">
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<label class="form-label">X</label>
|
<label class="form-label">X</label>
|
||||||
<input asp-for="Blocks[i].X" class="form-control form-control-sm" min="0" max="79" data-block-field="x" />
|
<select class="form-select form-select-sm"
|
||||||
|
id="Blocks_@(i)__X"
|
||||||
|
name="Blocks[@i].X"
|
||||||
|
data-block-field="x"
|
||||||
|
data-coordinate-axis="x"
|
||||||
|
data-coordinate-value="@Model.Blocks[i].X"></select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<label class="form-label">Y</label>
|
<label class="form-label">Y</label>
|
||||||
<input asp-for="Blocks[i].Y" class="form-control form-control-sm" min="0" max="79" data-block-field="y" />
|
<select class="form-select form-select-sm"
|
||||||
|
id="Blocks_@(i)__Y"
|
||||||
|
name="Blocks[@i].Y"
|
||||||
|
data-block-field="y"
|
||||||
|
data-coordinate-axis="y"
|
||||||
|
data-coordinate-value="@Model.Blocks[i].Y"></select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<label class="form-label">Width</label>
|
<label class="form-label">Width</label>
|
||||||
@ -1167,6 +1177,23 @@
|
|||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function populateCoordinateSelect(select, count, labelForValue, selectedValue) {
|
||||||
|
if (!select) return;
|
||||||
|
const selected = String(Math.max(0, Math.min(Number(selectedValue || 0), Math.max(count - 1, 0))));
|
||||||
|
const existingValues = [...select.options].map(option => option.value).join("|");
|
||||||
|
const nextValues = Array.from({ length: Math.max(count, 1) }, (_, index) => String(index)).join("|");
|
||||||
|
if (existingValues !== nextValues) {
|
||||||
|
select.replaceChildren(...Array.from({ length: Math.max(count, 1) }, (_, index) => {
|
||||||
|
const option = document.createElement("option");
|
||||||
|
option.value = String(index);
|
||||||
|
option.textContent = labelForValue(index);
|
||||||
|
return option;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
select.value = selected;
|
||||||
|
select.dataset.coordinateValue = selected;
|
||||||
|
}
|
||||||
|
|
||||||
function refreshGridCoordinateLabels() {
|
function refreshGridCoordinateLabels() {
|
||||||
const show = gridCoordinatesToggle?.checked === true;
|
const show = gridCoordinatesToggle?.checked === true;
|
||||||
panels.forEach(panel => {
|
panels.forEach(panel => {
|
||||||
@ -1665,11 +1692,16 @@
|
|||||||
const wrap = document.createElement("div");
|
const wrap = document.createElement("div");
|
||||||
wrap.className = "col-6";
|
wrap.className = "col-6";
|
||||||
wrap.innerHTML = `<label class="form-label">${label}</label>`;
|
wrap.innerHTML = `<label class="form-label">${label}</label>`;
|
||||||
const input = document.createElement("input");
|
const input = field === "x" || field === "y" ? document.createElement("select") : document.createElement("input");
|
||||||
input.className = "form-control form-control-sm";
|
input.className = field === "x" || field === "y" ? "form-select form-select-sm" : "form-control form-control-sm";
|
||||||
input.type = "number";
|
if (input instanceof HTMLInputElement) {
|
||||||
input.min = field === "x" || field === "y" ? "0" : "1";
|
input.type = "number";
|
||||||
input.max = field === "x" || field === "y" ? "79" : "80";
|
input.min = "1";
|
||||||
|
input.max = "80";
|
||||||
|
} else {
|
||||||
|
input.dataset.coordinateAxis = field;
|
||||||
|
input.dataset.coordinateValue = value;
|
||||||
|
}
|
||||||
input.name = `Blocks[${index}].${property}`;
|
input.name = `Blocks[${index}].${property}`;
|
||||||
input.value = value;
|
input.value = value;
|
||||||
input.dataset.blockField = field;
|
input.dataset.blockField = field;
|
||||||
@ -1738,6 +1770,7 @@
|
|||||||
blocks.push(button);
|
blocks.push(button);
|
||||||
attachBlockEvents(button);
|
attachBlockEvents(button);
|
||||||
createBlockEditor(block);
|
createBlockEditor(block);
|
||||||
|
writeBlock(button, readBlock(button));
|
||||||
checkOverlaps();
|
checkOverlaps();
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
@ -1818,8 +1851,8 @@
|
|||||||
function readBlock(block) {
|
function readBlock(block) {
|
||||||
const fields = fieldsFor(block);
|
const fields = fieldsFor(block);
|
||||||
return {
|
return {
|
||||||
x: Number(fields.x?.value || block.style.getPropertyValue("--x") || 0),
|
x: Number(fields.x?.value || fields.x?.dataset.coordinateValue || block.style.getPropertyValue("--x") || 0),
|
||||||
y: Number(fields.y?.value || block.style.getPropertyValue("--y") || 0),
|
y: Number(fields.y?.value || fields.y?.dataset.coordinateValue || block.style.getPropertyValue("--y") || 0),
|
||||||
w: Number(fields.w?.value || block.style.getPropertyValue("--w") || 1),
|
w: Number(fields.w?.value || block.style.getPropertyValue("--w") || 1),
|
||||||
h: Number(fields.h?.value || block.style.getPropertyValue("--h") || 1)
|
h: Number(fields.h?.value || block.style.getPropertyValue("--h") || 1)
|
||||||
};
|
};
|
||||||
@ -1827,13 +1860,18 @@
|
|||||||
|
|
||||||
function writeBlock(block, values) {
|
function writeBlock(block, values) {
|
||||||
const next = clampBlock(block, values);
|
const next = clampBlock(block, values);
|
||||||
|
const grid = gridFor(block);
|
||||||
|
const gridWidth = Number(grid?.dataset.gridWidth || 24);
|
||||||
|
const gridHeight = Number(grid?.dataset.gridHeight || 16);
|
||||||
|
const maxXOptions = Math.max(gridWidth - next.w + 1, 1);
|
||||||
|
const maxYOptions = Math.max(gridHeight - next.h + 1, 1);
|
||||||
block.style.setProperty("--x", next.x);
|
block.style.setProperty("--x", next.x);
|
||||||
block.style.setProperty("--y", next.y);
|
block.style.setProperty("--y", next.y);
|
||||||
block.style.setProperty("--w", next.w);
|
block.style.setProperty("--w", next.w);
|
||||||
block.style.setProperty("--h", next.h);
|
block.style.setProperty("--h", next.h);
|
||||||
const fields = fieldsFor(block);
|
const fields = fieldsFor(block);
|
||||||
if (fields.x) fields.x.value = next.x;
|
populateCoordinateSelect(fields.x, maxXOptions, gridColumnLabel, next.x);
|
||||||
if (fields.y) fields.y.value = next.y;
|
populateCoordinateSelect(fields.y, maxYOptions, value => String(value + 1), next.y);
|
||||||
if (fields.w) fields.w.value = next.w;
|
if (fields.w) fields.w.value = next.w;
|
||||||
if (fields.h) fields.h.value = next.h;
|
if (fields.h) fields.h.value = next.h;
|
||||||
scheduleGeometryRefresh();
|
scheduleGeometryRefresh();
|
||||||
@ -2467,7 +2505,10 @@
|
|||||||
saveLayoutAsync();
|
saveLayoutAsync();
|
||||||
});
|
});
|
||||||
|
|
||||||
blocks.forEach(attachBlockEvents);
|
blocks.forEach(block => {
|
||||||
|
attachBlockEvents(block);
|
||||||
|
writeBlock(block, readBlock(block));
|
||||||
|
});
|
||||||
|
|
||||||
editor.addEventListener("pointermove", event => {
|
editor.addEventListener("pointermove", event => {
|
||||||
if (!pointerState) return;
|
if (!pointerState) return;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user