david-swift d8de611510 Add support for auto-generated widget bindings
Additionally fix an update problem occurring with custom views
2024-01-22 21:45:31 +01:00

139 lines
3.9 KiB
Swift

//
// GTUIFileDialog.swift
// Adwaita
//
// Created by david-swift on 09.12.23.
//
import CAdw
import Foundation
/// A GTUI file dialog window.
public class GTUIFileDialog: WindowType {
/// The file dialog's pointer.
public var pointer: OpaquePointer?
/// Fields for additional data.
public var fields: [String: Any] = [:]
/// A link to the file dialog.
var selfAddr: UInt64 {
unsafeBitCast(self, to: UInt64.self)
}
/// The parent window.
var parent: OpaquePointer?
/// Whether the file dialog is an importer.
var isImporter = false
/// The selected folder in the file dialog.
var folder: URL?
/// A closure triggered on selecting a file in the dialog.
var onResult: (URL) -> Void = { _ in }
/// A closure triggered when the dialog is canceled.
var onCancel: () -> Void = { }
/// Initialize the window.
public init() {
pointer = gtk_file_dialog_new()
}
/// Set the window's parent window.
/// - Parameter parent: The parent window.
public func setParentWindow(_ parent: WindowType) {
if let window = parent as? GTUIWindow {
self.parent = .init(window.pointer)
}
}
/// Set the initial name.
/// - Parameter name: The parent window.
public func setInitialName(_ name: String) {
gtk_file_dialog_set_initial_name(pointer, name)
}
// swiftlint:disable discouraged_optional_collection
/// Set the allowed file extensions.
/// - Parameters:
/// - extensions: The file extensions.
public func setExtensions(_ extensions: [String]?) {
if let extensions {
let filter = gtk_file_filter_new()
for name in extensions {
gtk_file_filter_add_suffix(filter, name)
}
gtk_file_dialog_set_default_filter(pointer, filter)
} else {
gtk_file_dialog_set_default_filter(pointer, nil)
}
}
// swiftlint:enable discouraged_optional_collection
/// Display the file dialog.
public func show() {
if let folder {
gtk_file_dialog_set_initial_folder(pointer, g_file_new_for_path(folder.absoluteString))
}
if isImporter {
gtui_filedialog_open(UInt64(Int(bitPattern: pointer)), selfAddr, UInt64(Int(bitPattern: parent)))
} else {
gtui_filedialog_save(UInt64(Int(bitPattern: pointer)), selfAddr, UInt64(Int(bitPattern: parent)))
}
}
/// Run this when a file gets opened.
/// - Parameter path: The file path.
func onOpen(_ path: String) {
let url = URL(fileURLWithPath: path)
onResult(url)
}
/// Run this when a file gets saved.
/// - Parameter path: The file path.
func onSave(_ path: String) {
let url = URL(fileURLWithPath: path)
onResult(url)
}
/// Run this when the user cancels the action.
func onClose() {
onCancel()
}
}
/// Run when a file should be opened.
/// - Parameters:
/// - ptr: The pointer.
/// - file: The path to the file.
/// - userData: The file dialog data.
@_cdecl("filedialog_on_open_cb")
func filedialog_on_open_cb(
ptr: UnsafeMutableRawPointer,
file: UnsafePointer<CChar>?,
userData: UnsafeMutableRawPointer
) {
let dialog = Unmanaged<GTUIFileDialog>.fromOpaque(userData).takeUnretainedValue()
if let file {
dialog.onOpen(.init(cString: file))
} else {
dialog.onClose()
}
}
/// Run when a file should be saved.
/// - Parameters:
/// - ptr: The pointer.
/// - file: The path to the file.
/// - userData: The file dialog data.
@_cdecl("filedialog_on_save_cb")
func filedialog_on_save_cb(
ptr: UnsafeMutableRawPointer,
file: UnsafePointer<CChar>?,
userData: UnsafeMutableRawPointer
) {
let dialog = Unmanaged<GTUIFileDialog>.fromOpaque(userData).takeUnretainedValue()
if let file {
dialog.onSave(.init(cString: file))
} else {
dialog.onClose()
}
}