6

I have subclasses NSImageView and i want to draw a border around with rounded corners. It works but i need to clip off the image corners as well.

Please see my screenshot:

enter image description here

I have created this code to draw the border/corners.

- (void)drawRect:(NSRect)dirtyRect
{
    [super drawRect:dirtyRect];

    NSColor *strokeColor;
    if(self.isSelected)
        strokeColor = [NSColor colorFromHexRGB:@"f9eca2"];
    else
        strokeColor = [NSColor colorFromHexRGB:@"000000"];

    [strokeColor set];    
    [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(dirtyRect, 1, 1) xRadius:5 yRadius:5] stroke];
}

What should i do to make the image clip ?

EDIT:

Well i fixed it, but i feel its an ugly way to do it. Anything smarter?

NEW CODE:

- (void)drawRect:(NSRect)dirtyRect
{
    NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:NSInsetRect(dirtyRect, 2, 2) xRadius:5 yRadius:5];

    [path setLineWidth:4.0];
    [path addClip];

    [self.image drawAtPoint: NSZeroPoint
                 fromRect:dirtyRect
                 operation:NSCompositeSourceOver
                 fraction: 1.0];

    [super drawRect:dirtyRect];

    NSColor *strokeColor;
    if(self.isSelected)
    {
        strokeColor = [NSColor colorFromHexRGB:@"f9eca2"];
    }
    else
        strokeColor = [NSColor colorFromHexRGB:@"000000"];

    [strokeColor set];    
    [NSBezierPath setDefaultLineWidth:4.0];
    [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(dirtyRect, 2, 2) xRadius:5 yRadius:5] stroke];
}
Rasmus Styrk
  • 1,296
  • 2
  • 20
  • 36

2 Answers2

4

Set the corner radius of your NSImageViews layer also to 5 px and set its maskToBounds property to YES.

Vince
  • 525
  • 1
  • 3
  • 19
yinkou
  • 5,756
  • 2
  • 24
  • 40
  • 3
    `NSImageView` doesn't have a `clipsToBounds` property - It's an NS not a UI ImageView. – SteveF Sep 26 '12 at 10:36
  • 18
    Why does every second person on stackoverflow assume objective-c code == iOS? – strange Aug 30 '13 at 00:21
  • 3
    if you read carefully the answer you'll see he's talking about the image view's layer, which has a clipToBounds property even in AppKit. EDIT: don't forget to enable the layer by using `-[NSView setWantsLayer:YES]` – dvkch Jan 07 '15 at 02:48
  • @dvkch Except NSImageView, and it's CALayer, does *not* have a clipToBounds property. So this answer is wrong on all accounts. – Claus Jørgensen Aug 02 '15 at 02:32
  • But it has a maskToBounds which does the job. – yinkou Aug 02 '15 at 17:16
2

updated answer for XCode 8.3 and Swift 3.1

import Cocoa

class SomeViewController: NSViewController {
  @IBOutlet weak var artwork: NSImageView!

  override func viewDidLoad() {
    super.viewDidLoad()
    artwork.wantsLayer = true // Use a layer as backing store for this view
    artwork.canDrawSubviewsIntoLayer = true // Important, flatten all subviews into layer
    artwork.layer?.cornerRadius = 4.0
    artwork.layer?.masksToBounds = true // Mask layer
  }
}
gf3
  • 481
  • 2
  • 11