// Inhalts-Panel „Werkzeuge" — die Werkzeug-Palette (ArchiCAD-/Vectorworks-Stil). // Oben ein Umschalter „Liste ↔ Symbole" (Icon+Name als Zeilen ODER kompaktes // Icon-Raster). Darunter drei einheitlich gestylte Rubriken: 2D (Zeichnen), // 3D (BIM-Bauteile) und Bearbeiten (Ändern-Aktionen) — Werkzeuge UND Befehle // teilen denselben Knopf-Look (`.tp-item`), damit „Ändern" nicht mehr optisch // aus der Reihe fällt. // // Daten/Handler kommen über usePanelHost (kein Prop-Drilling). Werkzeug-Metadaten // aus der Tools-Registry (getTool), Befehls-Labels aus der Command-Registry. // // Bezeichner englisch, UI-Text/Kommentare deutsch (CONVENTIONS.md). Alle sichtbaren // Texte über t(...). import { useState } from "react"; import { t } from "../i18n"; import { usePanelHost } from "./host"; import type { ToolId } from "./host"; import { getTool } from "../tools/tools"; import { getCommand } from "../commands/registry"; import { CommandIcon } from "../ui/ribbon/CommandIcon"; // ── Icons ────────────────────────────────────────────────────────────────── // Keine echten Asset-Icons vorhanden: schlichte Inline-SVG-Glyphen je Werkzeug // (~16×16, stroke=currentColor, fill=none), damit das Icon die Textfarbe der // Zeile übernimmt. export function ToolIcon({ id }: { id: ToolId }) { const common = { width: 16, height: 16, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.4, strokeLinecap: "round" as const, strokeLinejoin: "round" as const, }; switch (id) { case "select": // Pfeil-Cursor (klassischer Zeiger mit Schweif). return ( ); case "wall": // Wandband: zwei parallele Kanten mit geschlossenen Enden (Wandstück). return ( ); case "ceiling": // Deckenplatte: gefülltes Rechteck mit Diagonal-Schraffur (Slab-Symbol). return ( ); case "window": // Fenster (SIA-Aufsicht): Wandöffnung mit doppelter Glaslinie. return ( ); case "door": // Tür (SIA-Aufsicht): Türblatt aufrecht + Viertelkreis-Schwenkbogen. return ( ); case "stair": // Treppe (SIA-Aufsicht): Wangen, gleichmäßige Tritte, Lauflinie mit // Aufwärts-Pfeil (Idee: Vollbogen ersetzt durch eine echte Treppe). return ( ); case "room": // Raum: umschlossene Fläche (Rechteck) mit Flächen-Marke (kleines Kreuz). return ( ); case "line": // Einzelne Diagonale. return ( ); case "polyline": // Dreisegmentiger Zickzack. return ( ); case "rect": // Rechteck-Umriss. return ( ); case "circle": // Kreis-Umriss. return ( ); case "arc": // Offener Bogen (gut 180°) mit Endpunkt-Markierungen. return ( ); case "ellipse": // Ellipse-Umriss (geneigt, unterscheidbar vom Kreis). return ( ); case "spline": // Glatte S-Kurve durch drei Wegpunkte. return ( ); case "bezier": // Kubische Bezier-Kurve mit sichtbaren Kontrollpunkt-Griffen. return ( ); case "dimension": // Masslinie mit Massstrichen (Diagonalstriche) an beiden Enden. return ( ); case "text": // Serifen-„A" als Text-Symbol. return ( ); case "textbox": // Spalten-Rahmen mit drei Textzeilen (Absatztext). return ( ); case "image": // Bild-Rahmen mit Bergsilhouette + Sonne (klassisches Bild-Icon). return ( ); default: return null; } } // ── Kategorien ─────────────────────────────────────────────────────────────── // Werkzeuge/Befehle in drei Rubriken sortiert (Nutzerwunsch: „sortiere nach 2D // und 3D und Bearbeiten"): reine Panel-Gruppierung (2D-Zeichnen · 3D/BIM- // Bauteile · Bearbeiten-Aktionen). const TOOLS_2D: ToolId[] = [ "line", "polyline", "rect", "circle", "arc", "ellipse", "spline", "bezier", "dimension", "text", "textbox", "image", ]; const TOOLS_3D: ToolId[] = ["wall", "ceiling", "window", "door", "stair", "room"]; const COMMANDS_3D = ["column", "ceilingopening", "roof", "extrude", "sectionline", "viewline"]; const COMMANDS_EDIT = ["move", "copy", "rotate", "mirror", "offset", "multiline", "trim", "extend", "fillet", "chamfer", "join", "measure"]; type ToolsView = "list" | "icons"; const VIEW_STORAGE_KEY = "dossier.toolsPanel.view"; function loadView(): ToolsView { try { return localStorage.getItem(VIEW_STORAGE_KEY) === "icons" ? "icons" : "list"; } catch { return "list"; } } // ── Panel ──────────────────────────────────────────────────────────────────── export function ToolsPanel() { const host = usePanelHost(); const [view, setView] = useState(loadView); const chooseView = (v: ToolsView) => { setView(v); try { localStorage.setItem(VIEW_STORAGE_KEY, v); } catch { /* Persistenz ist Best-Effort (privater Modus o. ä.). */ } }; // Ein Werkzeug-Knopf (Icon + Name). Boden-gebundene (`floorOnly`) Werkzeuge // sind ohne aktives Geschoss gesperrt; freie 2D-Werkzeuge bleiben nutzbar. const toolButton = (id: ToolId) => { const tool = getTool(id); const active = host.activeTool === id; const disabled = !!tool.floorOnly && !host.toolsEnabled; const label = t(tool.labelKey); const title = disabled ? t("tool.floorOnlyDisabled") : t(tool.hintKey(tool.init())); return ( ); }; // Ein Befehls-Knopf (Ändern-/BIM-Kommando ohne eigenen Werkzeug-Modus) — // gleicher Look wie die Werkzeuge (Nutzerwunsch: nicht „ganz anders"). const commandButton = (name: string) => { const cmd = getCommand(name); const label = cmd ? t(cmd.labelKey) : t(`cmd.${name}.label`); const active = host.activeCommand === name; return ( ); }; const bodyClass = "tp-body" + (view === "icons" ? " icons" : ""); return (
{/* Anzeige-Umschalter: nur Symbole ODER Symbol + Name (Liste). */}
{/* Auswahl-Werkzeug: immer als volle Zeile zuoberst (meistgenutzt). */}
{toolButton("select")}
{t("tools.cat.2d")}
{TOOLS_2D.map(toolButton)}
{t("tools.cat.3d")}
{TOOLS_3D.map(toolButton)} {COMMANDS_3D.map(commandButton)}
{t("tools.cat.edit")}
{COMMANDS_EDIT.map(commandButton)}
); }