Auswahl-Zustand aus App.tsx in useSelectionState() extrahiert

Bündelt die Auswahl-Mengen aller Bauteil-/Zeichnungs-Arten (Wand, 2D-
Zeichnung, Decke, Dach, Öffnung, Treppe, Raum, Extrusion, Stütze,
Kontext-Objekt) plus abgeleitete Einzel-Ids, die 2D-Zwischenablage und
den 3D-Live-Schnitt-Treiber (Teil der laufenden App.tsx-Verkleinerung).
This commit is contained in:
2026-07-22 00:42:07 +02:00
parent b3e6aaaec1
commit 448546994c
2 changed files with 161 additions and 60 deletions
+42 -60
View File
@@ -158,6 +158,7 @@ import { Content } from "./views/viewportContent";
import { useDialogState } from "./state/useDialogState"; import { useDialogState } from "./state/useDialogState";
import { useTopBarState } from "./state/useTopBarState"; import { useTopBarState } from "./state/useTopBarState";
import { useDrawingToolState } from "./state/useDrawingToolState"; import { useDrawingToolState } from "./state/useDrawingToolState";
import { useSelectionState } from "./state/useSelectionState";
import { useThemeModeState } from "./theme/useThemeMode"; import { useThemeModeState } from "./theme/useThemeMode";
import { CommandLine } from "./ui/CommandLine"; import { CommandLine } from "./ui/CommandLine";
import type { CommandLineHandle, CommandLineField, CommandLineOption } from "./ui/CommandLine"; import type { CommandLineHandle, CommandLineField, CommandLineOption } from "./ui/CommandLine";
@@ -455,66 +456,47 @@ export default function App() {
} = useDrawingToolState(project.wallTypes[0].id, project.lineStyles[0].id); } = useDrawingToolState(project.wallTypes[0].id, project.lineStyles[0].id);
// ── Auswahl (Store-Slice) ───────────────────────────────────────────────── // ── Auswahl (Store-Slice) ─────────────────────────────────────────────────
const selectedWallIds = useStore((s) => s.selectedWallIds); const {
const setSelectedWallIds = useStore((s) => s.setSelectedWallIds); selectedWallIds,
// 2D-Auswahl ist jetzt eine MENGE (Marquee/Mehrfach). Für die bestehende setSelectedWallIds,
// Einzel-Element-Maschinerie (Grips, Edit, Attribute, Object-Info) wird lokal selectedDrawingIds,
// der „eine" gewählte Zeichnungs-ID abgeleitet (nur bei genau einem Element); setSelectedDrawingIds,
// `setSelectedDrawingId` bleibt als bequeme Einzel-Setter-Hülle erhalten. selectedDrawingId,
const selectedDrawingIds = useStore((s) => s.selectedDrawingIds); setSelectedDrawingId,
const setSelectedDrawingIds = useStore((s) => s.setSelectedDrawingIds); drawingClipboard,
const selectedDrawingId = setDrawingClipboard,
selectedDrawingIds.length === 1 ? selectedDrawingIds[0] : null; selectedWallId,
const setSelectedDrawingId = (id: string | null) => selectedCeilingIds,
setSelectedDrawingIds(id ? [id] : []); setSelectedCeilingIds,
// Zwischenablage für 2D-Zeichenelemente (Ctrl/Cmd+C/V). Kopiert die GEWÄHLTEN selectedCeilingId,
// Drawing2D tief; Einfügen legt Klone mit neuen IDs auf dem AKTIVEN Geschoss selectedRoofIds,
// (Zeichnungsebene) an — so lässt sich z. B. importiertes Mobiliar über setSelectedRoofIds,
// Geschosse hinweg wiederverwenden. Kategorie/Stil bleiben erhalten. selectedRoofId,
const [drawingClipboard, setDrawingClipboard] = useState<Drawing2D[]>([]); selectedSectionLineId,
// Bequemer Einzel-Selektor (erste gewählte Wand). setSelectedSectionLineId,
const selectedWallId = selectedWallIds[0] ?? null; section3dCutId,
// Decken-Auswahl (MENGE); für die Einzel-Element-Maschinerie der „eine" setSection3dCutId,
// gewählte (bei genau einem Element). updateRoof,
const selectedCeilingIds = useStore((s) => s.selectedCeilingIds); moveRoofGrip,
const setSelectedCeilingIds = useStore((s) => s.setSelectedCeilingIds); moveRoofBy,
const selectedCeilingId = selectedOpeningIds,
selectedCeilingIds.length === 1 ? selectedCeilingIds[0] : null; setSelectedOpeningIds,
// Dach-Auswahl (MENGE); Einzel-Element bei genau einem gewählten Dach. selectedOpeningId,
const selectedRoofIds = useStore((s) => s.selectedRoofIds); selectedStairIds,
const setSelectedRoofIds = useStore((s) => s.setSelectedRoofIds); setSelectedStairIds,
const selectedRoofId = selectedRoofIds.length === 1 ? selectedRoofIds[0] : null; selectedStairId,
// Schnitt-/Ansichtslinien-Auswahl (Einzel-DrawingLevel-Id oder null). selectedRoomIds,
const selectedSectionLineId = useStore((s) => s.selectedSectionLineId); setSelectedRoomIds,
const setSelectedSectionLineId = useStore((s) => s.setSelectedSectionLineId); selectedRoomId,
// Welche Schnittlinie treibt den 3D-Live-Schnitt (reiner Ansichts-Zustand, selectedExtrudedSolidIds,
// unabhängig von der Auswahl — der Schnitt bleibt beim Klick woanders aktiv). setSelectedExtrudedSolidIds,
const [section3dCutId, setSection3dCutId] = useState<string | null>(null); selectedExtrudedSolidId,
const updateRoof = useStore((s) => s.updateRoof); selectedColumnIds,
const moveRoofGrip = useStore((s) => s.moveRoofGrip); setSelectedColumnIds,
const moveRoofBy = useStore((s) => s.moveRoofBy); selectedColumnId,
const selectedOpeningIds = useStore((s) => s.selectedOpeningIds); selectedContextObjectIds,
const setSelectedOpeningIds = useStore((s) => s.setSelectedOpeningIds); setSelectedContextObjectIds,
const selectedOpeningId = } = useSelectionState();
selectedOpeningIds.length === 1 ? selectedOpeningIds[0] : null;
const selectedStairIds = useStore((s) => s.selectedStairIds);
const setSelectedStairIds = useStore((s) => s.setSelectedStairIds);
const selectedStairId =
selectedStairIds.length === 1 ? selectedStairIds[0] : null;
const selectedRoomIds = useStore((s) => s.selectedRoomIds);
const setSelectedRoomIds = useStore((s) => s.setSelectedRoomIds);
const selectedRoomId =
selectedRoomIds.length === 1 ? selectedRoomIds[0] : null;
const selectedExtrudedSolidIds = useStore((s) => s.selectedExtrudedSolidIds);
const setSelectedExtrudedSolidIds = useStore((s) => s.setSelectedExtrudedSolidIds);
const selectedExtrudedSolidId =
selectedExtrudedSolidIds.length === 1 ? selectedExtrudedSolidIds[0] : null;
const selectedColumnIds = useStore((s) => s.selectedColumnIds);
const setSelectedColumnIds = useStore((s) => s.setSelectedColumnIds);
const selectedColumnId =
selectedColumnIds.length === 1 ? selectedColumnIds[0] : null;
const selectedContextObjectIds = useStore((s) => s.selectedContextObjectIds);
const setSelectedContextObjectIds = useStore((s) => s.setSelectedContextObjectIds);
// ── Kontextmenüs (transienter UI-State, bleibt lokal) ───────────────────── // ── Kontextmenüs (transienter UI-State, bleibt lokal) ─────────────────────
const { const {
+119
View File
@@ -0,0 +1,119 @@
// Bündelt die Auswahl-Zustände aller Bauteil-/Zeichnungs-Arten: je Art eine
// MENGE aus dem Store-Slice (Marquee/Mehrfachauswahl) plus ein daraus
// abgeleitetes Einzel-Element (nur bei genau einem gewählten Element) für die
// bestehende Einzel-Element-Maschinerie (Grips, Edit, Attribute, Object-Info).
// Dazu die 2D-Zeichenelement-Zwischenablage und den 3D-Live-Schnitt-Treiber
// (reiner Ansichts-Zustand, unabhängig von der Auswahl). Nur aus App()
// herausgezogen, um die Funktion zu entlasten — reine Zustands-Bündelung,
// keine Verhaltensänderung.
//
// Extrahiert aus App.tsx. Bezeichner englisch, Kommentare deutsch (CONVENTIONS.md).
import { useState } from "react";
import { useStore } from "./appStore";
import type { Drawing2D } from "../model/types";
export function useSelectionState() {
const selectedWallIds = useStore((s) => s.selectedWallIds);
const setSelectedWallIds = useStore((s) => s.setSelectedWallIds);
// 2D-Auswahl ist jetzt eine MENGE (Marquee/Mehrfach). Für die bestehende
// Einzel-Element-Maschinerie (Grips, Edit, Attribute, Object-Info) wird lokal
// der „eine" gewählte Zeichnungs-ID abgeleitet (nur bei genau einem Element);
// `setSelectedDrawingId` bleibt als bequeme Einzel-Setter-Hülle erhalten.
const selectedDrawingIds = useStore((s) => s.selectedDrawingIds);
const setSelectedDrawingIds = useStore((s) => s.setSelectedDrawingIds);
const selectedDrawingId =
selectedDrawingIds.length === 1 ? selectedDrawingIds[0] : null;
const setSelectedDrawingId = (id: string | null) =>
setSelectedDrawingIds(id ? [id] : []);
// Zwischenablage für 2D-Zeichenelemente (Ctrl/Cmd+C/V). Kopiert die GEWÄHLTEN
// Drawing2D tief; Einfügen legt Klone mit neuen IDs auf dem AKTIVEN Geschoss
// (Zeichnungsebene) an — so lässt sich z. B. importiertes Mobiliar über
// Geschosse hinweg wiederverwenden. Kategorie/Stil bleiben erhalten.
const [drawingClipboard, setDrawingClipboard] = useState<Drawing2D[]>([]);
// Bequemer Einzel-Selektor (erste gewählte Wand).
const selectedWallId = selectedWallIds[0] ?? null;
// Decken-Auswahl (MENGE); für die Einzel-Element-Maschinerie der „eine"
// gewählte (bei genau einem Element).
const selectedCeilingIds = useStore((s) => s.selectedCeilingIds);
const setSelectedCeilingIds = useStore((s) => s.setSelectedCeilingIds);
const selectedCeilingId =
selectedCeilingIds.length === 1 ? selectedCeilingIds[0] : null;
// Dach-Auswahl (MENGE); Einzel-Element bei genau einem gewählten Dach.
const selectedRoofIds = useStore((s) => s.selectedRoofIds);
const setSelectedRoofIds = useStore((s) => s.setSelectedRoofIds);
const selectedRoofId = selectedRoofIds.length === 1 ? selectedRoofIds[0] : null;
// Schnitt-/Ansichtslinien-Auswahl (Einzel-DrawingLevel-Id oder null).
const selectedSectionLineId = useStore((s) => s.selectedSectionLineId);
const setSelectedSectionLineId = useStore((s) => s.setSelectedSectionLineId);
// Welche Schnittlinie treibt den 3D-Live-Schnitt (reiner Ansichts-Zustand,
// unabhängig von der Auswahl — der Schnitt bleibt beim Klick woanders aktiv).
const [section3dCutId, setSection3dCutId] = useState<string | null>(null);
const updateRoof = useStore((s) => s.updateRoof);
const moveRoofGrip = useStore((s) => s.moveRoofGrip);
const moveRoofBy = useStore((s) => s.moveRoofBy);
const selectedOpeningIds = useStore((s) => s.selectedOpeningIds);
const setSelectedOpeningIds = useStore((s) => s.setSelectedOpeningIds);
const selectedOpeningId =
selectedOpeningIds.length === 1 ? selectedOpeningIds[0] : null;
const selectedStairIds = useStore((s) => s.selectedStairIds);
const setSelectedStairIds = useStore((s) => s.setSelectedStairIds);
const selectedStairId =
selectedStairIds.length === 1 ? selectedStairIds[0] : null;
const selectedRoomIds = useStore((s) => s.selectedRoomIds);
const setSelectedRoomIds = useStore((s) => s.setSelectedRoomIds);
const selectedRoomId =
selectedRoomIds.length === 1 ? selectedRoomIds[0] : null;
const selectedExtrudedSolidIds = useStore((s) => s.selectedExtrudedSolidIds);
const setSelectedExtrudedSolidIds = useStore((s) => s.setSelectedExtrudedSolidIds);
const selectedExtrudedSolidId =
selectedExtrudedSolidIds.length === 1 ? selectedExtrudedSolidIds[0] : null;
const selectedColumnIds = useStore((s) => s.selectedColumnIds);
const setSelectedColumnIds = useStore((s) => s.setSelectedColumnIds);
const selectedColumnId =
selectedColumnIds.length === 1 ? selectedColumnIds[0] : null;
const selectedContextObjectIds = useStore((s) => s.selectedContextObjectIds);
const setSelectedContextObjectIds = useStore((s) => s.setSelectedContextObjectIds);
return {
selectedWallIds,
setSelectedWallIds,
selectedDrawingIds,
setSelectedDrawingIds,
selectedDrawingId,
setSelectedDrawingId,
drawingClipboard,
setDrawingClipboard,
selectedWallId,
selectedCeilingIds,
setSelectedCeilingIds,
selectedCeilingId,
selectedRoofIds,
setSelectedRoofIds,
selectedRoofId,
selectedSectionLineId,
setSelectedSectionLineId,
section3dCutId,
setSection3dCutId,
updateRoof,
moveRoofGrip,
moveRoofBy,
selectedOpeningIds,
setSelectedOpeningIds,
selectedOpeningId,
selectedStairIds,
setSelectedStairIds,
selectedStairId,
selectedRoomIds,
setSelectedRoomIds,
selectedRoomId,
selectedExtrudedSolidIds,
setSelectedExtrudedSolidIds,
selectedExtrudedSolidId,
selectedColumnIds,
setSelectedColumnIds,
selectedColumnId,
selectedContextObjectIds,
setSelectedContextObjectIds,
};
}