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