Implement proper self destruction of signals
This commit is contained in:
parent
049b5b54f8
commit
4e95e4e655
@ -12,6 +12,8 @@ public class SignalData {
|
|||||||
|
|
||||||
/// The closure.
|
/// The closure.
|
||||||
public var closure: ([Any?]) -> Void
|
public var closure: ([Any?]) -> Void
|
||||||
|
/// Destroy the class.
|
||||||
|
public var selfDestruction: (() -> Void)?
|
||||||
|
|
||||||
/// The closure as a C handler.
|
/// The closure as a C handler.
|
||||||
var handler: @convention(c) (UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> Void {
|
var handler: @convention(c) (UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> Void {
|
||||||
@ -61,15 +63,20 @@ public class SignalData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the signal data.
|
/// Initialize the signal data.
|
||||||
/// - Parameter closure: The signal's closure.
|
/// - Parameters:
|
||||||
public convenience init(closure: @escaping () -> Void) {
|
/// - closure: The signal's closure.
|
||||||
self.init { _ in closure() }
|
/// - destroy: The self destruction.
|
||||||
|
public convenience init(closure: @escaping () -> Void, destroy: (() -> Void)? = nil) {
|
||||||
|
self.init(closure: { _ in closure() }, destroy: destroy)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the signal data.
|
/// Initialize the signal data.
|
||||||
/// - Parameter closure: The signal's closure.
|
/// - Parameters:
|
||||||
public init(closure: @escaping ([Any]) -> Void) {
|
/// - closure: The signal's closure.
|
||||||
|
/// - destroy: The self destruction.
|
||||||
|
public init(closure: @escaping ([Any]) -> Void, destroy: (() -> Void)? = nil) {
|
||||||
self.closure = closure
|
self.closure = closure
|
||||||
|
self.selfDestruction = destroy
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Connect the signal data to a signal.
|
/// Connect the signal data to a signal.
|
||||||
@ -88,12 +95,19 @@ public class SignalData {
|
|||||||
} else {
|
} else {
|
||||||
callback = unsafeBitCast(handler, to: GCallback.self)
|
callback = unsafeBitCast(handler, to: GCallback.self)
|
||||||
}
|
}
|
||||||
|
let destroy: GClosureNotify = { data, _ in
|
||||||
|
guard let data else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let signalData: SignalData = Unmanaged.fromOpaque(data).takeUnretainedValue()
|
||||||
|
signalData.selfDestruction?()
|
||||||
|
}
|
||||||
g_signal_connect_data(
|
g_signal_connect_data(
|
||||||
pointer,
|
pointer,
|
||||||
signal,
|
signal,
|
||||||
callback,
|
callback,
|
||||||
Unmanaged.passUnretained(self).toOpaque().cast(),
|
Unmanaged.passUnretained(self).toOpaque().cast(),
|
||||||
nil,
|
destroy,
|
||||||
G_CONNECT_AFTER
|
G_CONNECT_AFTER
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,7 +70,7 @@ extension Storage {
|
|||||||
if let data = fields[name + id] as? SignalData {
|
if let data = fields[name + id] as? SignalData {
|
||||||
data.closure = handler
|
data.closure = handler
|
||||||
} else {
|
} else {
|
||||||
let data = SignalData(closure: handler)
|
let data = SignalData(closure: handler) { [self] in fields[name + id] = nil }
|
||||||
fields[name + id] = data
|
fields[name + id] = data
|
||||||
data.connect(pointer: (pointer ?? opaquePointer)?.cast(), signal: name, argCount: argCount)
|
data.connect(pointer: (pointer ?? opaquePointer)?.cast(), signal: name, argCount: argCount)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -125,9 +125,11 @@ public struct AlertDialog: AdwaitaWidget {
|
|||||||
) where Data: ViewRenderData {
|
) where Data: ViewRenderData {
|
||||||
storage.fields[Self.visibleID + id] = _visible
|
storage.fields[Self.visibleID + id] = _visible
|
||||||
child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
|
child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
|
||||||
|
defer {
|
||||||
if let storage = storage.content["extra-child"]?.first, visible {
|
if let storage = storage.content["extra-child"]?.first, visible {
|
||||||
extraChild?.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
|
extraChild?.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
guard updateProperties else {
|
guard updateProperties else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -168,7 +170,6 @@ public struct AlertDialog: AdwaitaWidget {
|
|||||||
let dialog = storage.content[Self.dialogID + id]?.first?.opaquePointer
|
let dialog = storage.content[Self.dialogID + id]?.first?.opaquePointer
|
||||||
adw_dialog_close(dialog?.cast())
|
adw_dialog_close(dialog?.cast())
|
||||||
storage.content[Self.dialogID] = []
|
storage.content[Self.dialogID] = []
|
||||||
storage.content["extra-child"] = nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -173,11 +173,13 @@ public struct PreferencesDialog: AdwaitaWidget {
|
|||||||
if let storage = storage.content[.mainContent]?.first {
|
if let storage = storage.content[.mainContent]?.first {
|
||||||
child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
|
child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
|
||||||
}
|
}
|
||||||
|
defer {
|
||||||
for (index, page) in pages.enumerated() {
|
for (index, page) in pages.enumerated() {
|
||||||
if let preferences = storage.content["preferences-\(index)"] {
|
if let preferences = storage.content["preferences-\(index)"] {
|
||||||
page.update(groups: preferences, data: data, updateProperties: updateProperties)
|
page.update(groups: preferences, data: data, updateProperties: updateProperties)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
guard updateProperties else {
|
guard updateProperties else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -121,10 +121,12 @@ public struct Window: AdwaitaSceneElement {
|
|||||||
.storage(data: .init(sceneStorage: storage, appStorage: app), type: AdwaitaMainView.self)
|
.storage(data: .init(sceneStorage: storage, appStorage: app), type: AdwaitaMainView.self)
|
||||||
adw_application_window_set_content(window.pointer?.cast(), viewStorage.opaquePointer?.cast())
|
adw_application_window_set_content(window.pointer?.cast(), viewStorage.opaquePointer?.cast())
|
||||||
storage.content[.mainContent] = [viewStorage]
|
storage.content[.mainContent] = [viewStorage]
|
||||||
|
let observeID = "destroy"
|
||||||
let data = SignalData {
|
let data = SignalData {
|
||||||
storage.destroy = true
|
storage.destroy = true
|
||||||
|
} destroy: {
|
||||||
|
window.signals[observeID] = nil
|
||||||
}
|
}
|
||||||
let observeID = "destroy"
|
|
||||||
data.connect(pointer: window.pointer, signal: observeID)
|
data.connect(pointer: window.pointer, signal: observeID)
|
||||||
window.signals[observeID] = data
|
window.signals[observeID] = data
|
||||||
let template = getTemplate(content: content)
|
let template = getTemplate(content: content)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user