Files
Vorrania/ios/Sources/Baum.swift
T
ScarriffleandClaude Opus 5 d7002e2252 App: Einrueckung haelt auch bei Umbruch, Loeschen fragt mittig
Eingerueckt wurde mit fuehrenden Leerzeichen. Die verschieben aber nur die
ERSTE Zeile: Bricht ein langer Name um ("Schublade Links Unten"), faengt die
Fortsetzung wieder ganz links an und die Hierarchie ist weg.

In einem aufklappenden Menue laesst sich das nicht loesen - dort liefert man
nur Text ab, das System ignoriert jedes Layout (auch lineLimit). Die
Lagerort- und Kategorieauswahl erscheint deshalb jetzt als Liste
(.pickerStyle(.navigationLink)). Dort ist jede Zeile eine echte Ansicht, ein
Innenabstand rueckt den ganzen Block ein - auch die zweite Zeile. Das liest
sich bei vielen Lagerorten ohnehin besser als ein langes Aufklappmenue.

Zwei enge Zeilen bleiben Menues: Mindestbestand je Ort bei Artikel und
Gruppe, wo direkt daneben das Mengenfeld steht. Dort wuerde eine
Listenauswahl die Zeile sprengen; sie behalten die Leerzeichen-Einrueckung.

Der Loeschdialog war ein confirmationDialog und fuhr als Blase von unten
herein. Jetzt ein alert: steht mittig und will gelesen werden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-15 21:12:29 +02:00

61 lines
2.3 KiB
Swift

import SwiftUI
/// Eine Zeile einer flach ausgelegten Baumliste, mit ihrer Tiefe.
///
/// Lagerorte und Kategorien sind Baeume, kommen vom Server aber als flache
/// Liste nach Namen sortiert. Daraus wird eine Auswahl, in der "Garage → Fach A"
/// und "Keller → Fach A" irgendwo zwischen allem anderen stehen - Geschwister
/// und Kinder finden nie zusammen. Diese Reihenfolge stellt das her.
struct Baumzeile<T: TreeItem>: Identifiable {
let item: T
let tiefe: Int
var id: T.ID { item.id }
/// Name mit Einrueckung aus fuehrenden Leerzeichen.
///
/// Nur fuer aufklappende Menues, wo man ausser Text nichts abliefern kann.
/// Der Nachteil bleibt dort bestehen: Bricht ein langer Name um, faengt die
/// zweite Zeile ganz links an. Wo es geht, `BaumZeile` nehmen.
var label: String { String(repeating: " ", count: tiefe) + item.name }
}
/// Auswahlzeile mit echter Einrueckung.
///
/// Fuehrende Leerzeichen verschieben nur die erste Zeile - ein langer Name
/// bricht um und die Fortsetzung steht wieder ganz links, womit die Hierarchie
/// verloren geht. Ein Innenabstand rueckt dagegen den ganzen Block ein.
///
/// Verlangt eine Auswahl, die als Liste erscheint (`.pickerStyle(.navigationLink)`):
/// In einem aufklappenden Menue zeigt das System nur den Text und ignoriert
/// jedes Layout.
struct BaumZeile<T: TreeItem>: View {
let zeile: Baumzeile<T>
var body: some View {
Text(zeile.item.name)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.leading, CGFloat(zeile.tiefe) * 16)
}
}
/// Bringt eine flache Eltern-Kind-Liste in Baumreihenfolge, mit Tiefe.
///
/// Waisen - deren Elternteil weggefiltert oder geloescht ist - gelten als
/// oberste Ebene. Ohne diese Regel verschwaenden sie lautlos aus der Auswahl.
func baum<T: TreeItem>(_ liste: [T]) -> [Baumzeile<T>] {
let ids = Set(liste.map(\.id))
var ergebnis: [Baumzeile<T>] = []
func gehe(_ knoten: T, _ tiefe: Int) {
ergebnis.append(Baumzeile(item: knoten, tiefe: tiefe))
for kind in liste.filter({ $0.parentId == knoten.id }) {
gehe(kind, tiefe + 1)
}
}
for wurzel in liste.filter({ $0.parentId == nil || !ids.contains($0.parentId!) }) {
gehe(wurzel, 0)
}
return ergebnis
}