in that case what is the meaning of .list and .table options it does not affect the allowed result? It's not clear to me.
Post
Replies
Boosts
Views
Activity
That difference is that I adjust the viewport position so the text at end of the document is displayed in the current visible rect (NSView.visibleRect).
thank you, let me summarize the approach:
receive an estimated (too big or too small) content height
update content size with the estimated height
move viewport to the end of that height (either it is final or estimated)
layout end of the document there
do you think that approach translate well to any location in the middle of the document? What about the scrollview scrollbar that depends on the total content Size and updates as layoutmanager update its size, do you have any trick for that?
@DTS Engineer
thank you for your suggestion. I tried that approach now (and before) and it looks like calling enumerateTextLayoutFragments yields approximate/estimate layout positions.
Specifically, calling the suggested routine multiple times returns different values:
var lastLayoutFragment: NSTextLayoutFragment!
textLayoutManager.enumerateTextLayoutFragments(from: textLayoutManager.documentRange.endLocation,
options: [.reverse, .ensuresLayout]) { layoutFragment in
lastLayoutFragment = layoutFragment
return false
}
let lastLineMaxY = lastLayoutFragment.layoutFragmentFrame.maxY
print(lastLineMaxY)
in my test case case result with these values:
4302376.62016702
4092451.6843738933
3979224.5583475474
4565598.13343745
4332115.927268179
4331192.884374112
4331192.884374112
4331192.884374112
4331192.884374112
4331192.884374112
as we can see, the value eventually get "stable" and that is actuall height of the document. The initial values jumps (estimate) up and down without the pattern.
That behavior is aligned with values reported by usageBoundsForTextContainer and is a root of many issues.
In the example you provided is not different, hence I'd like to ask how does it suppose to work with estimated layout values?
the origin x = 5 most likely comes from NSTextContainer.lineFragmentPadding. The default value of this property is 5.0.
paragraphSeparatorRange is a newline/paragraph_separator itself
paragraphContentRange is just paragraph content, without the newline
values are available once the layout happen.
Content manager allows to addition one or more layout managers.
let layoutManager = NSTextLayoutManager()
layoutManager.textContainer = textContainer
let contentManager = NSTextContentStorage()
contentManager.addTextLayoutManager(layoutManager)
that you can later assess via contentManager.textLayoutManagers. Additionally there is a flag automaticallySynchronizesTextLayoutManagers (defaults to true) to facilitate synchronization of multiple layout managers for that content manager.
I don't think NSTextView / UITextView ever gets support for NSTextContentManager. That's one of the reasons I created STTextView, which is a custom TextKit 2 based text view implementation, you may want find useful in that regard.
2023 is not the year of ShapeEdit. again
I did setup it succesfully with socketpair() like below:
let socket_vector = Array<Int32>(unsafeUninitializedCapacity: 2) { buffer, initializedCount in
guard Darwin.socketpair(AF_UNIX, SOCK_DGRAM, 0, buffer.baseAddress) == 0 else {
assertionFailure(String(cString: Darwin.strerror(errno)!))
initializedCount = 0
return
}
initializedCount = 2
}
for socket_descriptor in socket_vector {
let virtioSocketNet = VZVirtioNetworkDeviceConfiguration()
let fh = FileHandle(fileDescriptor: socket_descriptor)
virtioSocketNet.attachment = VZFileHandleNetworkDeviceAttachment(fileHandle: fh)
config.networkDevices += [virtioSocketNet]
}
I struggle to send/receive anything with it.
Does anyone happen to have a working netcat/socat command that successfully sends anything?
I use Linux as a guest system, and interfaces register as enp0s2, enp0s3
(deleted)
I'm sure it's a bug, the TextEdit app in macOS 12.0.1 maintains selection properly for the very same RTF file. The NSAttributedString itself looks ok at first glance:
There's another interesting and unexpected (at least to me) behavior when setting the NSTextContentStorage.attributedString directly, the cursor (nor selection) is available at all and NSTextView is not editable
let docURL = Bundle.main.url(forResource: "Text", withExtension: "rtf")!
let attributedString = try! NSAttributedString(rtf: Data(contentsOf: docURL), documentAttributes: nil)
try! textContentStorage.attributedString = attributedString
I don't know if this is recommended, however since nobody picked up this questions, this is what I do:
I assume you use NSRulerView as an NSScrollView.verticalRulerView property. What I do, is override drawHashMarksAndLabels(in:) and use CoreText to draw numbers in the positions from NSTextLayoutManager
class LineNumberRulerView: NSRulerView {
private weak var textView: NSTextView?
init(textView: NSTextView) {
self.textView = textView
super.init(scrollView: textView.enclosingScrollView!, orientation: .verticalRuler)
clientView = textView.enclosingScrollView!.documentView
NotificationCenter.default.addObserver(forName: NSView.frameDidChangeNotification, object: textView, queue: nil) { [weak self] _ in
self?.needsDisplay = true
}
NotificationCenter.default.addObserver(forName: NSText.didChangeNotification, object: textView, queue: nil) { [weak self] _ in
self?.needsDisplay = true
}
}
public override func drawHashMarksAndLabels(in rect: NSRect) {
guard let context = NSGraphicsContext.current?.cgContext,
let textView = textView,
let textLayoutManager = textView.textLayoutManager
else {
return
}
let relativePoint = self.convert(NSZeroPoint, from: textView)
context.saveGState()
context.textMatrix = CGAffineTransform(scaleX: 1, y: isFlipped ? -1 : 1)
let attributes: [NSAttributedString.Key: Any] = [
.font: textView.font!,
.foregroundColor: NSColor.secondaryLabelColor
]
var lineNum = 1
textLayoutManager.enumerateTextLayoutFragments(from: nil, options: .ensuresLayout) { fragment in
let fragmentFrame = fragment.layoutFragmentFrame
for (subLineIdx, textLineFragment) in fragment.textLineFragments.enumerated() where subLineIdx == 0 {
let locationForFirstCharacter = textLineFragment.locationForCharacter(at: 0)
let ctline = CTLineCreateWithAttributedString(CFAttributedStringCreate(nil, "\(lineNum)" as CFString, attributes as CFDictionary))
context.textPosition = fragmentFrame.origin.applying(.init(translationX: 4, y: locationForFirstCharacter.y + relativePoint.y))
CTLineDraw(ctline, context)
}
lineNum += 1
return true
}
context.restoreGState()
}
}
Use NSTextView.textSelections, then use NSTextLayoutManager to get the position of a first selection NSTextRange and frame
let selectionTextLocation = textSelections.flatMap(\.textRanges)[0].location
next find a frame
textLayoutManager.enumerateSegments(in: NSTextRange(location: selectionTextLocation), type: .standard, options: .upstreamAffinity) { _, segmentFrame, baselinePosition, _ in
// use segmentFrame and baselinePosition to calculate insertion point location in NSTextContainer
}
It's still documented as available in macOS 12. How it can be "works as designed" and not supported at the same time?
Reported as FB9728793
I tested this with the sample app provided by Apple from https://developer.apple.com/documentation/fileprovider/macos_support/syncing_files_on_macos and as soon as I modify it to signal anything else than workingSet, signaling stop working.
I tried to signal using fileproviderctl CLI tool, and the effect is the same. only working set container is triggered
This problem is reported with number FB9673209