Source/Dispenser.m
author Jens Alfke <jens@mooseyard.com>
Fri Mar 07 11:43:02 2008 -0800 (2008-03-07)
changeset 0 e9f7ba4718e1
child 1 3eb7be1dd7b6
permissions -rw-r--r--
Initial check-in into Mercurial. Branched from 1.0 release of Apple's sample code. No longer requires garbage collection. Fixed some memory leaks of CG objects. Fixed a bug when advancing to the 8th row in the Checkers game.
     1 /*  This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
     2     http://developer.apple.com/samplecode/GeekGameBoard/
     3     Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
     4 
     5     Redistribution and use in source and binary forms, with or without modification, are permitted
     6     provided that the following conditions are met:
     7 
     8     * Redistributions of source code must retain the above copyright notice, this list of conditions
     9       and the following disclaimer.
    10     * Redistributions in binary form must reproduce the above copyright notice, this list of
    11       conditions and the following disclaimer in the documentation and/or other materials provided
    12       with the distribution.
    13 
    14     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
    15     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
    16     FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
    17     BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    18     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
    19     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
    20     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
    21     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    22 */
    23 #import "Dispenser.h"
    24 #import "Piece.h"
    25 #import "QuartzUtils.h"
    26 #import "GGBUtils.h"
    27 
    28 
    29 @implementation Dispenser
    30 
    31 
    32 - (id) initWithPrototype: (Bit*)prototype quantity: (unsigned)quantity frame: (CGRect)frame
    33 {
    34     self = [super init];
    35     if (self != nil) {
    36         self.backgroundColor = kTranslucentLightGrayColor;
    37         self.borderColor = kTranslucentGrayColor;
    38         self.borderWidth = 3;
    39         self.cornerRadius = 16;
    40         self.zPosition = kBoardZ;
    41         self.masksToBounds = YES;
    42         self.frame = frame;
    43         self.prototype = prototype;
    44         self.quantity = quantity;
    45     }
    46     return self;
    47 }
    48 
    49 
    50 - (void) dealloc
    51 {
    52     [_prototype release];
    53     [super dealloc];
    54 }
    55 
    56 
    57 @synthesize bit=_bit;
    58 
    59 
    60 - (Bit*) createBit
    61 {
    62     if( _prototype ) {
    63         Bit *bit = [_prototype copy];
    64         CGRect bounds = self.bounds;
    65         bit.position = GetCGRectCenter(bounds);
    66         return [bit autorelease];
    67     } else
    68         return nil;
    69 }
    70 
    71 - (void) x_regenerateCurrentBit
    72 {
    73     NSAssert(_bit==nil,@"Already have a currentBit");
    74 
    75     [CATransaction begin];
    76     [CATransaction setValue: (id)kCFBooleanTrue
    77                      forKey: kCATransactionDisableActions];
    78     self.bit = [self createBit];
    79     CGPoint pos = _bit.position;
    80     _bit.position = CGPointMake(pos.x, pos.y+70);
    81     [self addSublayer: _bit];
    82     [CATransaction commit];
    83     
    84     _bit.position = pos;
    85 }
    86 
    87 
    88 - (Bit*) prototype
    89 {
    90     return _prototype;
    91 }
    92 
    93 - (void) setPrototype: (Bit*)prototype
    94 {
    95     setObj(&_prototype, prototype);
    96     if( _bit ) {
    97         [_bit removeFromSuperlayer];
    98         self.bit = nil;
    99         if( prototype )
   100             [self x_regenerateCurrentBit];
   101     }
   102 }
   103 
   104 
   105 - (unsigned) quantity
   106 {
   107     return _quantity;
   108 }
   109 
   110 - (void) setQuantity: (unsigned)quantity
   111 {
   112     _quantity = quantity;
   113     if( quantity > 0 && !_bit )
   114         [self x_regenerateCurrentBit];
   115     else if( quantity==0 && _bit ) {
   116         [_bit removeFromSuperlayer];
   117         self.bit = nil;
   118     }
   119 }
   120 
   121 
   122 #pragma mark -
   123 #pragma mark DRAGGING BITS:
   124 
   125 
   126 - (Bit*) canDragBit: (Bit*)bit
   127 {
   128     bit = [super canDragBit: bit];
   129     if( bit==_bit ) {
   130         [[bit retain] autorelease];
   131         self.bit = nil;
   132     }
   133     return bit;
   134 }
   135 
   136 - (void) cancelDragBit: (Bit*)bit
   137 {
   138     if( ! _bit )
   139         self.bit = bit;
   140     else
   141         [bit removeFromSuperlayer];
   142 }
   143 
   144 - (void) draggedBit: (Bit*)bit to: (id<BitHolder>)dst
   145 {
   146     if( --_quantity > 0 )
   147         [self performSelector: @selector(x_regenerateCurrentBit) withObject: nil afterDelay: 0.0];
   148 }
   149 
   150 - (BOOL) canDropBit: (Bit*)bit atPoint: (CGPoint)point  
   151 {
   152     return [bit isEqual: _bit];
   153 }
   154 
   155 - (BOOL) dropBit: (Bit*)bit atPoint: (CGPoint)point
   156 {
   157     [bit removeFromSuperlayer];
   158     return YES;
   159 }
   160 
   161 
   162 #pragma mark -
   163 #pragma mark DRAG-AND-DROP:
   164 
   165 
   166 // An image from another app can be dragged onto a Dispenser to change the Piece's appearance.
   167 
   168 
   169 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
   170 {
   171     if( ! [_prototype isKindOfClass: [Piece class]] )
   172         return NSDragOperationNone;
   173     NSPasteboard *pb = [sender draggingPasteboard];
   174     if( [NSImage canInitWithPasteboard: pb] )
   175         return NSDragOperationCopy;
   176     else
   177         return NSDragOperationNone;
   178 }
   179 
   180 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
   181 {
   182     if( ! [_prototype isKindOfClass: [Piece class]] )
   183         return NO;
   184     CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard]);
   185     if( image ) {
   186         [(Piece*)_prototype setImage: image];
   187         self.prototype = _prototype; // recreates _bit
   188         return YES;
   189     } else
   190         return NO;
   191 }
   192 
   193 
   194 @end