Ebenen-Manager: Eye-Logik analog Geschosse + 'Alle anzeigen'-Mode

Eye-Knopf bleibt jetzt auch in „Nur aktive"-Mode sichtbar (dimmend, statt
zu verschwinden). Klick auf Eye in „Nur aktive" oder „Alle anzeigen"
wechselt automatisch zu „Ausgewählte" damit die Aktion wirkt.

Backend (layer_builder.apply_visibility): neuer e_mode 'all_force'
ueberschreibt das Eye-Flag (zeigt alle Ebenen). 'all' respektiert weiter
das Flag (= „Ausgewählte" im UI).

Frontend (EbenenManager):
- MODES: 'all_force'=„Alle anzeigen" hinzu, 'all' umbenannt zu „Ausgewählte"
- EbeneRow: eyeIcon/eyeOpacity/eyeTitle nach Mode, analog GeschossManager
- handleToggleVisible + Master-Eye: bei active/all_force → onModeChange('all')

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-20 13:26:25 +02:00
parent 68411a0ce9
commit b14eb1e5dd
2 changed files with 47 additions and 22 deletions
+5
View File
@@ -767,10 +767,15 @@ def apply_visibility(doc, zeichnungsebenen, ebenen, active_z_id, active_code, z_
is_active_e = (code == active_code)
eye_v = e_eye_vis.get(code, True)
eye_l = e_eye_locked.get(code, False)
# 'all_force' ueberschreibt das Eye-Flag (zeigt jede Ebene auch
# wenn die User-Sichtbarkeit aus war). 'all' respektiert das
# Flag (= "Ausgewählte" im UI).
if is_active_e:
e_vis, e_grey, e_lock = True, False, False
elif e_mode == "active":
e_vis, e_grey, e_lock = False, False, False
elif e_mode == "all_force":
e_vis, e_grey, e_lock = True, False, False
elif not eye_v:
e_vis, e_grey, e_lock = False, False, False
elif e_mode == "all":
+40 -20
View File
@@ -5,7 +5,8 @@ import ContextMenu from './ContextMenu'
import { setLayerStyle, deleteEbene, moveSelectionToEbene, openEbenenSettings } from '../lib/rhinoBridge'
const MODES = [
{ value: 'all', label: 'Alle anzeigen' },
{ value: 'all_force', label: 'Alle anzeigen' },
{ value: 'all', label: 'Ausgewählte' },
{ value: 'active', label: 'Nur aktive' },
{ value: 'grey', label: 'Andere grau' },
{ value: 'grey_locked', label: 'Andere grau & gesperrt' },
@@ -208,11 +209,33 @@ function _allCodes(ebenen) {
}
function EbeneRow({ e, depth, hasChildren, expanded, onToggleExpand, active, mode, onClick, onContextMenu, onToggleVisible, onToggleLock, onColorChange, onLwChange, onNameChange, onCodeChange, onDelete, autoEditCode, autoEditName, rowRef }) {
// Auge zeigt den Eye-State (User-Intention) — auch fuer die aktive Ebene.
// So sieht man auf einen Blick ob sie "normalerweise" sichtbar waere.
// Aktive Ebene rendert Rhino zwar immer sichtbar, das visible-Flag bleibt
// aber die gespeicherte Intention bis sie wieder de-aktiviert wird.
const eyeShown = mode !== 'active'
// Auge-Logik analog GeschossManager: immer rendern, nur dimmen wenn Mode
// das Eye-Flag ueberschreibt (active / all_force). Klick auf Auge in
// diesen Modi wechselt zu "Ausgewählte" damit die Aktion wirkt.
let eyeIcon, eyeOn, eyeOpacity, eyeTitle
if (active) {
eyeIcon = e.visible !== false ? 'visibility' : 'visibility_off'
eyeOn = true
eyeOpacity = 1
eyeTitle = e.visible !== false
? 'Normalerweise sichtbar (aktive Ebene wird trotzdem gezeigt)'
: 'Normalerweise ausgeblendet — wird nur sichtbar weil aktiv'
} else if (mode === 'all_force') {
eyeIcon = 'visibility'
eyeOn = true
eyeOpacity = 0.35
eyeTitle = 'Im „Alle anzeigen"-Mode immer sichtbar — Klick wechselt in „Ausgewählte"'
} else if (mode === 'active') {
eyeIcon = e.visible !== false ? 'visibility' : 'visibility_off'
eyeOn = false
eyeOpacity = 0.35
eyeTitle = 'Im „Nur aktive"-Mode ausgeblendet — Klick wechselt in „Ausgewählte"'
} else {
eyeIcon = e.visible !== false ? 'visibility' : 'visibility_off'
eyeOn = e.visible !== false
eyeOpacity = 1
eyeTitle = e.visible !== false ? 'Ausblenden' : 'Einblenden'
}
return (
<div
ref={rowRef}
@@ -247,21 +270,12 @@ function EbeneRow({ e, depth, hasChildren, expanded, onToggleExpand, active, mod
) : (
<span style={{ width: 14, flexShrink: 0 }} />
)}
{eyeShown ? (
<button
className={`btn-icon-sm ${e.visible !== false ? 'is-on' : ''}`}
className={`btn-icon-sm ${eyeOn ? 'is-on' : ''}`}
onClick={(ev) => { ev.stopPropagation(); onToggleVisible() }}
title={
active
? (e.visible !== false
? 'Normalerweise sichtbar (aktive Ebene wird trotzdem gezeigt)'
: 'Normalerweise ausgeblendet — wird nur sichtbar weil aktiv')
: (e.visible !== false ? 'Ausblenden' : 'Einblenden')
}
><Icon name={e.visible !== false ? 'visibility' : 'visibility_off'} size={14} /></button>
) : (
<span style={{ width: 18, flexShrink: 0 }} />
)}
title={eyeTitle}
style={{ opacity: eyeOpacity }}
><Icon name={eyeIcon} size={14} /></button>
<EditableText
value={e.code}
@@ -382,6 +396,10 @@ export default function EbenenManager({
const handleToggleVisible = (code) => {
const cur = _findInTree(ebenen, code)
if (cur) updateByCode(code, { visible: !(cur.visible !== false) })
// In "active" / "all_force" greift visible-Flag nicht — wer aufs Auge
// klickt will offensichtlich Sichtbarkeit kontrollieren, also direkt
// in den "Ausgewählte"-Mode wechseln damit die Aktion wirkt.
if (mode === 'active' || mode === 'all_force') onModeChange('all')
}
const handleToggleLock = (code) => {
const cur = _findInTree(ebenen, code)
@@ -555,11 +573,13 @@ export default function EbenenManager({
const anyVisible = ebenen.some(e => e.visible !== false)
// Wenn irgendeine sichtbar -> alle aus. Wenn keine sichtbar -> alle an.
onChange(ebenen.map(e => ({ ...e, visible: !anyVisible })))
if (mode === 'active' || mode === 'all_force') onModeChange('all')
}}
title={ebenen.every(e => e.visible !== false)
? 'Alle Ebenen ausblenden'
: 'Alle Ebenen einblenden'}
style={{ width: 18, height: 18 }}
style={{ width: 18, height: 18,
opacity: (mode === 'active' || mode === 'all_force') ? 0.5 : 1 }}
>
<Icon
name={ebenen.every(e => e.visible !== false) ? 'visibility' : 'visibility_off'}