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: