Skip to content

Commit a436751

Browse files
(fix: #28) Update scrollToVisible Loop (#29)
1 parent 86b9804 commit a436751

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

Sources/CodeEditTextView/TextView/TextView.swift

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -522,19 +522,29 @@ public class TextView: NSView, NSTextContent {
522522

523523
/// Scrolls the upmost selection to the visible rect if `scrollView` is not `nil`.
524524
public func scrollSelectionToVisible() {
525-
guard let scrollView,
526-
let selection = selectionManager.textSelections
527-
.sorted(by: { $0.boundingRect.origin.y < $1.boundingRect.origin.y }).first else {
525+
guard let scrollView else {
528526
return
529527
}
528+
529+
// There's a bit of a chicken-and-the-egg issue going on here. We need to know the rect to scroll to, but we
530+
// can't know the exact rect to make visible without laying out the text. Then, once text is laid out the
531+
// selection rect may be different again. To solve this, we loop until the frame doesn't change after a layout
532+
// pass and scroll to that rect.
533+
530534
var lastFrame: CGRect = .zero
531-
while lastFrame != selection.boundingRect {
535+
while let selection = selectionManager
536+
.textSelections
537+
.sorted(by: { $0.boundingRect.origin.y < $1.boundingRect.origin.y })
538+
.first,
539+
lastFrame != selection.boundingRect {
532540
lastFrame = selection.boundingRect
533541
layoutManager.layoutLines()
534542
selectionManager.updateSelectionViews()
535543
selectionManager.drawSelections(in: visibleRect)
536544
}
537-
scrollView.contentView.scrollToVisible(lastFrame)
545+
if lastFrame != .zero {
546+
scrollView.contentView.scrollToVisible(lastFrame)
547+
}
538548
}
539549

540550
deinit {

0 commit comments

Comments
 (0)