Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change NSPopover background color include triangle part?

Tags:

cocoa

How can I change NSPopover background color include triangle part?

enter image description here

like image 920
CocoaUser Avatar asked Nov 14 '13 13:11

CocoaUser


3 Answers

It's actually much simpler and you won't need private API.

Make the root view of your view controller a custom class

@implementation MyPopoverRootView

-(void)viewDidMoveToWindow
{
     NSView * aFrameView = [[self.window contentView] superview];
     MyPopoverBackgroundView * aBGView  =[[MyPopoverBackgroundView alloc] initWithFrame:aFrameView.bounds];
     aBGView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
     [aFrameView addSubview:aBGView positioned:NSWindowBelow relativeTo:aFrameView];
     [super viewDidMoveToWindow];
}

@end

Your background view just draws the desired color in its bounds.

@implementation MyPopoverBackgroundView

-(void)drawRect:(NSRect)dirtyRect
{
    [[NSColor whiteColor] set];
    NSRectFill(self.bounds);
}

@end
like image 67
Stefanf Avatar answered Nov 17 '22 17:11

Stefanf


Swift 3

override func viewDidMoveToWindow() {

    guard let frameView = window?.contentView?.superview else {
        return
    }

    let backgroundView = NSView(frame: frameView.bounds)
    backgroundView.wantsLayer = true
    backgroundView.layer?.backgroundColor = .white // colour of your choice
    backgroundView.autoresizingMask = [.viewWidthSizable, .viewHeightSizable]

    frameView.addSubview(backgroundView, positioned: .below, relativeTo: frameView)

}

If you want to change only the background colour of the popover (including the triangle/arrow), I figured that you don't need to create a subclass of NSView. A layer-backed NSView with a background colour should suffice.

Also, you don't need to call super.viewDidMoveToWindow() because its default implementation does nothing.

like image 23
beingadrian Avatar answered Nov 17 '22 18:11

beingadrian


Thanks to Stefanf I got this working. Here is a Swift version of the View code. As noted, this should be the class for the View set as your NSPopOver contentView.

class PopoverContentView:NSView {
    var backgroundView:PopoverBackgroundView?
    override func viewDidMoveToWindow() {
        super.viewDidMoveToWindow()
        if let frameView = self.window?.contentView?.superview {
            if backgroundView == nil {
                backgroundView = PopoverBackgroundView(frame: frameView.bounds)
                backgroundView!.autoresizingMask = NSAutoresizingMaskOptions([.ViewWidthSizable, .ViewHeightSizable]);
                frameView.addSubview(backgroundView!, positioned: NSWindowOrderingMode.Below, relativeTo: frameView)
            }
        }
    }
}



class PopoverBackgroundView:NSView {
    override func drawRect(dirtyRect: NSRect) {
        NSColor.redColor().set()
        NSRectFill(self.bounds)
    }
}
like image 9
Mike Bedar Avatar answered Nov 17 '22 18:11

Mike Bedar