ImageBrowserAppearance/ImageBrowserCell.m
/* |
Copyright (C) 2018 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
IKImageBrowserView's IKImageBrowserCell subclass for drawing its fancy appearance. |
*/ |
#import "ImageBrowserCell.h" |
//--------------------------------------------------------------------------------- |
// setBundleImageOnLayer |
// |
// Utility function that creates, and sets the image (from the bundle) on the layer. |
//--------------------------------------------------------------------------------- |
static void setBundleImageOnLayer(CALayer *layer, CFStringRef imageName) |
{ |
CGImageRef image = NULL; |
NSString *path = |
[[NSBundle mainBundle] pathForResource:((__bridge NSString *)imageName).stringByDeletingPathExtension |
ofType:((__bridge NSString *)imageName).pathExtension]; |
if (!path) |
{ |
return; |
} |
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path], NULL); |
if (!imageSource) |
{ |
return; |
} |
image = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL); |
if (!image) |
{ |
CFRelease(imageSource); |
return; |
} |
layer.contents = (__bridge id)image; |
CFRelease(imageSource); |
CFRelease(image); |
} |
#pragma mark - |
@implementation ImageBrowserCell |
//--------------------------------------------------------------------------------- |
// layerForType: |
// |
// Provides the layers for the given types. |
//--------------------------------------------------------------------------------- |
- (CALayer *)layerForType:(NSString*) type |
{ |
CGColorRef color; |
// retrieve some usefull rects |
NSRect frame = [self frame]; |
NSRect imageFrame = [self imageFrame]; |
NSRect relativeImageFrame = |
NSMakeRect(imageFrame.origin.x - frame.origin.x, |
imageFrame.origin.y - frame.origin.y, |
imageFrame.size.width, |
imageFrame.size.height); |
// place holder layer |
if (type == IKImageBrowserCellPlaceHolderLayer) |
{ |
// create a place holder layer |
CALayer *layer = [CALayer layer]; |
layer.frame = CGRectMake(0, 0, frame.size.width, frame.size.height); |
CALayer *placeHolderLayer = [CALayer layer]; |
placeHolderLayer.frame = *(CGRect*) &relativeImageFrame; |
CGFloat fillComponents[4] = {1.0, 1.0, 1.0, 0.3}; |
CGFloat strokeComponents[4] = {1.0, 1.0, 1.0, 0.9}; |
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); |
// set a background color |
color = CGColorCreate(colorSpace, fillComponents); |
placeHolderLayer.backgroundColor = color; |
CFRelease(color); |
// set a stroke color |
color = CGColorCreate(colorSpace, strokeComponents); |
placeHolderLayer.borderColor = color; |
CFRelease(color); |
placeHolderLayer.borderWidth = 2.0; |
placeHolderLayer.cornerRadius = 10; |
CFRelease(colorSpace); |
[layer addSublayer:placeHolderLayer]; |
return layer; |
} |
// foreground layer |
if (type == IKImageBrowserCellForegroundLayer) |
{ |
// no foreground layer on place holders |
if ([self cellState] != IKImageStateReady) |
{ |
return nil; |
} |
// create a foreground layer that will contain several childs layer |
CALayer *layer = [CALayer layer]; |
layer.frame = CGRectMake(0, 0, frame.size.width, frame.size.height); |
NSRect imageContainerFrame = [self imageContainerFrame]; |
NSRect relativeImageContainerFrame = |
NSMakeRect(imageContainerFrame.origin.x - frame.origin.x, |
imageContainerFrame.origin.y - frame.origin.y, |
imageContainerFrame.size.width, |
imageContainerFrame.size.height); |
// add a glossy overlay |
CALayer *glossyLayer = [CALayer layer]; |
glossyLayer.frame = *(CGRect *) &relativeImageContainerFrame; |
setBundleImageOnLayer(glossyLayer, CFSTR("glossy.png")); |
[layer addSublayer:glossyLayer]; |
// add a pin icon |
CALayer *pinLayer = [CALayer layer]; |
setBundleImageOnLayer(pinLayer, CFSTR("pin.tiff")); |
pinLayer.frame = CGRectMake((frame.size.width/2)-5, frame.size.height - 17, 24, 30); |
[layer addSublayer:pinLayer]; |
return layer; |
} |
// selection layer |
if (type == IKImageBrowserCellSelectionLayer) |
{ |
// create a selection layer |
CALayer *selectionLayer = [CALayer layer]; |
selectionLayer.frame = CGRectMake(0, 0, frame.size.width, frame.size.height); |
CGFloat fillComponents[4] = {1.0, 0, 0.5, 0.3}; |
CGFloat strokeComponents[4] = {1.0, 0.0, 0.5, 1.0}; |
// set a background color |
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); |
color = CGColorCreate(colorSpace, fillComponents); |
selectionLayer.backgroundColor = color; |
CFRelease(color); |
// set a border color |
color = CGColorCreate(colorSpace, strokeComponents); |
CFRelease(colorSpace); |
selectionLayer.borderColor = color; |
CFRelease(color); |
selectionLayer.borderWidth = 2.0; |
selectionLayer.cornerRadius = 5; |
return selectionLayer; |
} |
// Background layer. |
if (type == IKImageBrowserCellBackgroundLayer) |
{ |
// No background layer on place holders. |
if ([self cellState] != IKImageStateReady) |
{ |
return nil; |
} |
CALayer *layer = [CALayer layer]; |
layer.frame = CGRectMake(0, 0, frame.size.width, frame.size.height); |
NSRect backgroundRect = NSMakeRect(0, 0, frame.size.width, frame.size.height); |
CALayer *photoBackgroundLayer = [CALayer layer]; |
photoBackgroundLayer.frame = *(CGRect*) &backgroundRect; |
CGFloat fillComponents[4] = {0.95, 0.95, 0.95, 1.0}; |
CGFloat strokeComponents[4] = {0.2, 0.2, 0.2, 0.5}; |
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); |
color = CGColorCreate(colorSpace, fillComponents); |
photoBackgroundLayer.backgroundColor = color; |
CFRelease(color); |
color = CGColorCreate(colorSpace, strokeComponents); |
photoBackgroundLayer.borderColor = color; |
CFRelease(color); |
photoBackgroundLayer.borderWidth = 1.0; |
photoBackgroundLayer.shadowOpacity = 0.5; |
photoBackgroundLayer.cornerRadius = 3; |
CFRelease(colorSpace); |
[layer addSublayer:photoBackgroundLayer]; |
return layer; |
} |
return nil; |
} |
//--------------------------------------------------------------------------------- |
// imageFrame |
// |
// Define where the image should be drawn. |
//--------------------------------------------------------------------------------- |
- (NSRect)imageFrame |
{ |
// Get default imageFrame and aspect ratio. |
NSRect imageFrame = [super imageFrame]; |
if (imageFrame.size.height == 0 || imageFrame.size.width == 0) |
{ |
return NSZeroRect; |
} |
float aspectRatio = imageFrame.size.width / imageFrame.size.height; |
// Compute the rectangle included in container with a margin of at least 10 pixel at the bottom, |
// 5 pixel at the top and keep a correct aspect ratio. |
NSRect container = [self imageContainerFrame]; |
container = NSInsetRect(container, 8, 8); |
if (container.size.height <= 0) |
{ |
return NSZeroRect; |
} |
float containerAspectRatio = container.size.width / container.size.height; |
if (containerAspectRatio > aspectRatio){ |
imageFrame.size.height = container.size.height; |
imageFrame.origin.y = container.origin.y; |
imageFrame.size.width = imageFrame.size.height * aspectRatio; |
imageFrame.origin.x = container.origin.x + (container.size.width - imageFrame.size.width)*0.5; |
} |
else |
{ |
imageFrame.size.width = container.size.width; |
imageFrame.origin.x = container.origin.x; |
imageFrame.size.height = imageFrame.size.width / aspectRatio; |
imageFrame.origin.y = container.origin.y + container.size.height - imageFrame.size.height; |
} |
// Round it. |
imageFrame.origin.x = floorf(imageFrame.origin.x); |
imageFrame.origin.y = floorf(imageFrame.origin.y); |
imageFrame.size.width = ceilf(imageFrame.size.width); |
imageFrame.size.height = ceilf(imageFrame.size.height); |
return imageFrame; |
} |
//--------------------------------------------------------------------------------- |
// imageContainerFrame |
// |
// Override the default image container frame. |
//--------------------------------------------------------------------------------- |
- (NSRect)imageContainerFrame |
{ |
NSRect container = super.frame; |
// Make the image container 15 pixels up. |
container.origin.y += 15; |
container.size.height -= 15; |
return container; |
} |
//--------------------------------------------------------------------------------- |
// titleFrame |
// |
// Override the default frame for the title. |
//--------------------------------------------------------------------------------- |
- (NSRect)titleFrame |
{ |
// Get the default frame for the title. |
NSRect titleFrame = [super titleFrame]; |
// Move the title inside the 'photo' background image. |
NSRect container = [self frame]; |
titleFrame.origin.y = container.origin.y + 3; |
// Make sure the title has a 7px margin with the left/right borders. |
float margin = titleFrame.origin.x - (container.origin.x + 7); |
if (margin < 0) |
{ |
titleFrame = NSInsetRect(titleFrame, -margin, 0); |
} |
return titleFrame; |
} |
//--------------------------------------------------------------------------------- |
// selectionFrame |
// |
// Make the selection frame a little bit larger than the default one. |
//--------------------------------------------------------------------------------- |
- (NSRect)selectionFrame |
{ |
return NSInsetRect([self frame], -5, -5); |
} |
@end |
Copyright © 2018 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2018-05-03