Source/Dispenser.m
author Jens Alfke <jens@mooseyard.com>
Wed Mar 12 15:51:32 2008 -0700 (2008-03-12)
changeset 6 af9b2b929b03
parent 0 e9f7ba4718e1
child 8 45c82a071aca
permissions -rw-r--r--
Fixed: An exception in the Go game if you mouse down on the board but then drag to the captured-pieces area and release the mouse.
     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 #if ! TARGET_OS_ASPEN
   167 
   168 // An image from another app can be dragged onto a Dispenser to change the Piece's appearance.
   169 
   170 
   171 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
   172 {
   173     if( ! [_prototype isKindOfClass: [Piece class]] )
   174         return NSDragOperationNone;
   175     NSPasteboard *pb = [sender draggingPasteboard];
   176     if( [NSImage canInitWithPasteboard: pb] )
   177         return NSDragOperationCopy;
   178     else
   179         return NSDragOperationNone;
   180 }
   181 
   182 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
   183 {
   184     if( ! [_prototype isKindOfClass: [Piece class]] )
   185         return NO;
   186     CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard]);
   187     if( image ) {
   188         [(Piece*)_prototype setImage: image];
   189         self.prototype = _prototype; // recreates _bit
   190         return YES;
   191     } else
   192         return NO;
   193 }
   194 
   195 
   196 #endif
   197 
   198 @end