Day 14: Custom drawing (3)
Yesterday I’ve talked a bit about view geometry and the day before about dirty rectangles. Today I’ll give an example that uses these concepts of dirty areas in a view and bounds. This should also clarify an issue that keeps coming up in forums and mailing lists; weird drawing artifacts when controls are overlapping the view. To demonstrate, we create a simple project; a window with one custom view (stretched to the edges of the window) and we scatter a few random buttons on top if it. Our custom view overrides -drawRect: as below:
- (void)drawRect:(NSRect)dirtyRect
{
[[NSColor redColor] set];
NSFrameRect(dirtyRect);
}
First we resize the window, then click on the buttons; there’ll be a round rectangle around every button. Why is that? The button is clicked and the rectangle of the button gets marked as dirty. The button being semi-transparent, the view below will also have this region marked dirty. Our drawing code will get called after every press and that puts a border around the dirty part of the view (aka the button).
Now this may seem trivial, but it’s the most common reason for bad drawing and it spawns a lot of questions on mailing lists and forums. People often confuse the dirty-rect (the argument to the -drawRect: function) and the bounds of the frame. If we really just want to put a border around the frame, what we need to do is this:
- (void)drawRect:(NSRect)dirtyRect
{
[[NSColor redColor] set];
NSFrameRect([self bounds]);
}
Remember that when we draw, the bounds rectangle is the border of the view as seen from its inner coordinate system.