Source/GGBLayer.m
author Jens Alfke <jens@mooseyard.com>
Wed Mar 12 15:51:32 2008 -0700 (2008-03-12)
changeset 6 af9b2b929b03
parent 1 3eb7be1dd7b6
child 7 428a194e3e59
permissions -rw-r--r--
Fixed: An exception in the Go game if you mouse down on the board but then drag to the captured-pieces area and release the mouse.
jens@1
     1
//
jens@1
     2
//  GGBLayer.m
jens@1
     3
//  GGB-iPhone
jens@1
     4
//
jens@1
     5
//  Created by Jens Alfke on 3/7/08.
jens@1
     6
//  Copyright 2008 __MyCompanyName__. All rights reserved.
jens@1
     7
//
jens@1
     8
jens@1
     9
#import "GGBLayer.h"
jens@1
    10
#import "QuartzUtils.h"
jens@1
    11
jens@1
    12
jens@1
    13
@implementation GGBLayer
jens@1
    14
jens@1
    15
jens@1
    16
- (NSString*) description
jens@1
    17
{
jens@1
    18
    return [NSString stringWithFormat: @"%@[(%g,%g)]", self.class,self.position.x,self.position.y];
jens@1
    19
}
jens@1
    20
jens@1
    21
jens@4
    22
- (void) redisplayAll
jens@4
    23
{
jens@4
    24
    [self setNeedsDisplay];
jens@4
    25
    for( CALayer *layer in self.sublayers )
jens@4
    26
        if( [layer isKindOfClass: [GGBLayer class]] )
jens@4
    27
            ((GGBLayer*)layer).redisplayAll;
jens@4
    28
        else
jens@4
    29
            [layer setNeedsDisplay];
jens@4
    30
}
jens@4
    31
jens@4
    32
jens@1
    33
#if TARGET_OS_ASPEN
jens@1
    34
jens@1
    35
#pragma mark -
jens@1
    36
#pragma mark IPHONE VERSION:
jens@1
    37
jens@1
    38
jens@1
    39
- (id) copyWithZone: (NSZone*)zone
jens@1
    40
{
jens@1
    41
    GGBLayer *clone = [[[self class] alloc] init];
jens@1
    42
    clone.bounds = self.bounds;
jens@1
    43
    clone.position = self.position;
jens@1
    44
    clone.zPosition = self.zPosition;
jens@1
    45
    clone.anchorPoint = self.anchorPoint;
jens@1
    46
    clone.transform = self.transform;
jens@1
    47
    clone.hidden = self.hidden;
jens@1
    48
    clone.doubleSided = self.doubleSided;
jens@1
    49
    clone.sublayerTransform = self.sublayerTransform;
jens@1
    50
    clone.masksToBounds = self.masksToBounds;
jens@1
    51
    clone.contents = self.contents;                 // doesn't copy contents (shallow-copy)
jens@1
    52
    clone.contentsRect = self.contentsRect;
jens@1
    53
    clone.contentsGravity = self.contentsGravity;
jens@1
    54
    clone.minificationFilter = self.minificationFilter;
jens@1
    55
    clone.magnificationFilter = self.magnificationFilter;
jens@1
    56
    clone.opaque = self.opaque;
jens@1
    57
    clone.needsDisplayOnBoundsChange = self.needsDisplayOnBoundsChange;
jens@1
    58
    clone.edgeAntialiasingMask = self.edgeAntialiasingMask;
jens@1
    59
    clone.backgroundColor = self.backgroundColor;
jens@1
    60
    clone.opacity = self.opacity;
jens@1
    61
    clone.compositingFilter = self.compositingFilter;
jens@1
    62
    clone.filters = self.filters;
jens@1
    63
    clone.backgroundFilters = self.backgroundFilters;
jens@1
    64
    clone.actions = self.actions;
jens@1
    65
    clone.name = self.name;
jens@1
    66
    clone.style = self.style;
jens@1
    67
    
jens@1
    68
    clone.cornerRadius = self.cornerRadius;
jens@1
    69
    clone.borderWidth = self.borderWidth;
jens@1
    70
    clone.borderColor = self.borderColor;
jens@1
    71
    
jens@1
    72
    for( GGBLayer *sublayer in self.sublayers ) {
jens@1
    73
        sublayer = [sublayer copyWithZone: zone];
jens@1
    74
        [clone addSublayer: sublayer];
jens@1
    75
    }
jens@1
    76
    return clone;
jens@1
    77
}
jens@1
    78
jens@1
    79
jens@1
    80
- (CGFloat) cornerRadius    {return _cornerRadius;}
jens@1
    81
- (CGFloat) borderWidth     {return _borderWidth;}
jens@1
    82
- (CGColorRef) borderColor  {return _borderColor;}
jens@1
    83
jens@1
    84
- (void) setCornerRadius: (CGFloat)r
jens@1
    85
{
jens@1
    86
    if( r != _cornerRadius ) {
jens@1
    87
        _cornerRadius = r;
jens@1
    88
        [self setNeedsDisplay];
jens@1
    89
    }
jens@1
    90
}
jens@1
    91
jens@1
    92
jens@1
    93
- (void) setBorderWidth: (CGFloat)w
jens@1
    94
{
jens@1
    95
    if( w != _borderWidth ) {
jens@1
    96
        _borderWidth = w;
jens@1
    97
        self.needsDisplayOnBoundsChange = (_borderWidth>0.0 && _borderColor!=NULL);
jens@1
    98
        [self setNeedsDisplay];
jens@1
    99
    }
jens@1
   100
}
jens@1
   101
jens@1
   102
jens@1
   103
- (void) setBackgroundColor: (CGColorRef)color
jens@1
   104
{
jens@1
   105
    if( color != _realBGColor ) {
jens@1
   106
        CGColorRelease(_realBGColor);
jens@1
   107
        _realBGColor = CGColorRetain(color);
jens@1
   108
        [self setNeedsDisplay];
jens@1
   109
    }
jens@1
   110
}
jens@1
   111
jens@1
   112
jens@1
   113
- (void) setBorderColor: (CGColorRef)color
jens@1
   114
{
jens@1
   115
    if( color != _borderColor ) {
jens@1
   116
        CGColorRelease(_borderColor);
jens@1
   117
        _borderColor = CGColorRetain(color);
jens@1
   118
        self.needsDisplayOnBoundsChange = (_borderWidth>0.0 && _borderColor!=NULL);
jens@1
   119
        [self setNeedsDisplay];
jens@1
   120
    }
jens@1
   121
}
jens@1
   122
jens@1
   123
jens@1
   124
- (void)drawInContext:(CGContextRef)ctx
jens@1
   125
{
jens@4
   126
    [super drawInContext: ctx];
jens@4
   127
    
jens@1
   128
    CGContextSaveGState(ctx);
jens@1
   129
jens@1
   130
    if( _realBGColor ) {
jens@1
   131
        CGRect interior = CGRectInset(self.bounds, _borderWidth,_borderWidth);
jens@1
   132
        CGContextSetFillColorWithColor(ctx, _realBGColor);
jens@1
   133
        if( _cornerRadius <= 0.0 ) {
jens@1
   134
            CGContextFillRect(ctx,interior);
jens@1
   135
        } else {
jens@1
   136
            CGContextBeginPath(ctx);
jens@1
   137
            AddRoundRect(ctx,interior,_cornerRadius);
jens@1
   138
            CGContextFillPath(ctx);
jens@1
   139
        }
jens@1
   140
    }
jens@1
   141
    
jens@1
   142
    if( _borderWidth > 0.0 && _borderColor!=NULL ) {
jens@1
   143
        CGRect border = CGRectInset(self.bounds, _borderWidth/2.0, _borderWidth/2.0);
jens@1
   144
        CGContextSetStrokeColorWithColor(ctx, _borderColor);
jens@1
   145
        CGContextSetLineWidth(ctx, _borderWidth);
jens@1
   146
        
jens@1
   147
        if( _cornerRadius <= 0.0 ) {
jens@1
   148
            CGContextStrokeRect(ctx,border);
jens@1
   149
        } else {
jens@1
   150
            CGContextBeginPath(ctx);
jens@1
   151
            AddRoundRect(ctx,border,_cornerRadius);
jens@1
   152
            CGContextStrokePath(ctx);
jens@1
   153
        }
jens@1
   154
    }
jens@1
   155
    
jens@1
   156
    CGContextRestoreGState(ctx);
jens@1
   157
}
jens@1
   158
jens@1
   159
jens@1
   160
#else
jens@1
   161
jens@1
   162
#pragma mark -
jens@1
   163
#pragma mark MAC OS VERSION:
jens@1
   164
jens@1
   165
jens@1
   166
- (id) copyWithZone: (NSZone*)zone
jens@1
   167
{
jens@1
   168
    // NSLayer isn't copyable, but it is archivable. So create a copy by archiving to
jens@1
   169
    // a temporary data block, then unarchiving a new layer from that block.
jens@1
   170
    
jens@1
   171
    // One complication is that, due to a bug in Core Animation, CALayer can't archive
jens@1
   172
    // a pattern-based CGColor. So as a workaround, clear the background before archiving,
jens@1
   173
    // then restore it afterwards.
jens@1
   174
    
jens@1
   175
    // Also, archiving a CALayer with an image in it leaks memory. (Filed as rdar://5786865 )
jens@1
   176
    // As a workaround, clear the contents before archiving, then restore.
jens@1
   177
    
jens@1
   178
    CGColorRef bg = CGColorRetain(self.backgroundColor);
jens@1
   179
    self.backgroundColor = NULL;
jens@1
   180
    id contents = [self.contents retain];
jens@1
   181
    self.contents = nil;
jens@1
   182
    
jens@1
   183
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject: self];
jens@1
   184
    
jens@1
   185
    self.backgroundColor = bg;
jens@1
   186
    self.contents = contents;
jens@1
   187
jens@1
   188
    GGBLayer *clone = [NSKeyedUnarchiver unarchiveObjectWithData: data];
jens@1
   189
    clone.backgroundColor = bg;
jens@1
   190
    clone.contents = contents;
jens@1
   191
    CGColorRelease(bg);
jens@1
   192
    [contents release];
jens@1
   193
jens@1
   194
    return [clone retain];
jens@1
   195
}
jens@1
   196
jens@1
   197
jens@1
   198
#endif
jens@1
   199
jens@1
   200
jens@1
   201
@end