tags:

views:

616

answers:

1

I have question about NSView:

Imagine a Custom View where the mouseDown, mouseDrag and mouseUp methods are overriden so the user can drag a point (NSRect) on the screen. To drag it I need the mouse coordinates relative to the current view. This is not a problem when the parent of the view is the window, but how do I get them when the view is inside another view?

@implementation MyView

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        pointXPosition = 200.0f;
        pointYPosition = 200.0f;

        locked = NO;
    }
    return self;
}

- (void) drawRect:(NSRect)rect {

    NSRect point = NSMakeRect(pointXPosition, pointYPosition, 6.0f, 6.0f);
    [[NSColor redColor] set];
    NSRectFill(point);

}

- (void)mouseDown:(NSEvent *)theEvent {
    NSPoint mousePos = [theEvent locationInWindow];
    NSRect frame = [super frame];
    CGFloat deltaX = mousePos.x - frame.origin.x - pointXPosition;
    CGFloat deltaY = mousePos.y - frame.origin.y - pointYPosition;
    if(sqrtf(deltaX * deltaX + deltaY * deltaY) < 100.0f)
        locked = YES;
}

- (void)mouseUp:(NSEvent *)theEvent {
    locked = NO;
}

- (void)mouseDragged:(NSEvent *)theEvent {

    if(locked) {
        NSPoint mousePos = [theEvent locationInWindow];

        NSRect frame = [super frame];

        CGFloat oldXPos = pointXPosition;
        CGFloat oldYPos = pointYPosition;

        pointXPosition = mousePos.x - frame.origin.x;
        pointYPosition = mousePos.y - frame.origin.y;

        CGFloat rectToDisplayXMin = MIN(oldXPos, pointXPosition);
        CGFloat rectToDisplayYMin = MIN(oldYPos, pointYPosition);

        CGFloat rectWidthToDisplay = MAX(oldXPos, pointXPosition) - rectToDisplayXMin;
        CGFloat rectHeigthToDisplay = MAX(oldYPos, pointYPosition) - rectToDisplayYMin;

        NSRect dirtyRect = NSMakeRect(rectToDisplayXMin,
                                      rectToDisplayYMin,
                                      rectWidthToDisplay + 6.0f,
                                      rectHeigthToDisplay + 6.0f);

        [self setNeedsDisplayInRect:dirtyRect];
    }
}
+5  A: 

You don't need to convert to the local coordinate system manually. You can convert the point to the local coordinate system by sending the convertPoint:fromView: message to your view. Sending nil as the parameter to fromView will convert the point from the view's parent window (wherever that is). You can also send any other view to get the coordinates converted from that space as well:

// convert from the window's coordinate system to the local coordinate system
NSPoint clickPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];

// convert from some other view's cooridinate system
NSPoint otherPoint = [self convertPoint:somePoint fromView:someSuperview];
Jason Coco