Initial check-in into Mercurial. Branched from 1.0 release of Apple's sample code. No longer requires garbage collection. Fixed some memory leaks of CG objects. Fixed a bug when advancing to the 8th row in the Checkers game.
1 /* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
2 http://developer.apple.com/samplecode/GeekGameBoard/
3 Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
5 Redistribution and use in source and binary forms, with or without modification, are permitted
6 provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice, this list of conditions
9 and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice, this list of
11 conditions and the following disclaimer in the documentation and/or other materials provided
12 with the distribution.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
15 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
17 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
21 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 #import "QuartzUtils.h"
30 static CATransform3D kFaceUpTransform, kFaceDownTransform;
34 if( self==[Card class] ) {
35 kFaceUpTransform = kFaceDownTransform = CATransform3DIdentity;
36 // Construct a 180-degree rotation matrix:
37 kFaceDownTransform.m11 = kFaceDownTransform.m33 = -1;
38 // The more obvious way to create kFaceDownTransform would be to call
39 // CATransform3DMakeRotation(pi,0,1,0), but due to round-off errors, that transform
40 // will have non-zero values in some other places, making it appear to CA as a true
41 // 3D transform; this will then cause unexpected clipping behaviors when used.
46 + (NSRange) serialNumberRange;
48 NSAssert1(NO,@"%@ forgot to override +serialNumberRange",self);
49 return NSMakeRange(0,0);
53 - (id) initWithSerialNumber: (int)serial position: (CGPoint)pos
57 _serialNumber = serial;
58 self.bounds = CGRectMake(0,0,kCardWidth,kCardHeight);
60 self.edgeAntialiasingMask = 0;
61 _back = [self createBack];
62 [self addSublayer: _back];
63 _front = [self createFront];
64 _front.transform = kFaceDownTransform;
65 [self addSublayer: _front];
71 - (void)encodeWithCoder:(NSCoder *)aCoder
73 [super encodeWithCoder: aCoder];
74 [aCoder encodeInt: _serialNumber forKey: @"serialNumber"];
77 - (id)initWithCoder:(NSCoder *)aDecoder
79 self = [super initWithCoder: aDecoder];
81 _serialNumber = [aDecoder decodeIntForKey: @"serialNumber"];
87 - (NSString*) description
89 return [NSString stringWithFormat: @"%@[#%i]",self.class,_serialNumber];
93 @synthesize serialNumber=_serialNumber;
101 - (void) setFaceUp: (BOOL)up
103 if( up != _faceUp ) {
104 // The Card has separate sub-layers for its front and back. At any time, one of them
105 // is hidden, by having a 180 degree rotation about the Y axis.
106 // To flip the card, both front and back layers are flipped over.
108 xform = up ?kFaceUpTransform :kFaceDownTransform;
109 _front.transform = xform;
111 xform = up ?kFaceDownTransform :kFaceUpTransform;
112 _back.transform = xform;
118 - (CALayer*) createFront
120 CALayer *front = [[CALayer alloc] init];
121 front.bounds = CGRectMake(0,0,kCardWidth,kCardHeight);
122 front.position = CGPointMake(kCardWidth/2,kCardHeight/2);
123 front.edgeAntialiasingMask = 0;
124 front.backgroundColor = kWhiteColor;
125 front.cornerRadius = 8;
126 front.borderWidth = 1;
127 front.borderColor = CGColorCreateGenericGray(0.7, 1.0);
128 front.doubleSided = NO; // this makes the layer invisible when it's flipped
129 return [front autorelease];
133 - (CALayer*) createBack
135 CGSize size = self.bounds.size;
136 CALayer *back = [[CALayer alloc] init];
137 back.bounds = CGRectMake(0,0,size.width,size.height);
138 back.position = CGPointMake(kCardWidth/2,kCardHeight/2);
139 back.contents = (id) GetCGImageNamed(@"/Library/Desktop Pictures/Classic Aqua Blue.jpg");
140 back.contentsGravity = kCAGravityResize;
141 back.masksToBounds = YES;
142 back.borderWidth = 4;
143 back.borderColor = kWhiteColor;
144 back.cornerRadius = 8;
145 back.edgeAntialiasingMask = 0;
146 back.doubleSided = NO; // this makes the layer invisible when it's flipped
148 CATextLayer *label = AddTextLayer(back, @"\u2603", // Unicode snowman character
149 [NSFont systemFontOfSize: 0.9*size.width],
150 kCALayerWidthSizable|kCALayerHeightSizable);
151 label.foregroundColor = CGColorCreateGenericGray(1.0,0.5);
152 return [back autorelease];
157 #pragma mark DRAG-AND-DROP:
160 // An image from another app can be dragged onto a Card to change its background. */
163 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
165 NSPasteboard *pb = [sender draggingPasteboard];
166 if( [NSImage canInitWithPasteboard: pb] )
167 return NSDragOperationCopy;
169 return NSDragOperationNone;
172 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
174 CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard]);
176 CALayer *face = _faceUp ?_front :_back;
177 face.contents = (id) image;
178 face.contentsGravity = kCAGravityResizeAspectFill;
179 face.masksToBounds = YES;