forked from aparoksha/adwaita-swift
Make FileDialog a window
This commit is contained in:
parent
2249ef2d6a
commit
083b352348
@ -10,6 +10,7 @@
|
|||||||
- [Widget](protocols/Widget.md)
|
- [Widget](protocols/Widget.md)
|
||||||
- [WindowScene](protocols/WindowScene.md)
|
- [WindowScene](protocols/WindowScene.md)
|
||||||
- [WindowSceneGroup](protocols/WindowSceneGroup.md)
|
- [WindowSceneGroup](protocols/WindowSceneGroup.md)
|
||||||
|
- [WindowType](protocols/WindowType.md)
|
||||||
|
|
||||||
## Structs
|
## Structs
|
||||||
|
|
||||||
@ -20,6 +21,7 @@
|
|||||||
- [Clamp](structs/Clamp.md)
|
- [Clamp](structs/Clamp.md)
|
||||||
- [ContentModifier](structs/ContentModifier.md)
|
- [ContentModifier](structs/ContentModifier.md)
|
||||||
- [EitherView](structs/EitherView.md)
|
- [EitherView](structs/EitherView.md)
|
||||||
|
- [FileDialog](structs/FileDialog.md)
|
||||||
- [HStack](structs/HStack.md)
|
- [HStack](structs/HStack.md)
|
||||||
- [HeaderBar](structs/HeaderBar.md)
|
- [HeaderBar](structs/HeaderBar.md)
|
||||||
- [InspectorWrapper](structs/InspectorWrapper.md)
|
- [InspectorWrapper](structs/InspectorWrapper.md)
|
||||||
@ -59,6 +61,8 @@
|
|||||||
|
|
||||||
- [App](extensions/App.md)
|
- [App](extensions/App.md)
|
||||||
- [Array](extensions/Array.md)
|
- [Array](extensions/Array.md)
|
||||||
|
- [GTUIWindow](extensions/GTUIWindow.md)
|
||||||
|
- [Libadwaita.FileDialog](extensions/Libadwaita.FileDialog.md)
|
||||||
- [MenuItem](extensions/MenuItem.md)
|
- [MenuItem](extensions/MenuItem.md)
|
||||||
- [MenuItemGroup](extensions/MenuItemGroup.md)
|
- [MenuItemGroup](extensions/MenuItemGroup.md)
|
||||||
- [NativeWidgetPeer](extensions/NativeWidgetPeer.md)
|
- [NativeWidgetPeer](extensions/NativeWidgetPeer.md)
|
||||||
|
|||||||
@ -19,21 +19,17 @@ Whether the reference to the window should disappear in the next update.
|
|||||||
|
|
||||||
### `window`
|
### `window`
|
||||||
|
|
||||||
The GTUI window.
|
The window.
|
||||||
|
|
||||||
### `view`
|
### `view`
|
||||||
|
|
||||||
The content's storage.
|
The content's storage.
|
||||||
|
|
||||||
### `fileDialog`
|
|
||||||
|
|
||||||
The file dialog for the window.
|
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
### `init(id:window:view:)`
|
### `init(id:window:view:)`
|
||||||
|
|
||||||
Initialize a window storage.
|
Initialize a window storage.
|
||||||
- Parameters:
|
- Parameters:
|
||||||
- id: The window's identifier.
|
- id: The window's identifier.
|
||||||
- window: The GTUI window.
|
- window: The window.
|
||||||
- view: The content's storage.
|
- view: The content's storage.
|
||||||
|
|||||||
9
Documentation/Reference/extensions/GTUIWindow.md
Normal file
9
Documentation/Reference/extensions/GTUIWindow.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
**EXTENSION**
|
||||||
|
|
||||||
|
# `GTUIWindow`
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
### `setParentWindow(_:)`
|
||||||
|
|
||||||
|
Set the window's parent window.
|
||||||
|
- Parameter parent: The parent window.
|
||||||
48
Documentation/Reference/extensions/Libadwaita.FileDialog.md
Normal file
48
Documentation/Reference/extensions/Libadwaita.FileDialog.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
**EXTENSION**
|
||||||
|
|
||||||
|
# `Libadwaita.FileDialog`
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
### `importer`
|
||||||
|
|
||||||
|
An ID for the importer field.
|
||||||
|
|
||||||
|
### `folder`
|
||||||
|
|
||||||
|
An ID for the folder field.
|
||||||
|
|
||||||
|
### `result`
|
||||||
|
|
||||||
|
An ID for the result field.
|
||||||
|
|
||||||
|
### `cancel`
|
||||||
|
|
||||||
|
An ID for the cancel field.
|
||||||
|
|
||||||
|
### `isImporter`
|
||||||
|
|
||||||
|
Whether the file dialog is an importer.
|
||||||
|
|
||||||
|
### `folder`
|
||||||
|
|
||||||
|
The selected folder in the file dialog.
|
||||||
|
|
||||||
|
### `onResult`
|
||||||
|
|
||||||
|
A closure triggered on selecting a file in the dialog.
|
||||||
|
|
||||||
|
### `onCancel`
|
||||||
|
|
||||||
|
A closure triggered when the dialog is canceled.
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
### `setParentWindow(_:)`
|
||||||
|
|
||||||
|
Set the window's parent window.
|
||||||
|
- Parameter parent: The parent window.
|
||||||
|
|
||||||
|
Currently not implemented.
|
||||||
|
|
||||||
|
### `show()`
|
||||||
|
|
||||||
|
Display the file dialog.
|
||||||
20
Documentation/Reference/protocols/WindowType.md
Normal file
20
Documentation/Reference/protocols/WindowType.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
**PROTOCOL**
|
||||||
|
|
||||||
|
# `WindowType`
|
||||||
|
|
||||||
|
A window type.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
### `fields`
|
||||||
|
|
||||||
|
A dictionary for custom data.
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
### `setParentWindow(_:)`
|
||||||
|
|
||||||
|
Set a parent window.
|
||||||
|
- Parameter parent: The parent window.
|
||||||
|
|
||||||
|
### `show()`
|
||||||
|
|
||||||
|
Show the window.
|
||||||
90
Documentation/Reference/structs/FileDialog.md
Normal file
90
Documentation/Reference/structs/FileDialog.md
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
**STRUCT**
|
||||||
|
|
||||||
|
# `FileDialog`
|
||||||
|
|
||||||
|
A structure representing a file dialog window.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
### `id`
|
||||||
|
|
||||||
|
The window's identifier.
|
||||||
|
|
||||||
|
### `importer`
|
||||||
|
|
||||||
|
Whether the window is an importer.
|
||||||
|
|
||||||
|
### `open`
|
||||||
|
|
||||||
|
Whether an instance of the window type should be opened when the app is starting up.
|
||||||
|
|
||||||
|
### `parentID`
|
||||||
|
|
||||||
|
The identifier of the window's parent.
|
||||||
|
|
||||||
|
### `appShortcuts`
|
||||||
|
|
||||||
|
The keyboard shortcuts on the app level.
|
||||||
|
|
||||||
|
### `initialFolder`
|
||||||
|
|
||||||
|
The initial folder.
|
||||||
|
|
||||||
|
### `initialName`
|
||||||
|
|
||||||
|
The initial file name for the file exporter.
|
||||||
|
|
||||||
|
### `extensions`
|
||||||
|
|
||||||
|
The accepted extensions for the file importer.
|
||||||
|
|
||||||
|
### `folders`
|
||||||
|
|
||||||
|
Whether folders are accepted in the file importer.
|
||||||
|
|
||||||
|
### `result`
|
||||||
|
|
||||||
|
The closure to run when the import or export is successful.
|
||||||
|
|
||||||
|
### `cancel`
|
||||||
|
|
||||||
|
The closure to run when the import or export is not successful.
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
### `init(importer:initialFolder:extensions:folders:onOpen:onClose:)`
|
||||||
|
|
||||||
|
Create an importer file dialog window.
|
||||||
|
- Parameters:
|
||||||
|
- importer: The window's identifier.
|
||||||
|
- initialFolder: The URL to the folder open when being opened.
|
||||||
|
- extensions: The accepted file extensions.
|
||||||
|
- folders: Whether folders are accepted.
|
||||||
|
- onOpen: Run this when a file for importing has been chosen.
|
||||||
|
- onClose: Run this when the user cancelled the action.
|
||||||
|
|
||||||
|
### `init(exporter:initialFolder:initialName:onSave:onClose:)`
|
||||||
|
|
||||||
|
Create an exporter file dialog window.
|
||||||
|
- Parameters:
|
||||||
|
- exporter: The window's identifier.
|
||||||
|
- initialFolder: The URL to the folder open when being opened.
|
||||||
|
- initialName: The default file name.
|
||||||
|
- onSave: Run this when a path for exporting has been chosen.
|
||||||
|
- onClose: Run this when the user cancelled the action.
|
||||||
|
|
||||||
|
### `createWindow(app:)`
|
||||||
|
|
||||||
|
Get the storage for the window.
|
||||||
|
- Parameter app: The application.
|
||||||
|
- Returns: The storage.
|
||||||
|
|
||||||
|
### `update(_:app:)`
|
||||||
|
|
||||||
|
Update a window.
|
||||||
|
- Parameters:
|
||||||
|
- storage: The storage to update.
|
||||||
|
- app: The application.
|
||||||
|
|
||||||
|
### `update(window:)`
|
||||||
|
|
||||||
|
Update the window.
|
||||||
|
- Parameter window: The window.
|
||||||
@ -9,6 +9,10 @@ A type that signalizes an action.
|
|||||||
|
|
||||||
An action is signalized by toggling a boolean to `true` and back to `false`.
|
An action is signalized by toggling a boolean to `true` and back to `false`.
|
||||||
|
|
||||||
|
### `id`
|
||||||
|
|
||||||
|
A signal has a unique identifier.
|
||||||
|
|
||||||
### `update`
|
### `update`
|
||||||
|
|
||||||
Whether the action has caused an update.
|
Whether the action has caused an update.
|
||||||
|
|||||||
@ -31,50 +31,6 @@ The keyboard shortcuts.
|
|||||||
|
|
||||||
The keyboard shortcuts on the app level.
|
The keyboard shortcuts on the app level.
|
||||||
|
|
||||||
### `fileImporter`
|
|
||||||
|
|
||||||
The signal for the file importer.
|
|
||||||
|
|
||||||
### `fileExporter`
|
|
||||||
|
|
||||||
The signal for the file exporter.
|
|
||||||
|
|
||||||
### `initialImporterFolder`
|
|
||||||
|
|
||||||
The initial folder for the file importer.
|
|
||||||
|
|
||||||
### `initialExporterFolder`
|
|
||||||
|
|
||||||
The initial folder for the file exporter.
|
|
||||||
|
|
||||||
### `initialName`
|
|
||||||
|
|
||||||
The initial file name for the file exporter.
|
|
||||||
|
|
||||||
### `extensions`
|
|
||||||
|
|
||||||
The accepted extensions for the file importer.
|
|
||||||
|
|
||||||
### `folders`
|
|
||||||
|
|
||||||
Whether folders are accepted in the file importer.
|
|
||||||
|
|
||||||
### `importerResult`
|
|
||||||
|
|
||||||
The closure to run when the import is successful.
|
|
||||||
|
|
||||||
### `exporterResult`
|
|
||||||
|
|
||||||
The closure to run when the export is successful.
|
|
||||||
|
|
||||||
### `importerCancel`
|
|
||||||
|
|
||||||
The closure to run when the import is not successful.
|
|
||||||
|
|
||||||
### `exporterCancel`
|
|
||||||
|
|
||||||
The closure to run when the export is not successful.
|
|
||||||
|
|
||||||
### `defaultSize`
|
### `defaultSize`
|
||||||
|
|
||||||
The default window size.
|
The default window size.
|
||||||
@ -91,6 +47,10 @@ Whether the window is resizable.
|
|||||||
|
|
||||||
Whether the window is deletable.
|
Whether the window is deletable.
|
||||||
|
|
||||||
|
### `signals`
|
||||||
|
|
||||||
|
The signals for the importers and exporters.
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
### `init(id:open:content:)`
|
### `init(id:open:content:)`
|
||||||
|
|
||||||
@ -168,11 +128,6 @@ Add a keyboard shortcut.
|
|||||||
Update the keyboard shortcuts.
|
Update the keyboard shortcuts.
|
||||||
- Parameter window: The application window.
|
- Parameter window: The application window.
|
||||||
|
|
||||||
### `updateFileDialog(storage:)`
|
|
||||||
|
|
||||||
Open a file importer or exporter if a signal has been activated and update changes.
|
|
||||||
- Parameter storage: The window storage.
|
|
||||||
|
|
||||||
### `closeShortcut()`
|
### `closeShortcut()`
|
||||||
|
|
||||||
Add the shortcut "<Ctrl>w" which closes the window.
|
Add the shortcut "<Ctrl>w" which closes the window.
|
||||||
|
|||||||
@ -5,11 +5,15 @@
|
|||||||
// Created by david-swift on 30.11.23.
|
// Created by david-swift on 30.11.23.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
/// A type that signalizes an action.
|
/// A type that signalizes an action.
|
||||||
public struct Signal {
|
public struct Signal {
|
||||||
|
|
||||||
/// An action is signalized by toggling a boolean to `true` and back to `false`.
|
/// An action is signalized by toggling a boolean to `true` and back to `false`.
|
||||||
@State var boolean = false
|
@State var boolean = false
|
||||||
|
/// A signal has a unique identifier.
|
||||||
|
public let id: UUID = .init()
|
||||||
|
|
||||||
/// Whether the action has caused an update.
|
/// Whether the action has caused an update.
|
||||||
public var update: Bool { boolean }
|
public var update: Bool { boolean }
|
||||||
|
|||||||
74
Sources/Adwaita/Model/Extensions/Libadwaita.FileDialog.swift
Normal file
74
Sources/Adwaita/Model/Extensions/Libadwaita.FileDialog.swift
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
//
|
||||||
|
// Libadwaita.FileDialog.swift
|
||||||
|
// Adwaita
|
||||||
|
//
|
||||||
|
// Created by david-swift on 09.12.23.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Libadwaita
|
||||||
|
|
||||||
|
extension Libadwaita.FileDialog: WindowType {
|
||||||
|
|
||||||
|
/// An ID for the importer field.
|
||||||
|
static var importer: String { "importer" }
|
||||||
|
/// An ID for the folder field.
|
||||||
|
static var folder: String { "folder" }
|
||||||
|
/// An ID for the result field.
|
||||||
|
static var result: String { "result" }
|
||||||
|
/// An ID for the cancel field.
|
||||||
|
static var cancel: String { "cancel" }
|
||||||
|
|
||||||
|
/// Whether the file dialog is an importer.
|
||||||
|
var isImporter: Bool {
|
||||||
|
get {
|
||||||
|
fields[Self.importer] as? Bool ?? true
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
fields[Self.importer] = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// The selected folder in the file dialog.
|
||||||
|
var folder: URL? {
|
||||||
|
get {
|
||||||
|
fields[Self.folder] as? URL
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
fields[Self.folder] = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A closure triggered on selecting a file in the dialog.
|
||||||
|
var onResult: ((URL) -> Void) {
|
||||||
|
get {
|
||||||
|
fields[Self.result] as? (URL) -> Void ?? { _ in }
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
fields[Self.result] = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A closure triggered when the dialog is canceled.
|
||||||
|
var onCancel: (() -> Void) {
|
||||||
|
get {
|
||||||
|
fields[Self.cancel] as? () -> Void ?? { }
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
fields[Self.cancel] = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the window's parent window.
|
||||||
|
/// - Parameter parent: The parent window.
|
||||||
|
///
|
||||||
|
/// Currently not implemented.
|
||||||
|
public func setParentWindow(_ parent: WindowType) { }
|
||||||
|
|
||||||
|
/// Display the file dialog.
|
||||||
|
public func show() {
|
||||||
|
if isImporter {
|
||||||
|
self.open(folder: folder, onResult, onClose: onCancel)
|
||||||
|
} else {
|
||||||
|
self.save(folder: folder, onResult, onClose: onCancel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -57,7 +57,7 @@ public class GTUIApp: Application {
|
|||||||
let window = window.createWindow(app: self)
|
let window = window.createWindow(app: self)
|
||||||
sceneStorage.append(window)
|
sceneStorage.append(window)
|
||||||
if let parent {
|
if let parent {
|
||||||
window.window.setParent(parent)
|
window.window.setParentWindow(parent)
|
||||||
window.window.fields[overwriteParentID] = true
|
window.window.fields[overwriteParentID] = true
|
||||||
}
|
}
|
||||||
setParentWindows()
|
setParentWindows()
|
||||||
@ -69,7 +69,7 @@ public class GTUIApp: Application {
|
|||||||
func setParentWindows() {
|
func setParentWindows() {
|
||||||
for window in sceneStorage where !(window.window.fields[overwriteParentID] as? Bool ?? false) {
|
for window in sceneStorage where !(window.window.fields[overwriteParentID] as? Bool ?? false) {
|
||||||
if let parent = sceneStorage.first(where: { $0.id == window.parentID }) {
|
if let parent = sceneStorage.first(where: { $0.id == window.parentID }) {
|
||||||
window.window.setParent(parent.window)
|
window.window.setParentWindow(parent.window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,3 +9,15 @@ import Libadwaita
|
|||||||
|
|
||||||
/// A GTUI window.
|
/// A GTUI window.
|
||||||
public typealias GTUIWindow = Libadwaita.Window
|
public typealias GTUIWindow = Libadwaita.Window
|
||||||
|
|
||||||
|
extension GTUIWindow: WindowType {
|
||||||
|
|
||||||
|
/// Set the window's parent window.
|
||||||
|
/// - Parameter parent: The parent window.
|
||||||
|
public func setParentWindow(_ parent: WindowType) {
|
||||||
|
if let window = parent as? GTUIWindow {
|
||||||
|
self.setParent(window)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -16,23 +16,20 @@ public class WindowStorage {
|
|||||||
public var parentID: String?
|
public var parentID: String?
|
||||||
/// Whether the reference to the window should disappear in the next update.
|
/// Whether the reference to the window should disappear in the next update.
|
||||||
public var destroy = false
|
public var destroy = false
|
||||||
/// The GTUI window.
|
/// The window.
|
||||||
public var window: GTUIWindow
|
public var window: WindowType
|
||||||
/// The content's storage.
|
/// The content's storage.
|
||||||
public var view: ViewStorage?
|
public var view: ViewStorage?
|
||||||
/// The file dialog for the window.
|
|
||||||
public var fileDialog: FileDialog
|
|
||||||
|
|
||||||
/// Initialize a window storage.
|
/// Initialize a window storage.
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - id: The window's identifier.
|
/// - id: The window's identifier.
|
||||||
/// - window: The GTUI window.
|
/// - window: The window.
|
||||||
/// - view: The content's storage.
|
/// - view: The content's storage.
|
||||||
public init(id: String, window: GTUIWindow, view: ViewStorage?) {
|
public init(id: String, window: WindowType, view: ViewStorage?) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.window = window
|
self.window = window
|
||||||
self.view = view
|
self.view = view
|
||||||
fileDialog = .init(window)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
21
Sources/Adwaita/Model/User Interface/Window/WindowType.swift
Normal file
21
Sources/Adwaita/Model/User Interface/Window/WindowType.swift
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// GTUIWindowRepresentable.swift
|
||||||
|
// Adwaita
|
||||||
|
//
|
||||||
|
// Created by david-swift on 09.12.23.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Libadwaita
|
||||||
|
|
||||||
|
/// A window type.
|
||||||
|
public protocol WindowType {
|
||||||
|
|
||||||
|
/// A dictionary for custom data.
|
||||||
|
var fields: [String: Any] { get set }
|
||||||
|
/// Set a parent window.
|
||||||
|
/// - Parameter parent: The parent window.
|
||||||
|
func setParentWindow(_ parent: WindowType)
|
||||||
|
/// Show the window.
|
||||||
|
func show()
|
||||||
|
|
||||||
|
}
|
||||||
127
Sources/Adwaita/Window/FileDialog.swift
Normal file
127
Sources/Adwaita/Window/FileDialog.swift
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
//
|
||||||
|
// FileDialog.swift
|
||||||
|
// Adwaita
|
||||||
|
//
|
||||||
|
// Created by david-swift on 08.12.23.
|
||||||
|
//
|
||||||
|
|
||||||
|
// swiftlint:disable discouraged_optional_collection
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Libadwaita
|
||||||
|
|
||||||
|
/// A structure representing a file dialog window.
|
||||||
|
public struct FileDialog: WindowScene {
|
||||||
|
|
||||||
|
/// The window's identifier.
|
||||||
|
public var id: String
|
||||||
|
/// Whether the window is an importer.
|
||||||
|
public var importer = true
|
||||||
|
/// Whether an instance of the window type should be opened when the app is starting up.
|
||||||
|
public var open: Int { 0 }
|
||||||
|
/// The identifier of the window's parent.
|
||||||
|
public var parentID: String?
|
||||||
|
/// The keyboard shortcuts on the app level.
|
||||||
|
public var appShortcuts: [String: (GTUIApp) -> Void] = [:]
|
||||||
|
/// The initial folder.
|
||||||
|
var initialFolder: URL?
|
||||||
|
/// The initial file name for the file exporter.
|
||||||
|
var initialName: String?
|
||||||
|
/// The accepted extensions for the file importer.
|
||||||
|
var extensions: [String]?
|
||||||
|
/// Whether folders are accepted in the file importer.
|
||||||
|
var folders = false
|
||||||
|
/// The closure to run when the import or export is successful.
|
||||||
|
var result: ((URL) -> Void)?
|
||||||
|
/// The closure to run when the import or export is not successful.
|
||||||
|
var cancel: (() -> Void)?
|
||||||
|
|
||||||
|
/// Create an importer file dialog window.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - importer: The window's identifier.
|
||||||
|
/// - initialFolder: The URL to the folder open when being opened.
|
||||||
|
/// - extensions: The accepted file extensions.
|
||||||
|
/// - folders: Whether folders are accepted.
|
||||||
|
/// - onOpen: Run this when a file for importing has been chosen.
|
||||||
|
/// - onClose: Run this when the user cancelled the action.
|
||||||
|
public init(
|
||||||
|
importer: String,
|
||||||
|
initialFolder: URL? = nil,
|
||||||
|
extensions: [String]? = nil,
|
||||||
|
folders: Bool = false,
|
||||||
|
onOpen: @escaping (URL) -> Void,
|
||||||
|
onClose: @escaping () -> Void
|
||||||
|
) {
|
||||||
|
self.id = importer
|
||||||
|
self.initialFolder = initialFolder
|
||||||
|
self.extensions = extensions
|
||||||
|
self.folders = folders
|
||||||
|
self.result = onOpen
|
||||||
|
self.cancel = onClose
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an exporter file dialog window.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - exporter: The window's identifier.
|
||||||
|
/// - initialFolder: The URL to the folder open when being opened.
|
||||||
|
/// - initialName: The default file name.
|
||||||
|
/// - onSave: Run this when a path for exporting has been chosen.
|
||||||
|
/// - onClose: Run this when the user cancelled the action.
|
||||||
|
public init(
|
||||||
|
exporter: String,
|
||||||
|
initialFolder: URL? = nil,
|
||||||
|
initialName: String? = nil,
|
||||||
|
onSave: @escaping (URL) -> Void,
|
||||||
|
onClose: @escaping () -> Void
|
||||||
|
) {
|
||||||
|
self.id = exporter
|
||||||
|
self.importer = false
|
||||||
|
self.initialFolder = initialFolder
|
||||||
|
self.initialName = initialName
|
||||||
|
self.result = onSave
|
||||||
|
self.cancel = onClose
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the storage for the window.
|
||||||
|
/// - Parameter app: The application.
|
||||||
|
/// - Returns: The storage.
|
||||||
|
public func createWindow(app: GTUIApp) -> WindowStorage {
|
||||||
|
let window = Libadwaita.FileDialog(nil)
|
||||||
|
let windowStorage = WindowStorage(id: id, window: window, view: nil)
|
||||||
|
windowStorage.parentID = parentID
|
||||||
|
update(window: window)
|
||||||
|
return windowStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update a window.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - storage: The storage to update.
|
||||||
|
/// - app: The application.
|
||||||
|
public func update(_ storage: WindowStorage, app: GTUIApp) {
|
||||||
|
updateAppShortcuts(app: app)
|
||||||
|
if let window = storage.window as? Libadwaita.FileDialog {
|
||||||
|
update(window: window)
|
||||||
|
}
|
||||||
|
storage.destroy = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the window.
|
||||||
|
/// - Parameter window: The window.
|
||||||
|
func update(window: Libadwaita.FileDialog) {
|
||||||
|
window.isImporter = importer
|
||||||
|
window.folder = initialFolder
|
||||||
|
if let initialName {
|
||||||
|
window.setInitialName(initialName)
|
||||||
|
}
|
||||||
|
window.setExtensions(extensions, folders: folders)
|
||||||
|
if let result {
|
||||||
|
window.onResult = result
|
||||||
|
}
|
||||||
|
if let cancel {
|
||||||
|
window.onCancel = cancel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// swiftlint:enable discouraged_optional_collection
|
||||||
@ -27,28 +27,6 @@ public struct Window: WindowScene {
|
|||||||
var shortcuts: [String: (GTUIApplicationWindow) -> Void] = [:]
|
var shortcuts: [String: (GTUIApplicationWindow) -> Void] = [:]
|
||||||
/// The keyboard shortcuts on the app level.
|
/// The keyboard shortcuts on the app level.
|
||||||
public var appShortcuts: [String: (GTUIApp) -> Void] = [:]
|
public var appShortcuts: [String: (GTUIApp) -> Void] = [:]
|
||||||
/// The signal for the file importer.
|
|
||||||
var fileImporter: Signal = .init()
|
|
||||||
/// The signal for the file exporter.
|
|
||||||
var fileExporter: Signal = .init()
|
|
||||||
/// The initial folder for the file importer.
|
|
||||||
var initialImporterFolder: URL?
|
|
||||||
/// The initial folder for the file exporter.
|
|
||||||
var initialExporterFolder: URL?
|
|
||||||
/// The initial file name for the file exporter.
|
|
||||||
var initialName: String?
|
|
||||||
/// The accepted extensions for the file importer.
|
|
||||||
var extensions: [String]?
|
|
||||||
/// Whether folders are accepted in the file importer.
|
|
||||||
var folders = false
|
|
||||||
/// The closure to run when the import is successful.
|
|
||||||
var importerResult: ((URL) -> Void)?
|
|
||||||
/// The closure to run when the export is successful.
|
|
||||||
var exporterResult: ((URL) -> Void)?
|
|
||||||
/// The closure to run when the import is not successful.
|
|
||||||
var importerCancel: (() -> Void)?
|
|
||||||
/// The closure to run when the export is not successful.
|
|
||||||
var exporterCancel: (() -> Void)?
|
|
||||||
/// The default window size.
|
/// The default window size.
|
||||||
var defaultSize: (Int, Int)?
|
var defaultSize: (Int, Int)?
|
||||||
/// The window's title.
|
/// The window's title.
|
||||||
@ -57,6 +35,8 @@ public struct Window: WindowScene {
|
|||||||
var resizable = true
|
var resizable = true
|
||||||
/// Whether the window is deletable.
|
/// Whether the window is deletable.
|
||||||
var deletable = true
|
var deletable = true
|
||||||
|
/// The signals for the importers and exporters.
|
||||||
|
var signals: [Signal] = []
|
||||||
|
|
||||||
/// Create a window type with a certain identifier and user interface.
|
/// Create a window type with a certain identifier and user interface.
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
@ -81,7 +61,6 @@ public struct Window: WindowScene {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
windowStorage.parentID = parentID
|
windowStorage.parentID = parentID
|
||||||
updateFileDialog(storage: windowStorage)
|
|
||||||
return windowStorage
|
return windowStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +98,11 @@ public struct Window: WindowScene {
|
|||||||
updateShortcuts(window: window)
|
updateShortcuts(window: window)
|
||||||
updateAppShortcuts(app: app)
|
updateAppShortcuts(app: app)
|
||||||
}
|
}
|
||||||
updateFileDialog(storage: storage)
|
for signal in signals where signal.update {
|
||||||
|
Task {
|
||||||
|
app.showWindow(signal.id.uuidString)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set some general propreties of the window.
|
/// Set some general propreties of the window.
|
||||||
@ -159,15 +142,20 @@ public struct Window: WindowScene {
|
|||||||
folders: Bool = false,
|
folders: Bool = false,
|
||||||
onOpen: @escaping (URL) -> Void,
|
onOpen: @escaping (URL) -> Void,
|
||||||
onClose: @escaping () -> Void
|
onClose: @escaping () -> Void
|
||||||
) -> Self {
|
) -> Scene {
|
||||||
var newSelf = self
|
var newSelf = self
|
||||||
newSelf.fileImporter = signal
|
newSelf.signals.append(signal)
|
||||||
newSelf.initialImporterFolder = initialFolder
|
|
||||||
newSelf.extensions = extensions
|
|
||||||
newSelf.folders = folders
|
|
||||||
newSelf.importerResult = onOpen
|
|
||||||
newSelf.importerCancel = onClose
|
|
||||||
return newSelf
|
return newSelf
|
||||||
|
.overlay {
|
||||||
|
FileDialog(
|
||||||
|
importer: signal.id.uuidString,
|
||||||
|
initialFolder: initialFolder,
|
||||||
|
extensions: extensions,
|
||||||
|
folders: folders,
|
||||||
|
onOpen: onOpen,
|
||||||
|
onClose: onClose
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add an exporter file dialog to the window.
|
/// Add an exporter file dialog to the window.
|
||||||
@ -183,14 +171,19 @@ public struct Window: WindowScene {
|
|||||||
initialName: String? = nil,
|
initialName: String? = nil,
|
||||||
onSave: @escaping (URL) -> Void,
|
onSave: @escaping (URL) -> Void,
|
||||||
onClose: @escaping () -> Void
|
onClose: @escaping () -> Void
|
||||||
) -> Self {
|
) -> Scene {
|
||||||
var newSelf = self
|
var newSelf = self
|
||||||
newSelf.fileExporter = signal
|
newSelf.signals.append(signal)
|
||||||
newSelf.initialExporterFolder = initialFolder
|
|
||||||
newSelf.initialName = initialName
|
|
||||||
newSelf.exporterResult = onSave
|
|
||||||
newSelf.exporterCancel = onClose
|
|
||||||
return newSelf
|
return newSelf
|
||||||
|
.overlay {
|
||||||
|
FileDialog(
|
||||||
|
exporter: signal.id.uuidString,
|
||||||
|
initialFolder: initialFolder,
|
||||||
|
initialName: initialName,
|
||||||
|
onSave: onSave,
|
||||||
|
onClose: onClose
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a keyboard shortcut.
|
/// Add a keyboard shortcut.
|
||||||
@ -212,20 +205,6 @@ public struct Window: WindowScene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a file importer or exporter if a signal has been activated and update changes.
|
|
||||||
/// - Parameter storage: The window storage.
|
|
||||||
func updateFileDialog(storage: WindowStorage) {
|
|
||||||
storage.fileDialog.setExtensions(extensions, folders: folders)
|
|
||||||
if let initialName {
|
|
||||||
storage.fileDialog.setInitialName(initialName)
|
|
||||||
}
|
|
||||||
if fileImporter.update, let importerResult, let importerCancel {
|
|
||||||
storage.fileDialog.open(folder: initialImporterFolder, importerResult, onClose: importerCancel)
|
|
||||||
} else if fileExporter.update, let exporterResult, let exporterCancel {
|
|
||||||
storage.fileDialog.save(folder: initialExporterFolder, exporterResult, onClose: exporterCancel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add the shortcut "<Ctrl>w" which closes the window.
|
/// Add the shortcut "<Ctrl>w" which closes the window.
|
||||||
/// - Returns: The window.
|
/// - Returns: The window.
|
||||||
public func closeShortcut() -> Self {
|
public func closeShortcut() -> Self {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user