Compare commits

...
2 Commits
Author SHA1 Message Date
livio bb30f23d67 Riorganizza verticalmente il pannello layer 2026-09-24 09:04:13 +02:00
livio 87304b1568 Rimuovi oggetti e gruppi dal progetto 2026-09-24 08:50:31 +02:00
3 changed files with 154 additions and 26 deletions

No files matched your search

+2 -2
View File
@@ -28,8 +28,8 @@
<ApplicationId>com.companyname.lmemappecatastaliapp</ApplicationId> <ApplicationId>com.companyname.lmemappecatastaliapp</ApplicationId>
<!-- Versions --> <!-- Versions -->
<ApplicationDisplayVersion>0.2.24</ApplicationDisplayVersion> <ApplicationDisplayVersion>0.2.26</ApplicationDisplayVersion>
<ApplicationVersion>28</ApplicationVersion> <ApplicationVersion>30</ApplicationVersion>
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged --> <!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
<WindowsPackageType>None</WindowsPackageType> <WindowsPackageType>None</WindowsPackageType>
+54 -19
View File
@@ -176,10 +176,11 @@ input[type="checkbox"] {
position: absolute; position: absolute;
top: 72px; top: 72px;
right: 12px; right: 12px;
bottom: calc(var(--nav-height) + 8px);
z-index: 940; z-index: 940;
display: grid; display: grid;
width: min(320px, calc(100% - 24px)); box-sizing: border-box;
max-height: calc(100% - 152px); width: min(480px, 50vw);
overflow-y: auto; overflow-y: auto;
border: 1px solid var(--line); border: 1px solid var(--line);
border-radius: 8px; border-radius: 8px;
@@ -274,8 +275,12 @@ input[type="checkbox"] {
.layer-manager-block > summary, .layer-manager-block > summary,
.layer-manager-object > summary { .layer-manager-object > summary {
display: grid; display: grid;
grid-template-columns: 28px 20px minmax(0, 1fr) auto auto; grid-template-columns: 28px minmax(0, 1fr) 24px;
align-items: center; grid-template-areas:
"handle title count"
". visibility moves"
". actions moves";
align-items: start;
gap: 6px; gap: 6px;
min-height: 38px; min-height: 38px;
padding: 4px 6px; padding: 4px 6px;
@@ -283,14 +288,6 @@ input[type="checkbox"] {
list-style: none; list-style: none;
} }
.layer-manager-object > summary {
grid-template-columns: 28px 20px minmax(0, 1fr) auto auto auto;
}
.layer-manager-renamable > summary {
grid-template-columns: 28px 20px minmax(0, 1fr) auto auto auto;
}
.layer-manager-group > summary::-webkit-details-marker, .layer-manager-group > summary::-webkit-details-marker,
.layer-manager-block > summary::-webkit-details-marker, .layer-manager-block > summary::-webkit-details-marker,
.layer-manager-object > summary::-webkit-details-marker { .layer-manager-object > summary::-webkit-details-marker {
@@ -298,6 +295,7 @@ input[type="checkbox"] {
} }
.layer-drag-handle { .layer-drag-handle {
grid-area: handle;
width: 28px; width: 28px;
height: 28px; height: 28px;
border: 0; border: 0;
@@ -310,24 +308,58 @@ input[type="checkbox"] {
cursor: grab; cursor: grab;
} }
.layer-rename-button { .layer-row-actions {
grid-area: actions;
display: grid;
grid-template-columns: minmax(0, 1fr);
width: min(130px, 100%);
gap: 4px;
}
.layer-manager-group > summary > input,
.layer-manager-block > summary > input,
.layer-manager-object > summary > input {
grid-area: visibility;
justify-self: start;
width: 20px;
height: 20px;
margin: 1px 0;
}
.layer-rename-button,
.layer-remove-button {
width: 100%;
min-height: 28px; min-height: 28px;
padding: 0 8px; min-width: 0;
padding: 4px;
border: 1px solid #bfd4cd; border: 1px solid #bfd4cd;
border-radius: 4px; border-radius: 4px;
background: #eef8f5; background: #eef8f5;
color: var(--accent-strong); color: var(--accent-strong);
font-size: 10px; font-size: 10px;
font-weight: 800; font-weight: 800;
line-height: 1.15;
overflow-wrap: anywhere;
} }
.layer-rename-button:active { .layer-rename-button:active {
background: #d9eee7; background: #d9eee7;
} }
.layer-remove-button {
border-color: #fecaca;
background: #fff1f2;
color: #b42318;
}
.layer-remove-button:active {
background: #ffe4e6;
}
.layer-move-buttons { .layer-move-buttons {
grid-area: moves;
display: inline-grid; display: inline-grid;
grid-template-columns: 24px 24px; grid-template-columns: 24px;
gap: 2px; gap: 2px;
} }
@@ -349,6 +381,7 @@ input[type="checkbox"] {
} }
.layer-manager-title { .layer-manager-title {
grid-area: title;
min-width: 0; min-width: 0;
overflow-wrap: anywhere; overflow-wrap: anywhere;
font-size: 12px; font-size: 12px;
@@ -356,18 +389,20 @@ input[type="checkbox"] {
} }
.layer-manager-count { .layer-manager-count {
grid-area: count;
justify-self: end;
color: var(--muted); color: var(--muted);
font-size: 10px; font-size: 10px;
} }
.layer-manager-children { .layer-manager-children {
padding: 0 5px 5px 18px; padding: 0 4px 5px 6px;
} }
.layer-manager-details { .layer-manager-details {
display: grid; display: grid;
gap: 2px; gap: 2px;
padding: 0 8px 7px 40px; padding: 0 6px 7px 12px;
color: var(--muted); color: var(--muted);
font-size: 10px; font-size: 10px;
} }
@@ -918,8 +953,8 @@ footer {
.map-layer-panel { .map-layer-panel {
top: 68px; top: 68px;
right: 8px; right: 8px;
width: min(320px, calc(100% - 16px)); bottom: calc(var(--nav-height) + 8px);
max-height: calc(100% - 144px); width: 50vw;
} }
.tool-sheet { .tool-sheet {
+98 -5
View File
@@ -61,6 +61,7 @@ const lmeState = {
managerHiddenMeasurementSummaryIds: new Set(), managerHiddenMeasurementSummaryIds: new Set(),
managerHiddenMeasurementSideIds: new Set(), managerHiddenMeasurementSideIds: new Set(),
managerHiddenCategories: new Set(), managerHiddenCategories: new Set(),
managerRemovedCategories: new Set(),
managerObjectOrder: {}, managerObjectOrder: {},
managerCategoryNames: {}, managerCategoryNames: {},
managerExpandedRows: new Set(), managerExpandedRows: new Set(),
@@ -1251,6 +1252,60 @@ function renameManagedBlock(category, source, records) {
setInfo(`Gruppo rinominato: ${name}.`); setInfo(`Gruppo rinominato: ${name}.`);
} }
function managedCategoryCanRemove(category, records) {
return records.length > 0
&& ["drawings", "imported", "importedSheets", "selectedParcels", "gpsParcels"].includes(category.key);
}
function managedObjectCanRemove(record) {
return ["drawings", "imported", "importedSheets", "selectedParcels", "gpsParcels"].includes(record.categoryKey);
}
function layerManagerRowActions(renameButton, removeButton) {
if (!renameButton && !removeButton) {
return "";
}
return `<span class="layer-row-actions">${renameButton}${removeButton}</span>`;
}
function removeManagedRecords(records, subject) {
if (!records.length) {
return;
}
const message = records.length === 1
? `Rimuovere ${subject} dal progetto? Non verra incluso nel prossimo salvataggio.`
: `Rimuovere ${subject} e tutti i suoi ${records.length} oggetti dal progetto? Non verranno inclusi nel prossimo salvataggio.`;
if (!window.confirm(message)) {
return;
}
const removedIds = new Set(records.map(record => record.id));
const categoryKeys = new Set(records.map(record => record.categoryKey));
records.forEach(record => {
if (record.parent?.hasLayer?.(record.layer)) {
record.parent.removeLayer(record.layer);
}
lmeState.managerHiddenObjects.delete(record.id);
lmeState.managerHiddenObjectIds.delete(record.id);
lmeState.managerHiddenMeasurementSummaryIds.delete(record.id);
lmeState.managerHiddenMeasurementSideIds.delete(record.id);
});
categoryKeys.forEach(categoryKey => {
const order = lmeState.managerObjectOrder[categoryKey] || [];
lmeState.managerObjectOrder[categoryKey] = order.filter(id => !removedIds.has(id));
const category = layerManagerCategories().find(item => item.key === categoryKey);
if (category && managedRecordsForCategory(category).length === 0) {
lmeState.managerRemovedCategories.add(categoryKey);
delete lmeState.managerCategoryNames[categoryKey];
}
});
clearManagerHighlight();
refreshImportedMeasurements();
refreshDrawingMeasurements();
updateGpsInsideState();
refreshLayerManager();
setInfo(`${records.length === 1 ? "Oggetto rimosso" : `${records.length} oggetti rimossi`} dal progetto.`);
}
function managedObjectDetails(layer) { function managedObjectDetails(layer) {
const details = []; const details = [];
const properties = layer?.feature?.properties || {}; const properties = layer?.feature?.properties || {};
@@ -1306,6 +1361,11 @@ function refreshLayerManager() {
return; return;
} }
const records = managedRecordsForCategory(category); const records = managedRecordsForCategory(category);
if (records.length) {
lmeState.managerRemovedCategories.delete(category.key);
} else if (lmeState.managerRemovedCategories.has(category.key)) {
return;
}
const savedOrder = lmeState.managerObjectOrder[category.key] || []; const savedOrder = lmeState.managerObjectOrder[category.key] || [];
const positions = new Map(savedOrder.map((id, index) => [id, index])); const positions = new Map(savedOrder.map((id, index) => [id, index]));
records.sort((left, right) => records.sort((left, right) =>
@@ -1334,12 +1394,16 @@ function renderLayerManagerCategory(category, records) {
const renameButton = managedCategoryCanRename(category) const renameButton = managedCategoryCanRename(category)
? `<button type="button" class="layer-rename-button" aria-label="Rinomina gruppo" title="Rinomina">Rinomina</button>` ? `<button type="button" class="layer-rename-button" aria-label="Rinomina gruppo" title="Rinomina">Rinomina</button>`
: ""; : "";
group.classList.toggle("layer-manager-renamable", Boolean(renameButton)); const removeButton = managedCategoryCanRemove(category, records)
? `<button type="button" class="layer-remove-button" aria-label="Rimuovi gruppo dal progetto" title="Rimuovi dal progetto">Rimuovi</button>`
: "";
const rowActions = layerManagerRowActions(renameButton, removeButton);
group.classList.toggle("layer-manager-with-actions", Boolean(rowActions));
const visibleCount = records.filter(record => !lmeState.managerHiddenObjectIds.has(record.id)).length; const visibleCount = records.filter(record => !lmeState.managerHiddenObjectIds.has(record.id)).length;
const categoryVisible = !lmeState.managerHiddenCategories.has(category.key) const categoryVisible = !lmeState.managerHiddenCategories.has(category.key)
&& (!category.roots.length || category.roots.some(layer => lmeState.map.hasLayer(layer))); && (!category.roots.length || category.roots.some(layer => lmeState.map.hasLayer(layer)));
const visible = categoryVisible; const visible = categoryVisible;
group.innerHTML = `<summary><button type="button" class="layer-drag-handle" aria-label="Trascina gruppo">☰</button><input type="checkbox" ${visible ? "checked" : ""} aria-label="Mostra ${escapeHtml(categoryName)}"><span class="layer-manager-title">${escapeHtml(categoryName)}</span>${renameButton}${layerManagerMoveButtons("gruppo")}<span class="layer-manager-count">${records.length}</span></summary><div class="layer-manager-children"></div>`; group.innerHTML = `<summary><button type="button" class="layer-drag-handle" aria-label="Trascina gruppo">☰</button><input type="checkbox" ${visible ? "checked" : ""} aria-label="Mostra ${escapeHtml(categoryName)}"><span class="layer-manager-title">${escapeHtml(categoryName)}</span>${rowActions}${layerManagerMoveButtons("gruppo")}<span class="layer-manager-count">${records.length}</span></summary><div class="layer-manager-children"></div>`;
const checkbox = group.querySelector("input"); const checkbox = group.querySelector("input");
checkbox.indeterminate = categoryVisible && records.length > 0 && visibleCount < records.length; checkbox.indeterminate = categoryVisible && records.length > 0 && visibleCount < records.length;
checkbox.addEventListener("click", event => event.stopPropagation()); checkbox.addEventListener("click", event => event.stopPropagation());
@@ -1349,6 +1413,11 @@ function renderLayerManagerCategory(category, records) {
event.stopPropagation(); event.stopPropagation();
renameManagedCategory(category, records); renameManagedCategory(category, records);
}); });
group.querySelector(".layer-remove-button")?.addEventListener("click", event => {
event.preventDefault();
event.stopPropagation();
removeManagedRecords(records, `il gruppo '${categoryName}'`);
});
bindManagedParentHighlight(group, `category:${category.key}`, records); bindManagedParentHighlight(group, `category:${category.key}`, records);
const children = group.querySelector(".layer-manager-children"); const children = group.querySelector(".layer-manager-children");
if (category.blocks) { if (category.blocks) {
@@ -1375,8 +1444,11 @@ function renderLayerManagerBlock(category, source, records) {
const visibleCount = records.filter(record => !lmeState.managerHiddenObjectIds.has(record.id)).length; const visibleCount = records.filter(record => !lmeState.managerHiddenObjectIds.has(record.id)).length;
const visible = visibleCount === records.length; const visible = visibleCount === records.length;
const blockName = managedBlockName(source, records); const blockName = managedBlockName(source, records);
block.classList.add("layer-manager-renamable"); const rowActions = layerManagerRowActions(
block.innerHTML = `<summary><button type="button" class="layer-drag-handle" aria-label="Trascina blocco">☰</button><input type="checkbox" ${visible ? "checked" : ""} aria-label="Mostra ${escapeHtml(blockName)}"><span class="layer-manager-title">${escapeHtml(blockName)}</span><button type="button" class="layer-rename-button" aria-label="Rinomina gruppo" title="Rinomina">Rinomina</button>${layerManagerMoveButtons("blocco")}<span class="layer-manager-count">${records.length}</span></summary><div class="layer-manager-children"></div>`; `<button type="button" class="layer-rename-button" aria-label="Rinomina gruppo" title="Rinomina">Rinomina</button>`,
`<button type="button" class="layer-remove-button" aria-label="Rimuovi gruppo dal progetto" title="Rimuovi dal progetto">Rimuovi</button>`);
block.classList.add("layer-manager-with-actions");
block.innerHTML = `<summary><button type="button" class="layer-drag-handle" aria-label="Trascina blocco">☰</button><input type="checkbox" ${visible ? "checked" : ""} aria-label="Mostra ${escapeHtml(blockName)}"><span class="layer-manager-title">${escapeHtml(blockName)}</span>${rowActions}${layerManagerMoveButtons("blocco")}<span class="layer-manager-count">${records.length}</span></summary><div class="layer-manager-children"></div>`;
const checkbox = block.querySelector("input"); const checkbox = block.querySelector("input");
checkbox.indeterminate = visibleCount > 0 && !visible; checkbox.indeterminate = visibleCount > 0 && !visible;
checkbox.addEventListener("click", event => event.stopPropagation()); checkbox.addEventListener("click", event => event.stopPropagation());
@@ -1389,6 +1461,11 @@ function renderLayerManagerBlock(category, source, records) {
event.stopPropagation(); event.stopPropagation();
renameManagedBlock(category, source, records); renameManagedBlock(category, source, records);
}); });
block.querySelector(".layer-remove-button").addEventListener("click", event => {
event.preventDefault();
event.stopPropagation();
removeManagedRecords(records, `il gruppo '${blockName}'`);
});
bindManagedParentHighlight(block, `block:${category.key}:${source}`, records); bindManagedParentHighlight(block, `block:${category.key}:${source}`, records);
const children = block.querySelector(".layer-manager-children"); const children = block.querySelector(".layer-manager-children");
records.forEach((record, index) => children.appendChild(renderLayerManagerObject(record, index))); records.forEach((record, index) => children.appendChild(renderLayerManagerObject(record, index)));
@@ -1408,7 +1485,13 @@ function renderLayerManagerObject(record, index) {
const renameButton = managedObjectCanRename(record) const renameButton = managedObjectCanRename(record)
? `<button type="button" class="layer-rename-button" aria-label="Rinomina oggetto" title="Rinomina">Rinomina</button>` ? `<button type="button" class="layer-rename-button" aria-label="Rinomina oggetto" title="Rinomina">Rinomina</button>`
: ""; : "";
object.innerHTML = `<summary><button type="button" class="layer-drag-handle" aria-label="Trascina oggetto">☰</button><input type="checkbox" ${visible ? "checked" : ""} aria-label="Mostra oggetto"><span class="layer-manager-title">${escapeHtml(managedObjectLabel(record, index))}</span>${renameButton}${layerManagerMoveButtons("oggetto")}<span class="layer-manager-count">›</span></summary><div class="layer-manager-details"></div>`; const removeButton = managedObjectCanRemove(record)
? `<button type="button" class="layer-remove-button" aria-label="Rimuovi oggetto dal progetto" title="Rimuovi dal progetto">Rimuovi</button>`
: "";
const rowActions = layerManagerRowActions(renameButton, removeButton);
object.classList.toggle("layer-manager-with-actions", Boolean(rowActions));
const objectName = managedObjectLabel(record, index);
object.innerHTML = `<summary><button type="button" class="layer-drag-handle" aria-label="Trascina oggetto">☰</button><input type="checkbox" ${visible ? "checked" : ""} aria-label="Mostra oggetto"><span class="layer-manager-title">${escapeHtml(objectName)}</span>${rowActions}${layerManagerMoveButtons("oggetto")}<span class="layer-manager-count">›</span></summary><div class="layer-manager-details"></div>`;
const checkbox = object.querySelector("input"); const checkbox = object.querySelector("input");
checkbox.addEventListener("click", event => event.stopPropagation()); checkbox.addEventListener("click", event => event.stopPropagation());
checkbox.addEventListener("change", () => setManagedObjectVisible(record, checkbox.checked, true)); checkbox.addEventListener("change", () => setManagedObjectVisible(record, checkbox.checked, true));
@@ -1417,6 +1500,11 @@ function renderLayerManagerObject(record, index) {
event.stopPropagation(); event.stopPropagation();
renameManagedObject(record, index); renameManagedObject(record, index);
}); });
object.querySelector(".layer-remove-button")?.addEventListener("click", event => {
event.preventDefault();
event.stopPropagation();
removeManagedRecords([record], `'${objectName}'`);
});
object.querySelector(".layer-manager-title").addEventListener("click", event => { object.querySelector(".layer-manager-title").addEventListener("click", event => {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
@@ -2695,6 +2783,7 @@ function captureDisplayOptions() {
layerOrder: [...lmeState.layerOrder], layerOrder: [...lmeState.layerOrder],
layerObjectOrder: { ...lmeState.managerObjectOrder }, layerObjectOrder: { ...lmeState.managerObjectOrder },
layerCategoryNames: { ...lmeState.managerCategoryNames }, layerCategoryNames: { ...lmeState.managerCategoryNames },
removedLayerCategories: [...lmeState.managerRemovedCategories],
hiddenLayerObjects: [...lmeState.managerHiddenObjectIds], hiddenLayerObjects: [...lmeState.managerHiddenObjectIds],
hiddenLayerMeasurementSummaries: [...lmeState.managerHiddenMeasurementSummaryIds], hiddenLayerMeasurementSummaries: [...lmeState.managerHiddenMeasurementSummaryIds],
hiddenLayerMeasurementSides: [...lmeState.managerHiddenMeasurementSideIds], hiddenLayerMeasurementSides: [...lmeState.managerHiddenMeasurementSideIds],
@@ -2734,6 +2823,9 @@ function applyProjectDisplayOptions(options) {
if (options.layerCategoryNames && typeof options.layerCategoryNames === "object") { if (options.layerCategoryNames && typeof options.layerCategoryNames === "object") {
lmeState.managerCategoryNames = { ...options.layerCategoryNames }; lmeState.managerCategoryNames = { ...options.layerCategoryNames };
} }
if (Array.isArray(options.removedLayerCategories)) {
lmeState.managerRemovedCategories = new Set(options.removedLayerCategories);
}
if (Array.isArray(options.hiddenLayerObjects)) { if (Array.isArray(options.hiddenLayerObjects)) {
lmeState.managerHiddenObjectIds = new Set(options.hiddenLayerObjects); lmeState.managerHiddenObjectIds = new Set(options.hiddenLayerObjects);
} }
@@ -2835,6 +2927,7 @@ function resetLayerManagerProjectState() {
lmeState.managerHiddenMeasurementSummaryIds.clear(); lmeState.managerHiddenMeasurementSummaryIds.clear();
lmeState.managerHiddenMeasurementSideIds.clear(); lmeState.managerHiddenMeasurementSideIds.clear();
lmeState.managerHiddenCategories.clear(); lmeState.managerHiddenCategories.clear();
lmeState.managerRemovedCategories.clear();
lmeState.managerObjectOrder = {}; lmeState.managerObjectOrder = {};
lmeState.managerCategoryNames = {}; lmeState.managerCategoryNames = {};
clearManagerHighlight(); clearManagerHighlight();