Questions regarding NSRect...In the Hillegass book we are creating an NSRect into which we are drawing an oval (NSBezierPath *). Depending on where in our view we mouse down and subsequently drag, the NSRect's size.width and/or size.height may be negative (i.e. if we start in upper right, drag lower left - both are negative). When actually drawing, does the system use our negative width and/or height to merely locate the NSPoint of where we dragged? Thus updating the NSRect? And if we ever need the size of the NSRect, should we just use the absolute values?
In the chapter, the authors used the MIN() and MAX() macros to create an NSRect. However, in the challenge solution they provide these three methods in response to mouse events:
- (void)mouseDown:(NSEvent *)theEvent
{
NSPoint pointInView = [self convertPoint:[theEvent locationInWindow] fromView:nil];
// Why do we offset by 0.5? Because lines drawn exactly on the .0 will end up spread over two pixels.
workingOval = NSMakeRect(pointInView.x + 0.5, pointInView.y + 0.5, 0, 0);
[self setNeedsDisplay:YES];
}
- (void)mouseDragged:(NSEvent *)theEvent
{
NSPoint pointInView = [self convertPoint:[theEvent locationInWindow] fromView:nil];
workingOval.size.width = pointInView.x - (workingOval.origin.x - 0.5);
workingOval.size.height = pointInView.y - (workingOval.origin.y - 0.5);
[self setNeedsDisplay:YES];
}
- (void)mouseUp:(NSEvent *)theEvent
{
[[self document] addOvalWithRect:workingOval];
workingOval = NSZeroRect; // zero rect indicates we are not presently drawing
[self setNeedsDisplay:YES];
}
This code produces a successful rectangle regardless of the potential negative values. I understand that the negative values merely reflect the shift left with respect to the origin ( the point from which we "mouse downed"). What is going on behind the scenes in properly calculating the NSPoint to which we dragged?
An NSRect is just defined as an NSPoint and an NSSize. An NSSize is just defined as a pair of CGFloats, but the documentation says:
In the code you show above, absolutely nothing fancy is going on behind the scenes. You're creating a rectangle (workingOval) that happens to have a negative size or width, and you're not actually using it anywhere.
Depending on what you do with workingOval elsewhere, what's going on behind the scenes will be different. But it'll be one of three very simple things. Some methods treat a rect like (origin=(30, 40), size=(-10, -20)) as identical to (origin=(20, 20), size=(10, 20)); others treat it as an invalid rect; some make assumptions that they don't test and just give you garbage results. For example, NSMinX will return 30, not 10.