<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Displaying Line Numbers with NSTextView</title>
	<atom:link href="http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/</link>
	<description>On Mac OS X programming</description>
	<pubDate>Tue, 06 Jan 2009 11:15:15 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
		<item>
		<title>By: Bruce</title>
		<link>http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/#comment-30147</link>
		<dc:creator>Bruce</dc:creator>
		<pubDate>Wed, 12 Nov 2008 17:26:20 +0000</pubDate>
		<guid isPermaLink="false">http://www.noodlesoft.com/blog/?p=137#comment-30147</guid>
		<description>I wanted to add a few methods to your wonderful code that make it easier to navigate through the text.    The 5 methods are as follows, and they are to be added to NoodeLineNumberView.m:

1) physicalLineAtInsertion: returns the physical line in the text document where the insertion point is positioned in the textView.

2) logicalLineAtInsertion: returns the logical line in the textView where the insertion point is positioned in the text view

3) indexOfPhysicalLine: returns the character index of line corresponding to line number.

4) logicalLineIndexAtPhysicalCharacterIndex: returns the index of the  wrapped line of text in the text view corresponding to the physical line index obtained from 3.

5) gotoLine:   uses 3 &#38; 4 to position the insertion point in the text view at the beginning of 


There may be a more optimal way of doing things, but these work on small texts nicely...

Thank you for your line number contribution....

Bruce

Code:
-----------------------------------------------------------
-(unsigned) logicalLineAtInsertion
{
	NSTextView* tview = [self clientView];
	NSLayoutManager *layoutManager = [tview layoutManager];
	NSRange lineRange;
	unsigned numberOfLines, index, numberOfGlyphs = NSMaxRange([layoutManager glyphRangeForCharacterRange:NSMakeRange(0,[tview selectedRange].location) actualCharacterRange:NULL]);
	for (numberOfLines = 0, index = 0; index &#60; numberOfGlyphs; numberOfLines++){
		(void) [layoutManager lineFragmentRectForGlyphAtIndex:index
											   effectiveRange:&#38;lineRange];
		index = NSMaxRange(lineRange);
	}
	
	return numberOfLines;
	
	
	
}



-(unsigned) physicalLineAtInsertion
{
	NSTextView* tview = [self clientView];
	unsigned physical = [self lineNumberForCharacterIndex:[tview selectedRange].location inText:[tview string]] + 1;
	return physical;
	
	
}


-(unsigned) indexOfPhysicalLine:(unsigned) linenumber
{
	
	if (linenumber == 1) return 0;
	NSString *string = [[self clientView] string];
	unsigned numberOfLines, index, stringLength = [string length];
	for (index = 0, numberOfLines = 0; index &#60; stringLength; numberOfLines++)
	{
		index = NSMaxRange([string lineRangeForRange:NSMakeRange(index, 0)]);	
		if (numberOfLines ==  linenumber- 2) break;
	}
	
	return index;
	
	
}

-(unsigned) logicalLineIndexAtPhysicalCharacterIndex:(unsigned) physicalindex
{
	NSTextView* tview = [self clientView];
	NSLayoutManager *layoutManager = [tview layoutManager];
	NSRange lineRange;
	unsigned numberOfLines, index, numberOfGlyphs = NSMaxRange([layoutManager glyphRangeForCharacterRange:NSMakeRange(0,physicalindex) actualCharacterRange:NULL]);
	for (numberOfLines = 0, index = 0; index &#60; numberOfGlyphs; numberOfLines++){
		(void) [layoutManager lineFragmentRectForGlyphAtIndex:index
											   effectiveRange:&#38;lineRange];
		index = NSMaxRange(lineRange);
	}
	
	return index;
	
	
	
}

-(void) gotoLine:(unsigned) lineNumber
{
	
	NSTextView* tview = [self clientView];
	unsigned insertionLocation = [self logicalLineIndexAtPhysicalCharacterIndex:[self indexOfPhysicalLine:lineNumber]];
	[tview setSelectedRange:NSMakeRange(insertionLocation,0)];
	[tview scrollRangeToVisible:NSMakeRange(insertionLocation,0)];
}</description>
		<content:encoded><![CDATA[<p>I wanted to add a few methods to your wonderful code that make it easier to navigate through the text.    The 5 methods are as follows, and they are to be added to NoodeLineNumberView.m:</p>
<p>1) physicalLineAtInsertion: returns the physical line in the text document where the insertion point is positioned in the textView.</p>
<p>2) logicalLineAtInsertion: returns the logical line in the textView where the insertion point is positioned in the text view</p>
<p>3) indexOfPhysicalLine: returns the character index of line corresponding to line number.</p>
<p>4) logicalLineIndexAtPhysicalCharacterIndex: returns the index of the  wrapped line of text in the text view corresponding to the physical line index obtained from 3.</p>
<p>5) gotoLine:   uses 3 &amp; 4 to position the insertion point in the text view at the beginning of </p>
<p>There may be a more optimal way of doing things, but these work on small texts nicely&#8230;</p>
<p>Thank you for your line number contribution&#8230;.</p>
<p>Bruce</p>
<p>Code:<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
-(unsigned) logicalLineAtInsertion<br />
{<br />
	NSTextView* tview = [self clientView];<br />
	NSLayoutManager *layoutManager = [tview layoutManager];<br />
	NSRange lineRange;<br />
	unsigned numberOfLines, index, numberOfGlyphs = NSMaxRange([layoutManager glyphRangeForCharacterRange:NSMakeRange(0,[tview selectedRange].location) actualCharacterRange:NULL]);<br />
	for (numberOfLines = 0, index = 0; index &lt; numberOfGlyphs; numberOfLines++){<br />
		(void) [layoutManager lineFragmentRectForGlyphAtIndex:index<br />
											   effectiveRange:&amp;lineRange];<br />
		index = NSMaxRange(lineRange);<br />
	}</p>
<p>	return numberOfLines;</p>
<p>}</p>
<p>-(unsigned) physicalLineAtInsertion<br />
{<br />
	NSTextView* tview = [self clientView];<br />
	unsigned physical = [self lineNumberForCharacterIndex:[tview selectedRange].location inText:[tview string]] + 1;<br />
	return physical;</p>
<p>}</p>
<p>-(unsigned) indexOfPhysicalLine:(unsigned) linenumber<br />
{</p>
<p>	if (linenumber == 1) return 0;<br />
	NSString *string = [[self clientView] string];<br />
	unsigned numberOfLines, index, stringLength = [string length];<br />
	for (index = 0, numberOfLines = 0; index &lt; stringLength; numberOfLines++)<br />
	{<br />
		index = NSMaxRange([string lineRangeForRange:NSMakeRange(index, 0)]);<br />
		if (numberOfLines ==  linenumber- 2) break;<br />
	}</p>
<p>	return index;</p>
<p>}</p>
<p>-(unsigned) logicalLineIndexAtPhysicalCharacterIndex:(unsigned) physicalindex<br />
{<br />
	NSTextView* tview = [self clientView];<br />
	NSLayoutManager *layoutManager = [tview layoutManager];<br />
	NSRange lineRange;<br />
	unsigned numberOfLines, index, numberOfGlyphs = NSMaxRange([layoutManager glyphRangeForCharacterRange:NSMakeRange(0,physicalindex) actualCharacterRange:NULL]);<br />
	for (numberOfLines = 0, index = 0; index &lt; numberOfGlyphs; numberOfLines++){<br />
		(void) [layoutManager lineFragmentRectForGlyphAtIndex:index<br />
											   effectiveRange:&amp;lineRange];<br />
		index = NSMaxRange(lineRange);<br />
	}</p>
<p>	return index;</p>
<p>}</p>
<p>-(void) gotoLine:(unsigned) lineNumber<br />
{</p>
<p>	NSTextView* tview = [self clientView];<br />
	unsigned insertionLocation = [self logicalLineIndexAtPhysicalCharacterIndex:[self indexOfPhysicalLine:lineNumber]];<br />
	[tview setSelectedRange:NSMakeRange(insertionLocation,0)];<br />
	[tview scrollRangeToVisible:NSMakeRange(insertionLocation,0)];<br />
}</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Will</title>
		<link>http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/#comment-28954</link>
		<dc:creator>Will</dc:creator>
		<pubDate>Fri, 24 Oct 2008 06:09:41 +0000</pubDate>
		<guid isPermaLink="false">http://www.noodlesoft.com/blog/?p=137#comment-28954</guid>
		<description>Sorry, the quality on the youtube video is horrible.  The video did show the line numbers that the lineNumberForLocation: method found each time the mouse was clicked inside the ruler view, which I thought would be helpful, but you can't really see anything with the horrible youtube quality.  I'm open to suggestions for getting it to you or posting it to an alternative site.</description>
		<content:encoded><![CDATA[<p>Sorry, the quality on the youtube video is horrible.  The video did show the line numbers that the lineNumberForLocation: method found each time the mouse was clicked inside the ruler view, which I thought would be helpful, but you can&#8217;t really see anything with the horrible youtube quality.  I&#8217;m open to suggestions for getting it to you or posting it to an alternative site.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Will</title>
		<link>http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/#comment-28953</link>
		<dc:creator>Will</dc:creator>
		<pubDate>Fri, 24 Oct 2008 06:04:50 +0000</pubDate>
		<guid isPermaLink="false">http://www.noodlesoft.com/blog/?p=137#comment-28953</guid>
		<description>Alright, I put together a small video demonstrating the behavior inside my IDE application.  The problem must have something to do with the way I'm using it in my app, because I was unable to replicate the problem in your sample app while viewing the same file.  I should note that the only difference in the layout of the text view (just being a vertical split view), otherwise your code hasn't been altered, which is why I was surprised to see the issue in the first place.  I uploaded the video to youtube, you can find it at http://www.youtube.com/watch?v=HbIIctvGfWo and hopefully it will be done processing by the time you get a chance to look at it.  Youtube probably isn't the best place, but I couldn't think of anything else, if you have another way I can get the video to you, just let me know.  I appreciate you taking a look and if there's anything else I can do to help diagnose the problem just let me know.</description>
		<content:encoded><![CDATA[<p>Alright, I put together a small video demonstrating the behavior inside my IDE application.  The problem must have something to do with the way I&#8217;m using it in my app, because I was unable to replicate the problem in your sample app while viewing the same file.  I should note that the only difference in the layout of the text view (just being a vertical split view), otherwise your code hasn&#8217;t been altered, which is why I was surprised to see the issue in the first place.  I uploaded the video to youtube, you can find it at <a href="http://www.youtube.com/watch?v=HbIIctvGfWo" rel="nofollow">http://www.youtube.com/watch?v=HbIIctvGfWo</a> and hopefully it will be done processing by the time you get a chance to look at it.  Youtube probably isn&#8217;t the best place, but I couldn&#8217;t think of anything else, if you have another way I can get the video to you, just let me know.  I appreciate you taking a look and if there&#8217;s anything else I can do to help diagnose the problem just let me know.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: mr_noodle</title>
		<link>http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/#comment-28905</link>
		<dc:creator>mr_noodle</dc:creator>
		<pubDate>Thu, 23 Oct 2008 18:49:54 +0000</pubDate>
		<guid isPermaLink="false">http://www.noodlesoft.com/blog/?p=137#comment-28905</guid>
		<description>Will: I'm not seeing this. Can you give me a specific recipe or even better, post a movie of it happening?

One thing I did notice is that calculation of the line number from the mouse coordinates could be quicker as it does seem a bit pokey with huge files. But other than that, I'm not seeing any misplaced markers.</description>
		<content:encoded><![CDATA[<p>Will: I&#8217;m not seeing this. Can you give me a specific recipe or even better, post a movie of it happening?</p>
<p>One thing I did notice is that calculation of the line number from the mouse coordinates could be quicker as it does seem a bit pokey with huge files. But other than that, I&#8217;m not seeing any misplaced markers.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Will</title>
		<link>http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/#comment-28853</link>
		<dc:creator>Will</dc:creator>
		<pubDate>Thu, 23 Oct 2008 05:02:52 +0000</pubDate>
		<guid isPermaLink="false">http://www.noodlesoft.com/blog/?p=137#comment-28853</guid>
		<description>Thanks for posting this code, it was exactly what I was looking for and works great even with large amounts of text (I'm using it for a IDE type project).  However, I think I might have found a bug, although it might be a side effect of how you calculate the position for a new marker when the user clicks on the view.  If you scroll quickly through the document with a large number of lines, then click to add a new marker, it won't be added in the correct location.  Successive clicks get the marker closer and closer to where it should be and eventually it shows up in the proper place, while all the previously placed markers remain.  I'm not sure how to go about fixing this, and any suggestions would be welcome.  Thanks again.</description>
		<content:encoded><![CDATA[<p>Thanks for posting this code, it was exactly what I was looking for and works great even with large amounts of text (I&#8217;m using it for a IDE type project).  However, I think I might have found a bug, although it might be a side effect of how you calculate the position for a new marker when the user clicks on the view.  If you scroll quickly through the document with a large number of lines, then click to add a new marker, it won&#8217;t be added in the correct location.  Successive clicks get the marker closer and closer to where it should be and eventually it shows up in the proper place, while all the previously placed markers remain.  I&#8217;m not sure how to go about fixing this, and any suggestions would be welcome.  Thanks again.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jonathan Mitchell</title>
		<link>http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/#comment-28462</link>
		<dc:creator>Jonathan Mitchell</dc:creator>
		<pubDate>Wed, 15 Oct 2008 08:58:13 +0000</pubDate>
		<guid isPermaLink="false">http://www.noodlesoft.com/blog/?p=137#comment-28462</guid>
		<description>Thanks for the 0.4.1 update. Issues resolved. Looking Good.</description>
		<content:encoded><![CDATA[<p>Thanks for the 0.4.1 update. Issues resolved. Looking Good.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: mr_noodle</title>
		<link>http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/#comment-28024</link>
		<dc:creator>mr_noodle</dc:creator>
		<pubDate>Fri, 10 Oct 2008 17:43:19 +0000</pubDate>
		<guid isPermaLink="false">http://www.noodlesoft.com/blog/?p=137#comment-28024</guid>
		<description>Just uploaded a new version with some fixes. Unfortunately, there's an existing display bug with 10.4 which I'll have to investigate more later.

Jonathan: I changed the default font used. The misalignment is a font metrics issue but it seems that using Lucida Grande makes for better alignment and is what XCode uses.</description>
		<content:encoded><![CDATA[<p>Just uploaded a new version with some fixes. Unfortunately, there&#8217;s an existing display bug with 10.4 which I&#8217;ll have to investigate more later.</p>
<p>Jonathan: I changed the default font used. The misalignment is a font metrics issue but it seems that using Lucida Grande makes for better alignment and is what XCode uses.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jonathan Mitchell</title>
		<link>http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/#comment-27768</link>
		<dc:creator>Jonathan Mitchell</dc:creator>
		<pubDate>Tue, 07 Oct 2008 21:14:05 +0000</pubDate>
		<guid isPermaLink="false">http://www.noodlesoft.com/blog/?p=137#comment-27768</guid>
		<description>#2. I deleted the NSBox configuration and recreated it, only for the issue to promptly evaporate! So there may or may not be something there.

#3. This effect is slight I think though visible. Configure two NSTextViews side by side. Call  setFont:[NSFont userFixedPitchFontOfSize:[NSFont smallSystemFontSize]] on one, leave the other as is. Use { as a convenient test character - increase the font. Probably just a result of the different font metrics.
 Or maybe I am just seeing things.

As for #4,  direct draw rect approach seems to work:

- (void)drawRect:(NSRect)rect
{
	[[NSColor colorWithCalibratedWhite: 0.85 alpha: 1.0] set];
	[NSBezierPath fillRect: rect];
	[self drawHashMarksAndLabelsInRect:rect];
}</description>
		<content:encoded><![CDATA[<p>#2. I deleted the NSBox configuration and recreated it, only for the issue to promptly evaporate! So there may or may not be something there.</p>
<p>#3. This effect is slight I think though visible. Configure two NSTextViews side by side. Call  setFont:[NSFont userFixedPitchFontOfSize:[NSFont smallSystemFontSize]] on one, leave the other as is. Use { as a convenient test character - increase the font. Probably just a result of the different font metrics.<br />
 Or maybe I am just seeing things.</p>
<p>As for #4,  direct draw rect approach seems to work:</p>
<p>- (void)drawRect:(NSRect)rect<br />
{<br />
	[[NSColor colorWithCalibratedWhite: 0.85 alpha: 1.0] set];<br />
	[NSBezierPath fillRect: rect];<br />
	[self drawHashMarksAndLabelsInRect:rect];<br />
}</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: mr_noodle</title>
		<link>http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/#comment-27749</link>
		<dc:creator>mr_noodle</dc:creator>
		<pubDate>Tue, 07 Oct 2008 16:51:38 +0000</pubDate>
		<guid isPermaLink="false">http://www.noodlesoft.com/blog/?p=137#comment-27749</guid>
		<description>Jonathan: I'm not seeing #2 &#038; #3. Could you provide screenshots or more details on the configuration? As for #4, I don't want to use undocumented API. I could just override drawRect and draw the background myself. I'll play with it.

Stephane: Thanks for the heads up. Fixed both the typo and the bug (the bug crept in with the last update).

I'm a bit busy at the moment but I'll do another rev in the next couple days.</description>
		<content:encoded><![CDATA[<p>Jonathan: I&#8217;m not seeing #2 &#038; #3. Could you provide screenshots or more details on the configuration? As for #4, I don&#8217;t want to use undocumented API. I could just override drawRect and draw the background myself. I&#8217;ll play with it.</p>
<p>Stephane: Thanks for the heads up. Fixed both the typo and the bug (the bug crept in with the last update).</p>
<p>I&#8217;m a bit busy at the moment but I&#8217;ll do another rev in the next couple days.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: stephane</title>
		<link>http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/#comment-27737</link>
		<dc:creator>stephane</dc:creator>
		<pubDate>Tue, 07 Oct 2008 11:58:05 +0000</pubDate>
		<guid isPermaLink="false">http://www.noodlesoft.com/blog/?p=137#comment-27737</guid>
		<description>Very interesting code. There are 2 remaining issues though:

- typo in the About box: "The view will expand it's width"  it's -&#62; its

- if you enter 100 lines, the gutter correctly expands but if you add or remove lines then you may end up seeing 2 vertical lines on the right of the gutter or just 1.</description>
		<content:encoded><![CDATA[<p>Very interesting code. There are 2 remaining issues though:</p>
<p>- typo in the About box: &#8220;The view will expand it&#8217;s width&#8221;  it&#8217;s -&gt; its</p>
<p>- if you enter 100 lines, the gutter correctly expands but if you add or remove lines then you may end up seeing 2 vertical lines on the right of the gutter or just 1.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
