Reputation: 5057
I am designing a user interface containing several labels and text fields. I would like to style the UI like this:
NSWindow
I solved the first problem by making the content view a layer-backed view as described in Apple's documentation of NSView
:
A layer-backed view is a view that is backed by a Core Animation layer. Any drawing done by the view is the cached in the backing layer. You configured a layer-backed view by simply invoking
setWantsLayer:
with a value ofYES
. The view class will automatically create the a backing layer for you, and you use the view class’s drawing mechanisms. When using layer-backed views you should never interact directly with the layer.A layer-hosting view is a view that contains a Core Animation layer that you intend to manipulate directly. You create a layer-hosting view by instantiating an instance of a Core Animation layer class and setting that layer using the view’s
setLayer:
method. After doing so, you then invokesetWantsLayer:
with a value ofYES
. When using a layer-hosting view you should not rely on the view for drawing, nor should you add subviews to the layer-hosting view.
and then generating a CGColorRef
out of a CGPattern
which draws my CGImage
:
NSView *mainView = [[self window]contentView];
[mainView setWantsLayer:YES];
To set the background image as a pattern I used the answer from How to tile the contents of a CALayer here on SO to get the first task done.
However for the second task, adding the icon I used the code below:
CGImageRef iconImage = NULL;
NSString *path = [[NSBundle mainBundle] pathForResource:@"icon_128" ofType:@"png"];
if(path != nil) {
NSURL *imageURL = [NSURL fileURLWithPath:path];
provider = CGDataProviderCreateWithURL((CFURLRef)imageURL);
iconImage = CGImageCreateWithPNGDataProvider(provider,NULL,FALSE,kCGRenderingIntentDefault);
CFRelease(provider);
}
CALayer *iconLayer = [[CALayer alloc] init];
// layer is the mainView's layer
CGRect layerFrame = layer.frame;
CGFloat iconWidth = 128.f;
iconLayer.frame = CGRectMake(0.f, CGRectGetHeight(layerFrame)-iconWidth, 128.f, 128.f);
iconLayer.contents = (id)iconImage;
CGImageRelease(iconImage);
[layer insertSublayer:iconLayer atIndex:0];
[iconLayer release];
NSView
seems to be the cleanest solution. All the text labels could then be added as CATextLayers
etc. However if I understand Apple's documentation correctly I cannot add any controls to the view anymore. Would I have to code all the controls myself in custom CALayers
to get it working? Sounds like reinventing the wheel de luxe. I also have no idea how one would code a NSTextField
solely in CoreAnimation.Any advice on how split designing user interfaces with CoreAnimation and standard controls is appreciated.
Please note that I am talking about the Mac here.
Upvotes: 4
Views: 2737
Reputation: 50089
no layer backing needed IMHO:
for 1. I do a pattern image
NSImage *patternImage = [NSImage imageNamed:@"pattern"];
[window setBackgroungdColor:[NSColor colorWithPatternImage:patternImage]];
for 2. add an NSImageView as a subview of the contentview
NSImageView *v = ...
[[window contentView] addSubview:v];
on mac some views dont respond nicely IF layer backed :: e.g. pdfview
Upvotes: 1
Reputation: 1263
Make a superview container A. Add a subview B to A for all your NSView needs (buttons, etc.). Add a subview C to A for all your Core Animation needs.
Edit: Even better: use superview A for all your NSView needs and one subview C for your Core Animation needs, ignoring view B altogether.
Upvotes: 0