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.)
authorJens Alfke <jens@mooseyard.com>
Tue Mar 11 17:09:50 2008 -0700 (2008-03-11)
changeset 4d781b00f3ed4
parent 3 40d225cf9c43
child 5 3ba1f29595c7
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.)
Source/BoardUIView.m
Source/Card.h
Source/Card.m
Source/Deck.m
Source/GGBLayer.h
Source/GGBLayer.m
Source/GGBTextLayer.h
Source/GGBTextLayer.m
Source/Game.h
Source/Game.m
Source/KlondikeGame.m
Source/PlayingCard.m
Source/iPhoneAppDelegate.m
     1.1 --- a/Source/BoardUIView.m	Tue Mar 11 09:21:53 2008 -0700
     1.2 +++ b/Source/BoardUIView.m	Tue Mar 11 17:09:50 2008 -0700
     1.3 @@ -42,19 +42,33 @@
     1.4  
     1.5  - (void) startGameNamed: (NSString*)gameClassName
     1.6  {
     1.7 +    Class gameClass = NSClassFromString(gameClassName);
     1.8 +    NSAssert1(gameClass,@"Unknown game '%@'",gameClassName);
     1.9 +    
    1.10 +    setObj(&_game,nil);
    1.11      if( _gameboard ) {
    1.12          [_gameboard removeFromSuperlayer];
    1.13          _gameboard = nil;
    1.14      }
    1.15 +
    1.16 +    CALayer *rootLayer = self.layer;
    1.17 +    self.layer.affineTransform = CGAffineTransformIdentity;
    1.18 +    CGRect frame = rootLayer.frame;
    1.19 +    frame.origin.x = frame.origin.y = 0;
    1.20 +    rootLayer.bounds = frame;
    1.21 +
    1.22 +    if( [gameClass landscapeOriented] && frame.size.height > frame.size.width ) {
    1.23 +        rootLayer.affineTransform = CGAffineTransformMakeRotation(M_PI/2);
    1.24 +        frame = CGRectMake(0,0,frame.size.height,frame.size.width);
    1.25 +        rootLayer.bounds = frame;
    1.26 +    }
    1.27 +    
    1.28      _gameboard = [[GGBLayer alloc] init];
    1.29 -    _gameboard.frame = [self gameBoardFrame];
    1.30 -    _gameboard.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
    1.31 -    [self.layer addSublayer: _gameboard];
    1.32 +    _gameboard.frame = frame;
    1.33 +    [rootLayer addSublayer: _gameboard];
    1.34      [_gameboard release];
    1.35      
    1.36 -    Class gameClass = NSClassFromString(gameClassName);
    1.37 -    NSAssert1(gameClass,@"Unknown game '%@'",gameClassName);
    1.38 -    setObj(&_game, [[gameClass alloc] initWithBoard: _gameboard]);
    1.39 +    _game = [[gameClass alloc] initWithBoard: _gameboard];
    1.40  }
    1.41  
    1.42  
     2.1 --- a/Source/Card.h	Tue Mar 11 09:21:53 2008 -0700
     2.2 +++ b/Source/Card.h	Tue Mar 11 17:09:50 2008 -0700
     2.3 @@ -23,11 +23,6 @@
     2.4  #import "Bit.h"
     2.5  
     2.6  
     2.7 -/** Hardcoded dimensions of a Card */
     2.8 -#define kCardWidth  100
     2.9 -#define kCardHeight 150
    2.10 -
    2.11 -
    2.12  /* A card of some type (playing card, Community Chest, money, ...)
    2.13     Has an identifying serial number (could be in the range 1..52 for playing cards).
    2.14     Can be face-up or down. */
    2.15 @@ -43,6 +38,9 @@
    2.16      Abstract; must be overridden. */
    2.17  + (NSRange) serialNumberRange;
    2.18  
    2.19 ++ (CGSize) cardSize;
    2.20 ++ (void) setCardSize: (CGSize)size;
    2.21 +
    2.22  - (id) initWithSerialNumber: (int)serial position: (CGPoint)pos;
    2.23  
    2.24  @property (readonly) int serialNumber;
     3.1 --- a/Source/Card.m	Tue Mar 11 09:21:53 2008 -0700
     3.2 +++ b/Source/Card.m	Tue Mar 11 17:09:50 2008 -0700
     3.3 @@ -28,6 +28,8 @@
     3.4  @implementation Card
     3.5  
     3.6  
     3.7 +static CGSize sCardSize = {100,150};
     3.8 +
     3.9  static CATransform3D kFaceUpTransform, kFaceDownTransform;
    3.10  
    3.11  + (void) initialize
    3.12 @@ -51,12 +53,16 @@
    3.13  }
    3.14  
    3.15  
    3.16 ++ (CGSize) cardSize                 {return sCardSize;}
    3.17 ++ (void) setCardSize: (CGSize)size  {sCardSize = size;}
    3.18 +
    3.19 +
    3.20  - (id) initWithSerialNumber: (int)serial position: (CGPoint)pos
    3.21  {
    3.22      self = [super init];
    3.23      if (self != nil) {
    3.24          _serialNumber = serial;
    3.25 -        self.bounds = CGRectMake(0,0,kCardWidth,kCardHeight);
    3.26 +        self.bounds = CGRectMake(0,0,sCardSize.width,sCardSize.height);
    3.27          self.position = pos;
    3.28          self.edgeAntialiasingMask = 0;
    3.29          _back = [self createBack];
    3.30 @@ -111,11 +117,11 @@
    3.31  - (GGBLayer*) createFront
    3.32  {
    3.33      GGBLayer *front = [[GGBLayer alloc] init];
    3.34 -    front.bounds = CGRectMake(0,0,kCardWidth,kCardHeight);
    3.35 -    front.position = CGPointMake(kCardWidth/2,kCardHeight/2);
    3.36 +    front.bounds = CGRectMake(0,0,sCardSize.width,sCardSize.height);
    3.37 +    front.position = CGPointMake(sCardSize.width/2,sCardSize.height/2);
    3.38      front.edgeAntialiasingMask = 0;
    3.39      front.backgroundColor = kWhiteColor;
    3.40 -    front.cornerRadius = 8;
    3.41 +    front.cornerRadius = 8 * (sCardSize.height/150);
    3.42      front.borderWidth = 1;
    3.43      front.borderColor = CreateGray(0.7, 1.0);
    3.44      front.doubleSided = NO;         // this makes the layer invisible when it's flipped
    3.45 @@ -128,19 +134,29 @@
    3.46      CGSize size = self.bounds.size;
    3.47      GGBLayer *back = [[GGBLayer alloc] init];
    3.48      back.bounds = CGRectMake(0,0,size.width,size.height);
    3.49 -    back.position = CGPointMake(kCardWidth/2,kCardHeight/2);
    3.50 +    back.position = CGPointMake(sCardSize.width/2,sCardSize.height/2);
    3.51 +#if TARGET_OS_ASPEN
    3.52 +    back.backgroundColor = CreateRGB(0.0,0.5,0.5, 1.0);
    3.53 +#else
    3.54      back.contents = (id) GetCGImageNamed(@"/Library/Desktop Pictures/Classic Aqua Blue.jpg");
    3.55 +#endif
    3.56      back.contentsGravity = kCAGravityResize;
    3.57      back.masksToBounds = YES;
    3.58 -    back.borderWidth = 4;
    3.59 +    back.borderWidth = 4 * (sCardSize.height/150);
    3.60      back.borderColor = kWhiteColor;
    3.61 -    back.cornerRadius = 8;
    3.62 +    back.cornerRadius = 8 * (sCardSize.height/150);
    3.63      back.edgeAntialiasingMask = 0;
    3.64      back.doubleSided = NO;          // this makes the layer invisible when it's flipped
    3.65      
    3.66 +#if TARGET_OS_ASPEN
    3.67 +    // On iPhone, only Hiragana Kaku includes the coveted snowman glyph... who knows why?
    3.68 +    UIFont *font = [UIFont fontWithName: @"HiraKakuProN-W3" size: 1*size.width];
    3.69 +#else
    3.70 +    NSFont *font = [NSFont systemFontOfSize: 1*size.width];
    3.71 +#endif
    3.72      GGBTextLayer *label = [GGBTextLayer textLayerInSuperlayer: back
    3.73                                                       withText: @"\u2603"          // Unicode snowman character
    3.74 -                                                     fontSize: 0.9*size.width
    3.75 +                                                         font: font
    3.76                                                      alignment: kCALayerWidthSizable|kCALayerHeightSizable];
    3.77      label.foregroundColor = CreateGray(1.0,0.5);
    3.78      return [back autorelease];
     4.1 --- a/Source/Deck.m	Tue Mar 11 09:21:53 2008 -0700
     4.2 +++ b/Source/Deck.m	Tue Mar 11 17:09:50 2008 -0700
     4.3 @@ -40,7 +40,7 @@
     4.4  {
     4.5      self = [super init];
     4.6      if (self != nil) {
     4.7 -        self.bounds = CGRectMake(0,0,kCardWidth,kCardHeight);
     4.8 +        self.bounds = (CGRect){{0,0},[Card cardSize]};
     4.9          self.cornerRadius = 8;
    4.10          self.backgroundColor = kAlmostInvisibleWhiteColor;
    4.11          self.borderColor = kHighlightColor;
     5.1 --- a/Source/GGBLayer.h	Tue Mar 11 09:21:53 2008 -0700
     5.2 +++ b/Source/GGBLayer.h	Tue Mar 11 17:09:50 2008 -0700
     5.3 @@ -24,23 +24,8 @@
     5.4  }
     5.5  @property CGFloat cornerRadius, borderWidth;
     5.6  @property CGColorRef borderColor;
     5.7 -@property unsigned int autoresizingMask;
     5.8  #endif
     5.9  
    5.10 +- (void) redisplayAll;
    5.11 +
    5.12  @end
    5.13 -
    5.14 -
    5.15 -#if TARGET_OS_ASPEN
    5.16 -/* Bit definitions for `autoresizingMask' property. */
    5.17 -
    5.18 -enum CAAutoresizingMask
    5.19 -{
    5.20 -    kCALayerNotSizable	= 0,
    5.21 -    kCALayerMinXMargin	= 1U << 0,
    5.22 -    kCALayerWidthSizable	= 1U << 1,
    5.23 -    kCALayerMaxXMargin	= 1U << 2,
    5.24 -    kCALayerMinYMargin	= 1U << 3,
    5.25 -    kCALayerHeightSizable	= 1U << 4,
    5.26 -    kCALayerMaxYMargin	= 1U << 5
    5.27 -};
    5.28 -#endif
     6.1 --- a/Source/GGBLayer.m	Tue Mar 11 09:21:53 2008 -0700
     6.2 +++ b/Source/GGBLayer.m	Tue Mar 11 17:09:50 2008 -0700
     6.3 @@ -19,6 +19,17 @@
     6.4  }
     6.5  
     6.6  
     6.7 +- (void) redisplayAll
     6.8 +{
     6.9 +    [self setNeedsDisplay];
    6.10 +    for( CALayer *layer in self.sublayers )
    6.11 +        if( [layer isKindOfClass: [GGBLayer class]] )
    6.12 +            ((GGBLayer*)layer).redisplayAll;
    6.13 +        else
    6.14 +            [layer setNeedsDisplay];
    6.15 +}
    6.16 +
    6.17 +
    6.18  #if TARGET_OS_ASPEN
    6.19  
    6.20  #pragma mark -
    6.21 @@ -57,7 +68,6 @@
    6.22      clone.cornerRadius = self.cornerRadius;
    6.23      clone.borderWidth = self.borderWidth;
    6.24      clone.borderColor = self.borderColor;
    6.25 -    clone.autoresizingMask = self.autoresizingMask;
    6.26      
    6.27      for( GGBLayer *sublayer in self.sublayers ) {
    6.28          sublayer = [sublayer copyWithZone: zone];
    6.29 @@ -67,8 +77,6 @@
    6.30  }
    6.31  
    6.32  
    6.33 -@synthesize autoresizingMask=_autoresizingMask;
    6.34 -
    6.35  - (CGFloat) cornerRadius    {return _cornerRadius;}
    6.36  - (CGFloat) borderWidth     {return _borderWidth;}
    6.37  - (CGColorRef) borderColor  {return _borderColor;}
    6.38 @@ -115,6 +123,8 @@
    6.39  
    6.40  - (void)drawInContext:(CGContextRef)ctx
    6.41  {
    6.42 +    [super drawInContext: ctx];
    6.43 +    
    6.44      CGContextSaveGState(ctx);
    6.45  
    6.46      if( _realBGColor ) {
     7.1 --- a/Source/GGBTextLayer.h	Tue Mar 11 09:21:53 2008 -0700
     7.2 +++ b/Source/GGBTextLayer.h	Tue Mar 11 17:09:50 2008 -0700
     7.3 @@ -13,13 +13,13 @@
     7.4  @interface GGBTextLayer : GGBLayer
     7.5  {
     7.6      NSString *_string;
     7.7 -    CGFloat _fontSize;
     7.8 +    UIFont *_font;
     7.9      CGColorRef _foregroundColor;
    7.10      NSString *_alignmentMode;
    7.11  }
    7.12  
    7.13  @property(copy) id string;
    7.14 -@property CGFloat fontSize;
    7.15 +@property (retain) UIFont *font;
    7.16  @property CGColorRef foregroundColor;
    7.17  @property (copy) NSString *alignmentMode;
    7.18  
    7.19 @@ -31,7 +31,38 @@
    7.20                                 withText: (NSString*)text
    7.21                                 fontSize: (float) fontSize
    7.22                                alignment: (enum CAAutoresizingMask) align;
    7.23 ++ (GGBTextLayer*) textLayerInSuperlayer: (CALayer*)superlayer
    7.24 +                               withText: (NSString*)text
    7.25 +                                   font: (id)inputFont
    7.26 +                              alignment: (enum CAAutoresizingMask) align;
    7.27  
    7.28  @end
    7.29  
    7.30  
    7.31 +#if TARGET_OS_ASPEN
    7.32 +/* Bit definitions for `autoresizingMask' property. */
    7.33 +
    7.34 +enum CAAutoresizingMask
    7.35 +{
    7.36 +    kCALayerNotSizable	= 0,
    7.37 +    kCALayerMinXMargin	= 1U << 0,
    7.38 +    kCALayerWidthSizable	= 1U << 1,
    7.39 +    kCALayerMaxXMargin	= 1U << 2,
    7.40 +    kCALayerMinYMargin	= 1U << 3,
    7.41 +    kCALayerHeightSizable	= 1U << 4,
    7.42 +    kCALayerMaxYMargin	= 1U << 5
    7.43 +};
    7.44 +
    7.45 +enum
    7.46 +{
    7.47 +    kCALayerBottomMargin = kCALayerMaxYMargin,
    7.48 +    kCALayerTopMargin    = kCALayerMinYMargin
    7.49 +};
    7.50 +
    7.51 +#else
    7.52 +enum
    7.53 +{
    7.54 +    kCALayerBottomMargin = kCALayerMinYMargin,
    7.55 +    kCALayerTopMargin    = kCALayerMaxYMargin
    7.56 +};
    7.57 +#endif
     8.1 --- a/Source/GGBTextLayer.m	Tue Mar 11 09:21:53 2008 -0700
     8.2 +++ b/Source/GGBTextLayer.m	Tue Mar 11 17:09:50 2008 -0700
     8.3 @@ -18,17 +18,36 @@
     8.4                                 fontSize: (float) fontSize
     8.5                                alignment: (enum CAAutoresizingMask) align
     8.6  {
     8.7 +#if TARGET_OS_ASPEN
     8.8 +    UIFont *font = [UIFont systemFontOfSize: fontSize];
     8.9 +#else
    8.10 +    NSFont *font = [NSFont systemFontOfSize: fontSize];
    8.11 +#endif
    8.12 +    return [self textLayerInSuperlayer: superlayer
    8.13 +                              withText: text
    8.14 +                                  font: font
    8.15 +                             alignment: align];
    8.16 +}
    8.17 +
    8.18 +
    8.19 ++ (GGBTextLayer*) textLayerInSuperlayer: (CALayer*)superlayer
    8.20 +                               withText: (NSString*)text
    8.21 +                                   font: (id)inputFont
    8.22 +                              alignment: (enum CAAutoresizingMask) align
    8.23 +{
    8.24      GGBTextLayer *label = [[self alloc] init];
    8.25      label.string = text;
    8.26  
    8.27  #if TARGET_OS_ASPEN
    8.28 -    UIFont *font = [UIFont systemFontOfSize: fontSize];
    8.29 +    UIFont *font = inputFont;
    8.30 +    [label setNeedsDisplay];
    8.31 +    label.needsDisplayOnBoundsChange = YES;
    8.32  #else
    8.33 -    NSFont *font = [NSFont systemFontOfSize: fontSize];
    8.34 -    label.font = font;
    8.35 +    NSFont *font = inputFont;
    8.36 +    label.fontSize = font.pointSize;
    8.37  #endif
    8.38      
    8.39 -    label.fontSize = fontSize;
    8.40 +    label.font = font;
    8.41      label.foregroundColor = kBlackColor;
    8.42      
    8.43      NSString *mode;
    8.44 @@ -45,29 +64,116 @@
    8.45      if( [superlayer respondsToSelector: @selector(borderWidth)] )
    8.46          inset += ((GGBLayer*)superlayer).borderWidth;
    8.47      CGRect bounds = CGRectInset(superlayer.bounds, inset, inset);
    8.48 +    if( mode==@"center" )
    8.49 +        bounds = CGRectInset(bounds,-inset,0);
    8.50      CGFloat height = font.ascender;
    8.51 +    float descender = font.descender;
    8.52 +#if TARGET_OS_ASPEN
    8.53 +    descender = -descender;
    8.54 +#endif
    8.55      CGFloat y = bounds.origin.y;
    8.56 -    if( align & kCALayerHeightSizable )
    8.57 +    if( align & kCALayerHeightSizable ) {
    8.58          y += (bounds.size.height-height)/2.0;
    8.59 -    else if( align & kCALayerMinYMargin )
    8.60 +#if TARGET_OS_ASPEN
    8.61 +        y -= descender/2.0;
    8.62 +#endif
    8.63 +    } else if( align & kCALayerMinYMargin )
    8.64          y += bounds.size.height - height;
    8.65      align &= ~kCALayerHeightSizable;
    8.66 -    label.bounds = CGRectMake(0, font.descender,
    8.67 -                              bounds.size.width, height - font.descender);
    8.68 -    label.position = CGPointMake(bounds.origin.x,y+font.descender);
    8.69 +    label.bounds = CGRectMake(0, descender,
    8.70 +                              bounds.size.width, height - descender);
    8.71 +    label.position = CGPointMake(bounds.origin.x,y+descender);
    8.72      label.anchorPoint = CGPointMake(0,0);
    8.73      
    8.74 +#if ! TARGET_OS_ASPEN
    8.75      label.autoresizingMask = align;
    8.76 +#endif
    8.77      [superlayer addSublayer: label];
    8.78      [label release];
    8.79 +    
    8.80 +    //label.borderWidth = 1;
    8.81 +    //label.borderColor = kBlackColor;
    8.82 +    
    8.83      return label;
    8.84  }
    8.85  
    8.86  
    8.87  #if TARGET_OS_ASPEN
    8.88 -@synthesize string=_string, fontSize=_fontSize, 
    8.89 +@synthesize string=_string, font=_font, 
    8.90              foregroundColor=_foregroundColor, alignmentMode=_alignmentMode;
    8.91 +
    8.92 +
    8.93 +- (id) copyWithZone: (NSZone*)zone
    8.94 +{
    8.95 +    GGBTextLayer *clone = [super copyWithZone: zone];
    8.96 +    clone.string = _string;
    8.97 +    clone.font = _font;
    8.98 +    clone.foregroundColor = _foregroundColor;
    8.99 +    clone.alignmentMode = _alignmentMode;
   8.100 +    return clone;
   8.101 +}
   8.102 +
   8.103 +
   8.104 +- (void)drawInContext:(CGContextRef)ctx
   8.105 +{
   8.106 +    [super drawInContext: ctx];
   8.107 +    
   8.108 +    if( _string.length > 0 ) {
   8.109 +        CGContextSaveGState(ctx);
   8.110 +        UIGraphicsPushContext(ctx);
   8.111 +        
   8.112 +        if( _foregroundColor )
   8.113 +            CGContextSetFillColorWithColor(ctx, _foregroundColor);
   8.114 +        
   8.115 +        UITextAlignment align;
   8.116 +        if( [_alignmentMode isEqualToString: @"center"] )
   8.117 +            align = UITextAlignmentCenter;
   8.118 +        else if( [_alignmentMode isEqualToString: @"right"] )
   8.119 +            align = UITextAlignmentRight;
   8.120 +        else
   8.121 +            align = UITextAlignmentLeft;
   8.122 +        
   8.123 +        CGRect bounds = self.bounds;
   8.124 +        bounds.origin.y += _font.ascender+_font.descender - _font.leading;
   8.125 +        [_string drawInRect: bounds 
   8.126 +                   withFont: _font
   8.127 +              lineBreakMode: UILineBreakModeClip
   8.128 +                  alignment: align];
   8.129 +        
   8.130 +        UIGraphicsPopContext();
   8.131 +        CGContextRestoreGState(ctx);
   8.132 +    }
   8.133 +}
   8.134 +
   8.135 +
   8.136  #endif
   8.137  
   8.138  
   8.139  @end
   8.140 +
   8.141 +
   8.142 +/*
   8.143 + .times lt mm: (TimesLTMM)
   8.144 + times new roman: (TimesNewRomanBoldItalic, TimesNewRomanItalic, TimesNewRoman, TimesNewRomanBold)
   8.145 + phonepadtwo: (PhonepadTwo)
   8.146 + hiragino kaku gothic pron w3: (HiraKakuProN-W3)
   8.147 + helvetica neue: (HelveticaNeueBold, HelveticaNeue)
   8.148 + trebuchet ms: (TrebuchetMSItalic, TrebuchetMSBoldItalic, TrebuchetMSBold, TrebuchetMS)
   8.149 + courier new: (CourierNewBoldItalic, CourierNewBold, CourierNewItalic, CourierNew)
   8.150 + arial unicode ms: (arialuni)
   8.151 + georgia: (Georgia, GeorgiaBold, GeorgiaBoldItalic, GeorgiaItalic)
   8.152 + zapfino: (Zapfino)
   8.153 + arial rounded mt bold: (ArialRoundedMTBold)
   8.154 + db lcd temp: (DB_LCD_Temp-Black)
   8.155 + verdana: (Verdana, VerdanaItalic, VerdanaBoldItalic, VerdanaBold)
   8.156 + american typewriter: (AmericanTypewriterCondensedBold, AmericanTypewriter)
   8.157 + helvetica: (HelveticaBoldOblique, Helvetica, HelveticaOblique, HelveticaBold)
   8.158 + lock clock: (LockClock)
   8.159 + courier: (CourierBoldOblique, CourierOblique)
   8.160 + hiragino kaku gothic pron w6: (HiraKakuProN-W6)
   8.161 + arial: (ArialItalic, ArialBold, Arial, ArialBoldItalic)
   8.162 + .helvetica lt mm: (HelveticaLTMM)
   8.163 + stheiti: (STHeiti, STXihei)
   8.164 + applegothic: (AppleGothicRegular)
   8.165 + marker felt: (MarkerFeltThin)
   8.166 +*/
   8.167 \ No newline at end of file
     9.1 --- a/Source/Game.h	Tue Mar 11 09:21:53 2008 -0700
     9.2 +++ b/Source/Game.h	Tue Mar 11 17:09:50 2008 -0700
     9.3 @@ -36,6 +36,8 @@
     9.4      (By default it just returns the class name with the "Game" suffix removed.) */
     9.5  + (NSString*) displayName;
     9.6  
     9.7 ++ (BOOL) landscapeOriented;
     9.8 +
     9.9  @property (readonly, copy) NSArray *players;
    9.10  @property (readonly) Player *currentPlayer, *winner;
    9.11  
    10.1 --- a/Source/Game.m	Tue Mar 11 09:21:53 2008 -0700
    10.2 +++ b/Source/Game.m	Tue Mar 11 17:09:50 2008 -0700
    10.3 @@ -110,6 +110,12 @@
    10.4  #pragma mark GAMEPLAY METHODS TO BE OVERRIDDEN:
    10.5  
    10.6  
    10.7 ++ (BOOL) landscapeOriented
    10.8 +{
    10.9 +    return NO;
   10.10 +}
   10.11 +
   10.12 +
   10.13  - (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)src
   10.14  {
   10.15      return YES;
    11.1 --- a/Source/KlondikeGame.m	Tue Mar 11 09:21:53 2008 -0700
    11.2 +++ b/Source/KlondikeGame.m	Tue Mar 11 17:09:50 2008 -0700
    11.3 @@ -24,21 +24,19 @@
    11.4  #import "Deck.h"
    11.5  #import "PlayingCard.h"
    11.6  #import "Stack.h"
    11.7 +#import "QuartzUtils.h"
    11.8  
    11.9  
   11.10  #define kStackHeight 500
   11.11  
   11.12  
   11.13 -/**  WARNING: THIS CODE REQUIRES GARBAGE COLLECTION!
   11.14 - **  This sample application uses Objective-C 2.0 garbage collection.
   11.15 - **  Therefore, the source code in this file does NOT perform manual object memory management.
   11.16 - **  If you reuse any of this code in a process that isn't garbage collected, you will need to
   11.17 - **  add all necessary retain/release/autorelease calls, and implement -dealloc methods,
   11.18 - **  otherwise unpleasant leakage will occur!
   11.19 - **/
   11.20 +@implementation KlondikeGame
   11.21  
   11.22  
   11.23 -@implementation KlondikeGame
   11.24 ++ (BOOL) landscapeOriented
   11.25 +{
   11.26 +    return YES;
   11.27 +}
   11.28  
   11.29  
   11.30  - (id) initWithBoard: (GGBLayer*)board
   11.31 @@ -47,29 +45,43 @@
   11.32      if (self != nil) {
   11.33          [self setNumberOfPlayers: 1];
   11.34          
   11.35 +        CGSize boardSize = board.bounds.size;
   11.36 +        CGFloat xSpacing = floor(boardSize.width/7);
   11.37 +        CGSize kCardSize;
   11.38 +        kCardSize.width  = round(xSpacing * 0.9);  // 1/7th of width, with 10% gap
   11.39 +        kCardSize.height = round(kCardSize.width * 1.5);
   11.40 +        CGFloat gap = xSpacing-kCardSize.width;
   11.41 +        [Card setCardSize: kCardSize];
   11.42 +        
   11.43 +        CGPoint pos = {floor(gap/2)+kCardSize.width/2, floor(boardSize.height-kCardSize.height/2)};
   11.44          _deck = [[Deck alloc] initWithCardsOfClass: [PlayingCard class]];
   11.45          [_deck shuffle];
   11.46 -        _deck.position = CGPointMake(kCardWidth/2+16,kCardHeight/2+16);
   11.47 +        _deck.position = pos;
   11.48          [board addSublayer: _deck];
   11.49          
   11.50 +        pos.x += xSpacing;
   11.51          _sink = [[Deck alloc] init];
   11.52 -        _sink.position = CGPointMake(3*kCardWidth/2+32,kCardHeight/2+16);
   11.53 +        _sink.position = pos;
   11.54          [board addSublayer: _sink];
   11.55          
   11.56 +        pos.x += xSpacing;
   11.57          for( CardSuit suit=kSuitClubs; suit<=kSuitSpades; suit++ ) {
   11.58 +            pos.x += xSpacing;
   11.59              Deck *aces = [[Deck alloc] init];
   11.60 -            aces.position = CGPointMake(kCardWidth/2+16+(kCardWidth+16)*(suit%2),
   11.61 -                                        120+kCardHeight+(kCardHeight+16)*(suit/2));
   11.62 +            aces.position = pos;
   11.63              [board addSublayer: aces];
   11.64              _aces[suit] = aces;
   11.65          }
   11.66          
   11.67 +        CGRect stackFrame = {{floor(gap/2), gap}, 
   11.68 +                             {kCardSize.width, boardSize.height-kCardSize.height-2*gap}};
   11.69 +        CGPoint startPos = CGPointMake(kCardSize.width/2,kCardSize.height/2);
   11.70 +        CGSize spacing = {0, floor((stackFrame.size.height-kCardSize.height)/11.0)};
   11.71          for( int s=0; s<7; s++ ) {
   11.72 -            Stack *stack = [[Stack alloc] initWithStartPos: CGPointMake(kCardWidth/2,
   11.73 -                                                                        kStackHeight-kCardHeight/2.0)
   11.74 -                                                   spacing: CGSizeMake(0,-22)];
   11.75 -            stack.frame = CGRectMake(260+s*(kCardWidth+16),16, kCardWidth,kStackHeight);
   11.76 -            stack.backgroundColor = nil;
   11.77 +            Stack *stack = [[Stack alloc] initWithStartPos: startPos spacing: spacing];
   11.78 +            stack.frame = stackFrame;
   11.79 +            stackFrame.origin.x += xSpacing;
   11.80 +            stack.backgroundColor = nil; //kAlmostInvisibleWhiteColor;
   11.81              stack.dragAsStacks = YES;
   11.82              [board addSublayer: stack];
   11.83              
    12.1 --- a/Source/PlayingCard.m	Tue Mar 11 09:21:53 2008 -0700
    12.2 +++ b/Source/PlayingCard.m	Tue Mar 11 17:09:50 2008 -0700
    12.3 @@ -41,25 +41,37 @@
    12.4                        self.rankString, self.suitString];
    12.5      
    12.6      CGColorRef suitColor = self.suitColor;
    12.7 +    float scale = [Card cardSize].height/150;
    12.8 +    float cornerFontSize = MAX(18*scale, 14);
    12.9 +    float centerFontSize = 80*scale;
   12.10 +    
   12.11 +#if TARGET_OS_ASPEN
   12.12 +    UIFont *cornerFont = [UIFont boldSystemFontOfSize: cornerFontSize];
   12.13 +#else
   12.14 +    NSFont *cornerFont = [NSFont boldSystemFontOfSize: cornerFontSize];
   12.15 +#endif
   12.16      GGBTextLayer *label;
   12.17      label = [GGBTextLayer textLayerInSuperlayer: front
   12.18                                         withText: name
   12.19 -                                       fontSize: 18.0
   12.20 -                                      alignment: kCALayerMaxXMargin | kCALayerMinYMargin];
   12.21 +                                           font: cornerFont
   12.22 +                                      alignment: kCALayerMaxXMargin | kCALayerBottomMargin];
   12.23      label.foregroundColor = suitColor;
   12.24      label = [GGBTextLayer textLayerInSuperlayer: front
   12.25                                         withText: name
   12.26 -                                       fontSize: 18.0
   12.27 -                                      alignment: kCALayerMaxXMargin | kCALayerMaxYMargin];
   12.28 +                                           font: cornerFont
   12.29 +                                      alignment: kCALayerMaxXMargin | kCALayerTopMargin];
   12.30      label.foregroundColor = suitColor;
   12.31      label.anchorPoint = CGPointMake(1,1);
   12.32      [label setValue: [NSNumber numberWithFloat: M_PI] forKeyPath: @"transform.rotation"];
   12.33      
   12.34      label = [GGBTextLayer textLayerInSuperlayer: front
   12.35                                         withText: self.faceSymbol
   12.36 -                                       fontSize: 80
   12.37 +                                       fontSize: centerFontSize
   12.38                                        alignment: kCALayerWidthSizable | kCALayerHeightSizable];
   12.39      label.foregroundColor = suitColor;
   12.40 +    //label.borderWidth = 1;
   12.41 +    //label.borderColor = kBlackColor;
   12.42 +    
   12.43      return front;
   12.44  }
   12.45  
    13.1 --- a/Source/iPhoneAppDelegate.m	Tue Mar 11 09:21:53 2008 -0700
    13.2 +++ b/Source/iPhoneAppDelegate.m	Tue Mar 11 17:09:50 2008 -0700
    13.3 @@ -23,6 +23,9 @@
    13.4  
    13.5  - (void)applicationDidFinishLaunching:(UIApplication *)application 
    13.6  {	
    13.7 +    for( NSString *family in [UIFont familyNames] )
    13.8 +        NSLog(@"%@: (%@)", family, [[UIFont fontNamesForFamilyName: family] componentsJoinedByString: @", "]);
    13.9 +        
   13.10      // Create window
   13.11      self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
   13.12      _window.layer.backgroundColor = GetCGPatternNamed(@"Background.png");
   13.13 @@ -45,7 +48,7 @@
   13.14      [_window addSubview: _headline];
   13.15      
   13.16      // Start game:
   13.17 -    [self startGameNamed: @"GoGame"];
   13.18 +    [self startGameNamed: @"KlondikeGame"];
   13.19      
   13.20      // Show window
   13.21      [_window makeKeyAndVisible];