diff options
author | rowanbeentje <rowan@beent.je> | 2009-04-16 23:21:40 +0000 |
---|---|---|
committer | rowanbeentje <rowan@beent.je> | 2009-04-16 23:21:40 +0000 |
commit | 93bf3137c544b66a84a5a780264abef960f8a1b9 (patch) | |
tree | 9a5a3f9a1bd4712639528a8f26242ea5d6fb0b37 | |
parent | 4051d858d9e189b7c5bd0919e0bf952cb42898b8 (diff) | |
download | sequelpro-93bf3137c544b66a84a5a780264abef960f8a1b9.tar.gz sequelpro-93bf3137c544b66a84a5a780264abef960f8a1b9.tar.bz2 sequelpro-93bf3137c544b66a84a5a780264abef960f8a1b9.zip |
- Implement line numbering for CMTextView:
- Add an implementation of NoodleLineNumberView, by Paul Kim. Slightly tweaked to remove markers.
- Add to CMTextView (to enable it for other CMTextView uses, hook up the scrollView outlet to the containing scroll view)
-rw-r--r-- | Interfaces/English.lproj/Credits.rtf | 2 | ||||
-rw-r--r-- | Interfaces/English.lproj/DBView.xib | 28 | ||||
-rw-r--r-- | Source/CMTextView.h | 4 | ||||
-rw-r--r-- | Source/CMTextView.m | 6 | ||||
-rw-r--r-- | Source/NoodleLineNumberView.h | 60 | ||||
-rw-r--r-- | Source/NoodleLineNumberView.m | 493 | ||||
-rw-r--r-- | sequel-pro.xcodeproj/project.pbxproj | 6 |
7 files changed, 584 insertions, 15 deletions
diff --git a/Interfaces/English.lproj/Credits.rtf b/Interfaces/English.lproj/Credits.rtf index 731fa4d2..2f5301ee 100644 --- a/Interfaces/English.lproj/Credits.rtf +++ b/Interfaces/English.lproj/Credits.rtf @@ -1,7 +1,6 @@ {\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf430 {\fonttbl\f0\fnil\fcharset0 LucidaGrande;} {\colortbl;\red255\green255\blue255;\red25\green25\blue25;\red0\green27\blue199;} -\vieww9000\viewh8400\viewkind0 \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural \f0\b\fs22 \cf2 Current Developers @@ -40,6 +39,7 @@ Jason Hallford\ Carsten Bl\'fcm\ Andrea Salomoni\ Greg Hulands\ +Paul Kim (NoodleLineNumberView)\ \ \b Artwork diff --git a/Interfaces/English.lproj/DBView.xib b/Interfaces/English.lproj/DBView.xib index 60a03b6a..e318b30c 100644 --- a/Interfaces/English.lproj/DBView.xib +++ b/Interfaces/English.lproj/DBView.xib @@ -8,7 +8,6 @@ <string key="IBDocument.HIToolboxVersion">353.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="40"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -175,7 +174,6 @@ </object> <string key="NSFrame">{{1, 1}, {194, 393}}</string> <reference key="NSSuperview" ref="233472824"/> - <reference key="NSNextKeyView" ref="251040077"/> <reference key="NSDocView" ref="251040077"/> <object class="NSColor" key="NSBGColor" id="1024678221"> <int key="NSColorSpace">6</int> @@ -207,7 +205,6 @@ </object> <string key="NSFrameSize">{196, 395}</string> <reference key="NSSuperview" ref="355288374"/> - <reference key="NSNextKeyView" ref="73685676"/> <int key="NSsFlags">530</int> <reference key="NSVScroller" ref="693168867"/> <reference key="NSHScroller" ref="656188692"/> @@ -292,7 +289,6 @@ </object> <string key="NSFrame">{{1, 1}, {194, 123}}</string> <reference key="NSSuperview" ref="298226231"/> - <reference key="NSNextKeyView" ref="347093764"/> <reference key="NSDocView" ref="347093764"/> <reference key="NSBGColor" ref="1024678221"/> <int key="NScvFlags">4</int> @@ -319,7 +315,6 @@ </object> <string key="NSFrame">{{0, 404}, {196, 125}}</string> <reference key="NSSuperview" ref="355288374"/> - <reference key="NSNextKeyView" ref="685057119"/> <int key="NSsFlags">530</int> <reference key="NSVScroller" ref="245346414"/> <reference key="NSHScroller" ref="353686052"/> @@ -1246,7 +1241,6 @@ </object> <string key="NSFrame">{{1, 17}, {625, 289}}</string> <reference key="NSSuperview" ref="22340145"/> - <reference key="NSNextKeyView" ref="715508012"/> <reference key="NSDocView" ref="715508012"/> <reference key="NSBGColor" ref="1024678221"/> <int key="NScvFlags">4</int> @@ -1279,7 +1273,6 @@ </object> <string key="NSFrame">{{1, 0}, {625, 17}}</string> <reference key="NSSuperview" ref="22340145"/> - <reference key="NSNextKeyView" ref="926883367"/> <reference key="NSDocView" ref="926883367"/> <reference key="NSBGColor" ref="1024678221"/> <int key="NScvFlags">4</int> @@ -1288,7 +1281,6 @@ </object> <string key="NSFrame">{{-1, 22}, {627, 307}}</string> <reference key="NSSuperview" ref="220777809"/> - <reference key="NSNextKeyView" ref="16936123"/> <int key="NSsFlags">562</int> <reference key="NSVScroller" ref="943144555"/> <reference key="NSHScroller" ref="456666876"/> @@ -1722,7 +1714,6 @@ </object> <string key="NSFrame">{{1, 17}, {625, 141}}</string> <reference key="NSSuperview" ref="376224367"/> - <reference key="NSNextKeyView" ref="584834515"/> <reference key="NSDocView" ref="584834515"/> <reference key="NSBGColor" ref="1024678221"/> <int key="NScvFlags">4</int> @@ -1755,7 +1746,6 @@ </object> <string key="NSFrame">{{1, 0}, {625, 17}}</string> <reference key="NSSuperview" ref="376224367"/> - <reference key="NSNextKeyView" ref="459548655"/> <reference key="NSDocView" ref="459548655"/> <reference key="NSBGColor" ref="1024678221"/> <int key="NScvFlags">4</int> @@ -1764,7 +1754,6 @@ </object> <string key="NSFrame">{{-1, 22}, {627, 159}}</string> <reference key="NSSuperview" ref="1063281455"/> - <reference key="NSNextKeyView" ref="794929378"/> <int key="NSsFlags">562</int> <reference key="NSVScroller" ref="1019209947"/> <reference key="NSHScroller" ref="328951385"/> @@ -3696,7 +3685,7 @@ <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string> <string key="NSWindowContentMinSize">{256, 191}</string> <object class="NSView" key="NSWindowView" id="586457094"> - <reference key="NSNextResponder"/> + <nil key="NSNextResponder"/> <int key="NSvFlags">256</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -4321,7 +4310,6 @@ </object> </object> <string key="NSFrameSize">{519, 347}</string> - <reference key="NSSuperview"/> </object> <string key="NSScreenRect">{{0, 0}, {1440, 878}}</string> <string key="NSMinSize">{256, 213}</string> @@ -12602,6 +12590,14 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8</string> </object> <int key="connectionID">5406</int> </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">scrollView</string> + <reference key="source" ref="1055190999"/> + <reference key="destination" ref="71560786"/> + </object> + <int key="connectionID">5410</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -20877,7 +20873,7 @@ Y2hhbmdlIHRoZSBvcmRlcg</string> </object> </object> <nil key="sourceID"/> - <int key="maxID">5408</int> + <int key="maxID">5410</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -20925,6 +20921,10 @@ Y2hhbmdlIHRoZSBvcmRlcg</string> <object class="IBPartialClassDescription"> <string key="className">CMTextView</string> <string key="superclassName">NSTextView</string> + <object class="NSMutableDictionary" key="outlets"> + <string key="NS.key.0">scrollView</string> + <string key="NS.object.0">NSScrollView</string> + </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">Source/CMTextView.h</string> diff --git a/Source/CMTextView.h b/Source/CMTextView.h index b9787dfc..55bff15f 100644 --- a/Source/CMTextView.h +++ b/Source/CMTextView.h @@ -22,6 +22,7 @@ // Or mail to <lorenz@textor.ch> #import <Cocoa/Cocoa.h> +#import "NoodleLineNumberView.h" @interface CMTextView : NSTextView { BOOL autoindentEnabled; @@ -29,6 +30,9 @@ BOOL autoindentIgnoresEnter; BOOL autouppercaseKeywordsEnabled; BOOL delBackwardsWasPressed; + NoodleLineNumberView *lineNumberView; + + IBOutlet NSScrollView *scrollView; } - (BOOL) isNextCharMarkedBy:(id)attribute; diff --git a/Source/CMTextView.m b/Source/CMTextView.m index f0f1567c..427c66d1 100644 --- a/Source/CMTextView.m +++ b/Source/CMTextView.m @@ -1277,6 +1277,12 @@ SYNTAX HIGHLIGHTING! autoindentIgnoresEnter = NO; autouppercaseKeywordsEnabled = YES; delBackwardsWasPressed = NO; + + lineNumberView = [[NoodleLineNumberView alloc] initWithScrollView:scrollView]; + [scrollView setVerticalRulerView:lineNumberView]; + [scrollView setHasHorizontalRuler:NO]; + [scrollView setHasVerticalRuler:YES]; + [scrollView setRulersVisible:YES]; } - (void)textStorageDidProcessEditing:(NSNotification *)notification diff --git a/Source/NoodleLineNumberView.h b/Source/NoodleLineNumberView.h new file mode 100644 index 00000000..ca734a56 --- /dev/null +++ b/Source/NoodleLineNumberView.h @@ -0,0 +1,60 @@ +// +// NoodleLineNumberView.h +// Line View Test +// +// Created by Paul Kim on 9/28/08. +// Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import <Cocoa/Cocoa.h> + +@class NoodleLineNumberMarker; + +@interface NoodleLineNumberView : NSRulerView +{ + // Array of character indices for the beginning of each line + NSMutableArray *lineIndices; + NSFont *font; + NSColor *textColor; + NSColor *alternateTextColor; + NSColor *backgroundColor; +} + +- (id)initWithScrollView:(NSScrollView *)aScrollView; + +- (void)setFont:(NSFont *)aFont; +- (NSFont *)font; + +- (void)setTextColor:(NSColor *)color; +- (NSColor *)textColor; + +- (void)setAlternateTextColor:(NSColor *)color; +- (NSColor *)alternateTextColor; + +- (void)setBackgroundColor:(NSColor *)color; +- (NSColor *)backgroundColor; + +- (unsigned)lineNumberForLocation:(float)location; + +@end diff --git a/Source/NoodleLineNumberView.m b/Source/NoodleLineNumberView.m new file mode 100644 index 00000000..c5d76187 --- /dev/null +++ b/Source/NoodleLineNumberView.m @@ -0,0 +1,493 @@ +// +// NoodleLineNumberView.m +// Line View Test +// +// Created by Paul Kim on 9/28/08. +// Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +// This version of the NoodleLineNumberView for Sequel Pro removes marker +// functionality. + +#import "NoodleLineNumberView.h" + +#define DEFAULT_THICKNESS 22.0 +#define RULER_MARGIN 5.0 + +@interface NoodleLineNumberView (Private) + +- (NSMutableArray *)lineIndices; +- (void)invalidateLineIndices; +- (void)calculateLines; +- (unsigned)lineNumberForCharacterIndex:(unsigned)index inText:(NSString *)text; +- (NSDictionary *)textAttributes; + +@end + +@implementation NoodleLineNumberView + +- (id)initWithScrollView:(NSScrollView *)aScrollView +{ + if ((self = [super initWithScrollView:aScrollView orientation:NSVerticalRuler]) != nil) + { + [self setClientView:[aScrollView documentView]]; + } + return self; +} + +- (void)awakeFromNib +{ + [self setClientView:[[self scrollView] documentView]]; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [lineIndices release]; + [font release]; + + [super dealloc]; +} + +- (void)setFont:(NSFont *)aFont +{ + if (font != aFont) + { + [font autorelease]; + font = [aFont retain]; + } +} + +- (NSFont *)font +{ + if (font == nil) + { + return [NSFont labelFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]]; + } + return font; +} + +- (void)setTextColor:(NSColor *)color +{ + if (textColor != color) + { + [textColor autorelease]; + textColor = [color retain]; + } +} + +- (NSColor *)textColor +{ + if (textColor == nil) + { + return [NSColor colorWithCalibratedWhite:0.42 alpha:1.0]; + } + return textColor; +} + +- (void)setAlternateTextColor:(NSColor *)color +{ + if (alternateTextColor != color) + { + [alternateTextColor autorelease]; + alternateTextColor = [color retain]; + } +} + +- (NSColor *)alternateTextColor +{ + if (alternateTextColor == nil) + { + return [NSColor whiteColor]; + } + return alternateTextColor; +} + +- (void)setBackgroundColor:(NSColor *)color +{ + if (backgroundColor != color) + { + [backgroundColor autorelease]; + backgroundColor = [color retain]; + } +} + +- (NSColor *)backgroundColor +{ + return backgroundColor; +} + +- (void)setClientView:(NSView *)aView +{ + id oldClientView; + + oldClientView = [self clientView]; + + if ((oldClientView != aView) && [oldClientView isKindOfClass:[NSTextView class]]) + { + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSTextStorageDidProcessEditingNotification object:[(NSTextView *)oldClientView textStorage]]; + } + [super setClientView:aView]; + if ((aView != nil) && [aView isKindOfClass:[NSTextView class]]) + { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:NSTextStorageDidProcessEditingNotification object:[(NSTextView *)aView textStorage]]; + + [self invalidateLineIndices]; + } +} + +- (NSMutableArray *)lineIndices +{ + if (lineIndices == nil) + { + [self calculateLines]; + } + return lineIndices; +} + +- (void)invalidateLineIndices +{ + [lineIndices release]; + lineIndices = nil; +} + +- (void)textDidChange:(NSNotification *)notification +{ + // Invalidate the line indices. They will be recalculated and recached on demand. + [self invalidateLineIndices]; + + [self setNeedsDisplay:YES]; +} + +- (unsigned)lineNumberForLocation:(float)location +{ + unsigned line, count, index, rectCount, i; + NSRectArray rects; + NSRect visibleRect; + NSLayoutManager *layoutManager; + NSTextContainer *container; + NSRange nullRange; + NSMutableArray *lines; + id view; + + view = [self clientView]; + visibleRect = [[[self scrollView] contentView] bounds]; + + lines = [self lineIndices]; + + location += NSMinY(visibleRect); + + if ([view isKindOfClass:[NSTextView class]]) + { + nullRange = NSMakeRange(NSNotFound, 0); + layoutManager = [view layoutManager]; + container = [view textContainer]; + count = [lines count]; + + for (line = 0; line < count; line++) + { + index = [[lines objectAtIndex:line] unsignedIntValue]; + + rects = [layoutManager rectArrayForCharacterRange:NSMakeRange(index, 0) + withinSelectedCharacterRange:nullRange + inTextContainer:container + rectCount:&rectCount]; + + for (i = 0; i < rectCount; i++) + { + if ((location >= NSMinY(rects[i])) && (location < NSMaxY(rects[i]))) + { + return line + 1; + } + } + } + } + return NSNotFound; +} + +- (void)calculateLines +{ + id view; + + view = [self clientView]; + + if ([view isKindOfClass:[NSTextView class]]) + { + unsigned index, numberOfLines, stringLength, lineEnd, contentEnd; + NSString *text; + float oldThickness, newThickness; + + text = [view string]; + stringLength = [text length]; + [lineIndices release]; + lineIndices = [[NSMutableArray alloc] init]; + + index = 0; + numberOfLines = 0; + + do + { + [lineIndices addObject:[NSNumber numberWithUnsignedInt:index]]; + + index = NSMaxRange([text lineRangeForRange:NSMakeRange(index, 0)]); + numberOfLines++; + } + while (index < stringLength); + + // Check if text ends with a new line. + [text getLineStart:NULL end:&lineEnd contentsEnd:&contentEnd forRange:NSMakeRange([[lineIndices lastObject] unsignedIntValue], 0)]; + if (contentEnd < lineEnd) + { + [lineIndices addObject:[NSNumber numberWithUnsignedInt:index]]; + } + + oldThickness = [self ruleThickness]; + newThickness = [self requiredThickness]; + if (fabs(oldThickness - newThickness) > 1) + { + NSInvocation *invocation; + + // Not a good idea to resize the view during calculations (which can happen during + // display). Do a delayed perform (using NSInvocation since arg is a float). + invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(setRuleThickness:)]]; + [invocation setSelector:@selector(setRuleThickness:)]; + [invocation setTarget:self]; + [invocation setArgument:&newThickness atIndex:2]; + + [invocation performSelector:@selector(invoke) withObject:nil afterDelay:0.0]; + } + } +} + +- (unsigned)lineNumberForCharacterIndex:(unsigned)index inText:(NSString *)text +{ + unsigned left, right, mid, lineStart; + NSMutableArray *lines; + + lines = [self lineIndices]; + + // Binary search + left = 0; + right = [lines count]; + + while ((right - left) > 1) + { + mid = (right + left) / 2; + lineStart = [[lines objectAtIndex:mid] unsignedIntValue]; + + if (index < lineStart) + { + right = mid; + } + else if (index > lineStart) + { + left = mid; + } + else + { + return mid; + } + } + return left; +} + +- (NSDictionary *)textAttributes +{ + return [NSDictionary dictionaryWithObjectsAndKeys: + [self font], NSFontAttributeName, + [self textColor], NSForegroundColorAttributeName, + nil]; +} + +- (float)requiredThickness +{ + unsigned lineCount, digits, i; + NSMutableString *sampleString; + NSSize stringSize; + + lineCount = [[self lineIndices] count]; + digits = (unsigned)log10(lineCount) + 1; + sampleString = [NSMutableString string]; + for (i = 0; i < digits; i++) + { + // Use "8" since it is one of the fatter numbers. Anything but "1" + // will probably be ok here. I could be pedantic and actually find the fattest + // number for the current font but nah. + [sampleString appendString:@"8"]; + } + + stringSize = [sampleString sizeWithAttributes:[self textAttributes]]; + + // Round up the value. There is a bug on 10.4 where the display gets all wonky when scrolling if you don't + // return an integral value here. + return ceilf(MAX(DEFAULT_THICKNESS, stringSize.width + RULER_MARGIN * 2)); +} + +- (void)drawHashMarksAndLabelsInRect:(NSRect)aRect +{ + id view; + NSRect bounds; + + bounds = [self bounds]; + + if (backgroundColor != nil) + { + [backgroundColor set]; + NSRectFill(bounds); + + [[NSColor colorWithCalibratedWhite:0.58 alpha:1.0] set]; + [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMaxX(bounds) - 0/5, NSMinY(bounds)) toPoint:NSMakePoint(NSMaxX(bounds) - 0.5, NSMaxY(bounds))]; + } + + view = [self clientView]; + + if ([view isKindOfClass:[NSTextView class]]) + { + NSLayoutManager *layoutManager; + NSTextContainer *container; + NSRect visibleRect; + NSRange range, glyphRange, nullRange; + NSString *text, *labelText; + unsigned rectCount, index, line, count; + NSRectArray rects; + float ypos, yinset; + NSDictionary *textAttributes, *currentTextAttributes; + NSSize stringSize; + NSMutableArray *lines; + + layoutManager = [view layoutManager]; + container = [view textContainer]; + text = [view string]; + nullRange = NSMakeRange(NSNotFound, 0); + + yinset = [view textContainerInset].height; + visibleRect = [[[self scrollView] contentView] bounds]; + + textAttributes = [self textAttributes]; + + lines = [self lineIndices]; + + // Find the characters that are currently visible + glyphRange = [layoutManager glyphRangeForBoundingRect:visibleRect inTextContainer:container]; + range = [layoutManager characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL]; + + // Fudge the range a tad in case there is an extra new line at end. + // It doesn't show up in the glyphs so would not be accounted for. + range.length++; + + count = [lines count]; + index = 0; + + for (line = [self lineNumberForCharacterIndex:range.location inText:text]; line < count; line++) + { + index = [[lines objectAtIndex:line] unsignedIntValue]; + + if (NSLocationInRange(index, range)) + { + rects = [layoutManager rectArrayForCharacterRange:NSMakeRange(index, 0) + withinSelectedCharacterRange:nullRange + inTextContainer:container + rectCount:&rectCount]; + + if (rectCount > 0) + { + // Note that the ruler view is only as tall as the visible + // portion. Need to compensate for the clipview's coordinates. + ypos = yinset + NSMinY(rects[0]) - NSMinY(visibleRect); + + // Line numbers are internally stored starting at 0 + labelText = [NSString stringWithFormat:@"%d", line + 1]; + + stringSize = [labelText sizeWithAttributes:textAttributes]; + + currentTextAttributes = textAttributes; + + // Draw string flush right, centered vertically within the line + [labelText drawInRect: + NSMakeRect(NSWidth(bounds) - stringSize.width - RULER_MARGIN, + ypos + (NSHeight(rects[0]) - stringSize.height) / 2.0, + NSWidth(bounds) - RULER_MARGIN * 2.0, NSHeight(rects[0])) + withAttributes:currentTextAttributes]; + } + } + if (index > NSMaxRange(range)) + { + break; + } + } + } +} + + +#pragma mark NSCoding methods + +#define NOODLE_FONT_CODING_KEY @"font" +#define NOODLE_TEXT_COLOR_CODING_KEY @"textColor" +#define NOODLE_ALT_TEXT_COLOR_CODING_KEY @"alternateTextColor" +#define NOODLE_BACKGROUND_COLOR_CODING_KEY @"backgroundColor" + +- (id)initWithCoder:(NSCoder *)decoder +{ + if ((self = [super initWithCoder:decoder]) != nil) + { + if ([decoder allowsKeyedCoding]) + { + font = [[decoder decodeObjectForKey:NOODLE_FONT_CODING_KEY] retain]; + textColor = [[decoder decodeObjectForKey:NOODLE_TEXT_COLOR_CODING_KEY] retain]; + alternateTextColor = [[decoder decodeObjectForKey:NOODLE_ALT_TEXT_COLOR_CODING_KEY] retain]; + backgroundColor = [[decoder decodeObjectForKey:NOODLE_BACKGROUND_COLOR_CODING_KEY] retain]; + } + else + { + font = [[decoder decodeObject] retain]; + textColor = [[decoder decodeObject] retain]; + alternateTextColor = [[decoder decodeObject] retain]; + backgroundColor = [[decoder decodeObject] retain]; + } + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)encoder +{ + [super encodeWithCoder:encoder]; + + if ([encoder allowsKeyedCoding]) + { + [encoder encodeObject:font forKey:NOODLE_FONT_CODING_KEY]; + [encoder encodeObject:textColor forKey:NOODLE_TEXT_COLOR_CODING_KEY]; + [encoder encodeObject:alternateTextColor forKey:NOODLE_ALT_TEXT_COLOR_CODING_KEY]; + [encoder encodeObject:backgroundColor forKey:NOODLE_BACKGROUND_COLOR_CODING_KEY]; + } + else + { + [encoder encodeObject:font]; + [encoder encodeObject:textColor]; + [encoder encodeObject:alternateTextColor]; + [encoder encodeObject:backgroundColor]; + } +} + +@end diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index 518b1822..13762301 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -72,6 +72,7 @@ 4DECC4900EC2B436008D359E /* MCPKit_bundled.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4DECC3330EC2A170008D359E /* MCPKit_bundled.framework */; }; 4DECC4910EC2B436008D359E /* Growl.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4DECC3340EC2A170008D359E /* Growl.framework */; }; 58186D210F4CB38900851FE9 /* ConnectionErrorDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = 58186D1F0F4CB38900851FE9 /* ConnectionErrorDialog.xib */; }; + 5841423F0F97E11000A34B47 /* NoodleLineNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5841423E0F97E11000A34B47 /* NoodleLineNumberView.m */; }; 584F5F8F0F50ACD800036517 /* table-view-small.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 584F5F8E0F50ACD800036517 /* table-view-small.tiff */; }; 5885940F0F7AEE6000ED0E67 /* sparkle-public-key.pem in Resources */ = {isa = PBXBuildFile; fileRef = 5885940E0F7AEE6000ED0E67 /* sparkle-public-key.pem */; }; 58C56EF50F438E120035701E /* SPDataCellFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 58C56EF40F438E120035701E /* SPDataCellFormatter.m */; }; @@ -261,6 +262,8 @@ 4DECC3330EC2A170008D359E /* MCPKit_bundled.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MCPKit_bundled.framework; path = Frameworks/MCPKit_bundled.framework; sourceTree = "<group>"; }; 4DECC3340EC2A170008D359E /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Growl.framework; path = Frameworks/Growl.framework; sourceTree = "<group>"; }; 58186D200F4CB38900851FE9 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = Interfaces/English.lproj/ConnectionErrorDialog.xib; sourceTree = "<group>"; }; + 5841423D0F97E11000A34B47 /* NoodleLineNumberView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleLineNumberView.h; sourceTree = "<group>"; }; + 5841423E0F97E11000A34B47 /* NoodleLineNumberView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoodleLineNumberView.m; sourceTree = "<group>"; }; 584F5F8E0F50ACD800036517 /* table-view-small.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "table-view-small.tiff"; sourceTree = "<group>"; }; 588593F30F7AEC9500ED0E67 /* package-application.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "package-application.sh"; sourceTree = "<group>"; }; 5885940E0F7AEE6000ED0E67 /* sparkle-public-key.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "sparkle-public-key.pem"; sourceTree = "<group>"; }; @@ -543,6 +546,8 @@ 17E641810EF01FA8001BC333 /* CMTextView.m */, 58C56EF30F438E120035701E /* SPDataCellFormatter.h */, 58C56EF40F438E120035701E /* SPDataCellFormatter.m */, + 5841423D0F97E11000A34B47 /* NoodleLineNumberView.h */, + 5841423E0F97E11000A34B47 /* NoodleLineNumberView.m */, ); name = GUI; sourceTree = "<group>"; @@ -879,6 +884,7 @@ 296DC8BA0F909194002A3258 /* NSArray_DeepMutableCopy.m in Sources */, 296DC8BB0F909194002A3258 /* NSDictionary_DeepMutableCopy.m in Sources */, 296DC8BC0F909194002A3258 /* MGTemplateStandardFilters.m in Sources */, + 5841423F0F97E11000A34B47 /* NoodleLineNumberView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; |