Satelliten-Dialoge: embedded-Mode + GeschossDialog auch als echtes Fenster
Zwei Dinge: 1. embedded-Mode in den Dialog-Komponenten — wenn TRUE, kein Backdrop + keine MaxWidth-Constraint, das Dialog fuellt das ganze WebView statt wie ein kleines zentriertes Fenster IN dem WebView gerendert zu werden (= "Fenster im Fenster"-Effekt). Betroffen: - GeschossSettingsDialog - EbenenSettingsDialog - GeschossDialog Satelliten-Apps (GeschossSettingsApp, EbenenSettingsApp, GeschossDialogApp) passen jetzt `embedded` durch. 2. GeschossDialog (= der grosse Mehrfach-Editor hinter dem Pencil-Button) laeuft jetzt auch als Satelliten-Fenster — selbe Architektur wie die Settings-Dialoge. Backend hat neuen Handler _open_geschoss_dialog und neuen Message OPEN_GESCHOSS_DIALOG. Auf Save: ganze z-Liste replace + _apply(save_z=True). GeschossManager braucht den inline-Dialog-State nicht mehr; Pencil-Button ruft openGeschossDialog(zeichnungsebenen). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -221,6 +221,8 @@ class EbenenBridge(panel_base.BaseBridge):
|
|||||||
elif t == "OPEN_EBENEN_SETTINGS":
|
elif t == "OPEN_EBENEN_SETTINGS":
|
||||||
self._open_ebenen_settings(p.get("ebene") or {},
|
self._open_ebenen_settings(p.get("ebene") or {},
|
||||||
p.get("hatchPatterns") or [])
|
p.get("hatchPatterns") or [])
|
||||||
|
elif t == "OPEN_GESCHOSS_DIALOG":
|
||||||
|
self._open_geschoss_dialog(p.get("zeichnungsebenen") or [])
|
||||||
|
|
||||||
# ---- Helpers ----
|
# ---- Helpers ----
|
||||||
|
|
||||||
@@ -299,6 +301,27 @@ class EbenenBridge(panel_base.BaseBridge):
|
|||||||
size=(420, 600),
|
size=(420, 600),
|
||||||
on_save=on_save)
|
on_save=on_save)
|
||||||
|
|
||||||
|
def _open_geschoss_dialog(self, zeichnungsebenen):
|
||||||
|
"""Oeffnet den vollen GeschossDialog (Mehrfach-Editor) als
|
||||||
|
Satelliten-Fenster. Save schreibt die ganze z-Liste neu."""
|
||||||
|
if not isinstance(zeichnungsebenen, list):
|
||||||
|
print("[EBENEN] open_geschoss_dialog: keine Liste"); return
|
||||||
|
def on_save(payload):
|
||||||
|
doc = Rhino.RhinoDoc.ActiveDoc
|
||||||
|
if doc is None: return
|
||||||
|
new_z = payload.get("zeichnungsebenen") or []
|
||||||
|
if not new_z: return
|
||||||
|
e_raw = doc.Strings.GetValue("dossier_ebenen")
|
||||||
|
try: e_list = json.loads(e_raw) if e_raw else []
|
||||||
|
except Exception: e_list = []
|
||||||
|
self._apply(new_z, e_list, save_z=True, save_e=False)
|
||||||
|
panel_base.open_satellite_window(
|
||||||
|
"geschoss_dialog",
|
||||||
|
params={"zeichnungsebenen": zeichnungsebenen},
|
||||||
|
title="Zeichnungsebenen bearbeiten",
|
||||||
|
size=(560, 620),
|
||||||
|
on_save=on_save)
|
||||||
|
|
||||||
def _apply(self, zeichnungsebenen, ebenen, save_z=True, save_e=True):
|
def _apply(self, zeichnungsebenen, ebenen, save_z=True, save_e=True):
|
||||||
print("[EBENEN] _apply START z={} e={} (save_z={} save_e={})".format(
|
print("[EBENEN] _apply START z={} e={} (save_z={} save_e={})".format(
|
||||||
len(zeichnungsebenen) if zeichnungsebenen else 0,
|
len(zeichnungsebenen) if zeichnungsebenen else 0,
|
||||||
|
|||||||
@@ -26,17 +26,12 @@ export default function EbenenSettingsApp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<EbenenSettingsDialog
|
||||||
width: '100vw', height: '100vh',
|
embedded
|
||||||
background: 'var(--bg-base)',
|
ebene={ebene}
|
||||||
overflow: 'hidden',
|
hatchPatterns={hatchPatterns}
|
||||||
}}>
|
onSave={(updated) => bridgeSend('SAVE', updated)}
|
||||||
<EbenenSettingsDialog
|
onClose={() => bridgeSend('CANCEL', {})}
|
||||||
ebene={ebene}
|
/>
|
||||||
hatchPatterns={hatchPatterns}
|
|
||||||
onSave={(updated) => bridgeSend('SAVE', updated)}
|
|
||||||
onClose={() => bridgeSend('CANCEL', {})}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { useEffect } from 'react'
|
||||||
|
import GeschossDialog from './components/GeschossDialog'
|
||||||
|
import { notifyReady } from './lib/rhinoBridge'
|
||||||
|
|
||||||
|
function bridgeSend(type, payload = {}) {
|
||||||
|
if (!window.RHINO_MODE) { console.log('[Bridge] →', type, payload); return }
|
||||||
|
const json = JSON.stringify({ type, payload })
|
||||||
|
document.title = 'RHINOMSG::' + json
|
||||||
|
}
|
||||||
|
|
||||||
|
// recalcOkff direkt hier — gleiche Logik wie in ZeichnungsebenenApp.jsx,
|
||||||
|
// damit der Dialog die OKFF-Werte beim Editieren live updaten kann.
|
||||||
|
function recalcOkff(list) {
|
||||||
|
let acc = 0
|
||||||
|
return list.map(z => {
|
||||||
|
if (z.isGeschoss) {
|
||||||
|
const next = { ...z, okff: parseFloat(acc.toFixed(3)) }
|
||||||
|
acc += (z.hoehe ?? 3.0)
|
||||||
|
return next
|
||||||
|
}
|
||||||
|
return { ...z, okff: undefined }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function GeschossDialogApp() {
|
||||||
|
const initial = (typeof window !== 'undefined' && window.PANEL_PARAMS) || {}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
notifyReady()
|
||||||
|
const blockContext = (ev) => ev.preventDefault()
|
||||||
|
document.addEventListener('contextmenu', blockContext)
|
||||||
|
return () => document.removeEventListener('contextmenu', blockContext)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const z = initial.zeichnungsebenen || initial
|
||||||
|
if (!Array.isArray(z) || z.length === 0) {
|
||||||
|
return <div style={{ padding: 20, color: 'var(--text-muted)' }}>Keine Daten</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GeschossDialog
|
||||||
|
embedded
|
||||||
|
zeichnungsebenen={z}
|
||||||
|
recalcOkff={recalcOkff}
|
||||||
|
onSave={(updated) => bridgeSend('SAVE', { zeichnungsebenen: updated })}
|
||||||
|
onClose={() => bridgeSend('CANCEL', {})}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import GeschossSettingsDialog from './components/GeschossSettingsDialog'
|
import GeschossSettingsDialog from './components/GeschossSettingsDialog'
|
||||||
import { onMessage, notifyReady } from './lib/rhinoBridge'
|
import { notifyReady } from './lib/rhinoBridge'
|
||||||
|
|
||||||
// Inline send fuer SAVE/CANCEL — schickt direkt an Python-Bridge des
|
|
||||||
// Satelliten-Fensters.
|
|
||||||
function bridgeSend(type, payload = {}) {
|
function bridgeSend(type, payload = {}) {
|
||||||
if (!window.RHINO_MODE) { console.log('[Bridge] →', type, payload); return }
|
if (!window.RHINO_MODE) { console.log('[Bridge] →', type, payload); return }
|
||||||
const json = JSON.stringify({ type, payload })
|
const json = JSON.stringify({ type, payload })
|
||||||
@@ -11,33 +9,25 @@ function bridgeSend(type, payload = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function GeschossSettingsApp() {
|
export default function GeschossSettingsApp() {
|
||||||
// PANEL_PARAMS wurden von Python beim Window-Open injiziert.
|
|
||||||
const initial = (typeof window !== 'undefined' && window.PANEL_PARAMS) || {}
|
const initial = (typeof window !== 'undefined' && window.PANEL_PARAMS) || {}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
notifyReady()
|
notifyReady()
|
||||||
// Native Browser-Context-Menu unterdruecken
|
|
||||||
const blockContext = (ev) => ev.preventDefault()
|
const blockContext = (ev) => ev.preventDefault()
|
||||||
document.addEventListener('contextmenu', blockContext)
|
document.addEventListener('contextmenu', blockContext)
|
||||||
return () => document.removeEventListener('contextmenu', blockContext)
|
return () => document.removeEventListener('contextmenu', blockContext)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
// Wenn keine Daten da sind: leeres Frame
|
|
||||||
if (!initial || typeof initial !== 'object') {
|
if (!initial || typeof initial !== 'object') {
|
||||||
return <div style={{ padding: 20, color: 'var(--text-muted)' }}>Keine Daten</div>
|
return <div style={{ padding: 20, color: 'var(--text-muted)' }}>Keine Daten</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<GeschossSettingsDialog
|
||||||
width: '100vw', height: '100vh',
|
embedded
|
||||||
background: 'var(--bg-base)',
|
geschoss={initial}
|
||||||
overflow: 'hidden',
|
onSave={(updated) => bridgeSend('SAVE', updated)}
|
||||||
}}>
|
onClose={() => bridgeSend('CANCEL', {})}
|
||||||
<GeschossSettingsDialog
|
/>
|
||||||
geschoss={initial}
|
|
||||||
onSave={(updated) => bridgeSend('SAVE', updated)}
|
|
||||||
onClose={() => bridgeSend('CANCEL', {})}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ function SectionLabel({ children }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function EbenenSettingsDialog({ ebene, hatchPatterns = ['Solid'], onSave, onClose }) {
|
export default function EbenenSettingsDialog({ ebene, hatchPatterns = ['Solid'], onSave, onClose, embedded = false }) {
|
||||||
const [draft, setDraft] = useState({
|
const [draft, setDraft] = useState({
|
||||||
...ebene,
|
...ebene,
|
||||||
fill: {
|
fill: {
|
||||||
@@ -78,23 +78,35 @@ export default function EbenenSettingsDialog({ ebene, hatchPatterns = ['Solid'],
|
|||||||
...hatchPatterns.filter(p => p !== 'Solid' && p !== 'None'),
|
...hatchPatterns.filter(p => p !== 'Solid' && p !== 'None'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const wrapperStyle = embedded ? {
|
||||||
|
width: '100%', height: '100%',
|
||||||
|
background: 'var(--bg-dialog)',
|
||||||
|
display: 'flex', flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
} : {
|
||||||
|
position: 'absolute', inset: 0, zIndex: 150,
|
||||||
|
background: 'var(--bg-overlay)',
|
||||||
|
display: 'flex', alignItems: 'flex-start', justifyContent: 'center',
|
||||||
|
paddingTop: 30,
|
||||||
|
}
|
||||||
|
const innerStyle = embedded ? {
|
||||||
|
width: '100%', height: '100%',
|
||||||
|
display: 'flex', flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
} : {
|
||||||
|
background: 'var(--bg-dialog)',
|
||||||
|
border: '1px solid var(--border)',
|
||||||
|
borderRadius: 'var(--r-lg)',
|
||||||
|
boxShadow: 'var(--shadow-3)',
|
||||||
|
width: 'calc(100% - 16px)', maxWidth: 300,
|
||||||
|
display: 'flex', flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
maxHeight: 'calc(100vh - 60px)',
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div style={wrapperStyle}>
|
||||||
position: 'absolute', inset: 0, zIndex: 150,
|
<div style={innerStyle}>
|
||||||
background: 'var(--bg-overlay)',
|
|
||||||
display: 'flex', alignItems: 'flex-start', justifyContent: 'center',
|
|
||||||
paddingTop: 30,
|
|
||||||
}}>
|
|
||||||
<div style={{
|
|
||||||
background: 'var(--bg-dialog)',
|
|
||||||
border: '1px solid var(--border)',
|
|
||||||
borderRadius: 'var(--r-lg)',
|
|
||||||
boxShadow: 'var(--shadow-3)',
|
|
||||||
width: 'calc(100% - 16px)', maxWidth: 300,
|
|
||||||
display: 'flex', flexDirection: 'column',
|
|
||||||
overflow: 'hidden',
|
|
||||||
maxHeight: 'calc(100vh - 60px)',
|
|
||||||
}}>
|
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div style={{
|
<div style={{
|
||||||
display: 'flex', alignItems: 'center', gap: 6,
|
display: 'flex', alignItems: 'center', gap: 6,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import Icon from './Icon'
|
import Icon from './Icon'
|
||||||
|
|
||||||
export default function GeschossDialog({ zeichnungsebenen, recalcOkff, onSave, onClose }) {
|
export default function GeschossDialog({ zeichnungsebenen, recalcOkff, onSave, onClose, embedded = false }) {
|
||||||
const [draft, setDraft] = useState(zeichnungsebenen.map(z => ({ ...z })))
|
const [draft, setDraft] = useState(zeichnungsebenen.map(z => ({ ...z })))
|
||||||
|
|
||||||
const update = (i, field, val) => {
|
const update = (i, field, val) => {
|
||||||
@@ -56,23 +56,34 @@ export default function GeschossDialog({ zeichnungsebenen, recalcOkff, onSave, o
|
|||||||
del: { width: 22, flexShrink: 0 },
|
del: { width: 22, flexShrink: 0 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const wrapperStyle = embedded ? {
|
||||||
|
width: '100%', height: '100%',
|
||||||
|
background: 'var(--bg-dialog)',
|
||||||
|
display: 'flex', flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
} : {
|
||||||
|
position: 'absolute', inset: 0, zIndex: 100,
|
||||||
|
background: 'var(--bg-overlay)',
|
||||||
|
display: 'flex', alignItems: 'flex-start', justifyContent: 'center',
|
||||||
|
paddingTop: 40,
|
||||||
|
}
|
||||||
|
const innerStyle = embedded ? {
|
||||||
|
width: '100%', height: '100%',
|
||||||
|
display: 'flex', flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
} : {
|
||||||
|
background: 'var(--bg-dialog)',
|
||||||
|
border: '1px solid var(--border)',
|
||||||
|
borderRadius: 'var(--r-lg)',
|
||||||
|
width: 'calc(100% - 24px)',
|
||||||
|
boxShadow: 'var(--shadow)',
|
||||||
|
display: 'flex', flexDirection: 'column',
|
||||||
|
maxHeight: 'calc(100vh - 80px)',
|
||||||
|
overflow: 'hidden',
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div style={wrapperStyle}>
|
||||||
position: 'absolute', inset: 0, zIndex: 100,
|
<div style={innerStyle}>
|
||||||
background: 'var(--bg-overlay)',
|
|
||||||
display: 'flex', alignItems: 'flex-start', justifyContent: 'center',
|
|
||||||
paddingTop: 40,
|
|
||||||
}}>
|
|
||||||
<div style={{
|
|
||||||
background: 'var(--bg-dialog)',
|
|
||||||
border: '1px solid var(--border)',
|
|
||||||
borderRadius: 'var(--r-lg)',
|
|
||||||
width: 'calc(100% - 24px)',
|
|
||||||
boxShadow: 'var(--shadow)',
|
|
||||||
display: 'flex', flexDirection: 'column',
|
|
||||||
maxHeight: 'calc(100vh - 80px)',
|
|
||||||
overflow: 'hidden',
|
|
||||||
}}>
|
|
||||||
<div style={{
|
<div style={{
|
||||||
display: 'flex', alignItems: 'center', gap: 8,
|
display: 'flex', alignItems: 'center', gap: 8,
|
||||||
padding: '10px 14px', borderBottom: '1px solid var(--border)', flexShrink: 0,
|
padding: '10px 14px', borderBottom: '1px solid var(--border)', flexShrink: 0,
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { useState } from 'react'
|
|
||||||
import Icon from './Icon'
|
import Icon from './Icon'
|
||||||
import GeschossDialog from './GeschossDialog'
|
import { openGeschossSettings, openGeschossDialog } from '../lib/rhinoBridge'
|
||||||
import { openGeschossSettings } from '../lib/rhinoBridge'
|
|
||||||
|
|
||||||
function GeschossBadge({ name }) {
|
function GeschossBadge({ name }) {
|
||||||
return <span className="chip chip-info">{name}</span>
|
return <span className="chip chip-info">{name}</span>
|
||||||
@@ -85,7 +83,8 @@ export default function GeschossManager({
|
|||||||
zeichnungsebenen, activeId, onActiveChange, onChange, recalcOkff,
|
zeichnungsebenen, activeId, onActiveChange, onChange, recalcOkff,
|
||||||
mode, onModeChange,
|
mode, onModeChange,
|
||||||
}) {
|
}) {
|
||||||
const [dialogOpen, setDialogOpen] = useState(false)
|
// dialogOpen-State entfaellt — Bearbeiten-Dialog laeuft jetzt als
|
||||||
|
// Satelliten-Fenster via openGeschossDialog().
|
||||||
|
|
||||||
const sorted = [...zeichnungsebenen].reverse()
|
const sorted = [...zeichnungsebenen].reverse()
|
||||||
const gesamthoehe = zeichnungsebenen
|
const gesamthoehe = zeichnungsebenen
|
||||||
@@ -134,7 +133,7 @@ export default function GeschossManager({
|
|||||||
<button className="btn-icon-sm" onClick={addQuick} title="Zeichnungsebene hinzufügen">
|
<button className="btn-icon-sm" onClick={addQuick} title="Zeichnungsebene hinzufügen">
|
||||||
<Icon name="add" size={14} />
|
<Icon name="add" size={14} />
|
||||||
</button>
|
</button>
|
||||||
<button className="btn-icon-sm" onClick={() => setDialogOpen(true)} title="Bearbeiten">
|
<button className="btn-icon-sm" onClick={() => openGeschossDialog(zeichnungsebenen)} title="Bearbeiten">
|
||||||
<Icon name="edit" size={13} />
|
<Icon name="edit" size={13} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -166,15 +165,6 @@ export default function GeschossManager({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{dialogOpen && (
|
|
||||||
<GeschossDialog
|
|
||||||
zeichnungsebenen={zeichnungsebenen}
|
|
||||||
recalcOkff={recalcOkff}
|
|
||||||
onSave={(updated) => { onChange(updated); setDialogOpen(false) }}
|
|
||||||
onClose={() => setDialogOpen(false)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function Toggle({ label, checked, onChange, hint }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function GeschossSettingsDialog({ geschoss, onSave, onClose }) {
|
export default function GeschossSettingsDialog({ geschoss, onSave, onClose, embedded = false }) {
|
||||||
const [draft, setDraft] = useState({ ...geschoss })
|
const [draft, setDraft] = useState({ ...geschoss })
|
||||||
const set = (patch) => setDraft({ ...draft, ...patch })
|
const set = (patch) => setDraft({ ...draft, ...patch })
|
||||||
|
|
||||||
@@ -46,22 +46,37 @@ export default function GeschossSettingsDialog({ geschoss, onSave, onClose }) {
|
|||||||
const okff = draft.okff ?? 0
|
const okff = draft.okff ?? 0
|
||||||
const clipZ = (okff + schnitt).toFixed(2)
|
const clipZ = (okff + schnitt).toFixed(2)
|
||||||
|
|
||||||
|
// embedded=true: in einem Satelliten-Fenster gerendert — kein Backdrop,
|
||||||
|
// keine Width-Constraint, fuellt das ganze WebView.
|
||||||
|
const Wrapper = embedded ? 'div' : 'div'
|
||||||
|
const wrapperStyle = embedded ? {
|
||||||
|
width: '100%', height: '100%',
|
||||||
|
background: 'var(--bg-dialog)',
|
||||||
|
display: 'flex', flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
} : {
|
||||||
|
position: 'absolute', inset: 0, zIndex: 150,
|
||||||
|
background: 'var(--bg-overlay)',
|
||||||
|
display: 'flex', alignItems: 'flex-start', justifyContent: 'center',
|
||||||
|
paddingTop: 30,
|
||||||
|
}
|
||||||
|
const innerStyle = embedded ? {
|
||||||
|
width: '100%', height: '100%',
|
||||||
|
display: 'flex', flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
} : {
|
||||||
|
background: 'var(--bg-dialog)',
|
||||||
|
border: '1px solid var(--border)',
|
||||||
|
borderRadius: 'var(--r-lg)',
|
||||||
|
boxShadow: 'var(--shadow-3)',
|
||||||
|
width: 'calc(100% - 16px)', maxWidth: 280,
|
||||||
|
display: 'flex', flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<Wrapper style={wrapperStyle}>
|
||||||
position: 'absolute', inset: 0, zIndex: 150,
|
<div style={innerStyle}>
|
||||||
background: 'var(--bg-overlay)',
|
|
||||||
display: 'flex', alignItems: 'flex-start', justifyContent: 'center',
|
|
||||||
paddingTop: 30,
|
|
||||||
}}>
|
|
||||||
<div style={{
|
|
||||||
background: 'var(--bg-dialog)',
|
|
||||||
border: '1px solid var(--border)',
|
|
||||||
borderRadius: 'var(--r-lg)',
|
|
||||||
boxShadow: 'var(--shadow-3)',
|
|
||||||
width: 'calc(100% - 16px)', maxWidth: 280,
|
|
||||||
display: 'flex', flexDirection: 'column',
|
|
||||||
overflow: 'hidden',
|
|
||||||
}}>
|
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div style={{
|
<div style={{
|
||||||
display: 'flex', alignItems: 'center', gap: 6,
|
display: 'flex', alignItems: 'center', gap: 6,
|
||||||
@@ -155,6 +170,6 @@ export default function GeschossSettingsDialog({ geschoss, onSave, onClose }) {
|
|||||||
}}>Übernehmen</button>
|
}}>Übernehmen</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Wrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,6 +285,9 @@ export function openGeschossSettings(geschoss) {
|
|||||||
export function openEbenenSettings(ebene, hatchPatterns) {
|
export function openEbenenSettings(ebene, hatchPatterns) {
|
||||||
send('OPEN_EBENEN_SETTINGS', { ebene, hatchPatterns })
|
send('OPEN_EBENEN_SETTINGS', { ebene, hatchPatterns })
|
||||||
}
|
}
|
||||||
|
export function openGeschossDialog(zeichnungsebenen) {
|
||||||
|
send('OPEN_GESCHOSS_DIALOG', { zeichnungsebenen })
|
||||||
|
}
|
||||||
|
|
||||||
export function applyVisibility(activeZ, zeichnungsebenen, activeCode, ebenen, zMode, eMode) {
|
export function applyVisibility(activeZ, zeichnungsebenen, activeCode, ebenen, zMode, eMode) {
|
||||||
// Split-Panels koennen mit null/[] fuer fremde Slice aufrufen — Backend
|
// Split-Panels koennen mit null/[] fuer fremde Slice aufrufen — Backend
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import App from './App.jsx'
|
|||||||
import ZeichnungsebenenApp from './ZeichnungsebenenApp.jsx'
|
import ZeichnungsebenenApp from './ZeichnungsebenenApp.jsx'
|
||||||
import GeschossSettingsApp from './GeschossSettingsApp.jsx'
|
import GeschossSettingsApp from './GeschossSettingsApp.jsx'
|
||||||
import EbenenSettingsApp from './EbenenSettingsApp.jsx'
|
import EbenenSettingsApp from './EbenenSettingsApp.jsx'
|
||||||
|
import GeschossDialogApp from './GeschossDialogApp.jsx'
|
||||||
import GestaltungApp from './GestaltungApp.jsx'
|
import GestaltungApp from './GestaltungApp.jsx'
|
||||||
import AusschnitteApp from './AusschnitteApp.jsx'
|
import AusschnitteApp from './AusschnitteApp.jsx'
|
||||||
import MassstabApp from './MassstabApp.jsx'
|
import MassstabApp from './MassstabApp.jsx'
|
||||||
@@ -28,6 +29,7 @@ const RootApp = mode === 'gestaltung' ? GestaltungApp
|
|||||||
: mode === 'zeichnungsebenen' ? ZeichnungsebenenApp
|
: mode === 'zeichnungsebenen' ? ZeichnungsebenenApp
|
||||||
: mode === 'geschoss_settings' ? GeschossSettingsApp
|
: mode === 'geschoss_settings' ? GeschossSettingsApp
|
||||||
: mode === 'ebenen_settings' ? EbenenSettingsApp
|
: mode === 'ebenen_settings' ? EbenenSettingsApp
|
||||||
|
: mode === 'geschoss_dialog' ? GeschossDialogApp
|
||||||
: App
|
: App
|
||||||
|
|
||||||
window.onerror = function (msg, src, line, col, err) {
|
window.onerror = function (msg, src, line, col, err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user