Donovan
Donovan

Reputation: 6132

NSTextView caret size sometimes ignored

I'm changing the caret size using - (void)drawInsertionPointInRect:(NSRect)aRect color:(NSColor *)aColor turnedOn:(BOOL)flag. Anyway, when I move selection, the caret momentarily changes back to its default size.

Is there another method that draws the caret that I need to override?

What I'm currently doing:

- (void)drawInsertionPointInRect:(NSRect)aRect color:(NSColor *)aColor turnedOn:(BOOL)flag {

    aRect.origin.y -= 1;
    aRect.origin.x -= 1;
    aRect.size.width += 1;
    aRect.size.height += 1;

    [super drawInsertionPointInRect:aRect color:aColor turnedOn:flag];

}

Upvotes: 1

Views: 1359

Answers (3)

Shu Suzuki
Shu Suzuki

Reputation: 1184

I had a same problem. Donovan's answer solves it but when I tried to draw "transparent" caret I needed more things to do and I had a solution for it.

I made a blog post for it. http://programming.jugglershu.net/wp/?p=765

The answer for "how to draw thick and transparent caret" is ...

  • Draw transparent caret in _drawInsertionPointInRect:
  • Clear the caret in drawInsertionPointInRect by calling setNeedsDisplay method.

I hope this helps someone who want to do the same thing.

Upvotes: 1

Donovan
Donovan

Reputation: 6132

It seems that the only solution is to override the undocumented method - (void)_drawInsertionPointInRect:(NSRect)aRect color:(NSColor *)color. I was hoping for a better solution, though.

Upvotes: -1

Michael Dautermann
Michael Dautermann

Reputation: 89559

Original Answer:

If you're not doing it already, subclass NSTextView and then implement the drawInsertionPointInRect:color:turnedOn: method yourself to do the fancy caret drawing yourself.

Also pay attention to this line from the documentation:

The focus must be locked on the receiver when this method is invoked. You should not need to invoke this method directly.

Subclassing is the way to go.

More application-specific answer:

Instead of calling into [super drawInsertionPointInRect..., consider doing all the drawing yourself.

Something like this:

- (void)drawInsertionPointInRect:(NSRect)rect color:(NSColor *)color turnedOn:(BOOL)flag
{
    //Block Cursor
    if( flag )
    {
        NSPoint aPoint=NSMakePoint( rect.origin.x,rect.origin.y+rect.size.height/2);
        int glyphIndex = [[self layoutManager] glyphIndexForPoint:aPoint inTextContainer:[self textContainer]];
        NSRect glyphRect = [[self layoutManager] boundingRectForGlyphRange:NSMakeRange(glyphIndex, 1)  inTextContainer:[self textContainer]];

        [color set ];
        rect.size.width =rect.size.height/2;
        if(glyphRect.size.width > 0 && glyphRect.size.width < rect.size.width) 
            rect.size.width=glyphRect.size.width;
        NSRectFillUsingOperation( rect, NSCompositePlusDarker);
    } else {
        [self setNeedsDisplayInRect:[self visibleRect] avoidAdditionalLayout:NO];
    }
}

(the code for which I stole from here)

Upvotes: 2

Related Questions