Add typed widget references
This commit is contained in:
parent
5e625d6123
commit
f3bcae1f74
76 changed files with 4882 additions and 142 deletions
104
Tests/PorticoTests/WidgetRefTests.swift
Normal file
104
Tests/PorticoTests/WidgetRefTests.swift
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
import Testing
|
||||
@_spi(SGTKInternal) import Gtk
|
||||
@_spi(SGTKInternal) import Adw
|
||||
@_spi(Portico) import Portico
|
||||
|
||||
@MainActor @Suite(.serialized) struct WidgetRefTests {
|
||||
@Test func backwardReference() {
|
||||
guard Gtk.initCheck() else { return }
|
||||
let ref = WidgetRef<Adw.Carousel>()
|
||||
let root = AnyView(VStack {
|
||||
Carousel { Label(str: "a") }.ref(ref)
|
||||
CarouselIndicatorDots().carousel(ref.projectedValue)
|
||||
}).makeWidget(MountContext()) as! Gtk.Box
|
||||
|
||||
let first = root.getFirstChild()!
|
||||
let carousel = Adw.Carousel(retaining: first.pointer)
|
||||
let dots = Adw.CarouselIndicatorDots(retaining: first.getNextSibling()!.pointer)
|
||||
#expect(dots.getCarousel()?.pointer == carousel.pointer)
|
||||
}
|
||||
|
||||
@Test func forwardReference() {
|
||||
guard Gtk.initCheck() else { return }
|
||||
let ref = WidgetRef<Adw.Carousel>()
|
||||
let root = AnyView(VStack {
|
||||
CarouselIndicatorDots().carousel(ref.projectedValue)
|
||||
Carousel { Label(str: "a") }.ref(ref)
|
||||
}).makeWidget(MountContext()) as! Gtk.Box
|
||||
|
||||
let first = root.getFirstChild()!
|
||||
let dots = Adw.CarouselIndicatorDots(retaining: first.pointer)
|
||||
let carousel = Adw.Carousel(retaining: first.getNextSibling()!.pointer)
|
||||
#expect(dots.getCarousel()?.pointer == carousel.pointer)
|
||||
}
|
||||
|
||||
@Test func latePublishFromForEach() {
|
||||
guard Gtk.initCheck() else { return }
|
||||
let ref = WidgetRef<Adw.Carousel>()
|
||||
let items = StateBox<[Int]>([])
|
||||
let root = AnyView(VStack {
|
||||
CarouselIndicatorDots().carousel(ref.projectedValue)
|
||||
ForEach(Binding(items), id: \.self) { _ in
|
||||
Carousel().ref(ref)
|
||||
}
|
||||
}).makeWidget(MountContext()) as! Gtk.Box
|
||||
|
||||
let first = root.getFirstChild()!
|
||||
let dots = Adw.CarouselIndicatorDots(retaining: first.pointer)
|
||||
#expect(dots.getCarousel() == nil)
|
||||
|
||||
items.set([1])
|
||||
let rows = Gtk.Box(retaining: first.getNextSibling()!.pointer)
|
||||
let carousel = Adw.Carousel(retaining: rows.getFirstChild()!.pointer)
|
||||
#expect(dots.getCarousel()?.pointer == carousel.pointer)
|
||||
}
|
||||
|
||||
@Test func teardownClearsPublishedWidget() {
|
||||
guard Gtk.initCheck() else { return }
|
||||
let ref = WidgetRef<Adw.Carousel>()
|
||||
let items = StateBox<[Int]>([])
|
||||
let ctx = MountContext()
|
||||
_ = AnyView(VStack {
|
||||
CarouselIndicatorDots().carousel(ref.projectedValue)
|
||||
ForEach(Binding(items), id: \.self) { _ in
|
||||
Carousel().ref(ref)
|
||||
}
|
||||
}).makeWidget(ctx)
|
||||
|
||||
items.set([1])
|
||||
#expect(ref.wrappedValue != nil)
|
||||
ctx.registry.teardown()
|
||||
#expect(ref.wrappedValue == nil)
|
||||
}
|
||||
|
||||
/// A `WidgetRef` declared at the concrete subclass feeds a modifier whose property
|
||||
/// is declared `Gtk.Widget?`; the generated overload is generic, so `Binding`'s
|
||||
/// invariance does not reject it.
|
||||
@Test func widgetTypedBindingOverload() {
|
||||
guard Gtk.initCheck() else { return }
|
||||
let entryRef = WidgetRef<Gtk.Entry>()
|
||||
let root = AnyView(VStack {
|
||||
Entry().ref(entryRef)
|
||||
Label(str: "N").mnemonicWidget(entryRef.projectedValue)
|
||||
}).makeWidget(MountContext()) as! Gtk.Box
|
||||
|
||||
let first = root.getFirstChild()!
|
||||
let entry = Gtk.Entry(retaining: first.pointer)
|
||||
let label = Gtk.Label(retaining: first.getNextSibling()!.pointer)
|
||||
#expect(label.getMnemonicWidget()?.pointer == entry.pointer)
|
||||
}
|
||||
|
||||
@Test func loweredNullableBindingOverload() {
|
||||
guard Gtk.initCheck() else { return }
|
||||
let stackRef = WidgetRef<Gtk.Stack>()
|
||||
let root = AnyView(VStack {
|
||||
Stack().ref(stackRef)
|
||||
StackSidebar().stack(stackRef.projectedValue)
|
||||
}).makeWidget(MountContext()) as! Gtk.Box
|
||||
|
||||
let first = root.getFirstChild()!
|
||||
let stack = Gtk.Stack(retaining: first.pointer)
|
||||
let sidebar = Gtk.StackSidebar(retaining: first.getNextSibling()!.pointer)
|
||||
#expect(sidebar.getStack()?.pointer == stack.pointer)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue