Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom NSWindow with rounded corners which clip subviews

I'm trying to create a custom NSWindow, so I've created one with the proper borderless window mask and that works. I provide my own content view which is fine. But what I'm trying to do is draw with rounded corners that also clip subviews to those corners. Is this possible?

In my content view, I can override drawRect: and draw a path with round corners, but when I add subviews to this, they aren't clipped.

I can instead make my content view layer-backed and give it a corner radius (with masksToBounds set to YES) but when I add subviews, they're still not clipped by my round corners.

Is there a way to do this? Or some way to draw an NSWindow without a title bar and which I'd have full control over the drawing, and yet maintain the rounded, clipping corners?

like image 421
jbrennan Avatar asked Mar 02 '13 20:03

jbrennan


2 Answers

What I was able to do is provide a custom subclass of my NSWindow:

@implementation ELGRoundWindow

- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
{
    self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:bufferingType defer:flag];

    if ( self )
    {
        [self setStyleMask:NSBorderlessWindowMask];
        [self setOpaque:NO];
        [self setBackgroundColor:[NSColor clearColor]];
    }

    return self;
}


- (void) setContentView:(NSView *)aView
{
    aView.wantsLayer            = YES;
    aView.layer.frame           = aView.frame;
    aView.layer.cornerRadius    = 20.0;
    aView.layer.masksToBounds   = YES;


    [super setContentView:aView];

}

@end

and then in IB, I changed the class of my content view to ELGRoundView:

@implementation ELGRoundView

- (void)drawRect:(NSRect)dirtyRect
{
    [[NSColor colorWithCalibratedRed:0.0 green:0.5 blue:1 alpha:1] set];
    NSRectFill(dirtyRect);
}

@end

I placed another square subview in my content view with the following:

@implementation ELGSquareView

- (void)drawRect:(NSRect)dirtyRect
{
    [[NSColor colorWithCalibratedRed:0.0 green:0 blue:1 alpha:1] set];
    NSRectFill(dirtyRect);
}

@end

I ended up with:

Rounded window with clipped subview

like image 168
ericg Avatar answered Nov 01 '22 19:11

ericg


What @ericgorr is suggesting is correct. In addition if you want the window to be movable and resizable change the init of the NSWindow as follows,

- (id)initWithContentRect:(NSRect)contentRect
                 styleMask:(NSUInteger)aStyle
                   backing:(NSBackingStoreType)bufferingType
                     defer:(BOOL)flag
{
    self = [super initWithContentRect:contentRect
                            styleMask:aStyle
                              backing:bufferingType
                                defer:flag];
    if (self) {            
        [self setOpaque:NO];
        [self setBackgroundColor:[NSColor clearColor]];
        [self setMovableByWindowBackground:YES];
        [self setStyleMask:NSResizableWindowMask];
    }
    return self;
}

For further customisation refer Apple sample code http://developer.apple.com/library/mac/#samplecode/RoundTransparentWindow/Introduction/Intro.html

like image 5
ThE uSeFuL Avatar answered Nov 01 '22 20:11

ThE uSeFuL