Source/Dispenser.m
author Jens Alfke <jens@mooseyard.com>
Sat Jul 05 17:46:43 2008 -0700 (2008-07-05)
changeset 11 436cbdf56810
parent 9 a59acc683080
child 29 0b1c315ffc64
permissions -rw-r--r--
* Improved drag-and-drop (supports CandyBar)
* Fixed DiscPiece
* Inheritable layer styles
etc.
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@9
    75
    BeginDisableAnimations();
jens@0
    76
    self.bit = [self createBit];
jens@0
    77
    CGPoint pos = _bit.position;
jens@0
    78
    _bit.position = CGPointMake(pos.x, pos.y+70);
jens@0
    79
    [self addSublayer: _bit];
jens@9
    80
    EndDisableAnimations();
jens@0
    81
    
jens@0
    82
    _bit.position = pos;
jens@0
    83
}
jens@0
    84
jens@0
    85
jens@0
    86
- (Bit*) prototype
jens@0
    87
{
jens@0
    88
    return _prototype;
jens@0
    89
}
jens@0
    90
jens@0
    91
- (void) setPrototype: (Bit*)prototype
jens@0
    92
{
jens@0
    93
    setObj(&_prototype, prototype);
jens@0
    94
    if( _bit ) {
jens@0
    95
        [_bit removeFromSuperlayer];
jens@0
    96
        self.bit = nil;
jens@0
    97
        if( prototype )
jens@0
    98
            [self x_regenerateCurrentBit];
jens@0
    99
    }
jens@0
   100
}
jens@0
   101
jens@0
   102
jens@0
   103
- (unsigned) quantity
jens@0
   104
{
jens@0
   105
    return _quantity;
jens@0
   106
}
jens@0
   107
jens@0
   108
- (void) setQuantity: (unsigned)quantity
jens@0
   109
{
jens@0
   110
    _quantity = quantity;
jens@0
   111
    if( quantity > 0 && !_bit )
jens@0
   112
        [self x_regenerateCurrentBit];
jens@0
   113
    else if( quantity==0 && _bit ) {
jens@0
   114
        [_bit removeFromSuperlayer];
jens@0
   115
        self.bit = nil;
jens@0
   116
    }
jens@0
   117
}
jens@0
   118
jens@0
   119
jens@0
   120
#pragma mark -
jens@0
   121
#pragma mark DRAGGING BITS:
jens@0
   122
jens@0
   123
jens@0
   124
- (Bit*) canDragBit: (Bit*)bit
jens@0
   125
{
jens@0
   126
    bit = [super canDragBit: bit];
jens@0
   127
    if( bit==_bit ) {
jens@0
   128
        [[bit retain] autorelease];
jens@0
   129
        self.bit = nil;
jens@0
   130
    }
jens@0
   131
    return bit;
jens@0
   132
}
jens@0
   133
jens@0
   134
- (void) cancelDragBit: (Bit*)bit
jens@0
   135
{
jens@0
   136
    if( ! _bit )
jens@0
   137
        self.bit = bit;
jens@0
   138
    else
jens@0
   139
        [bit removeFromSuperlayer];
jens@0
   140
}
jens@0
   141
jens@0
   142
- (void) draggedBit: (Bit*)bit to: (id<BitHolder>)dst
jens@0
   143
{
jens@0
   144
    if( --_quantity > 0 )
jens@0
   145
        [self performSelector: @selector(x_regenerateCurrentBit) withObject: nil afterDelay: 0.0];
jens@0
   146
}
jens@0
   147
jens@0
   148
- (BOOL) canDropBit: (Bit*)bit atPoint: (CGPoint)point  
jens@0
   149
{
jens@0
   150
    return [bit isEqual: _bit];
jens@0
   151
}
jens@0
   152
jens@0
   153
- (BOOL) dropBit: (Bit*)bit atPoint: (CGPoint)point
jens@0
   154
{
jens@0
   155
    [bit removeFromSuperlayer];
jens@0
   156
    return YES;
jens@0
   157
}
jens@0
   158
jens@0
   159
jens@0
   160
#pragma mark -
jens@0
   161
#pragma mark DRAG-AND-DROP:
jens@0
   162
jens@0
   163
jens@8
   164
#if ! TARGET_OS_IPHONE
jens@1
   165
jens@0
   166
// An image from another app can be dragged onto a Dispenser to change the Piece's appearance.
jens@0
   167
jens@0
   168
jens@0
   169
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
jens@0
   170
{
jens@0
   171
    if( ! [_prototype isKindOfClass: [Piece class]] )
jens@0
   172
        return NSDragOperationNone;
jens@0
   173
    NSPasteboard *pb = [sender draggingPasteboard];
jens@0
   174
    if( [NSImage canInitWithPasteboard: pb] )
jens@0
   175
        return NSDragOperationCopy;
jens@0
   176
    else
jens@0
   177
        return NSDragOperationNone;
jens@0
   178
}
jens@0
   179
jens@0
   180
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
jens@0
   181
{
jens@0
   182
    if( ! [_prototype isKindOfClass: [Piece class]] )
jens@0
   183
        return NO;
jens@11
   184
    CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard],sender);
jens@0
   185
    if( image ) {
jens@0
   186
        [(Piece*)_prototype setImage: image];
jens@0
   187
        self.prototype = _prototype; // recreates _bit
jens@0
   188
        return YES;
jens@0
   189
    } else
jens@0
   190
        return NO;
jens@0
   191
}
jens@0
   192
jens@0
   193
jens@1
   194
#endif
jens@1
   195
jens@0
   196
@end