Re: Screen <--> View Coordinate system conversion
Re: Screen <--> View Coordinate system conversion
- Subject: Re: Screen <--> View Coordinate system conversion
- From: Graham Cox <email@hidden>
- Date: Sat, 16 Jan 2016 16:31:30 +1100
> On 16 Jan 2016, at 4:10 PM, Ken Thomases <email@hidden> wrote:
>
> NSView* view1 = /* ... */;
> NSRect rect = /* some rect in view1's internal coordinate space (relative to its bounds, not its frame) */;
> NSView* view2 = /* some view in another window */;
>
> rect = [view1 convertRect:rect toView:nil];
> rect = [view1.window convertRectToScreen:rect];
> rect = [view2.window convertRectFromScreen:rect];
> rect = [view2 convertRect:rect fromView:nil];
>
> rect is now in view2's internal coordinate space.
>
> Regards,
> Ken
>
Thanks Ken, this is exactly what I have - I changed to use -convertRect:toView:nil as Roland suggested rather than worrying about the backing.
The rect I convert is the bounds of view1. When I’m done converting, I set up an NSAffineTransform that translates to the resulting rect’s origin, (and also scales to match the original view, but I’m ignoring scaling until I get the basics working), then concat’s that transform with the current CTM.
So my -drawRect: looks something like this:
-(void) drawRect:(NSRect) dirty
{
NSRect localRect = [self convertBoundsFromAnotherView:view1]; // just the above code, using view1.bounds as the rect
NSAffineTransform* xfm = [NSAffineTransform transform];
[xfm translateXBy:localRect.origin.x yBy:localRect.origin.y]; // ignore scale for now
[NSGraphicsContext saveGraphicsState];
[xfm concat];
/* draw content using coordinate system of original view1 */
[NSGraphicsContext restoreGraphicsState];
}
Turns out, this is actually working - when I draw using the coordinates of view1, it does draw at the correct location.
What isn’t working is correctly setting the dirty rects when part of the view needs to be refreshed. This is what has been leading me astray - because the dirty region is misaligned, the drawing I’m doing is clipped, so it doesn’t appear unless by chance the dirty region does overlap where I’m trying to draw. I discovered this just now, after I posted originally. If I dirty the ENTIRE overlay view, it draws OK, because the whole view is dirty and so there’s no clipping. This *might* be acceptable because the overlay view only draws a few transitory elements, and doesn’t need to worry too much about limiting drawing for performance. But it would be nicer to be able to let -setNeedsDisplayInRect: work as it should.
So the question is how to keep the view aligned to the original view at all necessary times, not just when drawing.
I factored out the transform setting, and tried to do the same in an override of -setNeedsDisplayInRect, but that doesn’t seem to do it - it works slightly better, but there’s still clipping preventing correct drawing.
Is there a better place or better method to set up the overlay’s coordinate system so it is valid at all necessary times? There are the methods -translateOriginToPoint:, -setBoundsOrigin:, -scaleUnitSquareToSize: and so on - these seem likely candidates, but I’m no sure quite where to set these up. I’ll experiment…
—Graham
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden