Skip to content
This repository has been archived by the owner on Oct 17, 2024. It is now read-only.

Commit

Permalink
Add support for file dialogs
Browse files Browse the repository at this point in the history
  • Loading branch information
David authored and david-swift committed Dec 5, 2023
1 parent 9170382 commit 475c38a
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Documentation/Reference/classes/WindowStorage.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ The GTUI window.

The content's storage.

### `fileDialog`

The file dialog for the window.

## Methods
### `init(id:window:view:)`

Expand Down
70 changes: 70 additions & 0 deletions Documentation/Reference/structs/Window.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,50 @@ The keyboard shortcuts.

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.

## Methods
### `init(id:open:content:)`

Expand Down Expand Up @@ -69,6 +113,27 @@ Add windows that overlay the last instance of this window if presented.
- Parameter windows: The windows.
- Returns: The new windows and this window.

### `fileImporter(_:initialFolder:extensions:folders:onOpen:onClose:)`

Add an importer file dialog to the window.
- Parameters:
- signal: The signal for opening the dialog.
- 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.

### `fileExporter(_:initialFolder:initialName:onSave:onClose:)`

Add an exporter file dialog to the window.
- Parameters:
- signal: The signal for opening the dialog.
- 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.

### `keyboardShortcut(_:action:)`

Add a keyboard shortcut.
Expand All @@ -82,6 +147,11 @@ Add a keyboard shortcut.
Update the keyboard shortcuts.
- 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()`

Add the shortcut "<Ctrl>w" which closes the window.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public class WindowStorage {
public var window: GTUIWindow
/// The content's storage.
public var view: ViewStorage
/// The file dialog for the window.
public var fileDialog: FileDialog

/// Initialize a window storage.
/// - Parameters:
Expand All @@ -30,6 +32,7 @@ public class WindowStorage {
self.id = id
self.window = window
self.view = view
fileDialog = .init(window)
}

}
92 changes: 92 additions & 0 deletions Sources/Adwaita/Window/Window.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
// Created by david-swift on 14.09.23.
//

// swiftlint:disable discouraged_optional_collection

import Foundation
import Libadwaita

/// A structure representing an application window type.
Expand All @@ -24,6 +27,28 @@ public struct Window: WindowScene {
var shortcuts: [String: (GTUIApplicationWindow) -> Void] = [:]
/// The keyboard shortcuts on the app level.
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)?

/// Create a window type with a certain identifier and user interface.
/// - Parameters:
Expand All @@ -48,6 +73,7 @@ public struct Window: WindowScene {
return false
}
windowStorage.parentID = parentID
updateFileDialog(storage: windowStorage)
return windowStorage
}

Expand Down Expand Up @@ -81,6 +107,7 @@ public struct Window: WindowScene {
updateShortcuts(window: window)
updateAppShortcuts(app: app)
}
updateFileDialog(storage: storage)
}

/// Add windows that overlay the last instance of this window if presented.
Expand All @@ -94,6 +121,55 @@ public struct Window: WindowScene {
} + [self]
}

/// Add an importer file dialog to the window.
/// - Parameters:
/// - signal: The signal for opening the dialog.
/// - 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 func fileImporter(
_ signal: Signal,
initialFolder: URL? = nil,
extensions: [String]? = nil,
folders: Bool = false,
onOpen: @escaping (URL) -> Void,
onClose: @escaping () -> Void
) -> Self {
var newSelf = self
newSelf.fileImporter = signal
newSelf.initialImporterFolder = initialFolder
newSelf.extensions = extensions
newSelf.folders = folders
newSelf.importerResult = onOpen
newSelf.importerCancel = onClose
return newSelf
}

/// Add an exporter file dialog to the window.
/// - Parameters:
/// - signal: The signal for opening the dialog.
/// - 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 func fileExporter(
_ signal: Signal,
initialFolder: URL? = nil,
initialName: String? = nil,
onSave: @escaping (URL) -> Void,
onClose: @escaping () -> Void
) -> Self {
var newSelf = self
newSelf.fileExporter = signal
newSelf.initialExporterFolder = initialFolder
newSelf.initialName = initialName
newSelf.exporterResult = onSave
newSelf.exporterCancel = onClose
return newSelf
}

/// Add a keyboard shortcut.
/// - Parameters:
/// - shortcut: The keyboard shortcut.
Expand All @@ -113,10 +189,26 @@ 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.
/// - Returns: The window.
public func closeShortcut() -> Self {
keyboardShortcut("w".ctrl()) { $0.close() }
}

}

// swiftlint:enable discouraged_optional_collection

0 comments on commit 475c38a

Please sign in to comment.