Day 13: Custom drawing (2)
Yesterday I said I’d illustrate the idea of dirty rects, but on second thought I think it’s better to first talk about view geometry. As we all know, an NSView has a frame, which is it’s location inside a superview. The bounds of a view is its inner frame. It’s difficult to describe this, so I think and example is the easiest way. Say we have a view and its frame is 10,10,150,100 (x,y,width,height), if we inquire its bounds, it will be 0,0,150,100. Why is this and how is it useful?
When you subclass NSView to do custom drawing you need to be aware of the coordinate system. When your view’s -drawRect: is called you have to know that the coordinate 0,0 (x,y) is in the bottom-left corner. So to repeat; even if your views frame is 10,10,150,100, at the time you draw, 0,0 is in the bottom-left of the view. As your hierarchy of views is drawn, the 0,0 coordinate shifts depending on the current view. This means that no view has to be aware of its position and its superviews while you draw. This will explain tomorrow’s example code which uses bounds instead of frame to give our view a red border.
As said, the origin of a view is in the lower-left corner. This will seem a bit unintuitive probably since we’d expect 0,0 to be in the top-left. Luckily, this change is easily made; you can override -isFlipped to set the origin in the top-left corner instead. If your drawing appears upside-down, this might be worth a try. Be careful though, if your view is flipped and you’re drawing images or text, sometimes it’ll appear upside down. When you can leave 0,0 in the bottom-left, it’s usually advisable to do so.