Source/BoardView.m
changeset 4 d781b00f3ed4
parent 0 e9f7ba4718e1
child 5 3ba1f29595c7
     1.1 --- a/Source/BoardView.m	Fri Mar 07 11:43:02 2008 -0800
     1.2 +++ b/Source/BoardView.m	Tue Mar 11 17:09:50 2008 -0700
     1.3 @@ -28,6 +28,11 @@
     1.4  #import "GGBUtils.h"
     1.5  
     1.6  
     1.7 +@interface BoardView ()
     1.8 +- (void) _findDropTarget: (NSPoint)pos;
     1.9 +@end
    1.10 +
    1.11 +
    1.12  @implementation BoardView
    1.13  
    1.14  
    1.15 @@ -137,17 +142,40 @@
    1.16  
    1.17  - (void) mouseDown: (NSEvent*)ev
    1.18  {
    1.19 +    BOOL placing = NO;
    1.20      _dragStartPos = ev.locationInWindow;
    1.21      _dragBit = (Bit*) [self hitTestPoint: _dragStartPos
    1.22                          forLayerMatching: layerIsBit 
    1.23                                    offset: &_dragOffset];
    1.24 -    if( _dragBit ) {
    1.25 -        _dragMoved = NO;
    1.26 -        _dropTarget = nil;
    1.27 -        _oldHolder = _dragBit.holder;
    1.28 -        // Ask holder's and game's permission before dragging:
    1.29 -        if( _oldHolder )
    1.30 -            _dragBit = [_oldHolder canDragBit: _dragBit];
    1.31 +    
    1.32 +    if( ! _dragBit ) {
    1.33 +        // If no bit was clicked, see if it's a BitHolder the game will let the user add a Bit to:
    1.34 +        id<BitHolder> holder = (id<BitHolder>) [self hitTestPoint: _dragStartPos
    1.35 +                                                 forLayerMatching: layerIsBitHolder
    1.36 +                                                           offset: NULL];
    1.37 +        if( holder ) {
    1.38 +            _dragBit = [_game bitToPlaceInHolder: holder];
    1.39 +            if( _dragBit ) {
    1.40 +                _dragOffset.x = _dragOffset.y = 0;
    1.41 +                if( _dragBit.superlayer==nil )
    1.42 +                    _dragBit.position = NSPointToCGPoint([self convertPoint: _dragStartPos fromView: nil]);
    1.43 +                placing = YES;
    1.44 +            }
    1.45 +        }
    1.46 +    }
    1.47 +    
    1.48 +    if( ! _dragBit ) {
    1.49 +        Beep();
    1.50 +        return;
    1.51 +    }
    1.52 +    
    1.53 +    // Clicked on a Bit:
    1.54 +    _dragMoved = NO;
    1.55 +    _dropTarget = nil;
    1.56 +    _oldHolder = _dragBit.holder;
    1.57 +    // Ask holder's and game's permission before dragging:
    1.58 +    if( _oldHolder ) {
    1.59 +        _dragBit = [_oldHolder canDragBit: _dragBit];
    1.60          if( _dragBit && ! [_game canBit: _dragBit moveFrom: _oldHolder] ) {
    1.61              [_oldHolder cancelDragBit: _dragBit];
    1.62              _dragBit = nil;
    1.63 @@ -157,17 +185,25 @@
    1.64              NSBeep();
    1.65              return;
    1.66          }
    1.67 -        // Start dragging:
    1.68 -        _oldSuperlayer = _dragBit.superlayer;
    1.69 -        _oldLayerIndex = [_oldSuperlayer.sublayers indexOfObjectIdenticalTo: _dragBit];
    1.70 -        _oldPos = _dragBit.position;
    1.71 -        ChangeSuperlayer(_dragBit, self.layer, self.layer.sublayers.count);
    1.72 -        _dragBit.pickedUp = YES;
    1.73 -        [[NSCursor closedHandCursor] push];
    1.74 -    } else
    1.75 -        NSBeep();
    1.76 +    }
    1.77 +    
    1.78 +    // Start dragging:
    1.79 +    _oldSuperlayer = _dragBit.superlayer;
    1.80 +    _oldLayerIndex = [_oldSuperlayer.sublayers indexOfObjectIdenticalTo: _dragBit];
    1.81 +    _oldPos = _dragBit.position;
    1.82 +    ChangeSuperlayer(_dragBit, self.layer, self.layer.sublayers.count);
    1.83 +    _dragBit.pickedUp = YES;
    1.84 +    [[NSCursor closedHandCursor] push];
    1.85 +    
    1.86 +    if( placing ) {
    1.87 +        if( _oldSuperlayer )
    1.88 +            _dragBit.position = NSPointToCGPoint([self convertPoint: _dragStartPos fromView: nil]);
    1.89 +        _dragMoved = YES;
    1.90 +        [self _findDropTarget: _dragStartPos];
    1.91 +    }
    1.92  }
    1.93  
    1.94 +
    1.95  - (void) mouseDragged: (NSEvent*)ev
    1.96  {
    1.97      if( _dragBit ) {
    1.98 @@ -192,28 +228,37 @@
    1.99          [CATransaction commit];
   1.100  
   1.101          // Find what it's over:
   1.102 -        id<BitHolder> target = (id<BitHolder>) [self hitTestPoint: where
   1.103 -                                                 forLayerMatching: layerIsBitHolder
   1.104 -                                                           offset: NULL];
   1.105 -        if( target == _oldHolder )
   1.106 -            target = nil;
   1.107 -        if( target != _dropTarget ) {
   1.108 -            [_dropTarget willNotDropBit: _dragBit];
   1.109 -            _dropTarget.highlighted = NO;
   1.110 -            _dropTarget = nil;
   1.111 -        }
   1.112 -        if( target ) {
   1.113 -            CGPoint targetPos = [(CALayer*)target convertPoint: _dragBit.position
   1.114 -                                                     fromLayer: _dragBit.superlayer];
   1.115 -            if( [target canDropBit: _dragBit atPoint: targetPos]
   1.116 -               && [_game canBit: _dragBit moveFrom: _oldHolder to: target] ) {
   1.117 -                _dropTarget = target;
   1.118 -                _dropTarget.highlighted = YES;
   1.119 -            }
   1.120 +        [self _findDropTarget: pos];
   1.121 +    }
   1.122 +}
   1.123 +
   1.124 +
   1.125 +- (void) _findDropTarget: (NSPoint)locationInWindow
   1.126 +{
   1.127 +    locationInWindow.x += _dragOffset.x;
   1.128 +    locationInWindow.y += _dragOffset.y;
   1.129 +    id<BitHolder> target = (id<BitHolder>) [self hitTestPoint: locationInWindow
   1.130 +                                             forLayerMatching: layerIsBitHolder
   1.131 +                                                       offset: NULL];
   1.132 +    if( target == _oldHolder )
   1.133 +        target = nil;
   1.134 +    if( target != _dropTarget ) {
   1.135 +        [_dropTarget willNotDropBit: _dragBit];
   1.136 +        _dropTarget.highlighted = NO;
   1.137 +        _dropTarget = nil;
   1.138 +    }
   1.139 +    if( target ) {
   1.140 +        CGPoint targetPos = [(CALayer*)target convertPoint: _dragBit.position
   1.141 +                                                 fromLayer: _dragBit.superlayer];
   1.142 +        if( [target canDropBit: _dragBit atPoint: targetPos]
   1.143 +           && [_game canBit: _dragBit moveFrom: _oldHolder to: target] ) {
   1.144 +            _dropTarget = target;
   1.145 +            _dropTarget.highlighted = YES;
   1.146          }
   1.147      }
   1.148  }
   1.149  
   1.150 +
   1.151  - (void) mouseUp: (NSEvent*)ev
   1.152  {
   1.153      if( _dragBit ) {
   1.154 @@ -233,9 +278,13 @@
   1.155              } else {
   1.156                  // Nope, cancel:
   1.157                  [_dropTarget willNotDropBit: _dragBit];
   1.158 -                ChangeSuperlayer(_dragBit, _oldSuperlayer, _oldLayerIndex);
   1.159 -                _dragBit.position = _oldPos;
   1.160 -                [_oldHolder cancelDragBit: _dragBit];
   1.161 +                if( _oldSuperlayer ) {
   1.162 +                    ChangeSuperlayer(_dragBit, _oldSuperlayer, _oldLayerIndex);
   1.163 +                    _dragBit.position = _oldPos;
   1.164 +                    [_oldHolder cancelDragBit: _dragBit];
   1.165 +                } else {
   1.166 +                    [_dragBit removeFromSuperlayer];
   1.167 +                }
   1.168              }
   1.169          } else {
   1.170              // Just a click, without a drag: