Subclassing NSScrollView drawRect: Method

心已入冬 提交于 2019-12-05 14:49:31

As ughoavgfhw noted, NSScrollView doesn't usually do any drawing, and probably has a weird interaction with its child views in that way. I'd suggest putting something like the following in your text view's drawing code to draw this custom focus ring that you want*:

// We're going to be modifying the state for this, 
// so allow it to be restored later
[NSGraphicsContext saveGraphicsState];

// Choose the correct color; isFirstResponder is a custom     
// ivar set in becomeFirstResponder and resignFirstResponder
if( isFirstResponder && [[self window] isKeyWindow]){
    [myFocusedColor set];
} 
else {
    [myNotFocusedColor set];
}

// Create two rects, one slightly outset from the bounds,
// one slightly inset
NSRect bounds = [self bounds];
NSRect innerRect = NSInsetRect(bounds, 2, 2);
NSRect outerRect = NSMakeRect(bounds.origin.x - 2, 
                              bounds.origin.y - 2,
                              bounds.size.width + 4,
                              bounds.size.height + 4);

// Create a bezier path using those two rects; this will
// become the clipping path of the context
NSBezierPath * clipPath = [NSBezierPath bezierPathWithRect:outerRect];
[clipPath appendBezierPath:[NSBezierPath bezierPathWithRect:innerRect]];

// Change the current clipping path of the context to 
// the enclosed area of clipPath; "enclosed" defined by 
// winding rule. Drawing will be restricted to this area.
// N.B. that the winding rule makes the order that the
// rects were added to the path important.
[clipPath setWindingRule:NSEvenOddWindingRule];
[clipPath setClip];
// Fill the rect; drawing is clipped and the inner rect
// is not drawn in
[[NSBezierPath bezierPathWithRect:outerRect] fill];
[NSGraphicsContext restoreGraphicsState];

This should be a reasonable approximation of what AppKit does when it draws a focus ring. Of course, AppKit is sort of allowed to draw outside a view's bounds -- I can't guarantee that this is completely safe, but you seem to get a margin of 3 px to play with. You could draw the ring entirely inside the bounds if you wanted. A true focus ring extends slightly (2 px) inside the view anyways (as I've done here).

Apple docs on Setting the Clipping Region.

EDIT: After re-reading your comments on the question, I realize I may have long-winded-ly buried the real answer. Try either subclassing NSClipView and switching your scroll view's clip view for that, or using a custom view for the document view.


*: You could also put this in the drawing code of a custom view subclass which is set as the document view of the NSScrollView; then your text view could be a subview of that. Or substitute a custom NSClipView subclass.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!