This is DragCoordinator.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "DragCoordinator.h" #import "CardHolder.h" #import "GameCoordinator.h" #import "StackView.h" #import <appkit/View.h> #import <objc/List.h> // Recursivly search through the view hierarchy looking // for a tracking view. static CardHolder *findTrackingView( View * , const NXPoint * ); @implementation DragCoordinator - setTarget:anObject { target = anObject; return self; } - cardDragged:( const NXPoint * )dragPoint { CardHolder *receivingView = findTrackingView([ gameWindow contentView ], dragPoint ); // Handle highlighting. // If you notice very carefully I send messages to the // value nil. Doesn't bother me. Bother you? if( receivingView ) { // We're over a tracking view. // Unhighlight the old tracking view and highlight // the new view--if they're different. if( currentTrackView != receivingView ) { [ currentTrackView trackingHighlighted:NO ]; [ receivingView trackingHighlighted:YES ]; currentTrackView = receivingView; } } else { // We're not over a tracking view. // Unhighlight the old tracking view. [ currentTrackView trackingHighlighted:NO ]; currentTrackView = nil; } return self; } - cardReleased:aCard at:( const NXPoint * )releasePoint { CardHolder *receivingView = findTrackingView([ gameWindow contentView ], releasePoint ); if( receivingView ) { CardHolder *oldHolder = [[ aCard superview ] baseHolder ], *newHolder = [ receivingView baseHolder ]; // Inform the target of the card movement. // It will decide if the move is valid and if so it // will perform the view disconnect/connect. [ target card:aCard movedFrom:oldHolder to:newHolder ]; } else // Card wasn't released over a tracking view. // Beep. NXBeep (); // Unhighlight the previous tracking view. [ currentTrackView trackingHighlighted:NO ]; currentTrackView = nil; return self; } // Hits are tricky things. // If you're moving a card over a stack then the // hitTest: method will return the stack; Hovever, if // there is a card on the stack the hitTest: method // returns the card. Therefore, the view returned // by hitTest: is recursivly searched until the ultimate // goal is reached. // We're looking for a view under the cursor that // is a enabled tracking view. static CardHolder *findTrackingView( View *view, const NXPoint *windowPoint ) { CardHolder *theView = nil, *hitView = [ view hitTest:windowPoint ]; if([ hitView respondsTo:@selector(isTrackingEnabled) ]) if([ hitView isTrackingEnabled ]) theView = hitView; if( !theView ) { do { if( hitView = [ hitView superview ]) { NXRect boundsRect; NXPoint mousePoint = *windowPoint; if([[[ hitView getBounds:&boundsRect ] convertPoint:&mousePoint fromView:nil ] mouse:&mousePoint inRect:&boundsRect ]) if([ hitView respondsTo:@selector(isTrackingEnabled) ]) if([ hitView isTrackingEnabled ]) theView = hitView; } } while( !theView && hitView ); } return theView; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.