Re: Laying out text in NSTextView around a subview
Re: Laying out text in NSTextView around a subview
- Subject: Re: Laying out text in NSTextView around a subview
- From: Seth Willits <email@hidden>
- Date: Tue, 30 Apr 2013 11:35:16 -0700
On Apr 30, 2013, at 7:01 AM, Jason Brennan wrote:
> Yeah what I'm trying to do mostly is a "block" element in the text, "inline" is just a side thing, not essential. What I'm trying to do is best described as an analogy with HTML.
>
> Let's say I've got the following HTML:
>
> <p>This is a paragraph</p>
> <img/>
> <p>Another paragraph</p>
So a quick fiddle offers a potential simpler solution. This is not quite complete, but shows the idea. The only bit this doesn't handle is removing the view when the attachment cell is removed from the text storage. To deal with that you need to create a simple text storage subclass and in the replaceā¦: method, scan for ViewAttachments and remove the view from the superview.
(Using a single view instance like this, you also won't be able to show the same text storage in two different text views since the view can't be in two places at once.)
@interface ViewAttachment : NSTextAttachment
@end
@interface ViewAttachmentCell : NSTextAttachmentCell {
NSView * _view;
}
@property (readwrite, assign) NSView * view;
@end
@implementation AppDelegate
{
IBOutlet NSTextView * textView;
IBOutlet NSView * attachmentView;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSTextStorage * ts = textView.textStorage;
NSUInteger location = <pick something in the middle of a line>
ViewAttachmentCell * attachmentCell = [[[ViewAttachmentCell alloc] init] autorelease];
attachmentCell.view = attachmentView;
ViewAttachment * attachment = [[[ViewAttachment alloc] init] autorelease];
attachment.attachmentCell = attachmentCell;
NSAttributedString * attachStr = [NSAttributedString attributedStringWithAttachment:attachment];
[ts insertAttributedString:attachStr atIndex:location];
}
@end
@implementation ViewAttachment
@end
@implementation ViewAttachmentCell
@synthesize view = _view;
- (NSSize)cellSize
{
return self.view.frame.size;
}
- (NSRect)cellFrameForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(NSRect)lineFrag glyphPosition:(NSPoint)position characterIndex:(NSUInteger)charIndex
{
NSRect cellFrame = [super cellFrameForTextContainer:textContainer proposedLineFragment:lineFrag glyphPosition:position characterIndex:charIndex];
// Make it on its own line.
cellFrame.size.width = textContainer.containerSize.width;
// Side note: AFAICT, the x/y of the frame when calling super is always 0,0
// which seems contradictory to what the documentation suggests it should be.
// As a result, handling x/y seems unnecessary here, and works without it.
// Otherwise I'd expect to have to set x to 0 and bump the y if needed, etc.
return cellFrame;
}
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView characterIndex:(NSUInteger)charIndex layoutManager:(NSLayoutManager *)layoutManager
{
if (self.view.superview != controlView) {
[self.view removeFromSuperview];
[controlView addSubview:self.view];
}
// I'm not really sure if moving the view when the cell should draw is good
// enough, but it works in this quick example, anyway. You may need to change
// the frame whenever the text storage changes (smartly).
self.view.frame = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
}
@end
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden