0
votes

OK, here's what I have done:

  • I have an NSCollectionView
  • I wanted to be able to enable "selecting" items, and drawing a custom border when an items is selected
  • I subclassed NSCollectionViewItem (to enable selection)
  • I subclassed NSView for the NSCollectionViewItem view, in order to draw the border

The code

The view item

@implementation MSLibraryCollectionViewItem

- (void)setSelected:(BOOL)flag
{
    [super setSelected:flag];
    [(MSLibraryCollectionViewView*)[self view] setSelected:flag];
    [(MSLibraryCollectionViewView*)[self view] setNeedsDisplay:YES];
}

The custom view

@implementation MSLibraryCollectionViewView

/***************************************
 Initialisation
 ***************************************/

- (MSLibraryCollectionViewView*)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }

    return self;
}

/***************************************
 Drawing
 ***************************************/

- (void)drawRect:(NSRect)rect
{
    if ([self selected]) {
        //[[NSColor redColor] setFill];
        //NSRectFill(rect);
        //[super drawRect:rect];

            NSColor* gS = [NSColor colorWithCalibratedRed:0.06 green:0.45 blue:0.86 alpha:1.0];
        NSColor* gE = [NSColor colorWithCalibratedRed:0.12 green:0.64 blue:0.94 alpha:1.0];
        NSGradient* g = [[NSGradient alloc] initWithStartingColor:gE endingColor:gS];
        NSColor *borderColor = [NSColor colorFromGradient:g];

        NSRect frameRect = [self bounds];

        if(rect.size.height < frameRect.size.height)
            return;
        NSRect newRect = NSMakeRect(rect.origin.x+5, rect.origin.y+5, rect.size.width-10, rect.size.height-10);

        NSBezierPath *textViewSurround = [NSBezierPath bezierPathWithRoundedRect:newRect xRadius:7 yRadius:7];
        [textViewSurround setLineWidth:2.0];
        [borderColor set];
        [textViewSurround stroke];
    }
}

However, the seems to be something wrong with drawing. For example:

  • When resizing the Collection View's container, a weird line appears at the outer box
  • When an Collection View item is not 100% visible (e.g. because it's been scrolled down), the selection border doesn't appear at all (while I would expect it to draw just the visible portion).

Some Examples

NSCollectionView selected item drawing issue

NSCollectionView drawing issue

What's going on?


P.S. I'm not a guru with drawing and custom views in Cocoa - so any ideas/help is more than welcome!

1

1 Answers

1
votes

You switched from asking about a collection view to talking about an outline view, but I assume that was just a mental hiccup.

  • When an Outline View item is not 100% visible (e.g. because it's been scrolled down), the selection border doesn't appear at all (while I would expect it to draw just the visible portion).

That's because of this code in your -drawRect:.

    if(rect.size.height < frameRect.size.height)
        return;

It's specifically avoiding drawing a partial selection outline.

Regarding the weird line, I doubt that has to do with your collection item view's custom drawing. Does it stop happening if you disable the custom drawing? You could experiment with using an ordinary color rather than using the third-party +colorFromGradient: code you're using.

By the way, this line:

    NSRect newRect = NSMakeRect(rect.origin.x+5, rect.origin.y+5, rect.size.width-10, rect.size.height-10);

could be written more simply as:

    NSRect newRect = NSInsetRect(rect, 5, 5);