On Apr 26, 2008, at 08:47, an0 wrote:

Thanks. I've tried NSTrackingArea, and it seems a clearer concept and
easier to use. However, there are still two problems I can't fix:
1. Setting cursor in initWithFrame: and awakeFromNib does not have
effect. So I can't set the initial cursor.
2. Setting cursor together with tracking areas renders the cursor
setting ineffective. I found this from my mouseUp action. With the
code handling tracking areas, [[NSCursor openHandCursor] set] did not
give me an openHandCursor, but an arrowCursor.
-(void)mouseUp:(NSEvent *)event
{
   dragging=NO;

   [self removeTrackingArea:trackingRect];
   self.trackingRect = [[[NSTrackingArea alloc] initWithRect:[self
calculatedItemBounds]

options:NSTrackingCursorUpdate | NSTrackingActiveInActiveApp
                                                       owner:self
userInfo:nil] autorelease];

   [self addTrackingArea:trackingRect];
   [[NSCursor openHandCursor] set];
}

My guess is that the cursor you set is getting changed back to the arrow by the cursorUpdate: method of another view.

IIRC, you have a NSScrollView whose document view (view A) is something like a canvas, and has some smaller subviews (each a view B) that are like graphic objects on the canvas, which you want to be able to drag around. Let's say you want the cursor to be the crosshair cursor inside view A *except* when you're hovering over a B view (open hand cursor) or dragging a B view (closed hand cursor). To achieve this with NSTrackingArea, you could:

-- Create a tracking area for view A using options: NSTrackingCursorUpdate | NSTrackingActiveInActiveApp | NSTrackingInVisibleRect.

-- Create a tracking area for each view B using options: NSTrackingCursorUpdate | NSTrackingActiveInActiveApp | NSTrackingInVisibleRect.

You would do this *only once* for each view. The NSTrackingInVisibleRect option takes care of the housekeeping for you even if the views change size or position or visibleRect.

-- Add a cursorUpdate: override to view A, something like:

-(void)cursorUpdate:(NSEvent *)event
{
        if (<any B view is dragging>)
                [[NSCursor closedHandCursor] set];
        else
                [[NSCursor crosshairCursor] set];
}


-- Add a cursorUpdate: override to view B, something like:

-(void)cursorUpdate:(NSEvent *)event
{
        if (<any B view is dragging>)
                [[NSCursor closedHandCursor] set];
        else
                [[NSCursor openHandCursor] set];
}


-- In the mouseDown: method where you start dragging view B, put:

        dragging = YES;
[[self enclosingScrollView] setDocumentCursor:[NSCursor closedHandCursor]];

-- In the mouseUp: method where you stop dragging view B, put:

        dragging = NO;
[[self enclosingScrollView] setDocumentCursor:[NSCursor arrowCursor]];

I may have overlooked something, but I think is is all the cursor- handling code you would need.

(Well, if you have multiple windows with A views in them, or multiple A views in a window, or other kinds of views that use NSTrackingArea with the NSTrackingActiveInActiveApp option to control the cursor, this scheme isn't going to work properly. You could use NSTrackingActiveInKeyWindow or NSTrackingActiveWhenFirstResponder instead of NSTrackingActiveInActiveApp, perhaps, otherwise you'll have to do something application-wide to force the other views to leave the cursor alone during the drag.)

Note that if your mouse pointer goes outside the scroll view during a drag, the cursor may get changed by whatever view is under the mouse (e.g. a text field). I don't think there's much you can do about it if you don't own those views.

Note also that the cursorUpdate event is a bit strange. When the cursor enters a particular tracking area's bounds, the cursorEvent is not sent to the tracking area's owner (like mouseEntered/mouseExited are), and it's not sent to the view that the tracking area was installed into. It's sent to the topmost view under the mouse pointer, whatever that may happen to be.

HTH


_______________________________________________

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]

Reply via email to