@@ -26,11 +26,11 @@ class WinUIApplication: SwiftApplication {
26
26
}
27
27
}
28
28
29
- public struct WinUIBackend : AppBackend {
29
+ public final class WinUIBackend : AppBackend {
30
30
public typealias Window = WinUI . Window
31
31
public typealias Widget = WinUI . FrameworkElement
32
32
public typealias Menu = Void
33
- public typealias Alert = Void
33
+ public typealias Alert = WinUI . ContentDialog
34
34
35
35
public let defaultTableRowContentHeight = 20
36
36
public let defaultTableCellVerticalPadding = 4
@@ -53,6 +53,11 @@ public struct WinUIBackend: AppBackend {
53
53
}
54
54
55
55
private var internalState : InternalState
56
+ /// WinUI only allows one dialog at a time (subsequent dialogs throw
57
+ /// exceptions), so we limit ourselves.
58
+ private var dialogSemaphore = DispatchSemaphore ( value: 1 )
59
+
60
+ private var windows : [ Window ] = [ ]
56
61
57
62
public init ( ) {
58
63
internalState = InternalState ( )
@@ -82,6 +87,12 @@ public struct WinUIBackend: AppBackend {
82
87
83
88
public func createWindow( withDefaultSize size: SIMD2 < Int > ? ) -> Window {
84
89
let window = Window ( )
90
+ windows. append ( window)
91
+ window. closed. addHandler { _, _ in
92
+ self . windows. removeAll { other in
93
+ window === other
94
+ }
95
+ }
85
96
86
97
if internalState. dispatcherQueue == nil {
87
98
internalState. dispatcherQueue = window. dispatcherQueue
@@ -208,12 +219,6 @@ public struct WinUIBackend: AppBackend {
208
219
. with ( \. font, . system( size: 14 ) )
209
220
}
210
221
211
- private func fatalError( _ message: String ) -> Never {
212
- print ( message)
213
- fflush ( stdout)
214
- Foundation . exit ( 1 )
215
- }
216
-
217
222
public func setRootEnvironmentChangeHandler( to action: @escaping ( ) -> Void ) {
218
223
print ( " Implement set root environment change handler " )
219
224
// TODO
@@ -760,6 +765,64 @@ public struct WinUIBackend: AppBackend {
760
765
}
761
766
}
762
767
768
+ public func createAlert( ) -> Alert {
769
+ ContentDialog ( )
770
+ }
771
+
772
+ public func updateAlert(
773
+ _ alert: Alert ,
774
+ title: String ,
775
+ actionLabels: [ String ] ,
776
+ environment: EnvironmentValues
777
+ ) {
778
+ alert. title = title
779
+ if actionLabels. count >= 1 {
780
+ alert. primaryButtonText = actionLabels [ 0 ]
781
+ }
782
+ if actionLabels. count >= 2 {
783
+ alert. secondaryButtonText = actionLabels [ 1 ]
784
+ }
785
+ if actionLabels. count >= 3 {
786
+ alert. closeButtonText = actionLabels [ 2 ]
787
+ }
788
+ }
789
+
790
+ public func showAlert(
791
+ _ alert: Alert ,
792
+ window: Window ? ,
793
+ responseHandler handleResponse: @escaping ( Int ) -> Void
794
+ ) {
795
+ // WinUI only allows one dialog at a time so we limit ourselves using
796
+ // a semaphore.
797
+ guard let window = window ?? windows. first else {
798
+ print ( " warning: WinUI can't show alert without window " )
799
+ return
800
+ }
801
+
802
+ alert. xamlRoot = window. content. xamlRoot
803
+ dialogSemaphore. wait ( )
804
+ let promise = try ! alert. showAsync ( ) !
805
+ promise. completed = { operation, status in
806
+ self . dialogSemaphore. signal ( )
807
+ guard
808
+ status == . completed,
809
+ let operation,
810
+ let result = try ? operation. getResults ( )
811
+ else {
812
+ return
813
+ }
814
+ let index =
815
+ switch result {
816
+ case . primary: 0
817
+ case . secondary: 1
818
+ case . none: 2
819
+ default :
820
+ fatalError ( " WinUIBackend: Invalid dialog response " )
821
+ }
822
+ handleResponse ( index)
823
+ }
824
+ }
825
+
763
826
// public func createTable(rows: Int, columns: Int) -> Widget {
764
827
// let grid = Grid()
765
828
// grid.columnSpacing = 10
0 commit comments