Fang-Optionen und Display/Print-Umschalter in die Footerbar
Der Linien-Modus (Display/Print) wandert aus der Oberleiste und die Fang-Optionen aus der Werkzeug-Palette in die Statusleiste unten: - StatusBar: segmentierter Display/Print-Umschalter (Stil wie der Renderer-Umschalter) plus Fang-Pill mit nach oben öffnendem Popover (Master-Schalter + Endpunkt/Mittelpunkt/Schnittpunkt/Kante/Raster/ Ortho + Rastermass). - TopBar: Linien-Modus-Gruppe entfernt. - ToolsPanel: Fang-Abschnitt entfernt. - App reicht lineMode/snap an die StatusBar durch.
This commit is contained in:
+5
-3
@@ -2715,9 +2715,6 @@ export default function App() {
|
|||||||
referenceLines={referenceLines}
|
referenceLines={referenceLines}
|
||||||
onReferenceLines={setReferenceLines}
|
onReferenceLines={setReferenceLines}
|
||||||
referenceLinesEnabled={planActive}
|
referenceLinesEnabled={planActive}
|
||||||
lineMode={lineMode}
|
|
||||||
onLineMode={setLineMode}
|
|
||||||
lineModeEnabled={planActive}
|
|
||||||
combos={{
|
combos={{
|
||||||
// Ebenen-Kombinationen: Speichern = Snapshot des Layer-Baums →
|
// Ebenen-Kombinationen: Speichern = Snapshot des Layer-Baums →
|
||||||
// localStorage; Laden = Map lesen → Sichtbarkeits-Flags anwenden.
|
// localStorage; Laden = Map lesen → Sichtbarkeits-Flags anwenden.
|
||||||
@@ -2959,6 +2956,11 @@ export default function App() {
|
|||||||
rendererMode={rendererMode}
|
rendererMode={rendererMode}
|
||||||
webGpuAvailable={webGpuAvailable}
|
webGpuAvailable={webGpuAvailable}
|
||||||
onRendererModeChange={setRendererMode}
|
onRendererModeChange={setRendererMode}
|
||||||
|
lineMode={lineMode}
|
||||||
|
onLineModeChange={setLineMode}
|
||||||
|
lineModeEnabled={planActive}
|
||||||
|
snap={snap}
|
||||||
|
onSnapChange={setSnap}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Schwebendes Ressourcen-Fenster ÜBER allem (hoher z-index, abgedunkelter
|
{/* Schwebendes Ressourcen-Fenster ÜBER allem (hoher z-index, abgedunkelter
|
||||||
|
|||||||
@@ -119,7 +119,6 @@ function ToolIcon({ id }: { id: ToolId }) {
|
|||||||
|
|
||||||
export function ToolsPanel() {
|
export function ToolsPanel() {
|
||||||
const host = usePanelHost();
|
const host = usePanelHost();
|
||||||
const snap = host.snap;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="tools-panel">
|
<div className="tools-panel">
|
||||||
@@ -190,91 +189,6 @@ export function ToolsPanel() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{host.activeTool === "ceiling" && <div className="tools-sep" />}
|
{host.activeTool === "ceiling" && <div className="tools-sep" />}
|
||||||
|
|
||||||
{/* Fang-Abschnitt. Master-Checkbox steuert die übrigen Fang-Optionen. */}
|
|
||||||
<label className="tools-snap-row">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={snap.enabled}
|
|
||||||
onChange={(e) => host.onSnapChange({ ...snap, enabled: e.target.checked })}
|
|
||||||
/>
|
|
||||||
<span>{t("snap.enabled")}</span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label className="tools-snap-row">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={snap.endpoint}
|
|
||||||
disabled={!snap.enabled}
|
|
||||||
onChange={(e) => host.onSnapChange({ ...snap, endpoint: e.target.checked })}
|
|
||||||
/>
|
|
||||||
<span>{t("snap.endpoint")}</span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label className="tools-snap-row">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={snap.midpoint}
|
|
||||||
disabled={!snap.enabled}
|
|
||||||
onChange={(e) => host.onSnapChange({ ...snap, midpoint: e.target.checked })}
|
|
||||||
/>
|
|
||||||
<span>{t("snap.midpoint")}</span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label className="tools-snap-row">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={snap.intersection}
|
|
||||||
disabled={!snap.enabled}
|
|
||||||
onChange={(e) =>
|
|
||||||
host.onSnapChange({ ...snap, intersection: e.target.checked })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<span>{t("snap.intersection")}</span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label className="tools-snap-row">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={snap.onEdge}
|
|
||||||
disabled={!snap.enabled}
|
|
||||||
onChange={(e) => host.onSnapChange({ ...snap, onEdge: e.target.checked })}
|
|
||||||
/>
|
|
||||||
<span>{t("snap.onEdge")}</span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label className="tools-snap-row">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={snap.grid}
|
|
||||||
disabled={!snap.enabled}
|
|
||||||
onChange={(e) => host.onSnapChange({ ...snap, grid: e.target.checked })}
|
|
||||||
/>
|
|
||||||
<span>{t("snap.grid")}</span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label className="tools-snap-row">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={snap.ortho}
|
|
||||||
disabled={!snap.enabled}
|
|
||||||
onChange={(e) => host.onSnapChange({ ...snap, ortho: e.target.checked })}
|
|
||||||
/>
|
|
||||||
<span>{t("snap.ortho")}</span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label className="tools-field">
|
|
||||||
<span>{t("snap.gridSize")}</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
step={0.05}
|
|
||||||
min={0.01}
|
|
||||||
value={snap.gridSize}
|
|
||||||
onChange={(e) =>
|
|
||||||
host.onSnapChange({ ...snap, gridSize: Number(e.target.value) })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -803,6 +803,97 @@ body {
|
|||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Generische Segment-Pille für die Statusleiste (Linien-Darstellung, Fang) —
|
||||||
|
gleiche Masse/Optik wie .sb-renderer-toggle, aber nicht renderer-spezifisch. */
|
||||||
|
.sb-seg {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: stretch;
|
||||||
|
height: 16px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 999px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: var(--input);
|
||||||
|
}
|
||||||
|
.sb-seg.disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
.sb-seg-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
border: none;
|
||||||
|
border-left: 1px solid var(--border);
|
||||||
|
background: transparent;
|
||||||
|
color: var(--muted);
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
padding: 0 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.14s, color 0.14s;
|
||||||
|
}
|
||||||
|
.sb-seg-btn:first-child {
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
.sb-seg-btn:hover:not(:disabled) {
|
||||||
|
background: var(--accent-dim);
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.sb-seg-btn.active {
|
||||||
|
background: var(--accent);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.sb-seg-btn:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
/* Caret-Segment (öffnet das Fang-Popover) — schmaler als die Text-Segmente. */
|
||||||
|
.sb-seg-caret {
|
||||||
|
padding: 0 6px;
|
||||||
|
font-size: 9px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fang-Kontrolle: Wrapper ist relativ positioniert, damit das Popover NACH
|
||||||
|
OBEN öffnen kann (die Leiste sitzt ganz unten im App-Shell). */
|
||||||
|
.sb-snap-wrap {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
.sb-snap-popover {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 100%;
|
||||||
|
margin: 0 0 6px;
|
||||||
|
padding: 6px 0;
|
||||||
|
min-width: 170px;
|
||||||
|
background: var(--panel, #1c2128);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
|
||||||
|
z-index: 200;
|
||||||
|
}
|
||||||
|
.sb-snap-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 3px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.sb-snap-row input[type="checkbox"] {
|
||||||
|
accent-color: var(--accent);
|
||||||
|
}
|
||||||
|
.sb-snap-row-num {
|
||||||
|
justify-content: space-between;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.sb-snap-row-num input[type="number"] {
|
||||||
|
width: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Command-Line (Rhino-artig) — über der Statusleiste ──────────────────────
|
/* ── Command-Line (Rhino-artig) — über der Statusleiste ──────────────────────
|
||||||
Dunkle, ruhige Leiste mit Prompt links, klickbaren Inline-Optionen und einer
|
Dunkle, ruhige Leiste mit Prompt links, klickbaren Inline-Optionen und einer
|
||||||
monospace-Texteingabe rechts; das Autocomplete-Dropdown öffnet nach oben. */
|
monospace-Texteingabe rechts; das Autocomplete-Dropdown öffnet nach oben. */
|
||||||
|
|||||||
+210
-1
@@ -8,7 +8,9 @@
|
|||||||
// Rein gesteuert (controlled): alle Werte kommen aus App (Modell + View-State),
|
// Rein gesteuert (controlled): alle Werte kommen aus App (Modell + View-State),
|
||||||
// keine eigene Logik. Bezeichner englisch, UI-Text/Kommentare deutsch.
|
// keine eigene Logik. Bezeichner englisch, UI-Text/Kommentare deutsch.
|
||||||
|
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
import type { Vec2 } from "../model/types";
|
import type { Vec2 } from "../model/types";
|
||||||
|
import type { SnapSettings } from "../tools/types";
|
||||||
import { t } from "../i18n";
|
import { t } from "../i18n";
|
||||||
|
|
||||||
/** Plan-Renderer-Wahl, gespiegelt aus dem `?engine`-URL-Param (siehe PlanView). */
|
/** Plan-Renderer-Wahl, gespiegelt aus dem `?engine`-URL-Param (siehe PlanView). */
|
||||||
@@ -41,6 +43,199 @@ export interface StatusBarProps {
|
|||||||
* Live-Remount der Renderer-Hooks).
|
* Live-Remount der Renderer-Hooks).
|
||||||
*/
|
*/
|
||||||
onRendererModeChange: (mode: RendererMode) => void;
|
onRendererModeChange: (mode: RendererMode) => void;
|
||||||
|
/** Linien-Darstellung: „display" (Haarlinien) oder „print" (echte mm-Stärken). */
|
||||||
|
lineMode: "display" | "print";
|
||||||
|
/** Linien-Darstellung wechseln. */
|
||||||
|
onLineModeChange: (mode: "display" | "print") => void;
|
||||||
|
/** Nur im Grundriss sinnvoll — deaktiviert beide Segmente wenn `false`. */
|
||||||
|
lineModeEnabled: boolean;
|
||||||
|
/** Fang-Einstellungen (Werkzeug-übergreifend). */
|
||||||
|
snap: SnapSettings;
|
||||||
|
/** Fang-Einstellungen ändern. */
|
||||||
|
onSnapChange: (s: SnapSettings) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zweisegmentige Umschalt-Pille Display/Print für die Statusleiste — optisch
|
||||||
|
* an `.sb-renderer-toggle` angelehnt (gleiche Höhe/Radius), eigene Klasse
|
||||||
|
* `.sb-seg` weil sie generisch (nicht renderer-spezifisch) bleibt.
|
||||||
|
*/
|
||||||
|
function LineModeToggle({
|
||||||
|
lineMode,
|
||||||
|
onLineModeChange,
|
||||||
|
lineModeEnabled,
|
||||||
|
}: {
|
||||||
|
lineMode: "display" | "print";
|
||||||
|
onLineModeChange: (m: "display" | "print") => void;
|
||||||
|
lineModeEnabled: boolean;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<span className="sb-field">
|
||||||
|
<span className="sb-key">{t("topbar.lineModeGroup")}</span>
|
||||||
|
<span
|
||||||
|
className={`sb-seg${lineModeEnabled ? "" : " disabled"}`}
|
||||||
|
role="group"
|
||||||
|
aria-label={t("topbar.lineModeGroup")}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`sb-seg-btn${lineMode === "display" ? " active" : ""}`}
|
||||||
|
aria-pressed={lineMode === "display"}
|
||||||
|
disabled={!lineModeEnabled}
|
||||||
|
title={t("topbar.lineMode.display.hint")}
|
||||||
|
onClick={() => onLineModeChange("display")}
|
||||||
|
>
|
||||||
|
{t("topbar.lineMode.display")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`sb-seg-btn${lineMode === "print" ? " active" : ""}`}
|
||||||
|
aria-pressed={lineMode === "print"}
|
||||||
|
disabled={!lineModeEnabled}
|
||||||
|
title={t("topbar.lineMode.print.hint")}
|
||||||
|
onClick={() => onLineModeChange("print")}
|
||||||
|
>
|
||||||
|
{t("topbar.lineMode.print")}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fang-Kontrolle für die Statusleiste: eine Pille schaltet `snap.enabled`
|
||||||
|
* direkt um (Klick = an/aus, aktive Einfärbung wie der Renderer-Umschalter);
|
||||||
|
* ein kleiner Caret daneben öffnet ein NACH OBEN öffnendes Popover (Leiste
|
||||||
|
* sitzt unten) mit den Fang-Unteroptionen — 1:1 aus dem früheren
|
||||||
|
* ToolsPanel-„Fang-Abschnitt" übernommen. Schliesst bei Klick ausserhalb.
|
||||||
|
*/
|
||||||
|
function SnapControl({
|
||||||
|
snap,
|
||||||
|
onSnapChange,
|
||||||
|
}: {
|
||||||
|
snap: SnapSettings;
|
||||||
|
onSnapChange: (s: SnapSettings) => void;
|
||||||
|
}) {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const wrapRef = useRef<HTMLSpanElement | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) return;
|
||||||
|
const onDown = (e: MouseEvent) => {
|
||||||
|
if (wrapRef.current && !wrapRef.current.contains(e.target as Node)) {
|
||||||
|
setOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener("mousedown", onDown);
|
||||||
|
return () => document.removeEventListener("mousedown", onDown);
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className="sb-snap-wrap" ref={wrapRef}>
|
||||||
|
<span className={`sb-seg${open ? " open" : ""}`} role="group" aria-label={t("tool.snap")}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`sb-seg-btn${snap.enabled ? " active" : ""}`}
|
||||||
|
aria-pressed={snap.enabled}
|
||||||
|
title={t("tool.snap.hint")}
|
||||||
|
onClick={() => onSnapChange({ ...snap, enabled: !snap.enabled })}
|
||||||
|
>
|
||||||
|
{t("tool.snap")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`sb-seg-btn sb-seg-caret${open ? " active" : ""}`}
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded={open}
|
||||||
|
aria-label={t("tool.snap")}
|
||||||
|
title={t("tool.snap")}
|
||||||
|
onClick={() => setOpen((v) => !v)}
|
||||||
|
>
|
||||||
|
▴
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
{open && (
|
||||||
|
<div className="sb-snap-popover" role="dialog" aria-label={t("tool.snap")}>
|
||||||
|
<label className="sb-snap-row">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={snap.enabled}
|
||||||
|
onChange={(e) => onSnapChange({ ...snap, enabled: e.target.checked })}
|
||||||
|
/>
|
||||||
|
<span>{t("snap.enabled")}</span>
|
||||||
|
</label>
|
||||||
|
<label className="sb-snap-row">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={snap.endpoint}
|
||||||
|
disabled={!snap.enabled}
|
||||||
|
onChange={(e) => onSnapChange({ ...snap, endpoint: e.target.checked })}
|
||||||
|
/>
|
||||||
|
<span>{t("snap.endpoint")}</span>
|
||||||
|
</label>
|
||||||
|
<label className="sb-snap-row">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={snap.midpoint}
|
||||||
|
disabled={!snap.enabled}
|
||||||
|
onChange={(e) => onSnapChange({ ...snap, midpoint: e.target.checked })}
|
||||||
|
/>
|
||||||
|
<span>{t("snap.midpoint")}</span>
|
||||||
|
</label>
|
||||||
|
<label className="sb-snap-row">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={snap.intersection}
|
||||||
|
disabled={!snap.enabled}
|
||||||
|
onChange={(e) =>
|
||||||
|
onSnapChange({ ...snap, intersection: e.target.checked })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span>{t("snap.intersection")}</span>
|
||||||
|
</label>
|
||||||
|
<label className="sb-snap-row">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={snap.onEdge}
|
||||||
|
disabled={!snap.enabled}
|
||||||
|
onChange={(e) => onSnapChange({ ...snap, onEdge: e.target.checked })}
|
||||||
|
/>
|
||||||
|
<span>{t("snap.onEdge")}</span>
|
||||||
|
</label>
|
||||||
|
<label className="sb-snap-row">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={snap.grid}
|
||||||
|
disabled={!snap.enabled}
|
||||||
|
onChange={(e) => onSnapChange({ ...snap, grid: e.target.checked })}
|
||||||
|
/>
|
||||||
|
<span>{t("snap.grid")}</span>
|
||||||
|
</label>
|
||||||
|
<label className="sb-snap-row">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={snap.ortho}
|
||||||
|
disabled={!snap.enabled}
|
||||||
|
onChange={(e) => onSnapChange({ ...snap, ortho: e.target.checked })}
|
||||||
|
/>
|
||||||
|
<span>{t("snap.ortho")}</span>
|
||||||
|
</label>
|
||||||
|
<label className="sb-snap-row sb-snap-row-num">
|
||||||
|
<span>{t("snap.gridSize")}</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step={0.05}
|
||||||
|
min={0.01}
|
||||||
|
value={snap.gridSize}
|
||||||
|
onChange={(e) =>
|
||||||
|
onSnapChange({ ...snap, gridSize: Number(e.target.value) })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ein Wert-Feld im rechten Cluster: kleine Beschriftung + Wert. */
|
/** Ein Wert-Feld im rechten Cluster: kleine Beschriftung + Wert. */
|
||||||
@@ -72,6 +267,11 @@ export function StatusBar({
|
|||||||
rendererMode,
|
rendererMode,
|
||||||
webGpuAvailable,
|
webGpuAvailable,
|
||||||
onRendererModeChange,
|
onRendererModeChange,
|
||||||
|
lineMode,
|
||||||
|
onLineModeChange,
|
||||||
|
lineModeEnabled,
|
||||||
|
snap,
|
||||||
|
onSnapChange,
|
||||||
}: StatusBarProps) {
|
}: StatusBarProps) {
|
||||||
const coords = cursor
|
const coords = cursor
|
||||||
? `${fmt(cursor.x)}, ${fmt(cursor.y)}`
|
? `${fmt(cursor.x)}, ${fmt(cursor.y)}`
|
||||||
@@ -82,8 +282,17 @@ export function StatusBar({
|
|||||||
{/* Links: Werkzeug-Hinweis. */}
|
{/* Links: Werkzeug-Hinweis. */}
|
||||||
<span className="sb-hint">{hint}</span>
|
<span className="sb-hint">{hint}</span>
|
||||||
|
|
||||||
{/* Rechts: abgeleiteter Wert-Cluster. */}
|
{/* Rechts: abgeleiteter Wert-Cluster. Interaktive Kontrollen (Linien-
|
||||||
|
Darstellung, Fang) zuerst, danach die reinen Anzeigewerte. */}
|
||||||
<div className="sb-cluster">
|
<div className="sb-cluster">
|
||||||
|
<LineModeToggle
|
||||||
|
lineMode={lineMode}
|
||||||
|
onLineModeChange={onLineModeChange}
|
||||||
|
lineModeEnabled={lineModeEnabled}
|
||||||
|
/>
|
||||||
|
<Sep />
|
||||||
|
<SnapControl snap={snap} onSnapChange={onSnapChange} />
|
||||||
|
<Sep />
|
||||||
<span className="sb-field">
|
<span className="sb-field">
|
||||||
<span className="sb-key">{t("status.renderer")}</span>
|
<span className="sb-key">{t("status.renderer")}</span>
|
||||||
<span className="sb-renderer-toggle" role="group" aria-label={t("status.renderer")}>
|
<span className="sb-renderer-toggle" role="group" aria-label={t("status.renderer")}>
|
||||||
|
|||||||
@@ -141,12 +141,6 @@ export interface TopBarProps {
|
|||||||
/** Referenzlinien nur im Grundriss sinnvoll (sonst deaktiviert). */
|
/** Referenzlinien nur im Grundriss sinnvoll (sonst deaktiviert). */
|
||||||
referenceLinesEnabled: boolean;
|
referenceLinesEnabled: boolean;
|
||||||
|
|
||||||
// Linien-Darstellung: Display (Haarlinien) ↔ Print (echte mm-Strichstärken).
|
|
||||||
lineMode: "display" | "print";
|
|
||||||
onLineMode: (m: "display" | "print") => void;
|
|
||||||
/** Nur im Grundriss sinnvoll. */
|
|
||||||
lineModeEnabled: boolean;
|
|
||||||
|
|
||||||
// Sichtbarkeits-Kombinationen (Ebenen-/Zeichnungskombinationen).
|
// Sichtbarkeits-Kombinationen (Ebenen-/Zeichnungskombinationen).
|
||||||
/** Handler-Satz für die beiden Kombinations-Dropdowns. */
|
/** Handler-Satz für die beiden Kombinations-Dropdowns. */
|
||||||
combos: ComboMenuHandlers;
|
combos: ComboMenuHandlers;
|
||||||
@@ -855,9 +849,6 @@ export function TopBar({
|
|||||||
referenceLines,
|
referenceLines,
|
||||||
onReferenceLines,
|
onReferenceLines,
|
||||||
referenceLinesEnabled,
|
referenceLinesEnabled,
|
||||||
lineMode,
|
|
||||||
onLineMode,
|
|
||||||
lineModeEnabled,
|
|
||||||
combos,
|
combos,
|
||||||
resourcesOpen,
|
resourcesOpen,
|
||||||
onToggleResources,
|
onToggleResources,
|
||||||
@@ -1202,30 +1193,6 @@ export function TopBar({
|
|||||||
|
|
||||||
<Sep />
|
<Sep />
|
||||||
|
|
||||||
{/* Linien-Darstellung: Display (alle Haarlinien) ↔ Print (echte mm-
|
|
||||||
Strichstärken). Eine Einfach-Auswahl → als Dropdown (Trigger-Pill +
|
|
||||||
Häkchen-Liste, wie Detailgrad/Massstab), nicht mehr als Segment-Pillen.
|
|
||||||
Optionen tragen ein Icon plus Klartext. Nur im Grundriss sinnvoll. */}
|
|
||||||
<div className="tb-group" role="group" aria-label={t("topbar.lineModeGroup")}>
|
|
||||||
<label className="tb-field">
|
|
||||||
<span className="tb-label">{t("topbar.lineModeGroup")}</span>
|
|
||||||
<Dropdown
|
|
||||||
value={lineMode}
|
|
||||||
disabled={!lineModeEnabled}
|
|
||||||
onChange={(v) => onLineMode(v as "display" | "print")}
|
|
||||||
title={
|
|
||||||
lineModeEnabled
|
|
||||||
? `${t("topbar.lineMode.display.hint")} · ${t("topbar.lineMode.print.hint")}`
|
|
||||||
: t("topbar.lineModeGroup")
|
|
||||||
}
|
|
||||||
options={[
|
|
||||||
{ value: "display", label: t("topbar.lineMode.display") },
|
|
||||||
{ value: "print", label: t("topbar.lineMode.print") },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Rechte Gruppe: Layout-Menü · Ressourcen · Projektname. */}
|
{/* Rechte Gruppe: Layout-Menü · Ressourcen · Projektname. */}
|
||||||
<div className="topbar-right">
|
<div className="topbar-right">
|
||||||
{layoutMenu}
|
{layoutMenu}
|
||||||
|
|||||||
Reference in New Issue
Block a user