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