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>
61 lines
2.3 KiB
Swift
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
|
|
}
|