Tic-tac-toe works on the iPhone simulator!
authorJens Alfke <jens@mooseyard.com>
Mon Mar 10 17:30:57 2008 -0700 (2008-03-10)
changeset 13eb7be1dd7b6
parent 0 e9f7ba4718e1
child 2 7b0441db81e5
Tic-tac-toe works on the iPhone simulator!
GeekGameBoard-iPhone.xcodeproj/project.pbxproj
GeekGameBoard.xcodeproj/project.pbxproj
Resources/Background.png
Resources/Info-iPhone.plist
Resources/O.tiff
Resources/X.tiff
Source/Bit.h
Source/Bit.m
Source/BitHolder.h
Source/BoardUIView.h
Source/BoardUIView.m
Source/BoardView.h
Source/Card.h
Source/Card.m
Source/CheckersGame.m
Source/DemoBoardView.m
Source/Dispenser.m
Source/GGB-iPhone_Prefix.pch
Source/GGBLayer.h
Source/GGBLayer.m
Source/GGBTextLayer.h
Source/GGBTextLayer.m
Source/GGBUtils.h
Source/GGBUtils.m
Source/Game.h
Source/Game.m
Source/GoGame.m
Source/Grid.h
Source/Grid.m
Source/HexchequerGame.m
Source/KlondikeGame.m
Source/Piece.m
Source/PlayingCard.m
Source/QuartzUtils.h
Source/QuartzUtils.m
Source/Stack.m
Source/TicTacToeGame.m
Source/iPhoneAppDelegate.h
Source/iPhoneAppDelegate.m
Source/main-iPhone.m
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/GeekGameBoard-iPhone.xcodeproj/project.pbxproj	Mon Mar 10 17:30:57 2008 -0700
     1.3 @@ -0,0 +1,438 @@
     1.4 +// !$*UTF8*$!
     1.5 +{
     1.6 +	archiveVersion = 1;
     1.7 +	classes = {
     1.8 +	};
     1.9 +	objectVersion = 45;
    1.10 +	objects = {
    1.11 +
    1.12 +/* Begin PBXBuildFile section */
    1.13 +		1D3623EC0D0F72F000981E51 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */; };
    1.14 +		1D60589B0D05DD56006BFB54 /* main-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main-iPhone.m */; };
    1.15 +		1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
    1.16 +		1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
    1.17 +		279F4B590D85C51700B32DBF /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279F4B580D85C51700B32DBF /* AudioToolbox.framework */; };
    1.18 +		279F4B5B0D85C51700B32DBF /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279F4B5A0D85C51700B32DBF /* QuartzCore.framework */; };
    1.19 +		279F4B620D85C63000B32DBF /* GGBTextLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 279F4B610D85C63000B32DBF /* GGBTextLayer.m */; };
    1.20 +		279F4B6A0D85CBFC00B32DBF /* iPhoneAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 279F4B690D85CBFC00B32DBF /* iPhoneAppDelegate.m */; };
    1.21 +		279F4B740D85CDE900B32DBF /* ToolbarAdvanced.icns in Resources */ = {isa = PBXBuildFile; fileRef = 279F4B720D85CDE900B32DBF /* ToolbarAdvanced.icns */; };
    1.22 +		279F4C1D0D85D0AF00B32DBF /* X.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 279F4C1C0D85D0AF00B32DBF /* X.tiff */; };
    1.23 +		279F4C1F0D85D0CB00B32DBF /* O.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 279F4C1E0D85D0CB00B32DBF /* O.tiff */; };
    1.24 +		279F4C740D85D43800B32DBF /* Background.png in Resources */ = {isa = PBXBuildFile; fileRef = 279F4C730D85D43800B32DBF /* Background.png */; };
    1.25 +		27C99B0F0D820868005AFD4F /* BoardUIView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AE40D820868005AFD4F /* BoardUIView.m */; };
    1.26 +		27C99B100D820868005AFD4F /* Bit.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AE60D820868005AFD4F /* Bit.m */; };
    1.27 +		27C99B110D820868005AFD4F /* BitHolder.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AE80D820868005AFD4F /* BitHolder.m */; };
    1.28 +		27C99B120D820868005AFD4F /* Stack.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AEA0D820868005AFD4F /* Stack.m */; };
    1.29 +		27C99B130D820868005AFD4F /* Card.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AED0D820868005AFD4F /* Card.m */; };
    1.30 +		27C99B140D820868005AFD4F /* Deck.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AEF0D820868005AFD4F /* Deck.m */; };
    1.31 +		27C99B150D820868005AFD4F /* PlayingCard.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AF10D820868005AFD4F /* PlayingCard.m */; };
    1.32 +		27C99B160D820868005AFD4F /* Piece.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AF40D820868005AFD4F /* Piece.m */; };
    1.33 +		27C99B170D820868005AFD4F /* DiscPiece.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AF60D820868005AFD4F /* DiscPiece.m */; };
    1.34 +		27C99B180D820868005AFD4F /* Grid.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AF80D820868005AFD4F /* Grid.m */; };
    1.35 +		27C99B190D820868005AFD4F /* HexGrid.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AFA0D820868005AFD4F /* HexGrid.m */; };
    1.36 +		27C99B1A0D820868005AFD4F /* Dispenser.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AFC0D820868005AFD4F /* Dispenser.m */; };
    1.37 +		27C99B1B0D820868005AFD4F /* Game.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99AFF0D820868005AFD4F /* Game.m */; };
    1.38 +		27C99B1C0D820868005AFD4F /* TicTacToeGame.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99B010D820868005AFD4F /* TicTacToeGame.m */; };
    1.39 +		27C99B1D0D820868005AFD4F /* CheckersGame.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99B030D820868005AFD4F /* CheckersGame.m */; };
    1.40 +		27C99B1E0D820868005AFD4F /* HexchequerGame.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99B050D820868005AFD4F /* HexchequerGame.m */; };
    1.41 +		27C99B1F0D820868005AFD4F /* GoGame.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99B070D820868005AFD4F /* GoGame.m */; };
    1.42 +		27C99B200D820868005AFD4F /* KlondikeGame.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99B090D820868005AFD4F /* KlondikeGame.m */; };
    1.43 +		27C99B210D820868005AFD4F /* QuartzUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99B0B0D820868005AFD4F /* QuartzUtils.m */; };
    1.44 +		27C99B220D820868005AFD4F /* GGBUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99B0D0D820868005AFD4F /* GGBUtils.m */; };
    1.45 +		27C99B510D82106E005AFD4F /* GGBLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C99B500D82106E005AFD4F /* GGBLayer.m */; };
    1.46 +/* End PBXBuildFile section */
    1.47 +
    1.48 +/* Begin PBXFileReference section */
    1.49 +		1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
    1.50 +		1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
    1.51 +		1D6058910D05DD3D006BFB54 /* GGB-iPhone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "GGB-iPhone.app"; sourceTree = BUILT_PRODUCTS_DIR; };
    1.52 +		1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
    1.53 +		279F4B580D85C51700B32DBF /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
    1.54 +		279F4B5A0D85C51700B32DBF /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
    1.55 +		279F4B600D85C63000B32DBF /* GGBTextLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GGBTextLayer.h; sourceTree = "<group>"; };
    1.56 +		279F4B610D85C63000B32DBF /* GGBTextLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GGBTextLayer.m; sourceTree = "<group>"; };
    1.57 +		279F4B680D85CBFC00B32DBF /* iPhoneAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = iPhoneAppDelegate.h; path = Source/iPhoneAppDelegate.h; sourceTree = "<group>"; };
    1.58 +		279F4B690D85CBFC00B32DBF /* iPhoneAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = iPhoneAppDelegate.m; path = Source/iPhoneAppDelegate.m; sourceTree = "<group>"; };
    1.59 +		279F4B720D85CDE900B32DBF /* ToolbarAdvanced.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = ToolbarAdvanced.icns; path = /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ToolbarAdvanced.icns; sourceTree = "<absolute>"; };
    1.60 +		279F4C1C0D85D0AF00B32DBF /* X.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = X.tiff; sourceTree = "<group>"; };
    1.61 +		279F4C1E0D85D0CB00B32DBF /* O.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = O.tiff; sourceTree = "<group>"; };
    1.62 +		279F4C730D85D43800B32DBF /* Background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Background.png; sourceTree = "<group>"; };
    1.63 +		27C99AE30D820868005AFD4F /* BoardUIView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BoardUIView.h; sourceTree = "<group>"; };
    1.64 +		27C99AE40D820868005AFD4F /* BoardUIView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BoardUIView.m; sourceTree = "<group>"; };
    1.65 +		27C99AE50D820868005AFD4F /* Bit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bit.h; sourceTree = "<group>"; };
    1.66 +		27C99AE60D820868005AFD4F /* Bit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Bit.m; sourceTree = "<group>"; };
    1.67 +		27C99AE70D820868005AFD4F /* BitHolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitHolder.h; sourceTree = "<group>"; };
    1.68 +		27C99AE80D820868005AFD4F /* BitHolder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BitHolder.m; sourceTree = "<group>"; };
    1.69 +		27C99AE90D820868005AFD4F /* Stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Stack.h; sourceTree = "<group>"; };
    1.70 +		27C99AEA0D820868005AFD4F /* Stack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Stack.m; sourceTree = "<group>"; };
    1.71 +		27C99AEC0D820868005AFD4F /* Card.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Card.h; sourceTree = "<group>"; };
    1.72 +		27C99AED0D820868005AFD4F /* Card.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Card.m; sourceTree = "<group>"; };
    1.73 +		27C99AEE0D820868005AFD4F /* Deck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Deck.h; sourceTree = "<group>"; };
    1.74 +		27C99AEF0D820868005AFD4F /* Deck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Deck.m; sourceTree = "<group>"; };
    1.75 +		27C99AF00D820868005AFD4F /* PlayingCard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayingCard.h; sourceTree = "<group>"; };
    1.76 +		27C99AF10D820868005AFD4F /* PlayingCard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlayingCard.m; sourceTree = "<group>"; };
    1.77 +		27C99AF30D820868005AFD4F /* Piece.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Piece.h; sourceTree = "<group>"; };
    1.78 +		27C99AF40D820868005AFD4F /* Piece.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Piece.m; sourceTree = "<group>"; };
    1.79 +		27C99AF50D820868005AFD4F /* DiscPiece.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiscPiece.h; sourceTree = "<group>"; };
    1.80 +		27C99AF60D820868005AFD4F /* DiscPiece.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DiscPiece.m; sourceTree = "<group>"; };
    1.81 +		27C99AF70D820868005AFD4F /* Grid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Grid.h; sourceTree = "<group>"; };
    1.82 +		27C99AF80D820868005AFD4F /* Grid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Grid.m; sourceTree = "<group>"; };
    1.83 +		27C99AF90D820868005AFD4F /* HexGrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HexGrid.h; sourceTree = "<group>"; };
    1.84 +		27C99AFA0D820868005AFD4F /* HexGrid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HexGrid.m; sourceTree = "<group>"; };
    1.85 +		27C99AFB0D820868005AFD4F /* Dispenser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Dispenser.h; sourceTree = "<group>"; };
    1.86 +		27C99AFC0D820868005AFD4F /* Dispenser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Dispenser.m; sourceTree = "<group>"; };
    1.87 +		27C99AFE0D820868005AFD4F /* Game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Game.h; sourceTree = "<group>"; };
    1.88 +		27C99AFF0D820868005AFD4F /* Game.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Game.m; sourceTree = "<group>"; };
    1.89 +		27C99B000D820868005AFD4F /* TicTacToeGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TicTacToeGame.h; sourceTree = "<group>"; };
    1.90 +		27C99B010D820868005AFD4F /* TicTacToeGame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TicTacToeGame.m; sourceTree = "<group>"; };
    1.91 +		27C99B020D820868005AFD4F /* CheckersGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CheckersGame.h; sourceTree = "<group>"; };
    1.92 +		27C99B030D820868005AFD4F /* CheckersGame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CheckersGame.m; sourceTree = "<group>"; };
    1.93 +		27C99B040D820868005AFD4F /* HexchequerGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HexchequerGame.h; sourceTree = "<group>"; };
    1.94 +		27C99B050D820868005AFD4F /* HexchequerGame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HexchequerGame.m; sourceTree = "<group>"; };
    1.95 +		27C99B060D820868005AFD4F /* GoGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GoGame.h; sourceTree = "<group>"; };
    1.96 +		27C99B070D820868005AFD4F /* GoGame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GoGame.m; sourceTree = "<group>"; };
    1.97 +		27C99B080D820868005AFD4F /* KlondikeGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KlondikeGame.h; sourceTree = "<group>"; };
    1.98 +		27C99B090D820868005AFD4F /* KlondikeGame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KlondikeGame.m; sourceTree = "<group>"; };
    1.99 +		27C99B0A0D820868005AFD4F /* QuartzUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuartzUtils.h; sourceTree = "<group>"; };
   1.100 +		27C99B0B0D820868005AFD4F /* QuartzUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuartzUtils.m; sourceTree = "<group>"; };
   1.101 +		27C99B0C0D820868005AFD4F /* GGBUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GGBUtils.h; sourceTree = "<group>"; };
   1.102 +		27C99B0D0D820868005AFD4F /* GGBUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GGBUtils.m; sourceTree = "<group>"; };
   1.103 +		27C99B4F0D82106E005AFD4F /* GGBLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GGBLayer.h; sourceTree = "<group>"; };
   1.104 +		27C99B500D82106E005AFD4F /* GGBLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GGBLayer.m; sourceTree = "<group>"; };
   1.105 +		29B97316FDCFA39411CA2CEA /* main-iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "main-iPhone.m"; path = "Source/main-iPhone.m"; sourceTree = "<group>"; };
   1.106 +		32CA4F630368D1EE00C91783 /* GGB-iPhone_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GGB-iPhone_Prefix.pch"; path = "Source/GGB-iPhone_Prefix.pch"; sourceTree = "<group>"; };
   1.107 +		8D1107310486CEB800E47090 /* Info-iPhone.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iPhone.plist"; sourceTree = "<group>"; };
   1.108 +/* End PBXFileReference section */
   1.109 +
   1.110 +/* Begin PBXFrameworksBuildPhase section */
   1.111 +		1D60588F0D05DD3D006BFB54 /* Frameworks */ = {
   1.112 +			isa = PBXFrameworksBuildPhase;
   1.113 +			buildActionMask = 2147483647;
   1.114 +			files = (
   1.115 +				1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
   1.116 +				1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
   1.117 +				1D3623EC0D0F72F000981E51 /* CoreGraphics.framework in Frameworks */,
   1.118 +				279F4B590D85C51700B32DBF /* AudioToolbox.framework in Frameworks */,
   1.119 +				279F4B5B0D85C51700B32DBF /* QuartzCore.framework in Frameworks */,
   1.120 +			);
   1.121 +			runOnlyForDeploymentPostprocessing = 0;
   1.122 +		};
   1.123 +/* End PBXFrameworksBuildPhase section */
   1.124 +
   1.125 +/* Begin PBXGroup section */
   1.126 +		1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
   1.127 +			isa = PBXGroup;
   1.128 +			children = (
   1.129 +				1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */,
   1.130 +				1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,
   1.131 +				1D30AB110D05D00D00671497 /* Foundation.framework */,
   1.132 +			);
   1.133 +			name = "Linked Frameworks";
   1.134 +			sourceTree = "<group>";
   1.135 +		};
   1.136 +		1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = {
   1.137 +			isa = PBXGroup;
   1.138 +			children = (
   1.139 +			);
   1.140 +			name = "Other Frameworks";
   1.141 +			sourceTree = "<group>";
   1.142 +		};
   1.143 +		19C28FACFE9D520D11CA2CBB /* Products */ = {
   1.144 +			isa = PBXGroup;
   1.145 +			children = (
   1.146 +				1D6058910D05DD3D006BFB54 /* GGB-iPhone.app */,
   1.147 +			);
   1.148 +			name = Products;
   1.149 +			sourceTree = "<group>";
   1.150 +		};
   1.151 +		27C99AE00D820868005AFD4F /* Source */ = {
   1.152 +			isa = PBXGroup;
   1.153 +			children = (
   1.154 +				27C99AE30D820868005AFD4F /* BoardUIView.h */,
   1.155 +				27C99AE40D820868005AFD4F /* BoardUIView.m */,
   1.156 +				27C99B4F0D82106E005AFD4F /* GGBLayer.h */,
   1.157 +				27C99B500D82106E005AFD4F /* GGBLayer.m */,
   1.158 +				279F4B600D85C63000B32DBF /* GGBTextLayer.h */,
   1.159 +				279F4B610D85C63000B32DBF /* GGBTextLayer.m */,
   1.160 +				27C99AE50D820868005AFD4F /* Bit.h */,
   1.161 +				27C99AE60D820868005AFD4F /* Bit.m */,
   1.162 +				27C99AE70D820868005AFD4F /* BitHolder.h */,
   1.163 +				27C99AE80D820868005AFD4F /* BitHolder.m */,
   1.164 +				27C99AE90D820868005AFD4F /* Stack.h */,
   1.165 +				27C99AEA0D820868005AFD4F /* Stack.m */,
   1.166 +				27C99AF20D820868005AFD4F /* Boards and Pieces */,
   1.167 +				27C99AEB0D820868005AFD4F /* Cards */,
   1.168 +				27C99AFD0D820868005AFD4F /* Games */,
   1.169 +				27C99B0A0D820868005AFD4F /* QuartzUtils.h */,
   1.170 +				27C99B0B0D820868005AFD4F /* QuartzUtils.m */,
   1.171 +				27C99B0C0D820868005AFD4F /* GGBUtils.h */,
   1.172 +				27C99B0D0D820868005AFD4F /* GGBUtils.m */,
   1.173 +			);
   1.174 +			path = Source;
   1.175 +			sourceTree = "<group>";
   1.176 +		};
   1.177 +		27C99AEB0D820868005AFD4F /* Cards */ = {
   1.178 +			isa = PBXGroup;
   1.179 +			children = (
   1.180 +				27C99AEC0D820868005AFD4F /* Card.h */,
   1.181 +				27C99AED0D820868005AFD4F /* Card.m */,
   1.182 +				27C99AEE0D820868005AFD4F /* Deck.h */,
   1.183 +				27C99AEF0D820868005AFD4F /* Deck.m */,
   1.184 +				27C99AF00D820868005AFD4F /* PlayingCard.h */,
   1.185 +				27C99AF10D820868005AFD4F /* PlayingCard.m */,
   1.186 +			);
   1.187 +			name = Cards;
   1.188 +			sourceTree = "<group>";
   1.189 +		};
   1.190 +		27C99AF20D820868005AFD4F /* Boards and Pieces */ = {
   1.191 +			isa = PBXGroup;
   1.192 +			children = (
   1.193 +				27C99AF30D820868005AFD4F /* Piece.h */,
   1.194 +				27C99AF40D820868005AFD4F /* Piece.m */,
   1.195 +				27C99AF50D820868005AFD4F /* DiscPiece.h */,
   1.196 +				27C99AF60D820868005AFD4F /* DiscPiece.m */,
   1.197 +				27C99AF70D820868005AFD4F /* Grid.h */,
   1.198 +				27C99AF80D820868005AFD4F /* Grid.m */,
   1.199 +				27C99AF90D820868005AFD4F /* HexGrid.h */,
   1.200 +				27C99AFA0D820868005AFD4F /* HexGrid.m */,
   1.201 +				27C99AFB0D820868005AFD4F /* Dispenser.h */,
   1.202 +				27C99AFC0D820868005AFD4F /* Dispenser.m */,
   1.203 +			);
   1.204 +			name = "Boards and Pieces";
   1.205 +			sourceTree = "<group>";
   1.206 +		};
   1.207 +		27C99AFD0D820868005AFD4F /* Games */ = {
   1.208 +			isa = PBXGroup;
   1.209 +			children = (
   1.210 +				27C99AFE0D820868005AFD4F /* Game.h */,
   1.211 +				27C99AFF0D820868005AFD4F /* Game.m */,
   1.212 +				27C99B000D820868005AFD4F /* TicTacToeGame.h */,
   1.213 +				27C99B010D820868005AFD4F /* TicTacToeGame.m */,
   1.214 +				27C99B020D820868005AFD4F /* CheckersGame.h */,
   1.215 +				27C99B030D820868005AFD4F /* CheckersGame.m */,
   1.216 +				27C99B040D820868005AFD4F /* HexchequerGame.h */,
   1.217 +				27C99B050D820868005AFD4F /* HexchequerGame.m */,
   1.218 +				27C99B060D820868005AFD4F /* GoGame.h */,
   1.219 +				27C99B070D820868005AFD4F /* GoGame.m */,
   1.220 +				27C99B080D820868005AFD4F /* KlondikeGame.h */,
   1.221 +				27C99B090D820868005AFD4F /* KlondikeGame.m */,
   1.222 +			);
   1.223 +			name = Games;
   1.224 +			sourceTree = "<group>";
   1.225 +		};
   1.226 +		29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
   1.227 +			isa = PBXGroup;
   1.228 +			children = (
   1.229 +				27C99AE00D820868005AFD4F /* Source */,
   1.230 +				29B97315FDCFA39411CA2CEA /* Other Sources */,
   1.231 +				29B97317FDCFA39411CA2CEA /* Resources */,
   1.232 +				29B97323FDCFA39411CA2CEA /* Frameworks */,
   1.233 +				19C28FACFE9D520D11CA2CBB /* Products */,
   1.234 +				279F4B580D85C51700B32DBF /* AudioToolbox.framework */,
   1.235 +				279F4B5A0D85C51700B32DBF /* QuartzCore.framework */,
   1.236 +			);
   1.237 +			name = CustomTemplate;
   1.238 +			sourceTree = "<group>";
   1.239 +		};
   1.240 +		29B97315FDCFA39411CA2CEA /* Other Sources */ = {
   1.241 +			isa = PBXGroup;
   1.242 +			children = (
   1.243 +				279F4B680D85CBFC00B32DBF /* iPhoneAppDelegate.h */,
   1.244 +				279F4B690D85CBFC00B32DBF /* iPhoneAppDelegate.m */,
   1.245 +				32CA4F630368D1EE00C91783 /* GGB-iPhone_Prefix.pch */,
   1.246 +				29B97316FDCFA39411CA2CEA /* main-iPhone.m */,
   1.247 +			);
   1.248 +			name = "Other Sources";
   1.249 +			sourceTree = "<group>";
   1.250 +		};
   1.251 +		29B97317FDCFA39411CA2CEA /* Resources */ = {
   1.252 +			isa = PBXGroup;
   1.253 +			children = (
   1.254 +				279F4C730D85D43800B32DBF /* Background.png */,
   1.255 +				279F4C1C0D85D0AF00B32DBF /* X.tiff */,
   1.256 +				279F4C1E0D85D0CB00B32DBF /* O.tiff */,
   1.257 +				279F4B720D85CDE900B32DBF /* ToolbarAdvanced.icns */,
   1.258 +				8D1107310486CEB800E47090 /* Info-iPhone.plist */,
   1.259 +			);
   1.260 +			path = Resources;
   1.261 +			sourceTree = "<group>";
   1.262 +		};
   1.263 +		29B97323FDCFA39411CA2CEA /* Frameworks */ = {
   1.264 +			isa = PBXGroup;
   1.265 +			children = (
   1.266 +				1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
   1.267 +				1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
   1.268 +			);
   1.269 +			name = Frameworks;
   1.270 +			sourceTree = "<group>";
   1.271 +		};
   1.272 +/* End PBXGroup section */
   1.273 +
   1.274 +/* Begin PBXNativeTarget section */
   1.275 +		1D6058900D05DD3D006BFB54 /* GGB-iPhone */ = {
   1.276 +			isa = PBXNativeTarget;
   1.277 +			buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "GGB-iPhone" */;
   1.278 +			buildPhases = (
   1.279 +				1D60588D0D05DD3D006BFB54 /* Resources */,
   1.280 +				1D60588E0D05DD3D006BFB54 /* Sources */,
   1.281 +				1D60588F0D05DD3D006BFB54 /* Frameworks */,
   1.282 +			);
   1.283 +			buildRules = (
   1.284 +			);
   1.285 +			dependencies = (
   1.286 +			);
   1.287 +			name = "GGB-iPhone";
   1.288 +			productName = "GGB-iPhone";
   1.289 +			productReference = 1D6058910D05DD3D006BFB54 /* GGB-iPhone.app */;
   1.290 +			productType = "com.apple.product-type.application";
   1.291 +		};
   1.292 +/* End PBXNativeTarget section */
   1.293 +
   1.294 +/* Begin PBXProject section */
   1.295 +		29B97313FDCFA39411CA2CEA /* Project object */ = {
   1.296 +			isa = PBXProject;
   1.297 +			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "GeekGameBoard-iPhone" */;
   1.298 +			compatibilityVersion = "Xcode 3.1";
   1.299 +			hasScannedForEncodings = 1;
   1.300 +			mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
   1.301 +			projectDirPath = "";
   1.302 +			projectRoot = "";
   1.303 +			targets = (
   1.304 +				1D6058900D05DD3D006BFB54 /* GGB-iPhone */,
   1.305 +			);
   1.306 +		};
   1.307 +/* End PBXProject section */
   1.308 +
   1.309 +/* Begin PBXResourcesBuildPhase section */
   1.310 +		1D60588D0D05DD3D006BFB54 /* Resources */ = {
   1.311 +			isa = PBXResourcesBuildPhase;
   1.312 +			buildActionMask = 2147483647;
   1.313 +			files = (
   1.314 +				279F4B740D85CDE900B32DBF /* ToolbarAdvanced.icns in Resources */,
   1.315 +				279F4C1D0D85D0AF00B32DBF /* X.tiff in Resources */,
   1.316 +				279F4C1F0D85D0CB00B32DBF /* O.tiff in Resources */,
   1.317 +				279F4C740D85D43800B32DBF /* Background.png in Resources */,
   1.318 +			);
   1.319 +			runOnlyForDeploymentPostprocessing = 0;
   1.320 +		};
   1.321 +/* End PBXResourcesBuildPhase section */
   1.322 +
   1.323 +/* Begin PBXSourcesBuildPhase section */
   1.324 +		1D60588E0D05DD3D006BFB54 /* Sources */ = {
   1.325 +			isa = PBXSourcesBuildPhase;
   1.326 +			buildActionMask = 2147483647;
   1.327 +			files = (
   1.328 +				1D60589B0D05DD56006BFB54 /* main-iPhone.m in Sources */,
   1.329 +				27C99B0F0D820868005AFD4F /* BoardUIView.m in Sources */,
   1.330 +				27C99B100D820868005AFD4F /* Bit.m in Sources */,
   1.331 +				27C99B110D820868005AFD4F /* BitHolder.m in Sources */,
   1.332 +				27C99B120D820868005AFD4F /* Stack.m in Sources */,
   1.333 +				27C99B130D820868005AFD4F /* Card.m in Sources */,
   1.334 +				27C99B140D820868005AFD4F /* Deck.m in Sources */,
   1.335 +				27C99B150D820868005AFD4F /* PlayingCard.m in Sources */,
   1.336 +				27C99B160D820868005AFD4F /* Piece.m in Sources */,
   1.337 +				27C99B170D820868005AFD4F /* DiscPiece.m in Sources */,
   1.338 +				27C99B180D820868005AFD4F /* Grid.m in Sources */,
   1.339 +				27C99B190D820868005AFD4F /* HexGrid.m in Sources */,
   1.340 +				27C99B1A0D820868005AFD4F /* Dispenser.m in Sources */,
   1.341 +				27C99B1B0D820868005AFD4F /* Game.m in Sources */,
   1.342 +				27C99B1C0D820868005AFD4F /* TicTacToeGame.m in Sources */,
   1.343 +				27C99B1D0D820868005AFD4F /* CheckersGame.m in Sources */,
   1.344 +				27C99B1E0D820868005AFD4F /* HexchequerGame.m in Sources */,
   1.345 +				27C99B1F0D820868005AFD4F /* GoGame.m in Sources */,
   1.346 +				27C99B200D820868005AFD4F /* KlondikeGame.m in Sources */,
   1.347 +				27C99B210D820868005AFD4F /* QuartzUtils.m in Sources */,
   1.348 +				27C99B220D820868005AFD4F /* GGBUtils.m in Sources */,
   1.349 +				27C99B510D82106E005AFD4F /* GGBLayer.m in Sources */,
   1.350 +				279F4B620D85C63000B32DBF /* GGBTextLayer.m in Sources */,
   1.351 +				279F4B6A0D85CBFC00B32DBF /* iPhoneAppDelegate.m in Sources */,
   1.352 +			);
   1.353 +			runOnlyForDeploymentPostprocessing = 0;
   1.354 +		};
   1.355 +/* End PBXSourcesBuildPhase section */
   1.356 +
   1.357 +/* Begin XCBuildConfiguration section */
   1.358 +		1D6058940D05DD3E006BFB54 /* Debug */ = {
   1.359 +			isa = XCBuildConfiguration;
   1.360 +			buildSettings = {
   1.361 +				COPY_PHASE_STRIP = NO;
   1.362 +				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
   1.363 +				GCC_DYNAMIC_NO_PIC = NO;
   1.364 +				GCC_ENABLE_FIX_AND_CONTINUE = NO;
   1.365 +				GCC_OPTIMIZATION_LEVEL = 0;
   1.366 +				GCC_PRECOMPILE_PREFIX_HEADER = YES;
   1.367 +				GCC_PREFIX_HEADER = "Source/GGB-iPhone_Prefix.pch";
   1.368 +				INFOPLIST_FILE = "Resources/Info-iPhone.plist";
   1.369 +				PREBINDING = NO;
   1.370 +				PRODUCT_NAME = "GGB-iPhone";
   1.371 +			};
   1.372 +			name = Debug;
   1.373 +		};
   1.374 +		1D6058950D05DD3E006BFB54 /* Release */ = {
   1.375 +			isa = XCBuildConfiguration;
   1.376 +			buildSettings = {
   1.377 +				COPY_PHASE_STRIP = YES;
   1.378 +				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
   1.379 +				GCC_ENABLE_FIX_AND_CONTINUE = NO;
   1.380 +				GCC_PRECOMPILE_PREFIX_HEADER = YES;
   1.381 +				GCC_PREFIX_HEADER = "Source/GGB-iPhone_Prefix.pch";
   1.382 +				INFOPLIST_FILE = "Resources/Info-iPhone.plist";
   1.383 +				PREBINDING = NO;
   1.384 +				PRODUCT_NAME = "GGB-iPhone";
   1.385 +				WRAPPER_EXTENSION = app;
   1.386 +			};
   1.387 +			name = Release;
   1.388 +		};
   1.389 +		C01FCF4F08A954540054247B /* Debug */ = {
   1.390 +			isa = XCBuildConfiguration;
   1.391 +			buildSettings = {
   1.392 +				ALWAYS_SEARCH_USER_PATHS = NO;
   1.393 +				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
   1.394 +				"CODE_SIGN_IDENTITY[sdk=aspen*]" = "iPhone Developer";
   1.395 +				GCC_C_LANGUAGE_STANDARD = c99;
   1.396 +				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
   1.397 +				GCC_WARN_ABOUT_RETURN_TYPE = YES;
   1.398 +				GCC_WARN_UNUSED_VARIABLE = YES;
   1.399 +				ONLY_ACTIVE_ARCH = YES;
   1.400 +				PREBINDING = NO;
   1.401 +				SDKROOT = aspen1.2;
   1.402 +				WARNING_CFLAGS = "-Wall";
   1.403 +			};
   1.404 +			name = Debug;
   1.405 +		};
   1.406 +		C01FCF5008A954540054247B /* Release */ = {
   1.407 +			isa = XCBuildConfiguration;
   1.408 +			buildSettings = {
   1.409 +				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
   1.410 +				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
   1.411 +				PREBINDING = NO;
   1.412 +				SDKROOT = aspen1.2;
   1.413 +				WARNING_CFLAGS = "-Wall";
   1.414 +			};
   1.415 +			name = Release;
   1.416 +		};
   1.417 +/* End XCBuildConfiguration section */
   1.418 +
   1.419 +/* Begin XCConfigurationList section */
   1.420 +		1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "GGB-iPhone" */ = {
   1.421 +			isa = XCConfigurationList;
   1.422 +			buildConfigurations = (
   1.423 +				1D6058940D05DD3E006BFB54 /* Debug */,
   1.424 +				1D6058950D05DD3E006BFB54 /* Release */,
   1.425 +			);
   1.426 +			defaultConfigurationIsVisible = 0;
   1.427 +			defaultConfigurationName = Release;
   1.428 +		};
   1.429 +		C01FCF4E08A954540054247B /* Build configuration list for PBXProject "GeekGameBoard-iPhone" */ = {
   1.430 +			isa = XCConfigurationList;
   1.431 +			buildConfigurations = (
   1.432 +				C01FCF4F08A954540054247B /* Debug */,
   1.433 +				C01FCF5008A954540054247B /* Release */,
   1.434 +			);
   1.435 +			defaultConfigurationIsVisible = 0;
   1.436 +			defaultConfigurationName = Release;
   1.437 +		};
   1.438 +/* End XCConfigurationList section */
   1.439 +	};
   1.440 +	rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
   1.441 +}
     2.1 --- a/GeekGameBoard.xcodeproj/project.pbxproj	Fri Mar 07 11:43:02 2008 -0800
     2.2 +++ b/GeekGameBoard.xcodeproj/project.pbxproj	Mon Mar 10 17:30:57 2008 -0700
     2.3 @@ -24,6 +24,11 @@
     2.4  		276DFC570D00890C00D329AE /* Yellow Ball.png in Resources */ = {isa = PBXBuildFile; fileRef = 276DFC540D00890C00D329AE /* Yellow Ball.png */; };
     2.5  		276DFC580D00890C00D329AE /* White Ball.png in Resources */ = {isa = PBXBuildFile; fileRef = 276DFC550D00890C00D329AE /* White Ball.png */; };
     2.6  		2795C2B80CC278C800D7B2BD /* Piece.m in Sources */ = {isa = PBXBuildFile; fileRef = 2795C2B70CC278C800D7B2BD /* Piece.m */; };
     2.7 +		279F4D870D8606C200B32DBF /* GGBLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 279F4D840D8606C200B32DBF /* GGBLayer.m */; };
     2.8 +		279F4D880D8606C200B32DBF /* GGBTextLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 279F4D860D8606C200B32DBF /* GGBTextLayer.m */; };
     2.9 +		279F4DB20D8607AD00B32DBF /* O.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 279F4DB00D8607AD00B32DBF /* O.tiff */; };
    2.10 +		279F4DB30D8607AD00B32DBF /* X.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 279F4DB10D8607AD00B32DBF /* X.tiff */; };
    2.11 +		279F4DE20D8609C200B32DBF /* Background.png in Resources */ = {isa = PBXBuildFile; fileRef = 279F4DE10D8609C200B32DBF /* Background.png */; };
    2.12  		27B7543E0D08884F000516B9 /* Wood.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 27B7543D0D08884F000516B9 /* Wood.jpg */; };
    2.13  		27C999C30D81185E005AFD4F /* GGBUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C999C20D81185E005AFD4F /* GGBUtils.m */; };
    2.14  		27CCA8050CB8A3F9001CFE24 /* BoardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CCA8040CB8A3F9001CFE24 /* BoardView.m */; };
    2.15 @@ -73,9 +78,18 @@
    2.16  		276DFC550D00890C00D329AE /* White Ball.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "White Ball.png"; path = "Resources/White Ball.png"; sourceTree = "<group>"; };
    2.17  		2795C2B60CC278C800D7B2BD /* Piece.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Piece.h; sourceTree = "<group>"; };
    2.18  		2795C2B70CC278C800D7B2BD /* Piece.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Piece.m; sourceTree = "<group>"; };
    2.19 +		279F4D830D8606C200B32DBF /* GGBLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GGBLayer.h; sourceTree = "<group>"; };
    2.20 +		279F4D840D8606C200B32DBF /* GGBLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GGBLayer.m; sourceTree = "<group>"; };
    2.21 +		279F4D850D8606C200B32DBF /* GGBTextLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GGBTextLayer.h; sourceTree = "<group>"; };
    2.22 +		279F4D860D8606C200B32DBF /* GGBTextLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GGBTextLayer.m; sourceTree = "<group>"; };
    2.23 +		279F4DB00D8607AD00B32DBF /* O.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = O.tiff; path = Resources/O.tiff; sourceTree = "<group>"; };
    2.24 +		279F4DB10D8607AD00B32DBF /* X.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = X.tiff; path = Resources/X.tiff; sourceTree = "<group>"; };
    2.25 +		279F4DE10D8609C200B32DBF /* Background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Background.png; path = Resources/Background.png; sourceTree = "<group>"; };
    2.26  		27B7543D0D08884F000516B9 /* Wood.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = Wood.jpg; path = Resources/Wood.jpg; sourceTree = "<group>"; };
    2.27  		27C999C10D81185E005AFD4F /* GGBUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GGBUtils.h; sourceTree = "<group>"; };
    2.28  		27C999C20D81185E005AFD4F /* GGBUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GGBUtils.m; sourceTree = "<group>"; };
    2.29 +		27C99AB40D820500005AFD4F /* BoardUIView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BoardUIView.h; sourceTree = "<group>"; };
    2.30 +		27C99AB50D820500005AFD4F /* BoardUIView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BoardUIView.m; sourceTree = "<group>"; };
    2.31  		27CCA8030CB8A3F9001CFE24 /* BoardView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BoardView.h; sourceTree = "<group>"; };
    2.32  		27CCA8040CB8A3F9001CFE24 /* BoardView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BoardView.m; sourceTree = "<group>"; };
    2.33  		27CCA95E0CB8A74D001CFE24 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = /System/Library/Frameworks/Quartz.framework; sourceTree = "<absolute>"; };
    2.34 @@ -118,6 +132,8 @@
    2.35  			children = (
    2.36  				27CCA8030CB8A3F9001CFE24 /* BoardView.h */,
    2.37  				27CCA8040CB8A3F9001CFE24 /* BoardView.m */,
    2.38 +				27C99AB40D820500005AFD4F /* BoardUIView.h */,
    2.39 +				27C99AB50D820500005AFD4F /* BoardUIView.m */,
    2.40  				27CCABBD0CB9496B001CFE24 /* Bit.h */,
    2.41  				27CCABBE0CB9496B001CFE24 /* Bit.m */,
    2.42  				2731E2A60CD5630600E6E4C8 /* BitHolder.h */,
    2.43 @@ -127,6 +143,10 @@
    2.44  				27275C440CC70095009C4C6C /* Cards */,
    2.45  				27275C450CC700C4009C4C6C /* Boards and Pieces */,
    2.46  				27275C480CC700D8009C4C6C /* Games */,
    2.47 +				279F4D830D8606C200B32DBF /* GGBLayer.h */,
    2.48 +				279F4D840D8606C200B32DBF /* GGBLayer.m */,
    2.49 +				279F4D850D8606C200B32DBF /* GGBTextLayer.h */,
    2.50 +				279F4D860D8606C200B32DBF /* GGBTextLayer.m */,
    2.51  				2722526D0CC2E86600814095 /* QuartzUtils.h */,
    2.52  				2722526E0CC2E86600814095 /* QuartzUtils.m */,
    2.53  				27C999C10D81185E005AFD4F /* GGBUtils.h */,
    2.54 @@ -240,11 +260,14 @@
    2.55  				29B97318FDCFA39411CA2CEA /* MainMenu.nib */,
    2.56  				8D1107310486CEB800E47090 /* Info.plist */,
    2.57  				089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
    2.58 +				279F4DE10D8609C200B32DBF /* Background.png */,
    2.59  				276DFC400D00867000D329AE /* Green Ball.png */,
    2.60  				276DFC530D00890C00D329AE /* Red Ball.png */,
    2.61  				276DFC540D00890C00D329AE /* Yellow Ball.png */,
    2.62  				276DFC550D00890C00D329AE /* White Ball.png */,
    2.63  				27B7543D0D08884F000516B9 /* Wood.jpg */,
    2.64 +				279F4DB00D8607AD00B32DBF /* O.tiff */,
    2.65 +				279F4DB10D8607AD00B32DBF /* X.tiff */,
    2.66  			);
    2.67  			name = Resources;
    2.68  			sourceTree = "<group>";
    2.69 @@ -308,6 +331,9 @@
    2.70  				276DFC570D00890C00D329AE /* Yellow Ball.png in Resources */,
    2.71  				276DFC580D00890C00D329AE /* White Ball.png in Resources */,
    2.72  				27B7543E0D08884F000516B9 /* Wood.jpg in Resources */,
    2.73 +				279F4DB20D8607AD00B32DBF /* O.tiff in Resources */,
    2.74 +				279F4DB30D8607AD00B32DBF /* X.tiff in Resources */,
    2.75 +				279F4DE20D8609C200B32DBF /* Background.png in Resources */,
    2.76  			);
    2.77  			runOnlyForDeploymentPostprocessing = 0;
    2.78  		};
    2.79 @@ -340,6 +366,8 @@
    2.80  				2731E2A80CD5630600E6E4C8 /* BitHolder.m in Sources */,
    2.81  				274124060CFCCF9D00842A9B /* DemoBoardView.m in Sources */,
    2.82  				27C999C30D81185E005AFD4F /* GGBUtils.m in Sources */,
    2.83 +				279F4D870D8606C200B32DBF /* GGBLayer.m in Sources */,
    2.84 +				279F4D880D8606C200B32DBF /* GGBTextLayer.m in Sources */,
    2.85  			);
    2.86  			runOnlyForDeploymentPostprocessing = 0;
    2.87  		};
    2.88 @@ -412,6 +440,7 @@
    2.89  				GCC_WARN_ABOUT_RETURN_TYPE = YES;
    2.90  				GCC_WARN_UNUSED_VARIABLE = YES;
    2.91  				PREBINDING = NO;
    2.92 +				SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
    2.93  				WARNING_CFLAGS = "-Wall";
    2.94  			};
    2.95  			name = Debug;
    2.96 @@ -429,6 +458,7 @@
    2.97  				GCC_WARN_ABOUT_RETURN_TYPE = YES;
    2.98  				GCC_WARN_UNUSED_VARIABLE = YES;
    2.99  				PREBINDING = NO;
   2.100 +				SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
   2.101  				WARNING_CFLAGS = "-Wall";
   2.102  			};
   2.103  			name = Release;
     3.1 Binary file Resources/Background.png has changed
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/Resources/Info-iPhone.plist	Mon Mar 10 17:30:57 2008 -0700
     4.3 @@ -0,0 +1,26 @@
     4.4 +<?xml version="1.0" encoding="UTF-8"?>
     4.5 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     4.6 +<plist version="1.0">
     4.7 +<dict>
     4.8 +	<key>CFBundleDevelopmentRegion</key>
     4.9 +	<string>en</string>
    4.10 +    <key>CFBundleDisplayName</key>
    4.11 +	<string>${PRODUCT_NAME}</string>
    4.12 +	<key>CFBundleExecutable</key>
    4.13 +	<string>${EXECUTABLE_NAME}</string>
    4.14 +	<key>CFBundleIconFile</key>
    4.15 +	<string></string>
    4.16 +	<key>CFBundleIdentifier</key>
    4.17 +	<string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
    4.18 +	<key>CFBundleInfoDictionaryVersion</key>
    4.19 +	<string>6.0</string>
    4.20 +	<key>CFBundleName</key>
    4.21 +	<string>${PRODUCT_NAME}</string>
    4.22 +	<key>CFBundlePackageType</key>
    4.23 +	<string>APPL</string>
    4.24 +	<key>CFBundleSignature</key>
    4.25 +	<string>????</string>
    4.26 +	<key>CFBundleVersion</key>
    4.27 +	<string>1.0</string>
    4.28 +</dict>
    4.29 +</plist>
    4.30 \ No newline at end of file
     5.1 Binary file Resources/O.tiff has changed
     6.1 Binary file Resources/X.tiff has changed
     7.1 --- a/Source/Bit.h	Fri Mar 07 11:43:02 2008 -0800
     7.2 +++ b/Source/Bit.h	Mon Mar 10 17:30:57 2008 -0700
     7.3 @@ -20,7 +20,7 @@
     7.4      CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
     7.5      THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     7.6  */
     7.7 -#import <Quartz/Quartz.h>
     7.8 +#import "GGBLayer.h"
     7.9  
    7.10  
    7.11  @class Game, Player;
    7.12 @@ -39,7 +39,7 @@
    7.13  
    7.14  /** A moveable item in a card/board game.
    7.15      Abstract superclass of Card and Piece. */
    7.16 -@interface Bit : CALayer <NSCopying>
    7.17 +@interface Bit : GGBLayer
    7.18  {
    7.19      @private
    7.20      int _restingZ;      // Original z position, saved while pickedUp
     8.1 --- a/Source/Bit.m	Fri Mar 07 11:43:02 2008 -0800
     8.2 +++ b/Source/Bit.m	Mon Mar 10 17:30:57 2008 -0700
     8.3 @@ -30,43 +30,11 @@
     8.4  
     8.5  - (id) copyWithZone: (NSZone*)zone
     8.6  {
     8.7 -    // NSLayer isn't copyable, but it is archivable. So create a copy by archiving to
     8.8 -    // a temporary data block, then unarchiving a new layer from that block.
     8.9 -    
    8.10 -    // One complication is that, due to a bug in Core Animation, CALayer can't archive
    8.11 -    // a pattern-based CGColor. So as a workaround, clear the background before archiving,
    8.12 -    // then restore it afterwards.
    8.13 -    
    8.14 -    // Also, archiving a CALayer with an image in it leaks memory. (Filed as rdar://5786865 )
    8.15 -    // As a workaround, clear the contents before archiving, then restore.
    8.16 -    
    8.17 -    CGColorRef bg = CGColorRetain(self.backgroundColor);
    8.18 -    self.backgroundColor = NULL;
    8.19 -    id contents = [self.contents retain];
    8.20 -    self.contents = nil;
    8.21 -    
    8.22 -    NSData *data = [NSKeyedArchiver archivedDataWithRootObject: self];
    8.23 -    
    8.24 -    self.backgroundColor = bg;
    8.25 -    self.contents = contents;
    8.26 -
    8.27 -    Bit *clone = [NSKeyedUnarchiver unarchiveObjectWithData: data];
    8.28 -    clone.backgroundColor = bg;
    8.29 -    clone.contents = contents;
    8.30 -    CGColorRelease(bg);
    8.31 -    [contents release];
    8.32 -
    8.33 -    clone->_owner = _owner;             // _owner is not archived
    8.34 -    return [clone retain];
    8.35 +    Bit *clone = [super copyWithZone: zone];
    8.36 +    clone->_owner = _owner;
    8.37 +    return clone;
    8.38  }
    8.39  
    8.40 -
    8.41 -- (NSString*) description
    8.42 -{
    8.43 -    return [NSString stringWithFormat: @"%@[(%g,%g)]", self.class,self.position.x,self.position.y];
    8.44 -}
    8.45 -
    8.46 -
    8.47  @synthesize owner=_owner;
    8.48  
    8.49  - (BOOL) isFriendly         {return _owner.friendly;}
    8.50 @@ -124,9 +92,11 @@
    8.51          }
    8.52          
    8.53          self.zPosition = z;
    8.54 +#if !TARGET_OS_ASPEN
    8.55          self.shadowOpacity = shadow;
    8.56          self.shadowOffset = CGSizeMake(offset,-offset);
    8.57          self.shadowRadius = radius;
    8.58 +#endif
    8.59          self.opacity = opacity;
    8.60          self.scale *= scale;
    8.61      }
     9.1 --- a/Source/BitHolder.h	Fri Mar 07 11:43:02 2008 -0800
     9.2 +++ b/Source/BitHolder.h	Mon Mar 10 17:30:57 2008 -0700
     9.3 @@ -20,7 +20,7 @@
     9.4      CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
     9.5      THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     9.6  */
     9.7 -#import <Quartz/Quartz.h>
     9.8 +#import "GGBLayer.h"
     9.9  @class Bit;
    9.10  
    9.11  
    9.12 @@ -63,7 +63,7 @@
    9.13  
    9.14  
    9.15  /** A basic implementation of the BitHolder protocol. */
    9.16 -@interface BitHolder : CALayer <BitHolder>
    9.17 +@interface BitHolder : GGBLayer <BitHolder>
    9.18  {
    9.19      @protected
    9.20      Bit *_bit;
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/Source/BoardUIView.h	Mon Mar 10 17:30:57 2008 -0700
    10.3 @@ -0,0 +1,43 @@
    10.4 +//
    10.5 +//  BoardUIView.h
    10.6 +//  GeekGameBoard
    10.7 +//
    10.8 +//  Created by Jens Alfke on 3/7/08.
    10.9 +//  Copyright 2008 __MyCompanyName__. All rights reserved.
   10.10 +//
   10.11 +
   10.12 +#import <UIKit/UIKit.h>
   10.13 +@class GGBLayer, Bit, Card, Grid, Game;
   10.14 +@protocol BitHolder;
   10.15 +
   10.16 +
   10.17 +/** NSView that hosts a game. */
   10.18 +@interface BoardUIView : UIView
   10.19 +{
   10.20 +    @private
   10.21 +    Game *_game;                                // Current Game
   10.22 +    GGBLayer *_gameboard;                       // Game's main layer
   10.23 +    
   10.24 +    // Used during mouse-down tracking:
   10.25 +    CGPoint _dragStartPos;                      // Starting position of mouseDown
   10.26 +    Bit *_dragBit;                              // Bit being dragged
   10.27 +    id<BitHolder> _oldHolder;                   // Bit's original holder
   10.28 +    CALayer *_oldSuperlayer;                    // Bit's original superlayer
   10.29 +    int _oldLayerIndex;                         // Bit's original index in _oldSuperlayer.layers
   10.30 +    CGPoint _oldPos;                            // Bit's original x/y position
   10.31 +    CGPoint _dragOffset;                        // Offset of mouse position from _dragBit's origin
   10.32 +    BOOL _dragMoved;                            // Has the mouse moved more than 3 pixels since mouseDown?
   10.33 +    id<BitHolder> _dropTarget;                  // Current BitHolder the cursor is over
   10.34 +    
   10.35 +    // Used while handling incoming drags:
   10.36 +    GGBLayer *_viewDropTarget;                   // Current drop target during an incoming drag-n-drop
   10.37 +}
   10.38 +
   10.39 +- (void) startGameNamed: (NSString*)gameClassName;
   10.40 +
   10.41 +@property (readonly) Game *game;
   10.42 +@property (readonly) GGBLayer *gameboard;
   10.43 +
   10.44 +- (CGRect) gameBoardFrame;
   10.45 +
   10.46 +@end
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/Source/BoardUIView.m	Mon Mar 10 17:30:57 2008 -0700
    11.3 @@ -0,0 +1,222 @@
    11.4 +//
    11.5 +//  BoardUIView.m
    11.6 +//  GeekGameBoard
    11.7 +//
    11.8 +//  Created by Jens Alfke on 3/7/08.
    11.9 +//  Copyright 2008 __MyCompanyName__. All rights reserved.
   11.10 +//
   11.11 +
   11.12 +#import "BoardUIView.h"
   11.13 +#import "Bit.h"
   11.14 +#import "BitHolder.h"
   11.15 +#import "Game.h"
   11.16 +#import "QuartzUtils.h"
   11.17 +#import "GGBUtils.h"
   11.18 +
   11.19 +
   11.20 +@implementation BoardUIView
   11.21 +
   11.22 +
   11.23 +- (id)initWithFrame:(CGRect)frame {
   11.24 +    if ( (self = [super initWithFrame:frame]) ) {
   11.25 +        // Initialization code here.
   11.26 +    }
   11.27 +    return self;
   11.28 +}
   11.29 +
   11.30 +
   11.31 +- (void)dealloc
   11.32 +{
   11.33 +    [_game release];
   11.34 +    [super dealloc];
   11.35 +}
   11.36 +
   11.37 +
   11.38 +@synthesize game=_game, gameboard=_gameboard;
   11.39 +
   11.40 +
   11.41 +- (void) startGameNamed: (NSString*)gameClassName
   11.42 +{
   11.43 +    if( _gameboard ) {
   11.44 +        [_gameboard removeFromSuperlayer];
   11.45 +        _gameboard = nil;
   11.46 +    }
   11.47 +    _gameboard = [[GGBLayer alloc] init];
   11.48 +    _gameboard.frame = [self gameBoardFrame];
   11.49 +    _gameboard.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
   11.50 +    [self.layer addSublayer: _gameboard];
   11.51 +    [_gameboard release];
   11.52 +    
   11.53 +    Class gameClass = NSClassFromString(gameClassName);
   11.54 +    NSAssert1(gameClass,@"Unknown game '%@'",gameClassName);
   11.55 +    setObj(&_game, [[gameClass alloc] initWithBoard: _gameboard]);
   11.56 +}
   11.57 +
   11.58 +
   11.59 +- (CGRect) gameBoardFrame
   11.60 +{
   11.61 +    return self.layer.bounds;
   11.62 +}
   11.63 +
   11.64 +
   11.65 +#pragma mark -
   11.66 +#pragma mark HIT-TESTING:
   11.67 +
   11.68 +
   11.69 +// Hit-testing callbacks (to identify which layers caller is interested in):
   11.70 +typedef BOOL (*LayerMatchCallback)(CALayer*);
   11.71 +
   11.72 +static BOOL layerIsBit( CALayer* layer )        {return [layer isKindOfClass: [Bit class]];}
   11.73 +static BOOL layerIsBitHolder( CALayer* layer )  {return [layer conformsToProtocol: @protocol(BitHolder)];}
   11.74 +
   11.75 +
   11.76 +/** Locates the layer at a given point in window coords.
   11.77 +    If the leaf layer doesn't pass the layer-match callback, the nearest ancestor that does is returned.
   11.78 +    If outOffset is provided, the point's position relative to the layer is stored into it. */
   11.79 +- (CALayer*) hitTestPoint: (CGPoint)where
   11.80 +         forLayerMatching: (LayerMatchCallback)match
   11.81 +                   offset: (CGPoint*)outOffset
   11.82 +{
   11.83 +    where = [_gameboard convertPoint: where fromLayer: self.layer];
   11.84 +    CALayer *layer = [_gameboard hitTest: where];
   11.85 +    while( layer ) {
   11.86 +        if( match(layer) ) {
   11.87 +            CGPoint bitPos = [self.layer convertPoint: layer.position 
   11.88 +                              fromLayer: layer.superlayer];
   11.89 +            if( outOffset )
   11.90 +                *outOffset = CGPointMake( bitPos.x-where.x, bitPos.y-where.y);
   11.91 +            return layer;
   11.92 +        } else
   11.93 +            layer = layer.superlayer;
   11.94 +    }
   11.95 +    return nil;
   11.96 +}
   11.97 +
   11.98 +
   11.99 +#pragma mark -
  11.100 +#pragma mark MOUSE CLICKS & DRAGS:
  11.101 +
  11.102 +
  11.103 +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  11.104 +{
  11.105 +    NSAssert(touches.count==1,@"No multitouch support yet");
  11.106 +    UITouch *touch = touches.anyObject;
  11.107 +    
  11.108 +    _dragStartPos = touch.locationInView;
  11.109 +    _dragBit = (Bit*) [self hitTestPoint: _dragStartPos
  11.110 +                        forLayerMatching: layerIsBit 
  11.111 +                                  offset: &_dragOffset];
  11.112 +    if( _dragBit ) {
  11.113 +        _dragMoved = NO;
  11.114 +        _dropTarget = nil;
  11.115 +        _oldHolder = _dragBit.holder;
  11.116 +        // Ask holder's and game's permission before dragging:
  11.117 +        if( _oldHolder )
  11.118 +            _dragBit = [_oldHolder canDragBit: _dragBit];
  11.119 +        if( _dragBit && ! [_game canBit: _dragBit moveFrom: _oldHolder] ) {
  11.120 +            [_oldHolder cancelDragBit: _dragBit];
  11.121 +            _dragBit = nil;
  11.122 +        }
  11.123 +        if( ! _dragBit ) {
  11.124 +            _oldHolder = nil;
  11.125 +            Beep();
  11.126 +            return;
  11.127 +        }
  11.128 +        // Start dragging:
  11.129 +        _oldSuperlayer = _dragBit.superlayer;
  11.130 +        _oldLayerIndex = [_oldSuperlayer.sublayers indexOfObjectIdenticalTo: _dragBit];
  11.131 +        _oldPos = _dragBit.position;
  11.132 +        ChangeSuperlayer(_dragBit, self.layer, self.layer.sublayers.count);
  11.133 +        _dragBit.pickedUp = YES;
  11.134 +    } else
  11.135 +        Beep();
  11.136 +}
  11.137 +
  11.138 +
  11.139 +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
  11.140 +{
  11.141 +    NSAssert(touches.count==1,@"No multitouch support yet");
  11.142 +    UITouch *touch = touches.anyObject;
  11.143 +    
  11.144 +    if( _dragBit ) {
  11.145 +        // Get the mouse position, and see if we've moved 3 pixels since the mouseDown:
  11.146 +        CGPoint pos = touch.locationInView;
  11.147 +        if( fabs(pos.x-_dragStartPos.x)>=3 || fabs(pos.y-_dragStartPos.y)>=3 )
  11.148 +            _dragMoved = YES;
  11.149 +        
  11.150 +        // Move the _dragBit (without animation -- it's unnecessary and slows down responsiveness):
  11.151 +        pos.x += _dragOffset.x;
  11.152 +        pos.y += _dragOffset.y;
  11.153 +        
  11.154 +        CGPoint newPos = [_dragBit.superlayer convertPoint: pos fromLayer: self.layer];
  11.155 +
  11.156 +        [CATransaction flush];
  11.157 +        [CATransaction begin];
  11.158 +        [CATransaction setValue:(id)kCFBooleanTrue
  11.159 +                         forKey:kCATransactionDisableActions];
  11.160 +        _dragBit.position = newPos;
  11.161 +        [CATransaction commit];
  11.162 +
  11.163 +        // Find what it's over:
  11.164 +        id<BitHolder> target = (id<BitHolder>) [self hitTestPoint: pos
  11.165 +                                                 forLayerMatching: layerIsBitHolder
  11.166 +                                                           offset: NULL];
  11.167 +        if( target == _oldHolder )
  11.168 +            target = nil;
  11.169 +        if( target != _dropTarget ) {
  11.170 +            [_dropTarget willNotDropBit: _dragBit];
  11.171 +            _dropTarget.highlighted = NO;
  11.172 +            _dropTarget = nil;
  11.173 +        }
  11.174 +        if( target ) {
  11.175 +            CGPoint targetPos = [(CALayer*)target convertPoint: _dragBit.position
  11.176 +                                                     fromLayer: _dragBit.superlayer];
  11.177 +            if( [target canDropBit: _dragBit atPoint: targetPos]
  11.178 +               && [_game canBit: _dragBit moveFrom: _oldHolder to: target] ) {
  11.179 +                _dropTarget = target;
  11.180 +                _dropTarget.highlighted = YES;
  11.181 +            }
  11.182 +        }
  11.183 +    }
  11.184 +}
  11.185 +
  11.186 +
  11.187 +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
  11.188 +{
  11.189 +    if( _dragBit ) {
  11.190 +        if( _dragMoved ) {
  11.191 +            // Update the drag tracking to the final mouse position:
  11.192 +            [self touchesMoved: touches withEvent: event];
  11.193 +            _dropTarget.highlighted = NO;
  11.194 +            _dragBit.pickedUp = NO;
  11.195 +
  11.196 +            // Is the move legal?
  11.197 +            if( _dropTarget && [_dropTarget dropBit: _dragBit
  11.198 +                                            atPoint: [(CALayer*)_dropTarget convertPoint: _dragBit.position 
  11.199 +                                                                            fromLayer: _dragBit.superlayer]] ) {
  11.200 +                // Yes, notify the interested parties:
  11.201 +                [_oldHolder draggedBit: _dragBit to: _dropTarget];
  11.202 +                [_game bit: _dragBit movedFrom: _oldHolder to: _dropTarget];
  11.203 +            } else {
  11.204 +                // Nope, cancel:
  11.205 +                [_dropTarget willNotDropBit: _dragBit];
  11.206 +                ChangeSuperlayer(_dragBit, _oldSuperlayer, _oldLayerIndex);
  11.207 +                _dragBit.position = _oldPos;
  11.208 +                [_oldHolder cancelDragBit: _dragBit];
  11.209 +            }
  11.210 +        } else {
  11.211 +            // Just a click, without a drag:
  11.212 +            _dropTarget.highlighted = NO;
  11.213 +            _dragBit.pickedUp = NO;
  11.214 +            ChangeSuperlayer(_dragBit, _oldSuperlayer, _oldLayerIndex);
  11.215 +            [_oldHolder cancelDragBit: _dragBit];
  11.216 +            if( ! [_game clickedBit: _dragBit] )
  11.217 +                Beep();
  11.218 +        }
  11.219 +        _dropTarget = nil;
  11.220 +        _dragBit = nil;
  11.221 +    }
  11.222 +}
  11.223 +
  11.224 +
  11.225 +@end
    12.1 --- a/Source/BoardView.h	Fri Mar 07 11:43:02 2008 -0800
    12.2 +++ b/Source/BoardView.h	Mon Mar 10 17:30:57 2008 -0700
    12.3 @@ -21,7 +21,7 @@
    12.4      THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    12.5  */
    12.6  #import <Cocoa/Cocoa.h>
    12.7 -@class Bit, Card, Grid, Game;
    12.8 +@class GGBLayer, Bit, Card, Grid, Game;
    12.9  @protocol BitHolder;
   12.10  
   12.11  
   12.12 @@ -30,7 +30,7 @@
   12.13  {
   12.14      @private
   12.15      Game *_game;                                // Current Game
   12.16 -    CALayer *_gameboard;                        // Game's main layer
   12.17 +    GGBLayer *_gameboard;                       // Game's main layer
   12.18      
   12.19      // Used during mouse-down tracking:
   12.20      NSPoint _dragStartPos;                      // Starting position of mouseDown
    13.1 --- a/Source/Card.h	Fri Mar 07 11:43:02 2008 -0800
    13.2 +++ b/Source/Card.h	Mon Mar 10 17:30:57 2008 -0700
    13.3 @@ -35,7 +35,7 @@
    13.4  {
    13.5      @private
    13.6      int _serialNumber;
    13.7 -    CALayer *_front, *_back;
    13.8 +    GGBLayer *_front, *_back;
    13.9      BOOL _faceUp;
   13.10  }
   13.11  
   13.12 @@ -56,11 +56,11 @@
   13.13  /** Creates the sub-layer that displays the front side of the card.
   13.14      Subclasses should probably call the superclass method, configure the layer it returns
   13.15      (based on the card's serialNumber) and then return that layer. */
   13.16 -- (CALayer*) createFront;
   13.17 +- (GGBLayer*) createFront;
   13.18  
   13.19  /** Creates the sub-layer that displays the back side of the card.
   13.20      Subclasses should probably call the superclass method, configure the layer it returns and
   13.21      return that layer. */
   13.22 -- (CALayer*) createBack;
   13.23 +- (GGBLayer*) createBack;
   13.24  
   13.25  @end
    14.1 --- a/Source/Card.m	Fri Mar 07 11:43:02 2008 -0800
    14.2 +++ b/Source/Card.m	Mon Mar 10 17:30:57 2008 -0700
    14.3 @@ -21,6 +21,7 @@
    14.4      THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    14.5  */
    14.6  #import "Card.h"
    14.7 +#import "GGBTextLayer.h"
    14.8  #import "QuartzUtils.h"
    14.9  
   14.10  
   14.11 @@ -68,19 +69,11 @@
   14.12  }
   14.13  
   14.14  
   14.15 -- (void)encodeWithCoder:(NSCoder *)aCoder
   14.16 +- (id) copyWithZone: (NSZone*)zone
   14.17  {
   14.18 -    [super encodeWithCoder: aCoder];
   14.19 -    [aCoder encodeInt: _serialNumber forKey: @"serialNumber"];
   14.20 -}
   14.21 -
   14.22 -- (id)initWithCoder:(NSCoder *)aDecoder
   14.23 -{
   14.24 -    self = [super initWithCoder: aDecoder];
   14.25 -    if( self ) {
   14.26 -        _serialNumber = [aDecoder decodeIntForKey: @"serialNumber"];
   14.27 -    }
   14.28 -    return self;
   14.29 +    Card *clone = [super copyWithZone: zone];
   14.30 +    clone->_serialNumber = _serialNumber;
   14.31 +    return clone;
   14.32  }
   14.33  
   14.34  
   14.35 @@ -115,25 +108,25 @@
   14.36  }
   14.37  
   14.38  
   14.39 -- (CALayer*) createFront
   14.40 +- (GGBLayer*) createFront
   14.41  {
   14.42 -    CALayer *front = [[CALayer alloc] init];
   14.43 +    GGBLayer *front = [[GGBLayer alloc] init];
   14.44      front.bounds = CGRectMake(0,0,kCardWidth,kCardHeight);
   14.45      front.position = CGPointMake(kCardWidth/2,kCardHeight/2);
   14.46      front.edgeAntialiasingMask = 0;
   14.47      front.backgroundColor = kWhiteColor;
   14.48      front.cornerRadius = 8;
   14.49      front.borderWidth = 1;
   14.50 -    front.borderColor = CGColorCreateGenericGray(0.7, 1.0);
   14.51 +    front.borderColor = CreateGray(0.7, 1.0);
   14.52      front.doubleSided = NO;         // this makes the layer invisible when it's flipped
   14.53      return [front autorelease];
   14.54  }
   14.55  
   14.56  
   14.57 -- (CALayer*) createBack
   14.58 +- (GGBLayer*) createBack
   14.59  {
   14.60      CGSize size = self.bounds.size;
   14.61 -    CALayer *back = [[CALayer alloc] init];
   14.62 +    GGBLayer *back = [[GGBLayer alloc] init];
   14.63      back.bounds = CGRectMake(0,0,size.width,size.height);
   14.64      back.position = CGPointMake(kCardWidth/2,kCardHeight/2);
   14.65      back.contents = (id) GetCGImageNamed(@"/Library/Desktop Pictures/Classic Aqua Blue.jpg");
   14.66 @@ -145,10 +138,11 @@
   14.67      back.edgeAntialiasingMask = 0;
   14.68      back.doubleSided = NO;          // this makes the layer invisible when it's flipped
   14.69      
   14.70 -    CATextLayer *label = AddTextLayer(back, @"\u2603",          // Unicode snowman character
   14.71 -                                      [NSFont systemFontOfSize: 0.9*size.width],
   14.72 -                                      kCALayerWidthSizable|kCALayerHeightSizable);
   14.73 -    label.foregroundColor = CGColorCreateGenericGray(1.0,0.5);
   14.74 +    GGBTextLayer *label = [GGBTextLayer textLayerInSuperlayer: back
   14.75 +                                                     withText: @"\u2603"          // Unicode snowman character
   14.76 +                                                     fontSize: 0.9*size.width
   14.77 +                                                    alignment: kCALayerWidthSizable|kCALayerHeightSizable];
   14.78 +    label.foregroundColor = CreateGray(1.0,0.5);
   14.79      return [back autorelease];
   14.80  }    
   14.81  
   14.82 @@ -157,6 +151,8 @@
   14.83  #pragma mark DRAG-AND-DROP:
   14.84  
   14.85  
   14.86 +#if ! TARGET_OS_ASPEN
   14.87 +
   14.88  // An image from another app can be dragged onto a Card to change its background. */
   14.89  
   14.90  
   14.91 @@ -173,7 +169,7 @@
   14.92  {
   14.93      CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard]);
   14.94      if( image ) {
   14.95 -        CALayer *face = _faceUp ?_front :_back;
   14.96 +        GGBLayer *face = _faceUp ?_front :_back;
   14.97          face.contents = (id) image;
   14.98          face.contentsGravity = kCAGravityResizeAspectFill;
   14.99          face.masksToBounds = YES;
  14.100 @@ -182,5 +178,6 @@
  14.101          return NO;
  14.102  }
  14.103  
  14.104 +#endif
  14.105  
  14.106  @end
    15.1 --- a/Source/CheckersGame.m	Fri Mar 07 11:43:02 2008 -0800
    15.2 +++ b/Source/CheckersGame.m	Mon Mar 10 17:30:57 2008 -0700
    15.3 @@ -24,6 +24,7 @@
    15.4  #import "Grid.h"
    15.5  #import "Piece.h"
    15.6  #import "QuartzUtils.h"
    15.7 +#import "GGBUtils.h"
    15.8  
    15.9  
   15.10  @implementation CheckersGame
   15.11 @@ -64,8 +65,8 @@
   15.12      grid.position = pos;
   15.13      grid.allowsMoves = YES;
   15.14      grid.allowsCaptures = NO;
   15.15 -    grid.cellColor = CGColorCreateGenericGray(0.0, 0.25);
   15.16 -    grid.altCellColor = CGColorCreateGenericGray(1.0, 0.25);
   15.17 +    grid.cellColor = CreateGray(0.0, 0.25);
   15.18 +    grid.altCellColor = CreateGray(1.0, 0.25);
   15.19      grid.lineColor = nil;
   15.20      [self addPieces: @"Green Ball.png" toGrid: grid forPlayer: 0 rows: NSMakeRange(0,3) alternating: YES];
   15.21      [self addPieces: @"Red Ball.png"   toGrid: grid forPlayer: 1 rows: NSMakeRange(5,3) alternating: YES];
   15.22 @@ -73,7 +74,7 @@
   15.23  }
   15.24  
   15.25  
   15.26 -- (id) initWithBoard: (CALayer*)board
   15.27 +- (id) initWithBoard: (GGBLayer*)board
   15.28  {
   15.29      self = [super initWithBoard: board];
   15.30      if (self != nil) {
   15.31 @@ -102,12 +103,12 @@
   15.32      int playerIndex = self.currentPlayer.index;
   15.33      BOOL isKing = ([bit valueForKey: @"King"] != nil);
   15.34      
   15.35 -    [[NSSound soundNamed: (isKing ?@"Funk" :@"Tink")] play];
   15.36 +    PlaySound(isKing ?@"Funk" :@"Tink");
   15.37  
   15.38      // "King" a piece that made it to the last row:
   15.39      if( dst.row == (playerIndex ?0 :7) )
   15.40          if( ! isKing ) {
   15.41 -            [[NSSound soundNamed: @"Blow"] play];
   15.42 +            PlaySound(@"Blow");
   15.43              bit.scale = 1.4;
   15.44              [bit setValue: @"King" forKey: @"King"];
   15.45              // don't set isKing flag - piece can't jump again after being kinged.
   15.46 @@ -125,7 +126,7 @@
   15.47          capture = src.br;
   15.48      
   15.49      if( capture ) {
   15.50 -        [[NSSound soundNamed: @"Pop"] play];
   15.51 +        PlaySound(@"Pop");
   15.52          Bit *bit = capture.bit;
   15.53          _numPieces[bit.owner.index]--;
   15.54          [bit destroy];
    16.1 --- a/Source/DemoBoardView.m	Fri Mar 07 11:43:02 2008 -0800
    16.2 +++ b/Source/DemoBoardView.m	Mon Mar 10 17:30:57 2008 -0700
    16.3 @@ -22,6 +22,7 @@
    16.4  */
    16.5  #import "DemoBoardView.h"
    16.6  #import "Game.h"
    16.7 +#import "GGBTextLayer.h"
    16.8  #import "QuartzUtils.h"
    16.9  
   16.10  
   16.11 @@ -79,12 +80,13 @@
   16.12      [self registerForDraggedTypes: [NSArray arrayWithObject: NSFilenamesPboardType]];
   16.13      
   16.14      CGRect bounds = self.layer.bounds;
   16.15 -    self.layer.backgroundColor = GetCGPatternNamed(@"/Library/Desktop Pictures/Small Ripples graphite.png");
   16.16 +    self.layer.backgroundColor = GetCGPatternNamed(@"Background.png");
   16.17          
   16.18      bounds.size.height -= 32;
   16.19 -    _headline = AddTextLayer(self.layer,
   16.20 -                             nil, [NSFont boldSystemFontOfSize: 24], 
   16.21 -                             kCALayerWidthSizable | kCALayerMinYMargin);
   16.22 +    _headline = [GGBTextLayer textLayerInSuperlayer: self.layer
   16.23 +                                           withText: nil
   16.24 +                                           fontSize: 24
   16.25 +                                          alignment: kCALayerWidthSizable | kCALayerMinYMargin];
   16.26      
   16.27      [self startGameNamed: sCurrentGameName];
   16.28  }
    17.1 --- a/Source/Dispenser.m	Fri Mar 07 11:43:02 2008 -0800
    17.2 +++ b/Source/Dispenser.m	Mon Mar 10 17:30:57 2008 -0700
    17.3 @@ -163,6 +163,8 @@
    17.4  #pragma mark DRAG-AND-DROP:
    17.5  
    17.6  
    17.7 +#if ! TARGET_OS_ASPEN
    17.8 +
    17.9  // An image from another app can be dragged onto a Dispenser to change the Piece's appearance.
   17.10  
   17.11  
   17.12 @@ -191,4 +193,6 @@
   17.13  }
   17.14  
   17.15  
   17.16 +#endif
   17.17 +
   17.18  @end
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/Source/GGB-iPhone_Prefix.pch	Mon Mar 10 17:30:57 2008 -0700
    18.3 @@ -0,0 +1,9 @@
    18.4 +//
    18.5 +// Prefix header for all source files of the 'GGB-iPhone' target in the 'GGB-iPhone' project
    18.6 +//
    18.7 +
    18.8 +#ifdef __OBJC__
    18.9 +    #import <Foundation/Foundation.h>
   18.10 +    #import <UIKit/UIKit.h>
   18.11 +    #import <QuartzCore/QuartzCore.h>
   18.12 +#endif
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/Source/GGBLayer.h	Mon Mar 10 17:30:57 2008 -0700
    19.3 @@ -0,0 +1,46 @@
    19.4 +//
    19.5 +//  GGBLayer.h
    19.6 +//  GGB-iPhone
    19.7 +//
    19.8 +//  Created by Jens Alfke on 3/7/08.
    19.9 +//  Copyright 2008 __MyCompanyName__. All rights reserved.
   19.10 +//
   19.11 +
   19.12 +#if TARGET_OS_ASPEN
   19.13 +#import <QuartzCore/QuartzCore.h>
   19.14 +#else
   19.15 +#import <Quartz/Quartz.h>
   19.16 +#endif
   19.17 +
   19.18 +
   19.19 +@interface GGBLayer : CALayer <NSCopying>
   19.20 +
   19.21 +#if TARGET_OS_ASPEN
   19.22 +// For some reason, the CALayer class on iPhone OS doesn't have these!
   19.23 +{
   19.24 +    CGFloat _cornerRadius, _borderWidth;
   19.25 +    CGColorRef _borderColor, _realBGColor;
   19.26 +    unsigned int _autoresizingMask;
   19.27 +}
   19.28 +@property CGFloat cornerRadius, borderWidth;
   19.29 +@property CGColorRef borderColor;
   19.30 +@property unsigned int autoresizingMask;
   19.31 +#endif
   19.32 +
   19.33 +@end
   19.34 +
   19.35 +
   19.36 +#if TARGET_OS_ASPEN
   19.37 +/* Bit definitions for `autoresizingMask' property. */
   19.38 +
   19.39 +enum CAAutoresizingMask
   19.40 +{
   19.41 +    kCALayerNotSizable	= 0,
   19.42 +    kCALayerMinXMargin	= 1U << 0,
   19.43 +    kCALayerWidthSizable	= 1U << 1,
   19.44 +    kCALayerMaxXMargin	= 1U << 2,
   19.45 +    kCALayerMinYMargin	= 1U << 3,
   19.46 +    kCALayerHeightSizable	= 1U << 4,
   19.47 +    kCALayerMaxYMargin	= 1U << 5
   19.48 +};
   19.49 +#endif
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/Source/GGBLayer.m	Mon Mar 10 17:30:57 2008 -0700
    20.3 @@ -0,0 +1,191 @@
    20.4 +//
    20.5 +//  GGBLayer.m
    20.6 +//  GGB-iPhone
    20.7 +//
    20.8 +//  Created by Jens Alfke on 3/7/08.
    20.9 +//  Copyright 2008 __MyCompanyName__. All rights reserved.
   20.10 +//
   20.11 +
   20.12 +#import "GGBLayer.h"
   20.13 +#import "QuartzUtils.h"
   20.14 +
   20.15 +
   20.16 +@implementation GGBLayer
   20.17 +
   20.18 +
   20.19 +- (NSString*) description
   20.20 +{
   20.21 +    return [NSString stringWithFormat: @"%@[(%g,%g)]", self.class,self.position.x,self.position.y];
   20.22 +}
   20.23 +
   20.24 +
   20.25 +#if TARGET_OS_ASPEN
   20.26 +
   20.27 +#pragma mark -
   20.28 +#pragma mark IPHONE VERSION:
   20.29 +
   20.30 +
   20.31 +- (id) copyWithZone: (NSZone*)zone
   20.32 +{
   20.33 +    GGBLayer *clone = [[[self class] alloc] init];
   20.34 +    clone.bounds = self.bounds;
   20.35 +    clone.position = self.position;
   20.36 +    clone.zPosition = self.zPosition;
   20.37 +    clone.anchorPoint = self.anchorPoint;
   20.38 +    clone.transform = self.transform;
   20.39 +    clone.hidden = self.hidden;
   20.40 +    clone.doubleSided = self.doubleSided;
   20.41 +    clone.sublayerTransform = self.sublayerTransform;
   20.42 +    clone.masksToBounds = self.masksToBounds;
   20.43 +    clone.contents = self.contents;                 // doesn't copy contents (shallow-copy)
   20.44 +    clone.contentsRect = self.contentsRect;
   20.45 +    clone.contentsGravity = self.contentsGravity;
   20.46 +    clone.minificationFilter = self.minificationFilter;
   20.47 +    clone.magnificationFilter = self.magnificationFilter;
   20.48 +    clone.opaque = self.opaque;
   20.49 +    clone.needsDisplayOnBoundsChange = self.needsDisplayOnBoundsChange;
   20.50 +    clone.edgeAntialiasingMask = self.edgeAntialiasingMask;
   20.51 +    clone.backgroundColor = self.backgroundColor;
   20.52 +    clone.opacity = self.opacity;
   20.53 +    clone.compositingFilter = self.compositingFilter;
   20.54 +    clone.filters = self.filters;
   20.55 +    clone.backgroundFilters = self.backgroundFilters;
   20.56 +    clone.actions = self.actions;
   20.57 +    clone.name = self.name;
   20.58 +    clone.style = self.style;
   20.59 +    
   20.60 +    clone.cornerRadius = self.cornerRadius;
   20.61 +    clone.borderWidth = self.borderWidth;
   20.62 +    clone.borderColor = self.borderColor;
   20.63 +    clone.autoresizingMask = self.autoresizingMask;
   20.64 +    
   20.65 +    for( GGBLayer *sublayer in self.sublayers ) {
   20.66 +        sublayer = [sublayer copyWithZone: zone];
   20.67 +        [clone addSublayer: sublayer];
   20.68 +    }
   20.69 +    return clone;
   20.70 +}
   20.71 +
   20.72 +
   20.73 +@synthesize autoresizingMask=_autoresizingMask;
   20.74 +
   20.75 +- (CGFloat) cornerRadius    {return _cornerRadius;}
   20.76 +- (CGFloat) borderWidth     {return _borderWidth;}
   20.77 +- (CGColorRef) borderColor  {return _borderColor;}
   20.78 +
   20.79 +- (void) setCornerRadius: (CGFloat)r
   20.80 +{
   20.81 +    if( r != _cornerRadius ) {
   20.82 +        _cornerRadius = r;
   20.83 +        [self setNeedsDisplay];
   20.84 +    }
   20.85 +}
   20.86 +
   20.87 +
   20.88 +- (void) setBorderWidth: (CGFloat)w
   20.89 +{
   20.90 +    if( w != _borderWidth ) {
   20.91 +        _borderWidth = w;
   20.92 +        self.needsDisplayOnBoundsChange = (_borderWidth>0.0 && _borderColor!=NULL);
   20.93 +        [self setNeedsDisplay];
   20.94 +    }
   20.95 +}
   20.96 +
   20.97 +
   20.98 +- (void) setBackgroundColor: (CGColorRef)color
   20.99 +{
  20.100 +    if( color != _realBGColor ) {
  20.101 +        CGColorRelease(_realBGColor);
  20.102 +        _realBGColor = CGColorRetain(color);
  20.103 +        [self setNeedsDisplay];
  20.104 +    }
  20.105 +}
  20.106 +
  20.107 +
  20.108 +- (void) setBorderColor: (CGColorRef)color
  20.109 +{
  20.110 +    if( color != _borderColor ) {
  20.111 +        CGColorRelease(_borderColor);
  20.112 +        _borderColor = CGColorRetain(color);
  20.113 +        self.needsDisplayOnBoundsChange = (_borderWidth>0.0 && _borderColor!=NULL);
  20.114 +        [self setNeedsDisplay];
  20.115 +    }
  20.116 +}
  20.117 +
  20.118 +
  20.119 +- (void)drawInContext:(CGContextRef)ctx
  20.120 +{
  20.121 +    CGContextSaveGState(ctx);
  20.122 +
  20.123 +    if( _realBGColor ) {
  20.124 +        CGRect interior = CGRectInset(self.bounds, _borderWidth,_borderWidth);
  20.125 +        CGContextSetFillColorWithColor(ctx, _realBGColor);
  20.126 +        if( _cornerRadius <= 0.0 ) {
  20.127 +            CGContextFillRect(ctx,interior);
  20.128 +        } else {
  20.129 +            CGContextBeginPath(ctx);
  20.130 +            AddRoundRect(ctx,interior,_cornerRadius);
  20.131 +            CGContextFillPath(ctx);
  20.132 +        }
  20.133 +    }
  20.134 +    
  20.135 +    if( _borderWidth > 0.0 && _borderColor!=NULL ) {
  20.136 +        CGRect border = CGRectInset(self.bounds, _borderWidth/2.0, _borderWidth/2.0);
  20.137 +        CGContextSetStrokeColorWithColor(ctx, _borderColor);
  20.138 +        CGContextSetLineWidth(ctx, _borderWidth);
  20.139 +        
  20.140 +        if( _cornerRadius <= 0.0 ) {
  20.141 +            CGContextStrokeRect(ctx,border);
  20.142 +        } else {
  20.143 +            CGContextBeginPath(ctx);
  20.144 +            AddRoundRect(ctx,border,_cornerRadius);
  20.145 +            CGContextStrokePath(ctx);
  20.146 +        }
  20.147 +    }
  20.148 +    
  20.149 +    CGContextRestoreGState(ctx);
  20.150 +}
  20.151 +
  20.152 +
  20.153 +#else
  20.154 +
  20.155 +#pragma mark -
  20.156 +#pragma mark MAC OS VERSION:
  20.157 +
  20.158 +
  20.159 +- (id) copyWithZone: (NSZone*)zone
  20.160 +{
  20.161 +    // NSLayer isn't copyable, but it is archivable. So create a copy by archiving to
  20.162 +    // a temporary data block, then unarchiving a new layer from that block.
  20.163 +    
  20.164 +    // One complication is that, due to a bug in Core Animation, CALayer can't archive
  20.165 +    // a pattern-based CGColor. So as a workaround, clear the background before archiving,
  20.166 +    // then restore it afterwards.
  20.167 +    
  20.168 +    // Also, archiving a CALayer with an image in it leaks memory. (Filed as rdar://5786865 )
  20.169 +    // As a workaround, clear the contents before archiving, then restore.
  20.170 +    
  20.171 +    CGColorRef bg = CGColorRetain(self.backgroundColor);
  20.172 +    self.backgroundColor = NULL;
  20.173 +    id contents = [self.contents retain];
  20.174 +    self.contents = nil;
  20.175 +    
  20.176 +    NSData *data = [NSKeyedArchiver archivedDataWithRootObject: self];
  20.177 +    
  20.178 +    self.backgroundColor = bg;
  20.179 +    self.contents = contents;
  20.180 +
  20.181 +    GGBLayer *clone = [NSKeyedUnarchiver unarchiveObjectWithData: data];
  20.182 +    clone.backgroundColor = bg;
  20.183 +    clone.contents = contents;
  20.184 +    CGColorRelease(bg);
  20.185 +    [contents release];
  20.186 +
  20.187 +    return [clone retain];
  20.188 +}
  20.189 +
  20.190 +
  20.191 +#endif
  20.192 +
  20.193 +
  20.194 +@end
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/Source/GGBTextLayer.h	Mon Mar 10 17:30:57 2008 -0700
    21.3 @@ -0,0 +1,37 @@
    21.4 +//
    21.5 +//  GGBTextLayer.h
    21.6 +//  GGB-iPhone
    21.7 +//
    21.8 +//  Created by Jens Alfke on 3/10/08.
    21.9 +//  Copyright 2008 __MyCompanyName__. All rights reserved.
   21.10 +//
   21.11 +
   21.12 +#import "GGBLayer.h"
   21.13 +
   21.14 +
   21.15 +#if TARGET_OS_ASPEN
   21.16 +@interface GGBTextLayer : GGBLayer
   21.17 +{
   21.18 +    NSString *_string;
   21.19 +    CGFloat _fontSize;
   21.20 +    CGColorRef _foregroundColor;
   21.21 +    NSString *_alignmentMode;
   21.22 +}
   21.23 +
   21.24 +@property(copy) id string;
   21.25 +@property CGFloat fontSize;
   21.26 +@property CGColorRef foregroundColor;
   21.27 +@property (copy) NSString *alignmentMode;
   21.28 +
   21.29 +#else
   21.30 +@interface GGBTextLayer : CATextLayer
   21.31 +#endif
   21.32 +
   21.33 ++ (GGBTextLayer*) textLayerInSuperlayer: (CALayer*)superlayer
   21.34 +                               withText: (NSString*)text
   21.35 +                               fontSize: (float) fontSize
   21.36 +                              alignment: (enum CAAutoresizingMask) align;
   21.37 +
   21.38 +@end
   21.39 +
   21.40 +
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/Source/GGBTextLayer.m	Mon Mar 10 17:30:57 2008 -0700
    22.3 @@ -0,0 +1,73 @@
    22.4 +//
    22.5 +//  GGBTextLayer.m
    22.6 +//  GGB-iPhone
    22.7 +//
    22.8 +//  Created by Jens Alfke on 3/10/08.
    22.9 +//  Copyright 2008 __MyCompanyName__. All rights reserved.
   22.10 +//
   22.11 +
   22.12 +#import "GGBTextLayer.h"
   22.13 +#import "QuartzUtils.h"
   22.14 +
   22.15 +
   22.16 +@implementation GGBTextLayer
   22.17 +
   22.18 +
   22.19 ++ (GGBTextLayer*) textLayerInSuperlayer: (CALayer*)superlayer
   22.20 +                               withText: (NSString*)text
   22.21 +                               fontSize: (float) fontSize
   22.22 +                              alignment: (enum CAAutoresizingMask) align
   22.23 +{
   22.24 +    GGBTextLayer *label = [[self alloc] init];
   22.25 +    label.string = text;
   22.26 +
   22.27 +#if TARGET_OS_ASPEN
   22.28 +    UIFont *font = [UIFont systemFontOfSize: fontSize];
   22.29 +#else
   22.30 +    NSFont *font = [NSFont systemFontOfSize: fontSize];
   22.31 +    label.font = font;
   22.32 +#endif
   22.33 +    
   22.34 +    label.fontSize = fontSize;
   22.35 +    label.foregroundColor = kBlackColor;
   22.36 +    
   22.37 +    NSString *mode;
   22.38 +    if( align & kCALayerWidthSizable )
   22.39 +        mode = @"center";
   22.40 +    else if( align & kCALayerMinXMargin )
   22.41 +        mode = @"right";
   22.42 +    else
   22.43 +        mode = @"left";
   22.44 +    align |= kCALayerWidthSizable;
   22.45 +    label.alignmentMode = mode;
   22.46 +    
   22.47 +    CGFloat inset = 3;
   22.48 +    if( [superlayer respondsToSelector: @selector(borderWidth)] )
   22.49 +        inset += ((GGBLayer*)superlayer).borderWidth;
   22.50 +    CGRect bounds = CGRectInset(superlayer.bounds, inset, inset);
   22.51 +    CGFloat height = font.ascender;
   22.52 +    CGFloat y = bounds.origin.y;
   22.53 +    if( align & kCALayerHeightSizable )
   22.54 +        y += (bounds.size.height-height)/2.0;
   22.55 +    else if( align & kCALayerMinYMargin )
   22.56 +        y += bounds.size.height - height;
   22.57 +    align &= ~kCALayerHeightSizable;
   22.58 +    label.bounds = CGRectMake(0, font.descender,
   22.59 +                              bounds.size.width, height - font.descender);
   22.60 +    label.position = CGPointMake(bounds.origin.x,y+font.descender);
   22.61 +    label.anchorPoint = CGPointMake(0,0);
   22.62 +    
   22.63 +    label.autoresizingMask = align;
   22.64 +    [superlayer addSublayer: label];
   22.65 +    [label release];
   22.66 +    return label;
   22.67 +}
   22.68 +
   22.69 +
   22.70 +#if TARGET_OS_ASPEN
   22.71 +@synthesize string=_string, fontSize=_fontSize, 
   22.72 +            foregroundColor=_foregroundColor, alignmentMode=_alignmentMode;
   22.73 +#endif
   22.74 +
   22.75 +
   22.76 +@end
    23.1 --- a/Source/GGBUtils.h	Fri Mar 07 11:43:02 2008 -0800
    23.2 +++ b/Source/GGBUtils.h	Mon Mar 10 17:30:57 2008 -0700
    23.3 @@ -18,7 +18,7 @@
    23.4      CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
    23.5      THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    23.6  */
    23.7 -#import <Cocoa/Cocoa.h>
    23.8 +
    23.9  
   23.10  /** Handy utility for assigning a new value to a retained instance variable. Use as:
   23.11          setObj(&_instanceVar, newValue);
   23.12 @@ -26,6 +26,9 @@
   23.13  
   23.14  void setObj( id *variable, id newValue );
   23.15  
   23.16 -
   23.17  /** Just like setObj except that it _copies_ the new value. */
   23.18  void setObjCopy( id<NSCopying> *variable, id<NSCopying> newValue );
   23.19 +
   23.20 +
   23.21 +void PlaySound( NSString* name );
   23.22 +void Beep( void );
   23.23 \ No newline at end of file
    24.1 --- a/Source/GGBUtils.m	Fri Mar 07 11:43:02 2008 -0800
    24.2 +++ b/Source/GGBUtils.m	Mon Mar 10 17:30:57 2008 -0700
    24.3 @@ -20,6 +20,10 @@
    24.4  */
    24.5  #import "GGBUtils.h"
    24.6  
    24.7 +#if TARGET_OS_ASPEN
    24.8 +#import <AudioToolbox/AudioToolbox.h>
    24.9 +#endif
   24.10 +
   24.11  
   24.12  void setObj( id *variable, id newValue )
   24.13  {
   24.14 @@ -36,3 +40,28 @@
   24.15          *variable = [(id)newValue copy];
   24.16      }
   24.17  }
   24.18 +
   24.19 +
   24.20 +void PlaySound( NSString* name )
   24.21 +{
   24.22 +#if TARGET_OS_ASPEN
   24.23 +    NSURL *url = [NSURL fileURLWithPath: [@"/Library/Sounds/" stringByAppendingPathComponent: name]];
   24.24 +    SystemSoundID soundID;
   24.25 +    if( AudioServicesCreateSystemSoundID((CFURLRef)url,&soundID) != noErr ) {
   24.26 +        NSLog(@"Couldn't load sound %@",url);
   24.27 +        return;
   24.28 +    }
   24.29 +    AudioServicesPlaySystemSound(soundID);
   24.30 +#else
   24.31 +    [[NSSound soundNamed: name] play];
   24.32 +#endif
   24.33 +}
   24.34 +
   24.35 +void Beep()
   24.36 +{
   24.37 +#if TARGET_OS_ASPEN
   24.38 +    AudioServicesPlaySystemSound(kSystemSoundID_UserPreferredAlert);
   24.39 +#else
   24.40 +    NSBeep();
   24.41 +#endif
   24.42 +}
    25.1 --- a/Source/Game.h	Fri Mar 07 11:43:02 2008 -0800
    25.2 +++ b/Source/Game.h	Mon Mar 10 17:30:57 2008 -0700
    25.3 @@ -20,15 +20,14 @@
    25.4      CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
    25.5      THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    25.6  */
    25.7 -#import <Cocoa/Cocoa.h>
    25.8 -@class Bit, Player;
    25.9 +@class GGBLayer, Bit, Player;
   25.10  @protocol BitHolder;
   25.11  
   25.12  
   25.13  /** Abstract superclass. Keeps track of the rules and turns of a game. */
   25.14  @interface Game : NSObject
   25.15  {
   25.16 -    CALayer *_board;
   25.17 +    GGBLayer *_board;
   25.18      NSArray *_players;
   25.19      Player *_currentPlayer, *_winner;
   25.20  }
   25.21 @@ -45,7 +44,7 @@
   25.22  
   25.23  /** Designated initializer. After calling the superclass implementation,
   25.24      it should add the necessary Grids, Pieces, Cards, Decks etc. to the board. */
   25.25 -- (id) initWithBoard: (CALayer*)board;
   25.26 +- (id) initWithBoard: (GGBLayer*)board;
   25.27  
   25.28  /** Should return YES if it is legal for the given bit to be moved from its current holder.
   25.29      Default implementation always returns YES. */
    26.1 --- a/Source/Game.m	Fri Mar 07 11:43:02 2008 -0800
    26.2 +++ b/Source/Game.m	Mon Mar 10 17:30:57 2008 -0700
    26.3 @@ -51,7 +51,7 @@
    26.4  }
    26.5  
    26.6  
    26.7 -- (id) initWithBoard: (CALayer*)board
    26.8 +- (id) initWithBoard: (GGBLayer*)board
    26.9  {
   26.10      self = [super init];
   26.11      if (self != nil) {
    27.1 --- a/Source/GoGame.m	Fri Mar 07 11:43:02 2008 -0800
    27.2 +++ b/Source/GoGame.m	Mon Mar 10 17:30:57 2008 -0700
    27.3 @@ -26,6 +26,7 @@
    27.4  #import "Dispenser.h"
    27.5  #import "Stack.h"
    27.6  #import "QuartzUtils.h"
    27.7 +#import "GGBUtils.h"
    27.8  
    27.9  
   27.10  @implementation GoGame
   27.11 @@ -44,7 +45,7 @@
   27.12  }    
   27.13  
   27.14  
   27.15 -- (id) initWithBoard: (CALayer*)board
   27.16 +- (id) initWithBoard: (GGBLayer*)board
   27.17  {
   27.18      self = [super initWithBoard: board];
   27.19      if (self != nil) {
   27.20 @@ -153,7 +154,7 @@
   27.21              }
   27.22          }
   27.23      if( captured )
   27.24 -        [[NSSound soundNamed: @"Pop"] play];
   27.25 +        PlaySound(@"Pop");
   27.26          
   27.27      [self nextPlayer];
   27.28  }
    28.1 --- a/Source/Grid.h	Fri Mar 07 11:43:02 2008 -0800
    28.2 +++ b/Source/Grid.h	Mon Mar 10 17:30:57 2008 -0700
    28.3 @@ -25,7 +25,7 @@
    28.4  
    28.5  
    28.6  /** Abstract superclass of regular geometric grids of GridCells that Bits can be placed on. */
    28.7 -@interface Grid : CALayer
    28.8 +@interface Grid : GGBLayer
    28.9  {
   28.10      unsigned _nRows, _nColumns;                         
   28.11      CGSize _spacing;                                    
    29.1 --- a/Source/Grid.m	Fri Mar 07 11:43:02 2008 -0800
    29.2 +++ b/Source/Grid.m	Mon Mar 10 17:30:57 2008 -0700
    29.3 @@ -40,7 +40,7 @@
    29.4          _nColumns = nColumns;
    29.5          _spacing = spacing;
    29.6          _cellClass = [GridCell class];
    29.7 -        _lineColor = kBlackColor;
    29.8 +        self.lineColor = kBlackColor;
    29.9          _allowsMoves = YES;
   29.10          _usesDiagonals = YES;
   29.11  
   29.12 @@ -328,6 +328,8 @@
   29.13  #pragma mark DRAG-AND-DROP:
   29.14  
   29.15  
   29.16 +#if ! TARGET_OS_ASPEN
   29.17 +
   29.18  // An image from another app can be dragged onto a Dispenser to change the Piece's appearance.
   29.19  
   29.20  
   29.21 @@ -353,6 +355,7 @@
   29.22          return NO;
   29.23  }
   29.24  
   29.25 +#endif
   29.26  
   29.27  @end
   29.28  
   29.29 @@ -430,6 +433,8 @@
   29.30  - (Square*) l      {return self.fwdIsN ?self.w  :self.e;}
   29.31  
   29.32  
   29.33 +#if ! TARGET_OS_ASPEN
   29.34 +
   29.35  - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
   29.36  {
   29.37      CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard]);
   29.38 @@ -447,6 +452,8 @@
   29.39          return NO;
   29.40  }
   29.41  
   29.42 +#endif
   29.43 +
   29.44  @end
   29.45  
   29.46  
   29.47 @@ -483,4 +490,5 @@
   29.48      }
   29.49  }
   29.50  
   29.51 +
   29.52  @end
    30.1 --- a/Source/HexchequerGame.m	Fri Mar 07 11:43:02 2008 -0800
    30.2 +++ b/Source/HexchequerGame.m	Mon Mar 10 17:30:57 2008 -0700
    30.3 @@ -24,6 +24,7 @@
    30.4  #import "HexGrid.h"
    30.5  #import "Piece.h"
    30.6  #import "QuartzUtils.h"
    30.7 +#import "GGBUtils.h"
    30.8  
    30.9  
   30.10  @implementation HexchequerGame
   30.11 @@ -38,7 +39,7 @@
   30.12      [grid addCellsInHexagon];
   30.13      grid.allowsMoves = YES;
   30.14      grid.allowsCaptures = NO;      // no land-on captures, that is
   30.15 -    grid.cellColor = CGColorCreateGenericGray(1.0, 0.25);
   30.16 +    grid.cellColor = CreateGray(1.0, 0.25);
   30.17      grid.lineColor = kTranslucentLightGrayColor;
   30.18      
   30.19      [self addPieces: @"Green Ball.png" toGrid: grid forPlayer: 0 rows: NSMakeRange(0,2) alternating: NO];
   30.20 @@ -65,12 +66,12 @@
   30.21      int playerIndex = self.currentPlayer.index;
   30.22      BOOL isKing = ([bit valueForKey: @"King"] != nil);
   30.23      
   30.24 -    [[NSSound soundNamed: (isKing ?@"Funk" :@"Tink")] play];
   30.25 +    PlaySound(isKing ?@"Funk" :@"Tink");
   30.26  
   30.27      // "King" a piece that made it to the last row:
   30.28      if( dst.row == (playerIndex ?0 :8) )
   30.29          if( ! isKing ) {
   30.30 -            [[NSSound soundNamed: @"Blow"] play];
   30.31 +            PlaySound(@"Blow");
   30.32              bit.scale = 1.4;
   30.33              [bit setValue: @"King" forKey: @"King"];
   30.34              // don't set isKing flag - piece can't capture again after being kinged.
   30.35 @@ -92,7 +93,7 @@
   30.36          capture = src.r;
   30.37      
   30.38      if( capture ) {
   30.39 -        [[NSSound soundNamed: @"Pop"] play];
   30.40 +        PlaySound(@"Pop");
   30.41          Bit *bit = capture.bit;
   30.42          _numPieces[bit.owner.index]--;
   30.43          [bit destroy];
    31.1 --- a/Source/KlondikeGame.m	Fri Mar 07 11:43:02 2008 -0800
    31.2 +++ b/Source/KlondikeGame.m	Mon Mar 10 17:30:57 2008 -0700
    31.3 @@ -41,7 +41,7 @@
    31.4  @implementation KlondikeGame
    31.5  
    31.6  
    31.7 -- (id) initWithBoard: (CALayer*)board
    31.8 +- (id) initWithBoard: (GGBLayer*)board
    31.9  {
   31.10      self = [super initWithBoard: board];
   31.11      if (self != nil) {
    32.1 --- a/Source/Piece.m	Fri Mar 07 11:43:02 2008 -0800
    32.2 +++ b/Source/Piece.m	Mon Mar 10 17:30:57 2008 -0700
    32.3 @@ -40,20 +40,11 @@
    32.4  }
    32.5  
    32.6  
    32.7 -- (id) initWithCoder: (NSCoder*)decoder
    32.8 +- (id) copyWithZone: (NSZone*)zone
    32.9  {
   32.10 -    self = [super initWithCoder: decoder];
   32.11 -    if( self ) {
   32.12 -        self.imageName = [decoder decodeObjectForKey: @"imageName"];
   32.13 -        // (actual image (self.contents) was already restord by superclass)
   32.14 -    }
   32.15 -    return self;
   32.16 -}
   32.17 -
   32.18 -- (void) encodeWithCoder: (NSCoder*)coder
   32.19 -{
   32.20 -    [super encodeWithCoder: coder];
   32.21 -    [coder encodeObject: _imageName forKey: @"imageName"];
   32.22 +    Piece *clone = [super copyWithZone: zone];
   32.23 +    clone.imageName = self.imageName;
   32.24 +    return clone;
   32.25  }
   32.26  
   32.27  
    33.1 --- a/Source/PlayingCard.m	Fri Mar 07 11:43:02 2008 -0800
    33.2 +++ b/Source/PlayingCard.m	Mon Mar 10 17:30:57 2008 -0700
    33.3 @@ -21,6 +21,7 @@
    33.4      THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    33.5  */
    33.6  #import "PlayingCard.h"
    33.7 +#import "GGBTextLayer.h"
    33.8  #import "QuartzUtils.h"
    33.9  
   33.10  
   33.11 @@ -33,25 +34,31 @@
   33.12  }
   33.13  
   33.14  
   33.15 -- (CALayer*) createFront
   33.16 +- (GGBLayer*) createFront
   33.17  {
   33.18 -    CALayer *front = [super createFront];
   33.19 +    GGBLayer *front = [super createFront];
   33.20      NSString *name = [NSString stringWithFormat: @"%@%@",
   33.21                        self.rankString, self.suitString];
   33.22      
   33.23      CGColorRef suitColor = self.suitColor;
   33.24 -    CATextLayer *label;
   33.25 -    label = AddTextLayer(front, name, [NSFont systemFontOfSize: 18],
   33.26 -                         kCALayerMaxXMargin | kCALayerMinYMargin);
   33.27 +    GGBTextLayer *label;
   33.28 +    label = [GGBTextLayer textLayerInSuperlayer: front
   33.29 +                                       withText: name
   33.30 +                                       fontSize: 18.0
   33.31 +                                      alignment: kCALayerMaxXMargin | kCALayerMinYMargin];
   33.32      label.foregroundColor = suitColor;
   33.33 -    label = AddTextLayer(front, name, [NSFont systemFontOfSize: 18],
   33.34 -                         kCALayerMaxXMargin | kCALayerMaxYMargin);
   33.35 +    label = [GGBTextLayer textLayerInSuperlayer: front
   33.36 +                                       withText: name
   33.37 +                                       fontSize: 18.0
   33.38 +                                      alignment: kCALayerMaxXMargin | kCALayerMaxYMargin];
   33.39      label.foregroundColor = suitColor;
   33.40      label.anchorPoint = CGPointMake(1,1);
   33.41      [label setValue: [NSNumber numberWithFloat: M_PI] forKeyPath: @"transform.rotation"];
   33.42      
   33.43 -    label = AddTextLayer(front, self.faceSymbol, [NSFont systemFontOfSize: 80],
   33.44 -                         kCALayerWidthSizable | kCALayerHeightSizable);
   33.45 +    label = [GGBTextLayer textLayerInSuperlayer: front
   33.46 +                                       withText: self.faceSymbol
   33.47 +                                       fontSize: 80
   33.48 +                                      alignment: kCALayerWidthSizable | kCALayerHeightSizable];
   33.49      label.foregroundColor = suitColor;
   33.50      return front;
   33.51  }
   33.52 @@ -86,7 +93,7 @@
   33.53      static CGColorRef kSuitColor[4];
   33.54      if( ! kSuitColor[0] ) {
   33.55          kSuitColor[0] = kSuitColor[3] = kBlackColor;
   33.56 -        kSuitColor[1] = kSuitColor[2] = CGColorCreateGenericRGB(1, 0, 0, 1);
   33.57 +        kSuitColor[1] = kSuitColor[2] = CreateRGB(1, 0, 0, 1);
   33.58      }
   33.59      return kSuitColor[self.suit];
   33.60  }
    34.1 --- a/Source/QuartzUtils.h	Fri Mar 07 11:43:02 2008 -0800
    34.2 +++ b/Source/QuartzUtils.h	Mon Mar 10 17:30:57 2008 -0700
    34.3 @@ -20,7 +20,7 @@
    34.4      CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
    34.5      THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    34.6  */
    34.7 -#import <Quartz/Quartz.h>
    34.8 +#import "GGBLayer.h"
    34.9  
   34.10  
   34.11  /** Constants for various commonly used colors. */
   34.12 @@ -29,6 +29,15 @@
   34.13                    kAlmostInvisibleWhiteColor,
   34.14                    kHighlightColor;
   34.15  
   34.16 +#if TARGET_OS_ASPEN
   34.17 +// These don't exist on iPhone, so I implement them:
   34.18 +CGColorRef CreateGray(CGFloat gray, CGFloat alpha);
   34.19 +CGColorRef CreateRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha);
   34.20 +#else
   34.21 +#define CreateGray  CGColorCreateGenericGray
   34.22 +#define CreateRGB   CGColorCreateGenericRGB
   34.23 +#endif
   34.24 +
   34.25  
   34.26  /** Moves a layer from one superlayer to another, without changing its position onscreen. */
   34.27  void ChangeSuperlayer( CALayer *layer, CALayer *newSuperlayer, int index );
   34.28 @@ -36,11 +45,6 @@
   34.29  /** Removes a layer from its superlayer without any fade-out animation. */
   34.30  void RemoveImmediately( CALayer *layer );
   34.31  
   34.32 -/** Convenience for creating a CATextLayer. */
   34.33 -CATextLayer* AddTextLayer( CALayer *superlayer,
   34.34 -                           NSString *text, NSFont* font,
   34.35 -                           enum CAAutoresizingMask align );
   34.36 -
   34.37  
   34.38  /** Loads an image or pattern file into a CGImage or CGPattern.
   34.39      If the name begins with "/", it's interpreted as an absolute filesystem path.
   34.40 @@ -52,8 +56,10 @@
   34.41  CGImageRef GetCGImageNamed( NSString *name );
   34.42  CGColorRef GetCGPatternNamed( NSString *name );
   34.43  
   34.44 +#if ! TARGET_OS_ASPEN
   34.45  /** Loads image data from the pasteboard into a CGImage. */
   34.46  CGImageRef GetCGImageFromPasteboard( NSPasteboard *pb );
   34.47 +#endif
   34.48  
   34.49  /** Creates a CGPattern from a CGImage. Caller must release it. */
   34.50  CGPatternRef CreateImagePattern( CGImageRef image );
   34.51 @@ -67,4 +73,6 @@
   34.52  /** Returns the center point of a CGRect. */
   34.53  static inline CGPoint GetCGRectCenter( CGRect rect ) {
   34.54      return CGPointMake(CGRectGetMidX(rect),CGRectGetMidY(rect));
   34.55 -}
   34.56 \ No newline at end of file
   34.57 +}
   34.58 +
   34.59 +void AddRoundRect( CGContextRef ctx, CGRect rect, CGFloat radius );
    35.1 --- a/Source/QuartzUtils.m	Fri Mar 07 11:43:02 2008 -0800
    35.2 +++ b/Source/QuartzUtils.m	Mon Mar 10 17:30:57 2008 -0700
    35.3 @@ -21,6 +21,7 @@
    35.4      THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    35.5  */
    35.6  #import "QuartzUtils.h"
    35.7 +#import <QuartzCore/QuartzCore.h>
    35.8  
    35.9  
   35.10  CGColorRef kBlackColor, kWhiteColor, 
   35.11 @@ -32,15 +33,36 @@
   35.12  __attribute__((constructor))        // Makes this function run when the app loads
   35.13  static void InitQuartzUtils()
   35.14  {
   35.15 -    kBlackColor = CGColorCreateGenericGray(0.0, 1.0);
   35.16 -    kWhiteColor = CGColorCreateGenericGray(1.0, 1.0);
   35.17 -    kTranslucentGrayColor = CGColorCreateGenericGray(0.0, 0.5);
   35.18 -    kTranslucentLightGrayColor = CGColorCreateGenericGray(0.0, 0.25);
   35.19 -    kAlmostInvisibleWhiteColor = CGColorCreateGenericGray(1, 0.05);
   35.20 -    kHighlightColor = CGColorCreateGenericRGB(1, 1, 0, 0.5);
   35.21 +    kBlackColor = CreateGray(0.0, 1.0);
   35.22 +    kWhiteColor = CreateGray(1.0, 1.0);
   35.23 +    kTranslucentGrayColor = CreateGray(0.0, 0.5);
   35.24 +    kTranslucentLightGrayColor = CreateGray(0.0, 0.25);
   35.25 +    kAlmostInvisibleWhiteColor = CreateGray(1, 0.05);
   35.26 +    kHighlightColor = CreateRGB(1, 1, 0, 0.5);
   35.27  }
   35.28  
   35.29  
   35.30 +#if TARGET_OS_ASPEN
   35.31 +CGColorRef CreateGray(CGFloat gray, CGFloat alpha)
   35.32 +{
   35.33 +    CGColorSpaceRef graySpace = CGColorSpaceCreateDeviceGray();
   35.34 +    CGFloat components[2] = {gray,alpha};
   35.35 +    CGColorRef color = CGColorCreate(graySpace, components);
   35.36 +    CGColorSpaceRelease(graySpace);
   35.37 +    return color;
   35.38 +}
   35.39 +
   35.40 +CGColorRef CreateRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)
   35.41 +{
   35.42 +    CGColorSpaceRef rgbSpace = CGColorSpaceCreateDeviceRGB();
   35.43 +    CGFloat components[4] = {red,green,blue,alpha};
   35.44 +    CGColorRef color = CGColorCreate(rgbSpace, components);
   35.45 +    CGColorSpaceRelease(rgbSpace);
   35.46 +    return color;
   35.47 +}
   35.48 +#endif
   35.49 +
   35.50 +
   35.51  void ChangeSuperlayer( CALayer *layer, CALayer *newSuperlayer, int index )
   35.52  {
   35.53      // Disable actions, else the layer will move to the wrong place and then back!
   35.54 @@ -75,49 +97,13 @@
   35.55  }    
   35.56  
   35.57  
   35.58 -CATextLayer* AddTextLayer( CALayer *superlayer,
   35.59 -                           NSString *text, NSFont* font,
   35.60 -                           enum CAAutoresizingMask align )
   35.61 -{
   35.62 -    CATextLayer *label = [[CATextLayer alloc] init];
   35.63 -    label.string = text;
   35.64 -    label.font = font;
   35.65 -    label.fontSize = font.pointSize;
   35.66 -    label.foregroundColor = kBlackColor;
   35.67 -    
   35.68 -    NSString *mode;
   35.69 -    if( align & kCALayerWidthSizable )
   35.70 -        mode = @"center";
   35.71 -    else if( align & kCALayerMinXMargin )
   35.72 -        mode = @"right";
   35.73 -    else
   35.74 -        mode = @"left";
   35.75 -    align |= kCALayerWidthSizable;
   35.76 -    label.alignmentMode = mode;
   35.77 -    
   35.78 -    CGFloat inset = superlayer.borderWidth + 3;
   35.79 -    CGRect bounds = CGRectInset(superlayer.bounds, inset, inset);
   35.80 -    CGFloat height = font.ascender;
   35.81 -    CGFloat y = bounds.origin.y;
   35.82 -    if( align & kCALayerHeightSizable )
   35.83 -        y += (bounds.size.height-height)/2.0;
   35.84 -    else if( align & kCALayerMinYMargin )
   35.85 -        y += bounds.size.height - height;
   35.86 -    align &= ~kCALayerHeightSizable;
   35.87 -    label.bounds = CGRectMake(0, font.descender,
   35.88 -                              bounds.size.width, height - font.descender);
   35.89 -    label.position = CGPointMake(bounds.origin.x,y+font.descender);
   35.90 -    label.anchorPoint = CGPointMake(0,0);
   35.91 -    
   35.92 -    label.autoresizingMask = align;
   35.93 -    [superlayer addSublayer: label];
   35.94 -    [label release];
   35.95 -    return label;
   35.96 -}
   35.97 -
   35.98 -
   35.99  CGImageRef CreateCGImageFromFile( NSString *path )
  35.100  {
  35.101 +#if TARGET_OS_ASPEN
  35.102 +    UIImage *uiImage = [UIImage imageWithContentsOfFile: path];
  35.103 +    if(!uiImage) NSLog(@"Warning: UIImage imageWithContentsOfFile failed on file %@",path);
  35.104 +    return CGImageRetain(uiImage.CGImage);
  35.105 +#else
  35.106      CGImageRef image = NULL;
  35.107      CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: path];
  35.108      CGImageSourceRef src = CGImageSourceCreateWithURL(url, NULL);
  35.109 @@ -127,11 +113,18 @@
  35.110          if(!image) NSLog(@"Warning: CGImageSourceCreateImageAtIndex failed on file %@ (ptr size=%u)",path,sizeof(void*));
  35.111      }
  35.112      return image;
  35.113 +#endif
  35.114  }
  35.115  
  35.116  
  35.117  CGImageRef GetCGImageNamed( NSString *name )
  35.118  {
  35.119 +#if TARGET_OS_ASPEN
  35.120 +    name = name.lastPathComponent;
  35.121 +    UIImage *uiImage = [UIImage imageNamed: name];
  35.122 +    NSCAssert1(uiImage,@"Couldn't find bundle image resource '%@'",name);
  35.123 +    return uiImage.CGImage;
  35.124 +#else
  35.125      // For efficiency, loaded images are cached in a dictionary by name.
  35.126      static NSMutableDictionary *sMap;
  35.127      if( ! sMap )
  35.128 @@ -153,6 +146,7 @@
  35.129          CGImageRelease(image);
  35.130      }
  35.131      return image;
  35.132 +#endif
  35.133  }
  35.134  
  35.135  
  35.136 @@ -173,6 +167,7 @@
  35.137  }
  35.138  
  35.139  
  35.140 +#if ! TARGET_OS_ASPEN
  35.141  CGImageRef GetCGImageFromPasteboard( NSPasteboard *pb )
  35.142  {
  35.143      CGImageSourceRef src = NULL;
  35.144 @@ -195,11 +190,17 @@
  35.145          return image;
  35.146      } else
  35.147          return NULL;
  35.148 -}    
  35.149 +}
  35.150 +#endif
  35.151  
  35.152  
  35.153  float GetPixelAlpha( CGImageRef image, CGSize imageSize, CGPoint pt )
  35.154  {
  35.155 +#if TARGET_OS_ASPEN
  35.156 +    // iPhone uses "flipped" (i.e. normal) coords, so images are wrong-way-up
  35.157 +    pt.y = imageSize.height - pt.y;
  35.158 +#endif
  35.159 +    
  35.160      // Trivial reject:
  35.161      if( pt.x<0 || pt.x>=imageSize.width || pt.y<0 || pt.y>=imageSize.height )
  35.162          return 0.0;
  35.163 @@ -271,3 +272,24 @@
  35.164      CGPatternRelease(pattern);
  35.165      return color;
  35.166  }
  35.167 +
  35.168 +
  35.169 +#pragma mark -
  35.170 +#pragma mark PATHS:
  35.171 +
  35.172 +
  35.173 +void AddRoundRect( CGContextRef ctx, CGRect rect, CGFloat radius )
  35.174 +{
  35.175 +    radius = MIN(radius, floorf(rect.size.width/2));
  35.176 +    float x0 = CGRectGetMinX(rect), y0 = CGRectGetMinY(rect),
  35.177 +    x1 = CGRectGetMaxX(rect), y1 = CGRectGetMaxY(rect);
  35.178 +    
  35.179 +    CGContextBeginPath(ctx);
  35.180 +    CGContextMoveToPoint(ctx,x0+radius,y0);
  35.181 +    CGContextAddArcToPoint(ctx,x1,y0, x1,y1, radius);
  35.182 +    CGContextAddArcToPoint(ctx,x1,y1, x0,y1, radius);
  35.183 +    CGContextAddArcToPoint(ctx,x0,y1, x0,y0, radius);
  35.184 +    CGContextAddArcToPoint(ctx,x0,y0, x1,y0, radius);
  35.185 +    CGContextClosePath(ctx);
  35.186 +}
  35.187 +
    36.1 --- a/Source/Stack.m	Fri Mar 07 11:43:02 2008 -0800
    36.2 +++ b/Source/Stack.m	Mon Mar 10 17:30:57 2008 -0700
    36.3 @@ -72,7 +72,7 @@
    36.4  - (void) dump
    36.5  {
    36.6      printf("Stack = ");
    36.7 -    for( CALayer *layer in self.sublayers )
    36.8 +    for( GGBLayer *layer in self.sublayers )
    36.9          printf("%s @z=%g   ", [[layer description] UTF8String],layer.zPosition);
   36.10      printf("\n");
   36.11  }
    37.1 --- a/Source/TicTacToeGame.m	Fri Mar 07 11:43:02 2008 -0800
    37.2 +++ b/Source/TicTacToeGame.m	Mon Mar 10 17:30:57 2008 -0700
    37.3 @@ -29,16 +29,24 @@
    37.4  
    37.5  @implementation TicTacToeGame
    37.6  
    37.7 -- (void) x_createDispenser: (NSString*)imageName forPlayer: (int)playerNumber x: (int)x
    37.8 +- (void) x_createDispenser: (NSString*)imageName forPlayer: (int)playerNumber
    37.9  {
   37.10      Piece *p = [[Piece alloc] initWithImageNamed: imageName scale: 80];
   37.11      p.owner = [self.players objectAtIndex: playerNumber];
   37.12 +    CGFloat x = floor(CGRectGetMidX(_board.bounds));
   37.13 +#if TARGET_OS_ASPEN
   37.14 +    x = x - 80 + 160*playerNumber;
   37.15 +    CGFloat y = 360;
   37.16 +#else
   37.17 +    x += (playerNumber==0 ?-230 :230);
   37.18 +    CGFloat y = 175;
   37.19 +#endif
   37.20      _dispenser[playerNumber] = [[Dispenser alloc] initWithPrototype: p quantity: 0
   37.21 -                                                        frame: CGRectMake(x,16, 120,120)];
   37.22 +                                                        frame: CGRectMake(x-45,y-45, 90,90)];
   37.23      [_board addSublayer: _dispenser[playerNumber]];
   37.24  }
   37.25  
   37.26 -- (id) initWithBoard: (CALayer*)board
   37.27 +- (id) initWithBoard: (GGBLayer*)board
   37.28  {
   37.29      self = [super initWithBoard: board];
   37.30      if (self != nil) {
   37.31 @@ -46,18 +54,16 @@
   37.32          
   37.33          // Create a 3x3 grid:
   37.34          CGFloat center = floor(CGRectGetMidX(board.bounds));
   37.35 -        _grid = [[RectGrid alloc] initWithRows: 3 columns: 3 frame: CGRectMake(center-150,16, 300,300)];
   37.36 +        _grid = [[RectGrid alloc] initWithRows: 3 columns: 3 frame: CGRectMake(center-150,0, 300,300)];
   37.37          [_grid addAllCells];
   37.38          _grid.allowsMoves = _grid.allowsCaptures = NO;
   37.39 -        _grid.cellColor = CGColorCreateGenericGray(1.0, 0.25);
   37.40 +        _grid.cellColor = CreateGray(1.0, 0.25);
   37.41          _grid.lineColor = kTranslucentLightGrayColor;
   37.42          [board addSublayer: _grid];
   37.43          
   37.44          // Create piece dispensers for the two players:
   37.45 -        [self x_createDispenser: @"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ToolbarUtilitiesFolderIcon.icns"
   37.46 -                     forPlayer: 0 x: center-290];
   37.47 -        [self x_createDispenser: @"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ToolbarAdvanced.icns"
   37.48 -                     forPlayer: 1 x: center+170];
   37.49 +        [self x_createDispenser: @"X.tiff" forPlayer: 0];
   37.50 +        [self x_createDispenser: @"O.tiff" forPlayer: 1];
   37.51          
   37.52          // And they're off!
   37.53          [self nextPlayer];
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/Source/iPhoneAppDelegate.h	Mon Mar 10 17:30:57 2008 -0700
    38.3 @@ -0,0 +1,25 @@
    38.4 +//
    38.5 +//  GGB_iPhoneAppDelegate.h
    38.6 +//  GGB-iPhone
    38.7 +//
    38.8 +//  Created by Jens Alfke on 3/7/08.
    38.9 +//  Copyright __MyCompanyName__ 2008. All rights reserved.
   38.10 +//
   38.11 +
   38.12 +#import <UIKit/UIKit.h>
   38.13 +
   38.14 +@class BoardUIView;
   38.15 +
   38.16 +@interface GGB_iPhoneAppDelegate : NSObject <UIModalViewDelegate> {
   38.17 +    UIWindow *_window;
   38.18 +    BoardUIView *_contentView;
   38.19 +    UILabel *_headline;
   38.20 +}
   38.21 +
   38.22 +@property (nonatomic, retain) UIWindow *window;
   38.23 +@property (nonatomic, retain) BoardUIView *contentView;
   38.24 +@property (nonatomic, retain) UILabel *headline;
   38.25 +
   38.26 +- (void) startGameNamed: (NSString*)gameClassName;
   38.27 +
   38.28 +@end
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/Source/iPhoneAppDelegate.m	Mon Mar 10 17:30:57 2008 -0700
    39.3 @@ -0,0 +1,126 @@
    39.4 +//
    39.5 +//  GGB_iPhoneAppDelegate.m
    39.6 +//  GGB-iPhone
    39.7 +//
    39.8 +//  Created by Jens Alfke on 3/7/08.
    39.9 +//  Copyright __MyCompanyName__ 2008. All rights reserved.
   39.10 +//
   39.11 +
   39.12 +#import "GGB_iPhoneAppDelegate.h"
   39.13 +#import "BoardUIView.h"
   39.14 +#import "Game.h"
   39.15 +#import "QuartzUtils.h"
   39.16 +#import "GGBUtils.h"
   39.17 +
   39.18 +
   39.19 +@implementation GGB_iPhoneAppDelegate
   39.20 +
   39.21 +
   39.22 +@synthesize window=_window;
   39.23 +@synthesize contentView=_contentView;
   39.24 +@synthesize headline=_headline;
   39.25 +
   39.26 +
   39.27 +- (void)applicationDidFinishLaunching:(UIApplication *)application 
   39.28 +{	
   39.29 +    // Create window
   39.30 +    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
   39.31 +    _window.layer.backgroundColor = GetCGPatternNamed(@"Background.png");
   39.32 +    
   39.33 +    // Set up content view
   39.34 +    CGRect rHeadline,rContent;
   39.35 +    CGRectDivide([[UIScreen mainScreen] applicationFrame],
   39.36 +                 &rHeadline, &rContent, 35, CGRectMinYEdge);
   39.37 +    
   39.38 +    self.contentView = [[[BoardUIView alloc] initWithFrame: rContent] autorelease];
   39.39 +    [_window addSubview: _contentView];
   39.40 +    
   39.41 +    self.headline = [[[UILabel alloc] initWithFrame: rHeadline] autorelease];
   39.42 +    _headline.backgroundColor = nil;
   39.43 +    _headline.opaque = NO;
   39.44 +    _headline.textAlignment = UITextAlignmentCenter;
   39.45 +    _headline.font = [UIFont boldSystemFontOfSize: 20];
   39.46 +    _headline.minimumFontSize = 14;
   39.47 +    _headline.adjustsFontSizeToFit = YES;
   39.48 +    [_window addSubview: _headline];
   39.49 +    
   39.50 +    // Start game:
   39.51 +    [self startGameNamed: @"TicTacToeGame"];
   39.52 +    
   39.53 +    // Show window
   39.54 +    [_window makeKeyAndVisible];
   39.55 +}
   39.56 +
   39.57 +
   39.58 +- (void)dealloc 
   39.59 +{
   39.60 +    [_contentView release];
   39.61 +    [_headline release];
   39.62 +    [_window release];
   39.63 +    [super dealloc];
   39.64 +}
   39.65 +
   39.66 +
   39.67 +- (void) startGameNamed: (NSString*)gameClassName
   39.68 +{
   39.69 +    Game *game = _contentView.game;
   39.70 +    [game removeObserver: self  forKeyPath: @"currentPlayer"];
   39.71 +    [game removeObserver: self forKeyPath: @"winner"];
   39.72 +    
   39.73 +    if( gameClassName == nil )
   39.74 +        gameClassName = [[game class] className];
   39.75 +    
   39.76 +    [_contentView startGameNamed: gameClassName];
   39.77 +    
   39.78 +    game = _contentView.game;
   39.79 +    [game addObserver: self 
   39.80 +           forKeyPath: @"currentPlayer"
   39.81 +              options: NSKeyValueObservingOptionInitial
   39.82 +              context: NULL];
   39.83 +    [game addObserver: self
   39.84 +           forKeyPath: @"winner"
   39.85 +              options: 0 
   39.86 +              context: NULL];
   39.87 +}
   39.88 +
   39.89 +
   39.90 +- (void)observeValueForKeyPath:(NSString *)keyPath 
   39.91 +                      ofObject:(id)object 
   39.92 +                        change:(NSDictionary *)change
   39.93 +                       context:(void *)context
   39.94 +{
   39.95 +    Game *game = _contentView.game;
   39.96 +    if( object == game ) {
   39.97 +        Player *p = game.winner;
   39.98 +        NSString *msg;
   39.99 +        if( p ) {
  39.100 +            PlaySound(@"Sosumi");
  39.101 +            msg = @"%@ wins!";
  39.102 +        } else {
  39.103 +            p = game.currentPlayer;
  39.104 +            msg = @"Your turn, %@";
  39.105 +        }
  39.106 +        _headline.text = [NSString stringWithFormat: msg, p.name];
  39.107 +        
  39.108 +        if( game.winner ) {
  39.109 +            UIAlertView *alert;
  39.110 +            alert = [[UIAlertView alloc] initWithTitle: msg
  39.111 +                                               message: @"Congratulations!"
  39.112 +                                              delegate:self
  39.113 +                                         defaultButton:@"OK" 
  39.114 +                                          cancelButton:nil otherButtons:nil];
  39.115 +            [alert show];
  39.116 +            [alert release];
  39.117 +        }            
  39.118 +    }
  39.119 +}
  39.120 +
  39.121 +
  39.122 +- (void)modalView:(UIModalView *)modalView didDismissWithButtonIndex:(NSInteger)buttonIndex;
  39.123 +{
  39.124 +    // Start new game:
  39.125 +    [self startGameNamed: nil];
  39.126 +}
  39.127 +
  39.128 +
  39.129 +@end
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/Source/main-iPhone.m	Mon Mar 10 17:30:57 2008 -0700
    40.3 @@ -0,0 +1,17 @@
    40.4 +//
    40.5 +//  main.m
    40.6 +//  GGB-iPhone
    40.7 +//
    40.8 +//  Created by Jens Alfke on 3/7/08.
    40.9 +//  Copyright __MyCompanyName__ 2008. All rights reserved.
   40.10 +//
   40.11 +
   40.12 +#import <UIKit/UIKit.h>
   40.13 +
   40.14 +int main(int argc, char *argv[])
   40.15 +{
   40.16 +    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   40.17 +    int retVal = UIApplicationMain(argc, argv, nil, @"GGB_iPhoneAppDelegate");
   40.18 +    [pool release];
   40.19 +    return retVal;
   40.20 +}