david-swift 4e95e4e655
Some checks failed
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Has been cancelled
Implement proper self destruction of signals
2025-08-14 23:24:30 +02:00

83 lines
2.7 KiB
Swift

//
// WindowView.swift
// Adwaita
//
// Created by david-swift on 06.08.24.
//
/// A storage type is a view storage or a scene storage.
public protocol Storage: AnyObject {
/// The pointer.
var opaquePointer: OpaquePointer? { get }
/// Additional fields.
var fields: [String: Any] { get set }
}
extension Storage {
/// Connect a handler to the observer of a property.
/// - Parameters:
/// - name: The property's name.
/// - id: The handlers id to separate form others connecting to the signal.
/// - pointer: A custom pointer instead of the stored one.
/// - handler: The signal's handler.
public func notify(
name: String,
id: String = "",
pointer: OpaquePointer? = nil,
handler: @escaping () -> Void
) {
let name = "notify::" + name
connectSignal(name: name, id: id, argCount: 1, pointer: pointer, handler: handler)
}
/// Connect a handler to a signal.
/// - Parameters:
/// - name: The signal's name.
/// - id: The handlers id to separate form others connecting to the signal.
/// - connectFlags: The GConnectFlags.
/// - argCount: The number of additional arguments (without the first and the last one).
/// - pointer: A custom pointer instead of the stored one.
/// - handler: The signal's handler.
public func connectSignal(
name: String,
id: String = "",
argCount: Int = 0,
pointer: OpaquePointer? = nil,
handler: @escaping () -> Void
) {
connectSignal(name: name, id: id, argCount: argCount, pointer: pointer) { _ in
handler()
}
}
/// Connect a handler to a signal.
/// - Parameters:
/// - name: The signal's name.
/// - id: The handlers id to separate form others connecting to the signal.
/// - argCount: The number of additional arguments (without the first and the last one).
/// - pointer: A custom pointer instead of the stored one.
/// - handler: The signal's handler.
public func connectSignal(
name: String,
id: String = "",
argCount: Int = 0,
pointer: OpaquePointer? = nil,
handler: @escaping ([Any]) -> Void
) {
if let data = fields[name + id] as? SignalData {
data.closure = handler
} else {
let data = SignalData(closure: handler) { [self] in fields[name + id] = nil }
fields[name + id] = data
data.connect(pointer: (pointer ?? opaquePointer)?.cast(), signal: name, argCount: argCount)
}
}
}
extension ViewStorage: Storage { }
extension SceneStorage: Storage { }