Source/Stack.m
author Jens Alfke <jens@mooseyard.com>
Sun Feb 06 16:31:03 2011 -0800 (2011-02-06)
changeset 29 0b1c315ffc64
parent 1 3eb7be1dd7b6
permissions -rw-r--r--
Minor compiler-compatibility fixes.
     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 "Stack.h"
    24 #import "QuartzUtils.h"
    25 
    26 
    27 @implementation Stack
    28 
    29 
    30 - (id) initWithStartPos: (CGPoint)startPos spacing: (CGSize)spacing
    31            wrapInterval: (int)wrapInterval wrapSpacing: (CGSize)wrapSpacing
    32 {
    33     self = [super init];
    34     if (self != nil) {
    35         _startPos = startPos;
    36         _spacing = spacing;
    37         _wrapInterval = wrapInterval;
    38         _wrapSpacing = wrapSpacing;
    39         self.cornerRadius = 8;
    40         self.backgroundColor = kAlmostInvisibleWhiteColor;
    41         self.borderColor = kHighlightColor;
    42         _bits = [[NSMutableArray alloc] init];
    43     }
    44     return self;
    45 }
    46 
    47 - (id) initWithStartPos: (CGPoint)startPos spacing: (CGSize)spacing;
    48 {
    49     return [self initWithStartPos: startPos spacing: spacing 
    50                      wrapInterval: INT_MAX wrapSpacing: CGSizeZero];
    51 }
    52 
    53 
    54 - (void) dealloc
    55 {
    56     [_bits release];
    57     [super dealloc];
    58 }
    59 
    60 
    61 @synthesize spacing=_spacing, wrapSpacing=_wrapSpacing, startPos=_startPos, wrapInterval=_wrapInterval;
    62 @synthesize dragAsStacks=_dragAsStacks;
    63 @synthesize bits=_bits;
    64 
    65 
    66 - (NSUInteger) numberOfBits
    67 {
    68     return _bits.count;
    69 }
    70 
    71 - (void) setNumberOfBits: (NSUInteger)n
    72 {
    73     NSAssert2(n<=_bits.count,@"Cannot increase numberOfBits (from %u to %u)", _bits.count,n);
    74     while( _bits.count > n )
    75         [self removeBit: self.topBit];
    76 }
    77 
    78 - (Bit*) topBit
    79 {
    80     return [_bits lastObject];
    81 }
    82 
    83 
    84 - (void) dump
    85 {
    86     printf("Stack = ");
    87     for( GGBLayer *layer in self.sublayers )
    88         printf("%s @z=%g   ", [[layer description] UTF8String],layer.zPosition);
    89     printf("\n");
    90 }
    91 
    92 
    93 - (void) x_repositionBit: (Bit*)bit forIndex: (int)i
    94 {
    95     bit.position = CGPointMake(_startPos.x + _spacing.width *(i%_wrapInterval) + _wrapSpacing.width *(i/_wrapInterval),
    96                                _startPos.y + _spacing.height*(i%_wrapInterval) + _wrapSpacing.height*(i/_wrapInterval));
    97 }
    98 
    99 - (void) addBit: (Bit*)bit
   100 {
   101     if( [bit isKindOfClass: [DraggedStack class]] ) {
   102         for( Bit *subBit in [(DraggedStack*)bit bits] )
   103             [self addBit: subBit];
   104     } else {
   105         int n = _bits.count;
   106         [_bits addObject: bit];
   107         ChangeSuperlayer(bit, self, n);
   108         [self x_repositionBit: bit forIndex: n];
   109     }
   110 }
   111 
   112 
   113 - (void) removeBit: (Bit*)bit
   114 {
   115     NSUInteger index = [_bits indexOfObjectIdenticalTo: bit];
   116     if( index != NSNotFound ) {
   117         [bit removeFromSuperlayer];
   118         [_bits removeObjectAtIndex: index];
   119     }
   120 }
   121 
   122 
   123 - (void) setHighlighted: (BOOL)highlighted
   124 {
   125     [super setHighlighted: highlighted];
   126     self.borderWidth = (highlighted ?6 :0);
   127 }
   128 
   129 
   130 - (Bit*) canDragBit: (Bit*)bit
   131 {
   132     NSInteger index = [_bits indexOfObjectIdenticalTo: bit];
   133     if( index==NSNotFound )
   134         return nil;
   135     if( _dragAsStacks && index < _bits.count-1 ) {
   136         // Move bit and those above it into a temporary DraggedStack:
   137         NSRange r = NSMakeRange(index,_bits.count-index);
   138         NSArray *bitsToDrag = [_bits subarrayWithRange: r];
   139         [_bits removeObjectsInRange: r];
   140         DraggedStack *stack = [[DraggedStack alloc] initWithBits: bitsToDrag];
   141         [self addSublayer: stack];
   142         [stack release];
   143         stack.anchorPoint = CGPointMake( bit.position.x/stack.bounds.size.width,
   144                                          bit.position.y/stack.bounds.size.height );
   145         stack.position = bit.position;
   146         return stack;
   147     } else {
   148         [bit retain];
   149         [_bits removeObjectIdenticalTo: bit];
   150         return [bit autorelease];
   151     }
   152 }
   153 
   154 
   155 - (void) cancelDragBit: (Bit*)bit
   156 {
   157     [self addBit: bit];
   158     if( [bit isKindOfClass: [DraggedStack class]] ) {
   159         [bit removeFromSuperlayer];
   160     }
   161 }
   162 
   163 
   164 - (void) draggedBit: (Bit*)bit to: (id<BitHolder>)dst
   165 {
   166     int i=0;
   167     for( Bit *bit in self.sublayers )
   168         [self x_repositionBit: bit forIndex: i++];
   169 }
   170 
   171 
   172 - (BOOL) dropBit: (Bit*)bit atPoint: (CGPoint)point
   173 {
   174     [self addBit: bit];
   175     return YES;
   176 }
   177 
   178 @end
   179 
   180 
   181 
   182 
   183 @implementation DraggedStack
   184 
   185 
   186 - (id) initWithBits: (NSArray*)bits
   187 {
   188     self = [super init];
   189     if( self ) {
   190         CGRect bounds = CGRectZero;
   191         for( Bit *bit in bits ) {
   192             bounds = CGRectUnion(bounds, bit.frame);
   193             [self addSublayer: bit];
   194         }
   195         self.bounds = bounds;
   196         self.anchorPoint = CGPointZero;
   197         self.position = CGPointZero;
   198     }
   199     return self;
   200 }
   201 
   202 - (NSArray*) bits
   203 {
   204     return [self.sublayers.copy autorelease];
   205 }
   206 
   207 @end