Skip to content

Commit 2a6db52

Browse files
committed
Improve NSHostingPopover
1 parent f8b3321 commit 2a6db52

File tree

3 files changed

+34
-15
lines changed

3 files changed

+34
-15
lines changed

Sources/Intermodular/Helpers/AppKit or UIKit/AppKitOrUIKit.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public typealias AppKitOrUIKitWindow = NSWindow
9393

9494
extension NSView {
9595
public static var layoutFittingCompressedSize: CGSize {
96-
.init(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
96+
.init(width: 0, height: 0)
9797
}
9898

9999
public static var layoutFittingExpandedSize: CGSize {

Sources/Intermodular/Helpers/AppKit/NSHostingPopover.swift

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,33 @@ import Swift
99
import SwiftUI
1010

1111
open class NSHostingPopover<Content: View>: NSPopover {
12-
var presentationManager: PresentationManager!
12+
private var presentationManager: PresentationManager!
1313

14-
var _contentViewController: NSHostingController<ContentWrapper> {
15-
contentViewController as! NSHostingController<ContentWrapper>
14+
private var _contentViewController: CocoaHostingController<ContentWrapper> {
15+
contentViewController as! CocoaHostingController<ContentWrapper>
1616
}
1717

1818
public var rootView: Content {
1919
get {
20-
_contentViewController.rootView.content
20+
_contentViewController.mainView.content
2121
} set {
22-
_contentViewController.rootView = .init(content: newValue, owner: self)
22+
_contentViewController.mainView.content = newValue
2323

24-
contentSize = _contentViewController.sizeThatFits(in: Screen.main.bounds.size)
24+
_contentViewController.view.layout()
2525
}
2626
}
2727

2828
public init(rootView: Content) {
2929
super.init()
3030

3131
presentationManager = .init(self)
32-
33-
contentViewController = NSHostingController(rootView: ContentWrapper(content: rootView, owner: self))
34-
contentSize = _contentViewController.sizeThatFits(in: Screen.main.bounds.size)
32+
33+
let contentViewController = CocoaHostingController(mainView: ContentWrapper(content: rootView, owner: self))
34+
35+
contentViewController.parentPopover = self
36+
37+
self.animates = true
38+
self.contentViewController = contentViewController
3539
}
3640

3741
public required init?(coder: NSCoder) {
@@ -42,20 +46,23 @@ open class NSHostingPopover<Content: View>: NSPopover {
4246
// MARK: - Auxiliary Implementation -
4347

4448
extension NSHostingPopover {
45-
struct ContentWrapper: View {
46-
let content: Content
49+
private struct ContentWrapper: View {
50+
var content: Content
4751

4852
weak var owner: NSHostingPopover?
4953

5054
var body: some View {
51-
owner.ifSome { owner in
55+
if let owner = owner {
5256
content
5357
.environment(\.presentationManager, owner.presentationManager)
58+
.onChangeOfFrame { _ in
59+
owner._contentViewController.view.layout()
60+
}
5461
}
5562
}
5663
}
5764

58-
class PresentationManager: SwiftUIX.PresentationManager {
65+
private class PresentationManager: SwiftUIX.PresentationManager {
5966
private unowned let popover: NSHostingPopover
6067

6168
public var isPresented: Bool {

Sources/Intramodular/Bridging/CocoaHostingController.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ open class CocoaHostingController<Content: View>: AppKitOrUIKitHostingController
2020
#endif
2121
var _isResizingParentWindow: Bool = false
2222
var _didResizeParentWindowOnce: Bool = false
23+
24+
#if os(macOS)
25+
weak var parentPopover: NSPopover?
26+
#endif
2327

2428
public var mainView: Content {
2529
get {
@@ -125,7 +129,15 @@ open class CocoaHostingController<Content: View>: AppKitOrUIKitHostingController
125129
override open func viewDidLayout() {
126130
super.viewDidLayout()
127131

128-
preferredContentSize = sizeThatFits(in: Screen.main.bounds.size)
132+
let size = sizeThatFits(in: NSView.layoutFittingCompressedSize)
133+
134+
DispatchQueue.main.async {
135+
if let popover = self.parentPopover {
136+
popover.contentSize = size
137+
} else {
138+
self.preferredContentSize = size
139+
}
140+
}
129141
}
130142
#endif
131143

0 commit comments

Comments
 (0)