TextKit_LineNumbers icon indicating copy to clipboard operation
TextKit_LineNumbers copied to clipboard

Inserting new line does not add a new line number/change current line

Open mbcoder17 opened this issue 10 years ago • 10 comments

If I press enter to go to a new line, a new line is not created until I begin typing on that line.

mbcoder17 avatar Jul 18 '15 02:07 mbcoder17

Yes, I see the problem. This seems to be a consequence of how the NSLayoutManager's enumerateLineFragmentsForGlyphRange method works. Since there are no characters on the last line, there are no line fragments to draw. I'm not sure how to resolve this easily.

I suppose, one could add code after the enumerateLineFragmentsForGlyphRange call to draw a final line number when the last line is empty. The trick will be to calculate the rectangle in which to draw the final line number.

alldritt avatar Jul 19 '15 17:07 alldritt

@alldritt How would one go about doing that? I am not very familiar with stuff like this, but I love the library.

mbcoder17 avatar Jul 19 '15 18:07 mbcoder17

Hi,

On Jul 19, 2015, at 11:03 AM, mbcoder17 [email protected] wrote:

@alldritt How would one go about doing that? I am not very familiar with stuff like this, but I love the library.

This code in LineNumberLayoutManager.m should do the trick:

  • (void) drawBackgroundForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin { [super drawBackgroundForGlyphRange:glyphsToShow atPoint:origin];

    // Draw line numbers. Note that the background for line number gutter is drawn by the LineNumberTextView class. NSDictionary* atts = @{NSFontAttributeName : [UIFont systemFontOfSize:10.0], NSForegroundColorAttributeName : [UIColor whiteColor]}; __block CGRect gutterRect = CGRectZero; __block NSUInteger paraNumber;

    [self enumerateLineFragmentsForGlyphRange:glyphsToShow usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer *textContainer, NSRange glyphRange, BOOL *stop) { NSRange charRange = [self characterRangeForGlyphRange:glyphRange actualGlyphRange:nil]; NSRange paraRange = [self.textStorage.string paragraphRangeForRange:charRange];

                                   //   Only draw line numbers for the paragraph's first line fragment.  Subsiquent fragments are wrapped portions of the paragraph and don't
                                   //   get the line number.
                                   if (charRange.location == paraRange.location) {
                                       gutterRect = CGRectOffset(CGRectMake(0, rect.origin.y, 40.0, rect.size.height), origin.x, origin.y);
                                       paraNumber = [self _paraNumberForRange:charRange];
                                       NSString* ln = [NSString stringWithFormat:@"%ld", (unsigned long) paraNumber + 1];
                                       CGSize size = [ln sizeWithAttributes:atts];
    
                                       [ln drawInRect:CGRectOffset(gutterRect, CGRectGetWidth(gutterRect) - 4 - size.width, (CGRectGetHeight(gutterRect) - size.height) / 2.0)
                                       withAttributes:atts];
                                   }
                               }];
    

    // Deal with the special case of an empty last line where enumerateLineFragmentsForGlyphRange has no line // fragments to draw. if (NSMaxRange(glyphsToShow) > self.numberOfGlyphs) { NSString* ln = [NSString stringWithFormat:@"%ld", (unsigned long) paraNumber + 2]; CGSize size = [ln sizeWithAttributes:atts];

    gutterRect = CGRectOffset(gutterRect, 0.0, CGRectGetHeight(gutterRect));
    [ln drawInRect:CGRectOffset(gutterRect, CGRectGetWidth(gutterRect) - 4 - size.width, (CGRectGetHeight(gutterRect) - size.height) / 2.0)
    withAttributes:atts];
    

    } }

Cheers -Mark


Mark Alldritt Late Night Software Ltd. www.latenightsw.com 250-380-1725 (888-999-3210)

alldritt avatar Jul 20 '15 18:07 alldritt

Hmmmm, this didn't work for me. When I press enter after a line the next line still doesn't have a line number. After some logging, I don't think the if statement is getting called to begin with.

mbcoder17 avatar Jul 20 '15 23:07 mbcoder17

Hello,

On Jul 20, 2015, at 4:34 PM, mbcoder17 [email protected] wrote:

Hmmmm, this didn't work for me. When I press enter after a line the next line still doesn't have a line number.

I commited the changes to GitHub. You can check out a fresh copy. Its working for me.

Cheers -Mark


Mark Alldritt Late Night Software Ltd. www.latenightsw.com 250-380-1725 (888-999-3210)

alldritt avatar Jul 21 '15 05:07 alldritt

@alldritt Try this to reproduce the issue I'm having. Remove everything in the textview, type something on the first line, then press enter. For me a second line number is not added...

mbcoder17 avatar Jul 21 '15 14:07 mbcoder17

Hi,

On Jul 21, 2015, at 7:47 AM, mbcoder17 [email protected] wrote:

Try this to reproduce the issue I'm having. Remove everything in the textview, type something on the first line, then press enter. For me a second line number is not added…

Fascinating. It seems that drawBackgroundForGlyphRange is not called at all when there are no glyphs to display, and so my code never gets a chance to draw the line number. Some other solution is going to be needed to catch this particular problem-nothing obvious comes to mind.

Cheers -Mark


Mark Alldritt Late Night Software Ltd. www.latenightsw.com 250-380-1725 (888-999-3210)

alldritt avatar Jul 21 '15 16:07 alldritt

Any luck in finding a solution for this??

mbcoder17 avatar Sep 05 '15 14:09 mbcoder17

Hello,

On Sep 5, 2015, at 7:38 AM, Jacob [email protected] wrote:

Any luck in finding a solution for this??

Sorry, no. I’ve been working on other projects and have not devoted any time to this problem.

Cheers -Mark


Mark Alldritt Late Night Software Ltd. www.latenightsw.com 250-380-1725 (888-999-3210)

alldritt avatar Sep 08 '15 19:09 alldritt

I just updated/ran the code and can't reproduce this issue: https://github.com/alldritt/TextKit_LineNumbers/pull/5

dirtyhenry avatar Jan 26 '21 13:01 dirtyhenry