Wandtyp-Kürzel: Component.abbrev + wallTypeLabel() + Kürzel-Feld im ResourceManager; Geschoss-Dropdown schmal
This commit is contained in:
@@ -545,6 +545,9 @@ export const de = {
|
|||||||
"resources.components.placeholder": "Bauteil",
|
"resources.components.placeholder": "Bauteil",
|
||||||
"resources.col.name": "Name",
|
"resources.col.name": "Name",
|
||||||
"resources.col.color": "Farbe",
|
"resources.col.color": "Farbe",
|
||||||
|
"resources.col.abbrev": "Kürzel",
|
||||||
|
"resources.col.abbrev.hint": "Kurz-Code für Wandtyp-Dropdowns (z. B. «BET», «HLZ»)",
|
||||||
|
"resources.col.abbrev.placeholder": "z. B. BET",
|
||||||
"resources.col.hatch": "Schnittschraffur",
|
"resources.col.hatch": "Schnittschraffur",
|
||||||
"resources.col.viewHatch": "Ansichtsschraffur",
|
"resources.col.viewHatch": "Ansichtsschraffur",
|
||||||
"resources.viewHatch.none": "(keine)",
|
"resources.viewHatch.none": "(keine)",
|
||||||
|
|||||||
@@ -539,6 +539,9 @@ export const en: Record<TranslationKey, string> = {
|
|||||||
"resources.components.placeholder": "Component",
|
"resources.components.placeholder": "Component",
|
||||||
"resources.col.name": "Name",
|
"resources.col.name": "Name",
|
||||||
"resources.col.color": "Color",
|
"resources.col.color": "Color",
|
||||||
|
"resources.col.abbrev": "Code",
|
||||||
|
"resources.col.abbrev.hint": "Short code for wall-type dropdowns (e.g. «CON», «BRK»)",
|
||||||
|
"resources.col.abbrev.placeholder": "e.g. CON",
|
||||||
"resources.col.hatch": "Section hatch",
|
"resources.col.hatch": "Section hatch",
|
||||||
"resources.col.viewHatch": "View hatch",
|
"resources.col.viewHatch": "View hatch",
|
||||||
"resources.viewHatch.none": "(none)",
|
"resources.viewHatch.none": "(none)",
|
||||||
|
|||||||
@@ -227,6 +227,12 @@ export interface Component {
|
|||||||
* Render-Modus „textured".
|
* Render-Modus „textured".
|
||||||
*/
|
*/
|
||||||
material?: ComponentMaterial;
|
material?: ComponentMaterial;
|
||||||
|
/**
|
||||||
|
* Optionales Kürzel für Wandtyp-Labels (z. B. „BET", „HLZ", „GKB", „DAE").
|
||||||
|
* Wird von `wallTypeLabel()` genutzt, um Wandtyp-Dropdowns kompakt darzustellen
|
||||||
|
* (z. B. „BET 24" statt dem vollen Namen). Fehlt es, greift der Name.
|
||||||
|
*/
|
||||||
|
abbrev?: string;
|
||||||
/** Verschneidungs-Rang: höher läuft am Stoß durch (Backbone). */
|
/** Verschneidungs-Rang: höher läuft am Stoß durch (Backbone). */
|
||||||
joinPriority: number;
|
joinPriority: number;
|
||||||
}
|
}
|
||||||
@@ -1374,6 +1380,35 @@ export const collectVisibleCodes = (layers: LayerCategory[]): Set<string> => {
|
|||||||
export const wallTypeThickness = (wt: WallType): number =>
|
export const wallTypeThickness = (wt: WallType): number =>
|
||||||
wt.layers.reduce((sum, l) => sum + l.thickness, 0);
|
wt.layers.reduce((sum, l) => sum + l.thickness, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kompakter Anzeigetext für einen Wandtyp im Dropdown (VW-Stil).
|
||||||
|
* - Einschichtig mit Kürzel: „BET 24" (Kürzel + Dicke in cm)
|
||||||
|
* - Mehrschichtig mit Kürzeln: „GKB·BET·DAE" + Gesamtdicke „(25.5)"
|
||||||
|
* - Ohne Kürzel: Name bleibt — kein Rückfall auf rohen Namen, nur keine Kurzform.
|
||||||
|
*
|
||||||
|
* `project.components` wird genutzt, um `Component.abbrev` aufzulösen.
|
||||||
|
* Ist kein abbrev gesetzt, erscheint der volle Name unverändert.
|
||||||
|
*/
|
||||||
|
export function wallTypeLabel(
|
||||||
|
wt: WallType | CeilingType,
|
||||||
|
components: Component[],
|
||||||
|
): string {
|
||||||
|
const resolve = (id: string) => components.find((c) => c.id === id);
|
||||||
|
const totalCm = +(wallTypeThickness(wt) * 100).toFixed(1);
|
||||||
|
// cm-Zahl: "24" statt "24.0", "17.5" bleibt "17.5"
|
||||||
|
const cmStr = totalCm % 1 === 0 ? String(totalCm | 0) : String(totalCm);
|
||||||
|
|
||||||
|
// Alle Schichten haben ein Kürzel → Kurzform bauen
|
||||||
|
const abbrevs = wt.layers.map((l) => resolve(l.componentId)?.abbrev ?? "");
|
||||||
|
const allHaveAbbrev = abbrevs.every((a) => a.length > 0);
|
||||||
|
if (allHaveAbbrev) {
|
||||||
|
if (wt.layers.length === 1) return `${abbrevs[0]} ${cmStr}`;
|
||||||
|
return `${abbrevs.join("·")} (${cmStr})`;
|
||||||
|
}
|
||||||
|
// Fallback: voller Name
|
||||||
|
return wt.name;
|
||||||
|
}
|
||||||
|
|
||||||
/** Formatiert Meter mit zwei Nachkommastellen, z. B. "0.35 m". */
|
/** Formatiert Meter mit zwei Nachkommastellen, z. B. "0.35 m". */
|
||||||
export const formatM = (meters: number): string => meters.toFixed(2) + " m";
|
export const formatM = (meters: number): string => meters.toFixed(2) + " m";
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import { t } from "../i18n";
|
import { t } from "../i18n";
|
||||||
import { formatM } from "../model/types";
|
import { formatM, wallTypeLabel } from "../model/types";
|
||||||
import { PEN_WEIGHTS } from "../model/types";
|
import { PEN_WEIGHTS } from "../model/types";
|
||||||
import type { AttributeSource } from "../model/types";
|
import type { AttributeSource } from "../model/types";
|
||||||
import { usePanelHost } from "./host";
|
import { usePanelHost } from "./host";
|
||||||
@@ -75,7 +75,11 @@ export function AttributesPanel() {
|
|||||||
value={host.activeWallTypeId}
|
value={host.activeWallTypeId}
|
||||||
disabled={!host.toolsEnabled}
|
disabled={!host.toolsEnabled}
|
||||||
onChange={(v) => host.onActiveWallTypeId(v)}
|
onChange={(v) => host.onActiveWallTypeId(v)}
|
||||||
options={project.wallTypes.map((wt) => ({ value: wt.id, label: wt.name }))}
|
options={project.wallTypes.map((wt) => ({
|
||||||
|
value: wt.id,
|
||||||
|
label: wallTypeLabel(wt, project.components),
|
||||||
|
title: wt.name,
|
||||||
|
}))}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -581,10 +581,8 @@ export function CeilingSection({
|
|||||||
onChange={(id) => host.onSetCeilingType(id)}
|
onChange={(id) => host.onSetCeilingType(id)}
|
||||||
options={ceiling.ceilingTypes.map((ct) => ({
|
options={ceiling.ceilingTypes.map((ct) => ({
|
||||||
value: ct.id,
|
value: ct.id,
|
||||||
label: t("objinfo.wall.presetLabel", {
|
label: ct.label,
|
||||||
name: ct.name,
|
title: ct.name,
|
||||||
thickness: ct.thickness.toFixed(2),
|
|
||||||
}),
|
|
||||||
}))}
|
}))}
|
||||||
title={t("objinfo.ceiling.preset")}
|
title={t("objinfo.ceiling.preset")}
|
||||||
width={150}
|
width={150}
|
||||||
@@ -717,10 +715,8 @@ export function WallSection({
|
|||||||
onChange={(id) => host.onSetWallType(id)}
|
onChange={(id) => host.onSetWallType(id)}
|
||||||
options={wall.wallTypes.map((wt) => ({
|
options={wall.wallTypes.map((wt) => ({
|
||||||
value: wt.id,
|
value: wt.id,
|
||||||
label: t("objinfo.wall.presetLabel", {
|
label: wt.label,
|
||||||
name: wt.name,
|
title: wt.name,
|
||||||
thickness: wt.thickness.toFixed(2),
|
|
||||||
}),
|
|
||||||
}))}
|
}))}
|
||||||
title={t("objinfo.wall.preset")}
|
title={t("objinfo.wall.preset")}
|
||||||
width={150}
|
width={150}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
flattenCategories,
|
flattenCategories,
|
||||||
getCeilingType,
|
getCeilingType,
|
||||||
getWallType,
|
getWallType,
|
||||||
|
wallTypeLabel,
|
||||||
wallTypeThickness,
|
wallTypeThickness,
|
||||||
} from "../model/types";
|
} from "../model/types";
|
||||||
import type {
|
import type {
|
||||||
@@ -48,6 +49,8 @@ import { stairGeometry, stairBBox } from "../geometry/stair";
|
|||||||
export interface WallTypeChoice {
|
export interface WallTypeChoice {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
/** Kurz-Label für das Dropdown (aus wallTypeLabel: Kürzel+Dicke oder Name). */
|
||||||
|
label: string;
|
||||||
/** Gesamtdicke (Meter) — informativ im Dropdown-Label. */
|
/** Gesamtdicke (Meter) — informativ im Dropdown-Label. */
|
||||||
thickness: number;
|
thickness: number;
|
||||||
/** Anzahl Schichten (1 = einschichtig). */
|
/** Anzahl Schichten (1 = einschichtig). */
|
||||||
@@ -359,6 +362,7 @@ function wallSelection(project: Project, wall: Wall): Selection {
|
|||||||
wallTypes: project.wallTypes.map((t) => ({
|
wallTypes: project.wallTypes.map((t) => ({
|
||||||
id: t.id,
|
id: t.id,
|
||||||
name: t.name,
|
name: t.name,
|
||||||
|
label: wallTypeLabel(t, project.components),
|
||||||
thickness: wallTypeThickness(t),
|
thickness: wallTypeThickness(t),
|
||||||
layerCount: t.layers.length,
|
layerCount: t.layers.length,
|
||||||
})),
|
})),
|
||||||
@@ -414,6 +418,7 @@ function ceilingSelection(project: Project, ceiling: Ceiling): Selection {
|
|||||||
ceilingTypes: (project.ceilingTypes ?? []).map((t) => ({
|
ceilingTypes: (project.ceilingTypes ?? []).map((t) => ({
|
||||||
id: t.id,
|
id: t.id,
|
||||||
name: t.name,
|
name: t.name,
|
||||||
|
label: wallTypeLabel(t, project.components),
|
||||||
thickness: wallTypeThickness(t),
|
thickness: wallTypeThickness(t),
|
||||||
layerCount: t.layers.length,
|
layerCount: t.layers.length,
|
||||||
})),
|
})),
|
||||||
|
|||||||
+2
-1
@@ -4040,7 +4040,8 @@ body {
|
|||||||
padding-left: 56px;
|
padding-left: 56px;
|
||||||
}
|
}
|
||||||
.objinfo-subfield .tb-dd-trigger {
|
.objinfo-subfield .tb-dd-trigger {
|
||||||
width: 100%;
|
width: auto;
|
||||||
|
max-width: 140px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Attribute-Palette (AttributesPanel) ─────────────────────────────── */
|
/* ── Attribute-Palette (AttributesPanel) ─────────────────────────────── */
|
||||||
|
|||||||
@@ -763,6 +763,13 @@ function ComponentDetail({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="res-fields">
|
<div className="res-fields">
|
||||||
|
<FieldRow label={t("resources.col.abbrev")} hint={t("resources.col.abbrev.hint")}>
|
||||||
|
<TextField
|
||||||
|
value={component.abbrev ?? ""}
|
||||||
|
onChange={(v) => onPatch({ abbrev: v || undefined })}
|
||||||
|
placeholder={t("resources.col.abbrev.placeholder")}
|
||||||
|
/>
|
||||||
|
</FieldRow>
|
||||||
<FieldRow
|
<FieldRow
|
||||||
label={t("resources.col.foreground")}
|
label={t("resources.col.foreground")}
|
||||||
hint={t("resources.col.foreground.hint")}
|
hint={t("resources.col.foreground.hint")}
|
||||||
|
|||||||
Reference in New Issue
Block a user