Skip to content

Commit f204605

Browse files
committed
Merge branch 'itembox' into jump-to-definition
2 parents a763fa5 + ac1b50c commit f204605

File tree

6 files changed

+72
-23
lines changed

6 files changed

+72
-23
lines changed

Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Views/MockCompletionDelegate.swift

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ class MockCompletionDelegate: CodeSuggestionDelegate, ObservableObject {
6060
}
6161
}
6262

63-
private func randomSuggestions() -> [Suggestion] {
64-
let count = Int.random(in: 0..<20)
63+
private func randomSuggestions(_ count: Int? = nil) -> [Suggestion] {
64+
let count = count ?? Int.random(in: 0..<20)
6565
var suggestions: [Suggestion] = []
6666
for _ in 0..<count {
6767
let randomString = (0..<Int.random(in: 1..<text.count)).map {
@@ -72,6 +72,8 @@ class MockCompletionDelegate: CodeSuggestionDelegate, ObservableObject {
7272
return suggestions
7373
}
7474

75+
var moveCount = 0
76+
7577
func completionSuggestionsRequested(
7678
textView: TextViewController,
7779
cursorPosition: CursorPosition
@@ -84,10 +86,15 @@ class MockCompletionDelegate: CodeSuggestionDelegate, ObservableObject {
8486
textView: TextViewController,
8587
cursorPosition: CursorPosition
8688
) -> [CodeSuggestionEntry]? {
87-
if Bool.random() {
88-
randomSuggestions()
89-
} else {
90-
nil
89+
moveCount += 1
90+
switch moveCount {
91+
case 1:
92+
return randomSuggestions(2)
93+
case 2:
94+
return randomSuggestions(20)
95+
default:
96+
moveCount = 0
97+
return nil
9198
}
9299
}
93100

Sources/CodeEditSourceEditor/CodeSuggestion/Model/SuggestionViewModel.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ final class SuggestionViewModel: ObservableObject {
3131
self.activeTextView = textView
3232
self.delegate = delegate
3333
itemsRequestTask = Task {
34+
defer { itemsRequestTask = nil }
35+
3436
do {
3537
guard let completionItems = await delegate.completionSuggestionsRequested(
3638
textView: textView,
@@ -68,6 +70,8 @@ final class SuggestionViewModel: ObservableObject {
6870
position: CursorPosition,
6971
close: () -> Void
7072
) {
73+
guard itemsRequestTask == nil else { return }
74+
7175
if activeTextView !== textView {
7276
close()
7377
return
@@ -76,7 +80,8 @@ final class SuggestionViewModel: ObservableObject {
7680
guard let newItems = delegate.completionOnCursorMove(
7781
textView: textView,
7882
cursorPosition: position
79-
) else {
83+
),
84+
!newItems.isEmpty else {
8085
close()
8186
return
8287
}

Sources/CodeEditSourceEditor/CodeSuggestion/TableView/CodeSuggestionLabelView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ struct CodeSuggestionLabelView: View {
2424
)
2525

2626
// Main label
27-
HStack(spacing: 0) {
27+
HStack(spacing: font.charWidth) {
2828
Text(suggestion.label)
2929
.foregroundStyle(suggestion.deprecated ? Color(secondaryLabelColor) : Color(labelColor))
3030

Sources/CodeEditSourceEditor/CodeSuggestion/TableView/SuggestionViewController.swift

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import SwiftUI
1010
import Combine
1111

1212
class SuggestionViewController: NSViewController {
13+
var tintView: NSView!
1314
var tableView: NSTableView!
1415
var scrollView: NSScrollView!
1516
var noItemsLabel: NSTextField!
@@ -29,7 +30,14 @@ class SuggestionViewController: NSViewController {
2930
super.loadView()
3031
view.wantsLayer = true
3132
view.layer?.cornerRadius = 8.5
32-
view.layer?.backgroundColor = .clear
33+
view.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor
34+
35+
tintView = NSView()
36+
tintView.translatesAutoresizingMaskIntoConstraints = false
37+
tintView.wantsLayer = true
38+
tintView.layer?.cornerRadius = 8.5
39+
tintView.layer?.backgroundColor = .clear
40+
view.addSubview(tintView)
3341

3442
tableView = NSTableView()
3543
configureTableView()
@@ -46,6 +54,11 @@ class SuggestionViewController: NSViewController {
4654
view.addSubview(scrollView)
4755

4856
NSLayoutConstraint.activate([
57+
tintView.topAnchor.constraint(equalTo: view.topAnchor),
58+
tintView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
59+
tintView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
60+
tintView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
61+
4962
noItemsLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
5063
noItemsLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 10),
5164
noItemsLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
@@ -78,22 +91,23 @@ class SuggestionViewController: NSViewController {
7891
blue: color.blueComponent * 0.95,
7992
alpha: 1.0
8093
)
81-
view.layer?.backgroundColor = newColor.cgColor
94+
tintView.layer?.backgroundColor = newColor.cgColor
8295
} else {
83-
view.layer?.backgroundColor = .clear
96+
tintView.layer?.backgroundColor = .clear
8497
}
8598
case .darkAqua:
86-
view.layer?.backgroundColor = controller.theme.background.cgColor
99+
tintView.layer?.backgroundColor = controller.theme.background.cgColor
87100
default:
88101
return
89102
}
103+
updateSize(using: controller)
104+
}
90105

106+
func updateSize(using controller: TextViewController) {
91107
guard model?.items.isEmpty == false else {
92108
let size = NSSize(width: 256, height: noItemsLabel.fittingSize.height + 20)
93109
preferredContentSize = size
94-
view.window?.setContentSize(size)
95-
view.window?.contentMinSize = size
96-
view.window?.contentMaxSize = size
110+
(self.view.window?.windowController as? SuggestionController)?.updateWindowSize(newSize: size)
97111
return
98112
}
99113
guard let rowView = tableView.view(atColumn: 0, row: 0, makeIfNecessary: true) else {
@@ -104,16 +118,17 @@ class SuggestionViewController: NSViewController {
104118
let numberOfVisibleRows = min(CGFloat(model?.items.count ?? 0), SuggestionController.MAX_VISIBLE_ROWS)
105119
let newHeight = rowHeight * numberOfVisibleRows + SuggestionController.WINDOW_PADDING * 2
106120

107-
let maxLength = min((model?.items.max(by: { $0.label.count < $1.label.count })?.label.count ?? 16) + 4, 48)
108-
let newWidth = max(256, CGFloat(maxLength) * controller.font.charWidth)
121+
let maxLength = min(
122+
(model?.items.reduce(0, { max($0, $1.label.count + ($1.detail?.count ?? 0)) }) ?? 16) + 4,
123+
64
124+
)
125+
let newWidth = CGFloat(maxLength) * controller.font.charWidth
109126

110127
view.constraints.filter({ $0.firstAnchor == view.heightAnchor }).forEach { $0.isActive = false }
111128
view.heightAnchor.constraint(equalToConstant: newHeight).isActive = true
112129

113-
preferredContentSize = NSSize(width: newWidth, height: newHeight)
114-
view.window?.setContentSize(NSSize(width: newWidth, height: newHeight))
115-
view.window?.contentMinSize = NSSize(width: newWidth, height: newHeight)
116-
view.window?.contentMaxSize = NSSize(width: .infinity, height: newHeight)
130+
let newSize = NSSize(width: newWidth, height: newHeight)
131+
(self.view.window?.windowController as? SuggestionController)?.updateWindowSize(newSize: newSize)
117132
}
118133

119134
func configureTableView() {
@@ -158,6 +173,9 @@ class SuggestionViewController: NSViewController {
158173
scrollView.isHidden = model.items.isEmpty
159174
}
160175
tableView.reloadData()
176+
if let activeTextView = model?.activeTextView {
177+
updateSize(using: activeTextView)
178+
}
161179
}
162180

163181
@objc private func tableViewClicked(_ sender: Any?) {
@@ -204,7 +222,7 @@ extension SuggestionViewController: NSTableViewDataSource, NSTableViewDelegate {
204222
rootView: CodeSuggestionLabelView(
205223
suggestion: model.items[row],
206224
labelColor: textView.theme.text.color,
207-
secondaryLabelColor: textView.theme.comments.color,
225+
secondaryLabelColor: textView.theme.text.color.withAlphaComponent(0.5),
208226
font: textView.font
209227
)
210228
)

Sources/CodeEditSourceEditor/CodeSuggestion/Window/SuggestionController+Window.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,20 @@ extension SuggestionController {
5959
}
6060
}
6161

62+
func updateWindowSize(newSize: NSSize) {
63+
guard let window else { return }
64+
let oldFrame = window.frame
65+
66+
window.minSize = newSize
67+
window.maxSize = NSSize(width: CGFloat.infinity, height: newSize.height)
68+
69+
window.setContentSize(newSize)
70+
71+
if isWindowAboveCursor && oldFrame.size.height != newSize.height {
72+
window.setFrameOrigin(oldFrame.origin)
73+
}
74+
}
75+
6276
// MARK: - Private Methods
6377

6478
static func makeWindow() -> NSWindow {

Sources/CodeEditSourceEditor/Controller/TextViewController+Lifecycle.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,12 @@ extension TextViewController {
294294
}
295295

296296
private func handleShowCompletions(_ event: NSEvent) -> NSEvent? {
297-
if let completionDelegate = self.completionDelegate, let cursorPosition = cursorPositions.first {
297+
if let completionDelegate = self.completionDelegate,
298+
let cursorPosition = cursorPositions.first {
299+
if SuggestionController.shared.isVisible {
300+
SuggestionController.shared.close()
301+
return event
302+
}
298303
SuggestionController.shared.showCompletions(
299304
textView: self,
300305
delegate: completionDelegate,

0 commit comments

Comments
 (0)