Reputation: 18132
I have a bunch of NSTextView
s that I would like to share a single selection. I basically want this to behave like selecting text on a web page, where there are multiple text views but you can drag to sequentially select text among them.
I found this document which states that it is possible to have multiple NSTextContainer
objects sharing a single NSLayoutManager
and thus share the selection. This is halfway to what I want, except for the fact that one NSLayoutManager
can only have a single NSTextStorage
object. I want each text view to have its own NSTextStorage
so that each text view can have its own text, but I still want to be able to select text in multiple text views with one drag. Is this possible?
Upvotes: 7
Views: 1325
Reputation: 18132
There's no easy way to solve this problem (as I tried to find by asking this question). It involves all the mouse event handling and text selection calculations you'd expect, so I wrote the code and have open sourced it as INDSequentialTextSelectionManager
.
Upvotes: 4
Reputation: 7381
To make this separate text containers work, you would calculate the drawn size of each part of the string and limit the NSTextView to that size:
NSLayoutManager * layout = [[NSLayoutManager alloc] init];
NSString * storedString = @"A\nquick\nBrown\nFox";
NSTextStorage * storage = [[NSTextStorage alloc] initWithString:storedString];
[storage addLayoutManager:layout];
//I assume you have a parent view to add the text views
NSView * view;
//Assuming you want to split up into separate view by line break
NSArray * paragraphs = [storedString componentsSeparatedByString:@"\n"];
for (NSString * paragraph in paragraphs)
{
NSSize paragraphSize = [paragraph sizeWithAttributes:@{}];
//Create a text container only big enough for the string to be displayed by the text view
NSTextContainer * paragraphContainer = [[NSTextContainer alloc] initWithContainerSize:paragraphSize];
[layout addTextContainer:paragraphContainer];
//Use autolayout or calculate size/placement as you go along
NSRect lazyRectWithoutSizeOrPlacement = NSMakeRect(0, 0, 0, 0);
NSTextView * textView = [[NSTextView alloc] initWithFrame:lazyRectWithoutSizeOrPlacement
textContainer:paragraphContainer];
[view addSubview:textView];
}
You can add a delegate to the NSLayoutManager to watch your text container usage:
- (void)layoutManager:(NSLayoutManager *)aLayoutManager
didCompleteLayoutForTextContainer:(NSTextContainer *)aTextContainer
atEnd:(BOOL)flag
{
if (aTextContainer == nil)
{
//All text was unable to be displayed in existing containers. A new NSTextContainer is needed.
}
}
Upvotes: 0