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 (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to