diff -r e9f7ba4718e1 -r d781b00f3ed4 Source/BoardView.m --- a/Source/BoardView.m Fri Mar 07 11:43:02 2008 -0800 +++ b/Source/BoardView.m Tue Mar 11 17:09:50 2008 -0700 @@ -28,6 +28,11 @@ #import "GGBUtils.h" +@interface BoardView () +- (void) _findDropTarget: (NSPoint)pos; +@end + + @implementation BoardView @@ -137,17 +142,40 @@ - (void) mouseDown: (NSEvent*)ev { + BOOL placing = NO; _dragStartPos = ev.locationInWindow; _dragBit = (Bit*) [self hitTestPoint: _dragStartPos forLayerMatching: layerIsBit offset: &_dragOffset]; - if( _dragBit ) { - _dragMoved = NO; - _dropTarget = nil; - _oldHolder = _dragBit.holder; - // Ask holder's and game's permission before dragging: - if( _oldHolder ) - _dragBit = [_oldHolder canDragBit: _dragBit]; + + if( ! _dragBit ) { + // If no bit was clicked, see if it's a BitHolder the game will let the user add a Bit to: + id holder = (id) [self hitTestPoint: _dragStartPos + forLayerMatching: layerIsBitHolder + offset: NULL]; + if( holder ) { + _dragBit = [_game bitToPlaceInHolder: holder]; + if( _dragBit ) { + _dragOffset.x = _dragOffset.y = 0; + if( _dragBit.superlayer==nil ) + _dragBit.position = NSPointToCGPoint([self convertPoint: _dragStartPos fromView: nil]); + placing = YES; + } + } + } + + if( ! _dragBit ) { + Beep(); + return; + } + + // Clicked on a Bit: + _dragMoved = NO; + _dropTarget = nil; + _oldHolder = _dragBit.holder; + // Ask holder's and game's permission before dragging: + if( _oldHolder ) { + _dragBit = [_oldHolder canDragBit: _dragBit]; if( _dragBit && ! [_game canBit: _dragBit moveFrom: _oldHolder] ) { [_oldHolder cancelDragBit: _dragBit]; _dragBit = nil; @@ -157,17 +185,25 @@ NSBeep(); return; } - // Start dragging: - _oldSuperlayer = _dragBit.superlayer; - _oldLayerIndex = [_oldSuperlayer.sublayers indexOfObjectIdenticalTo: _dragBit]; - _oldPos = _dragBit.position; - ChangeSuperlayer(_dragBit, self.layer, self.layer.sublayers.count); - _dragBit.pickedUp = YES; - [[NSCursor closedHandCursor] push]; - } else - NSBeep(); + } + + // Start dragging: + _oldSuperlayer = _dragBit.superlayer; + _oldLayerIndex = [_oldSuperlayer.sublayers indexOfObjectIdenticalTo: _dragBit]; + _oldPos = _dragBit.position; + ChangeSuperlayer(_dragBit, self.layer, self.layer.sublayers.count); + _dragBit.pickedUp = YES; + [[NSCursor closedHandCursor] push]; + + if( placing ) { + if( _oldSuperlayer ) + _dragBit.position = NSPointToCGPoint([self convertPoint: _dragStartPos fromView: nil]); + _dragMoved = YES; + [self _findDropTarget: _dragStartPos]; + } } + - (void) mouseDragged: (NSEvent*)ev { if( _dragBit ) { @@ -192,28 +228,37 @@ [CATransaction commit]; // Find what it's over: - id target = (id) [self hitTestPoint: where - forLayerMatching: layerIsBitHolder - offset: NULL]; - if( target == _oldHolder ) - target = nil; - if( target != _dropTarget ) { - [_dropTarget willNotDropBit: _dragBit]; - _dropTarget.highlighted = NO; - _dropTarget = nil; - } - if( target ) { - CGPoint targetPos = [(CALayer*)target convertPoint: _dragBit.position - fromLayer: _dragBit.superlayer]; - if( [target canDropBit: _dragBit atPoint: targetPos] - && [_game canBit: _dragBit moveFrom: _oldHolder to: target] ) { - _dropTarget = target; - _dropTarget.highlighted = YES; - } + [self _findDropTarget: pos]; + } +} + + +- (void) _findDropTarget: (NSPoint)locationInWindow +{ + locationInWindow.x += _dragOffset.x; + locationInWindow.y += _dragOffset.y; + id target = (id) [self hitTestPoint: locationInWindow + forLayerMatching: layerIsBitHolder + offset: NULL]; + if( target == _oldHolder ) + target = nil; + if( target != _dropTarget ) { + [_dropTarget willNotDropBit: _dragBit]; + _dropTarget.highlighted = NO; + _dropTarget = nil; + } + if( target ) { + CGPoint targetPos = [(CALayer*)target convertPoint: _dragBit.position + fromLayer: _dragBit.superlayer]; + if( [target canDropBit: _dragBit atPoint: targetPos] + && [_game canBit: _dragBit moveFrom: _oldHolder to: target] ) { + _dropTarget = target; + _dropTarget.highlighted = YES; } } } + - (void) mouseUp: (NSEvent*)ev { if( _dragBit ) { @@ -233,9 +278,13 @@ } else { // Nope, cancel: [_dropTarget willNotDropBit: _dragBit]; - ChangeSuperlayer(_dragBit, _oldSuperlayer, _oldLayerIndex); - _dragBit.position = _oldPos; - [_oldHolder cancelDragBit: _dragBit]; + if( _oldSuperlayer ) { + ChangeSuperlayer(_dragBit, _oldSuperlayer, _oldLayerIndex); + _dragBit.position = _oldPos; + [_oldHolder cancelDragBit: _dragBit]; + } else { + [_dragBit removeFromSuperlayer]; + } } } else { // Just a click, without a drag: