On Sun, Apr 27, 2008 at 3:34 PM, Quincey Morris <[EMAIL PROTECTED]> wrote: > > On Apr 26, 2008, at 23:14, an0 wrote: > Setting a cursor always "works", but is useless if something else changes > it immediately afterwards. I think that might be what's happening here. > (Also, if view comes from a NIB, initWithCoder may be called instead of > initWithFrame.) "What's happening here" is exactly what I want to know. I think awakeFromNib should set the scene no matter initWithCoder or initWithFrame is called, so I do my initialization in awakeFromNib.
> I think you have 2 separate cursor management problems to solve: > > 1. When not dragging. Tracking areas may be useful, even if the items are > not subviews. You should have a cursorUpdate method, otherwise some default > implementation of it may keep changing the cursor on you. The cursorUpdate > event will tell you which NSTrackingArea is involved, so you can use that to > work out how to choose the cursor. > > 2. When dragging. Tracking areas don't matter, because (presumably) you > just want to force a single cursor wherever the mouse goes. Your > cursorUpdate method needs to take the dragging state into account. As I said > before, you may not be able to control the cursor completely, when it is > *outside* your view during a drag. What you said is exactly what I've done. > If you change the NSTrackingArea at mouseUp, you should probably specify > the NSTrackingAssumeInside option too, since (presumably) you are placing > the tracking area so that the mouse is actually inside. (The documentation > for this option is almost completely wrong. See the Leopard developer > release notes if you want the correct description.) I've appended NSTrackingAssumeInside option as you advise, but the misbehavior remains. At this point, I think it is more convenient if I make my code available, so that you can know better what I am trying to achieve and find what I've done inappropriately and revise it accordingly. Thank you for your time in advance. The code is simple and short. DraggableItemView.h: #import <Cocoa/Cocoa.h> @interface DraggableItemView : NSView { NSPoint location; NSTrackingArea *trackingRect; // private variables that track state BOOL dragging; BOOL inTrackingRect; NSPoint lastDragLocation; } @property(retain) NSTrackingArea *trackingRect; // ----------------------------------- // Modify the Rectange location // ----------------------------------- - (void)offsetLocationByX:(float)x andY:(float)y; -(IBAction)setItemPropertiesToDefault:(id)sender; // ----------------------------------- // Various Accessor Methods // ----------------------------------- - (void)setLocation:(NSPoint)point; - (NSPoint)location; - (NSRect)calculatedItemBounds; - (BOOL)isPointInItem:(NSPoint)testPoint; @end DraggableItemView.m: #import "DraggableItemView.h" @implementation DraggableItemView @synthesize trackingRect; - (void)awakeFromNib { [self setItemPropertiesToDefault:self]; } - (void)dealloc { [trackingRect release]; [super dealloc]; } // ----------------------------------- // Draw the View Content // ----------------------------------- - (void)drawRect:(NSRect)rect { // erase the background by drawing white [[NSColor whiteColor] setFill]; [NSBezierPath fillRect:rect]; // set the current color for the draggable item [[NSColor redColor] setFill]; // draw the draggable item [NSBezierPath fillRect:[self calculatedItemBounds]]; } - (BOOL)isOpaque { return YES; } // ----------------------------------- // Modify the item location // ----------------------------------- - (void)offsetLocationByX:(float)x andY:(float)y { // tell the display to redraw the old rect [self setNeedsDisplayInRect:[self calculatedItemBounds]]; // since the offset can be generated by both mouse moves // and moveUp:, moveDown:, etc.. actions, we'll invert // the deltaY amount based on if the view is flipped or // not. int invertDeltaY = [self isFlipped] ? -1: 1; location.x=location.x+x; location.y=location.y+y*invertDeltaY; // invalidate the new rect location so that it'll // be redrawn [self setNeedsDisplayInRect:[self calculatedItemBounds]]; } // ----------------------------------- // Hit test the item // ----------------------------------- - (BOOL)isPointInItem:(NSPoint)testPoint { BOOL itemHit=NO; // test first if we're in the rough bounds itemHit = NSPointInRect(testPoint,[self calculatedItemBounds]); // yes, lets further refine the testing if (itemHit) { } return itemHit; } // ----------------------------------- // Handle Mouse Events // ----------------------------------- -(void)mouseDown:(NSEvent *)event { NSPoint clickLocation; BOOL itemHit=NO; // convert the click location into the view coords clickLocation = [self convertPoint:[event locationInWindow] fromView:nil]; // did the click occur in the item? itemHit = [self isPointInItem:clickLocation]; // Yes it did, note that we're starting to drag if (itemHit) { // flag the instance variable that indicates // a drag was actually started dragging=YES; // store the starting click location; lastDragLocation=clickLocation; // set the cursor to the closed hand cursor // for the duration of the drag [[NSCursor closedHandCursor] set]; } } -(void)mouseDragged:(NSEvent *)event { if (dragging) { NSPoint newDragLocation=[self convertPoint:[event locationInWindow] fromView:nil]; // offset the pill by the change in mouse movement // in the event [self offsetLocationByX:(newDragLocation.x-lastDragLocation.x) andY:(newDragLocation.y-lastDragLocation.y)]; // save the new drag location for the next drag event lastDragLocation=newDragLocation; } } -(void)mouseUp:(NSEvent *)event { dragging=NO; [self removeTrackingArea:trackingRect]; self.trackingRect = [[[NSTrackingArea alloc] initWithRect:[self calculatedItemBounds] options:NSTrackingCursorUpdate | NSTrackingActiveInActiveApp | NSTrackingAssumeInside owner:self userInfo:nil] autorelease]; [self addTrackingArea:trackingRect]; [self displayIfNeeded]; [[NSCursor openHandCursor] set]; } // ----------------------------------- // First Responder Methods // ----------------------------------- - (BOOL)acceptsFirstResponder { return YES; } - (IBAction)setItemPropertiesToDefault:(id)sender { [self setLocation:NSMakePoint(0.0,0.0)]; NSTrackingAreaOptions options = NSTrackingCursorUpdate | NSTrackingActiveInActiveApp; NSPoint localPoint = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:nil]; if ([self isPointInItem:localPoint]) { inTrackingRect = YES; options |= NSTrackingAssumeInside; [[NSCursor openHandCursor] set]; } else { inTrackingRect = NO; } if (trackingRect) { [self removeTrackingArea:trackingRect]; } self.trackingRect = [[[NSTrackingArea alloc] initWithRect:[self calculatedItemBounds] options:options owner:self userInfo:nil] autorelease]; [self addTrackingArea:trackingRect]; } -(void)cursorUpdate:(NSEvent *)event { if (dragging) { return; } if (!inTrackingRect) { [[NSCursor openHandCursor] set]; } else { [[NSCursor arrowCursor] set]; } inTrackingRect = !inTrackingRect; } - (void)setLocation:(NSPoint)point { // test to see if the point actually changed if (!NSEqualPoints(point,location)) { // tell the display to redraw the old rect [self setNeedsDisplayInRect:[self calculatedItemBounds]]; // reassign the rect location=point; // display the new rect [self setNeedsDisplayInRect:[self calculatedItemBounds]]; } } - (NSPoint)location { return location; } - (NSRect)calculatedItemBounds { NSRect calculatedRect; // calculate the bounds of the draggable item // relative to the location calculatedRect.origin=location; calculatedRect.size.width=60.0; calculatedRect.size.height=20.0; return calculatedRect; } @end _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to [EMAIL PROTECTED]