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.
     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     BeginDisableAnimations();
    76     self.bit = [self createBit];
    77     CGPoint pos = _bit.position;
    78     _bit.position = CGPointMake(pos.x, pos.y+70);
    79     [self addSublayer: _bit];
    80     EndDisableAnimations();
    81     
    82     _bit.position = pos;
    83 }
    84 
    85 
    86 - (Bit*) prototype
    87 {
    88     return _prototype;
    89 }
    90 
    91 - (void) setPrototype: (Bit*)prototype
    92 {
    93     setObj(&_prototype, prototype);
    94     if( _bit ) {
    95         [_bit removeFromSuperlayer];
    96         self.bit = nil;
    97         if( prototype )
    98             [self x_regenerateCurrentBit];
    99     }
   100 }
   101 
   102 
   103 - (unsigned) quantity
   104 {
   105     return _quantity;
   106 }
   107 
   108 - (void) setQuantity: (unsigned)quantity
   109 {
   110     _quantity = quantity;
   111     if( quantity > 0 && !_bit )
   112         [self x_regenerateCurrentBit];
   113     else if( quantity==0 && _bit ) {
   114         [_bit removeFromSuperlayer];
   115         self.bit = nil;
   116     }
   117 }
   118 
   119 
   120 #pragma mark -
   121 #pragma mark DRAGGING BITS:
   122 
   123 
   124 - (Bit*) canDragBit: (Bit*)bit
   125 {
   126     bit = [super canDragBit: bit];
   127     if( bit==_bit ) {
   128         [[bit retain] autorelease];
   129         self.bit = nil;
   130     }
   131     return bit;
   132 }
   133 
   134 - (void) cancelDragBit: (Bit*)bit
   135 {
   136     if( ! _bit )
   137         self.bit = bit;
   138     else
   139         [bit removeFromSuperlayer];
   140 }
   141 
   142 - (void) draggedBit: (Bit*)bit to: (id<BitHolder>)dst
   143 {
   144     if( --_quantity > 0 )
   145         [self performSelector: @selector(x_regenerateCurrentBit) withObject: nil afterDelay: 0.0];
   146 }
   147 
   148 - (BOOL) canDropBit: (Bit*)bit atPoint: (CGPoint)point  
   149 {
   150     return [bit isEqual: _bit];
   151 }
   152 
   153 - (BOOL) dropBit: (Bit*)bit atPoint: (CGPoint)point
   154 {
   155     [bit removeFromSuperlayer];
   156     return YES;
   157 }
   158 
   159 
   160 #pragma mark -
   161 #pragma mark DRAG-AND-DROP:
   162 
   163 
   164 #if ! TARGET_OS_IPHONE
   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],sender);
   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 #endif
   195 
   196 @end