Revision: 18366
          http://bibdesk.svn.sourceforge.net/bibdesk/?rev=18366&view=rev
Author:   hofman
Date:     2012-01-05 22:39:00 +0000 (Thu, 05 Jan 2012)
Log Message:
-----------
Show line numbers in rule view subclass in error editor

Modified Paths:
--------------
    trunk/bibdesk/BDSKErrorEditor.m
    trunk/bibdesk/Bibdesk.xcodeproj/project.pbxproj

Added Paths:
-----------
    trunk/bibdesk/BDSKLineNumberView.h
    trunk/bibdesk/BDSKLineNumberView.m

Modified: trunk/bibdesk/BDSKErrorEditor.m
===================================================================
--- trunk/bibdesk/BDSKErrorEditor.m     2012-01-05 07:36:04 UTC (rev 18365)
+++ trunk/bibdesk/BDSKErrorEditor.m     2012-01-05 22:39:00 UTC (rev 18366)
@@ -45,6 +45,7 @@
 #import "BDSKAppController.h"
 #import "BDSKStringEncodingManager.h"
 #import "NSWindowController_BDSKExtensions.h"
+#import "BDSKLineNumberView.h"
 
 static char BDSKErrorEditorObservationContext;
 
@@ -108,8 +109,15 @@
     [syntaxHighlightCheckbox setState:NSOnState];
     
     // faster layout if it's not antialiased, and fixed pitch makes 
pretty-printed files look right
-    [textView setFont:[NSFont userFixedPitchFontOfSize:10.0]];
-
+    [textView setFont:[NSFont userFixedPitchFontOfSize:0.0]];
+    
+    NSScrollView *scrollView = [textView enclosingScrollView];
+    BDSKLineNumberView *lineNumberView = [[[BDSKLineNumberView alloc] 
initWithScrollView:scrollView orientation:NSVerticalRuler] autorelease];
+    [lineNumberView setClientView:textView];
+    [scrollView setVerticalRulerView:lineNumberView];
+    [scrollView setHasVerticalRuler:YES];
+    [scrollView setRulersVisible:YES];
+    
     [self loadFile:self];
     
     NSString *prefix = (isPasteDrag) ? NSLocalizedString(@"Paste/Drag Data", 
@"Partial window title") : NSLocalizedString(@"Source Data", @"Partial window 
title");

Added: trunk/bibdesk/BDSKLineNumberView.h
===================================================================
--- trunk/bibdesk/BDSKLineNumberView.h                          (rev 0)
+++ trunk/bibdesk/BDSKLineNumberView.h  2012-01-05 22:39:00 UTC (rev 18366)
@@ -0,0 +1,45 @@
+//
+//  BDSKLineNumberView.h
+//  Bibdesk
+//
+//  Created by Christiaan Hofman on 1/5/12.
+/*
+ This software is Copyright (c) 2012
+ Christiaan Hofman. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+ - Neither the name of Christiaan Hofman nor the names of any
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface BDSKLineNumberView : NSRulerView {
+    NSPointerArray *lineCharacterIndexes;
+}
+@end

Added: trunk/bibdesk/BDSKLineNumberView.m
===================================================================
--- trunk/bibdesk/BDSKLineNumberView.m                          (rev 0)
+++ trunk/bibdesk/BDSKLineNumberView.m  2012-01-05 22:39:00 UTC (rev 18366)
@@ -0,0 +1,186 @@
+//
+//  BDSKLineNumberView.m
+//  Bibdesk
+//
+//  Created by Christiaan Hofman on 1/5/12.
+/*
+ This software is Copyright (c) 2012
+ Christiaan Hofman. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+ - Neither the name of Christiaan Hofman nor the names of any
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "BDSKLineNumberView.h"
+#import "NSInvocation_BDSKExtensions.h"
+
+#define DEFAULT_THICKNESS   22.0
+#define RULER_MARGIN        4.0
+
+@implementation BDSKLineNumberView
+
+static NSDictionary *lineNumberAttributes = nil;
+
++ (void)initialize {
+    BDSKINITIALIZE;
+    lineNumberAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
+        [NSFont labelFontOfSize:[NSFont 
systemFontSizeForControlSize:NSMiniControlSize]], NSFontAttributeName, 
+        [NSColor colorWithCalibratedWhite:0.33 alpha:1.0], 
NSForegroundColorAttributeName,
+        nil];
+}
+
+- (void)dealloc {
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+    BDSKDESTROY(lineCharacterIndexes);
+    [super dealloc];
+}
+
+- (void)textDidChange:(NSNotification *)notification {
+       BDSKDESTROY(lineCharacterIndexes);
+    [self setNeedsDisplay:YES];
+}
+
+- (void)viewFrameDidChange:(NSNotification *)notification {
+    [self setNeedsDisplay:YES];
+}
+
+- (void)setClientView:(NSView *)aView {
+       id oldClientView = [self clientView];
+    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+       
+    if ([oldClientView isKindOfClass:[NSTextView class]]) {
+               [nc removeObserver:self 
name:NSTextStorageDidProcessEditingNotification object:[(NSTextView 
*)oldClientView textStorage]];
+               [nc removeObserver:self name:NSViewFrameDidChangeNotification 
object:oldClientView ];
+    }
+    
+    [super setClientView:aView];
+    
+    if ([aView isKindOfClass:[NSTextView class]]) {
+               [nc addObserver:self selector:@selector(textDidChange:) 
name:NSTextStorageDidProcessEditingNotification object:[(NSTextView *)aView 
textStorage]];
+               [nc addObserver:self selector:@selector(viewFrameDidChange:) 
name:NSViewFrameDidChangeNotification object:aView];
+    }
+    BDSKDESTROY(lineCharacterIndexes);
+}
+
+static inline CGFloat ruleThicknessForLineCount(NSUInteger count) {
+    NSUInteger i = (NSUInteger)log10(count) + 1;
+    NSMutableString *string = [NSMutableString string];
+    while (i-- > 0) [string appendString:@"0"];
+    return ceilf(fmax(DEFAULT_THICKNESS, [string 
sizeWithAttributes:lineNumberAttributes].width + RULER_MARGIN * 2));
+}
+
+static NSPointerArray *createLineCharacterIndexesForString(NSString *string) {
+    NSUInteger idx = 0, stringLength = [string length], lineEnd, contentsEnd;
+    NSPointerArray *lineCharacterIndexes = [[NSPointerArray alloc] 
initWithOptions:NSPointerFunctionsOpaqueMemory | 
NSPointerFunctionsIntegerPersonality];
+    
+    do {
+        [lineCharacterIndexes addPointer:(void *)idx];
+        idx = NSMaxRange([string lineRangeForRange:NSMakeRange(idx, 0)]);
+    } while (idx < stringLength);
+
+    [string getLineStart:NULL end:&lineEnd contentsEnd:&contentsEnd 
forRange:NSMakeRange((NSUInteger)[lineCharacterIndexes 
pointerAtIndex:[lineCharacterIndexes count] - 1], 0)];
+    if (contentsEnd < lineEnd)
+        [lineCharacterIndexes addPointer:(void *)idx];
+    
+    return lineCharacterIndexes;
+}
+
+- (NSPointerArray *)lineCharacterIndexes {
+       if (lineCharacterIndexes == nil) {
+        id view = [self clientView];
+        
+        if ([view isKindOfClass:[NSTextView class]]) {
+            lineCharacterIndexes = createLineCharacterIndexesForString([view 
string]);
+            
+            CGFloat oldThickness = [self ruleThickness];
+            CGFloat newThickness = 
ruleThicknessForLineCount([lineCharacterIndexes count]);
+            if (fabs(oldThickness - newThickness) >= 1.0) {
+                NSInvocation *invocation = [NSInvocation 
invocationWithTarget:self selector:@selector(setRuleThickness:)];
+                [invocation setArgument:&newThickness atIndex:2];
+                [invocation performSelector:@selector(invoke) withObject:nil 
afterDelay:0.0];
+            }
+        }
+    }
+       return lineCharacterIndexes;
+}
+
+- (NSUInteger)lineForCharacterIndex:(NSUInteger)anIndex {
+       NSPointerArray *lines = [self lineCharacterIndexes];
+    NSUInteger left = 0, right = [lines count], mid, lineStart;
+
+    while (right - left > 1) {
+        mid = (right + left) / 2;
+        lineStart = (NSUInteger)[lines pointerAtIndex:mid];
+        if (anIndex < lineStart)
+            right = mid;
+        else if (anIndex > lineStart)
+            left = mid;
+        else
+            return mid;
+    }
+    return left;
+}
+
+- (void)drawHashMarksAndLabelsInRect:(NSRect)aRect {
+    id view = [self clientView];
+       NSRect bounds = NSInsetRect([self bounds], RULER_MARGIN, 0.0);
+       
+    if ([view isKindOfClass:[NSTextView class]]) {
+        NSLayoutManager *lm = [view layoutManager];
+        NSTextContainer *container = [view textContainer];
+        NSRect visibleRect = [[[self scrollView] contentView] bounds];
+        NSRange range = [lm characterRangeForGlyphRange:[lm 
glyphRangeForBoundingRect:visibleRect inTextContainer:container] 
actualGlyphRange:NULL];
+        NSRange nullRange = NSMakeRange(NSNotFound, 0);
+        NSString *label;
+        NSRectArray rects;
+        CGFloat offset = [view textContainerInset].height - 
NSMinY(visibleRect);
+        NSSize labelSize;
+               NSPointerArray *lines = [self lineCharacterIndexes];
+        NSUInteger rectCount, i, line, count = [lines count];
+        
+        // one extra for any newline at the end, which doesn't have a glyph
+        range.length++;
+        
+        for (line = [self lineForCharacterIndex:range.location]; line < count; 
line++) {
+            i = (NSUInteger)[lines pointerAtIndex:line];
+            
+            if (NSLocationInRange(i, range)) {
+                rects = [lm rectArrayForCharacterRange:NSMakeRange(i, 0) 
withinSelectedCharacterRange:nullRange inTextContainer:container 
rectCount:&rectCount];
+                if (rectCount > 0) {
+                    label = [NSString stringWithFormat:@"%lu", (unsigned 
long)(line + 1)];
+                    labelSize = [label 
sizeWithAttributes:lineNumberAttributes];
+                    [label drawInRect:NSMakeRect(NSMaxX(bounds) - 
labelSize.width, offset + NSMidY(rects[0]) - 0.5 * labelSize.height, 
NSWidth(bounds), NSHeight(rects[0])) withAttributes:lineNumberAttributes];
+                }
+            }
+                       if (i > NSMaxRange(range))
+                               break;
+        }
+    }
+}
+
+@end

Modified: trunk/bibdesk/Bibdesk.xcodeproj/project.pbxproj
===================================================================
--- trunk/bibdesk/Bibdesk.xcodeproj/project.pbxproj     2012-01-05 07:36:04 UTC 
(rev 18365)
+++ trunk/bibdesk/Bibdesk.xcodeproj/project.pbxproj     2012-01-05 22:39:00 UTC 
(rev 18366)
@@ -94,6 +94,7 @@
                CE11B0060AE8FD53008C47AC /* scriptGroup.tiff in Resources */ = 
{isa = PBXBuildFile; fileRef = CE11B0050AE8FD53008C47AC /* scriptGroup.tiff */; 
};
                CE129A180B44088900416D19 /* BDSKEntrezGroupServer.m in Sources 
*/ = {isa = PBXBuildFile; fileRef = CE129A160B44088900416D19 /* 
BDSKEntrezGroupServer.m */; };
                CE12A1700B44AED200416D19 /* SearchGroupServers.plist in 
Resources */ = {isa = PBXBuildFile; fileRef = CE12A16F0B44AED100416D19 /* 
SearchGroupServers.plist */; };
+               CE15198214B62E47003AE698 /* BDSKLineNumberView.m in Sources */ 
= {isa = PBXBuildFile; fileRef = CE15198014B62E47003AE698 /* 
BDSKLineNumberView.m */; };
                CE15C0D80AA5B9A3002C555F /* BDSKErrorManager.m in Sources */ = 
{isa = PBXBuildFile; fileRef = CE15C0D60AA5B9A3002C555F /* BDSKErrorManager.m 
*/; };
                CE15E6230FCC28B1009FCBF1 /* BibDocument_UI.m in Sources */ = 
{isa = PBXBuildFile; fileRef = CE15E6210FCC28B1009FCBF1 /* BibDocument_UI.m */; 
};
                CE1782FC1158EFCB00B2EBDF /* BookmarkSheet.xib in Resources */ = 
{isa = PBXBuildFile; fileRef = CE1782FB1158EFCB00B2EBDF /* BookmarkSheet.xib 
*/; };
@@ -890,6 +891,8 @@
                CE129A150B44088900416D19 /* BDSKEntrezGroupServer.h */ = {isa = 
PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = 
BDSKEntrezGroupServer.h; sourceTree = "<group>"; };
                CE129A160B44088900416D19 /* BDSKEntrezGroupServer.m */ = {isa = 
PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; 
path = BDSKEntrezGroupServer.m; sourceTree = "<group>"; };
                CE12A16F0B44AED100416D19 /* SearchGroupServers.plist */ = {isa 
= PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = 
SearchGroupServers.plist; sourceTree = "<group>"; };
+               CE15197F14B62E47003AE698 /* BDSKLineNumberView.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
BDSKLineNumberView.h; sourceTree = "<group>"; };
+               CE15198014B62E47003AE698 /* BDSKLineNumberView.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= BDSKLineNumberView.m; sourceTree = "<group>"; };
                CE15C0D50AA5B9A3002C555F /* BDSKErrorManager.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
BDSKErrorManager.h; sourceTree = "<group>"; };
                CE15C0D60AA5B9A3002C555F /* BDSKErrorManager.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= BDSKErrorManager.m; sourceTree = "<group>"; };
                CE15E6200FCC28B1009FCBF1 /* BibDocument_UI.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
BibDocument_UI.h; sourceTree = "<group>"; };
@@ -2067,6 +2070,7 @@
                                CE3B682909D1B0190017D339 /* 
BDSKImagePopUpButtonCell.m */,
                                CE33D61A136AB8A700ACE924 /* 
BDSKImportTextView.m */,
                                F92405010BC5856900672839 /* 
BDSKLevelIndicatorCell.m */,
+                               CE15198014B62E47003AE698 /* 
BDSKLineNumberView.m */,
                                CEF536691192EFE400027C3C /* 
BDSKNotesOutlineView.m */,
                                CE62E0BE0F4C4A5500BDF01E /* BDSKOutlineView.m 
*/,
                                F941B7E908AA574200F04ECD /* BDSKOverlayWindow.m 
*/,
@@ -2664,6 +2668,7 @@
                                CE24B35210C3E9E100818EDF /* 
BDSKLastImportGroup.h */,
                                F92405000BC5856900672839 /* 
BDSKLevelIndicatorCell.h */,
                                CE24B33210C3E13900818EDF /* BDSKLibraryGroup.h 
*/,
+                               CE15197F14B62E47003AE698 /* 
BDSKLineNumberView.h */,
                                F911D7100CFE90050009C77B /* BDSKLinkedFile.h */,
                                F9201DFF0B72504C007E45BB /* BDSKMacro.h */,
                                CE3B5E7A09CEDE470017D339 /* BDSKMacroResolver.h 
*/,
@@ -3789,6 +3794,7 @@
                                CE0CD73C1459812300488DE1 /* 
NSAttributedString+Scripting.m in Sources */,
                                CEA498A21481183600AB81C5 /* 
BDSKAddressTextField.m in Sources */,
                                CEA498A61481185100AB81C5 /* 
BDSKAddressTextFieldCell.m in Sources */,
+                               CE15198214B62E47003AE698 /* 
BDSKLineNumberView.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Ridiculously easy VDI. With Citrix VDI-in-a-Box, you don't need a complex
infrastructure or vast IT resources to deliver seamless, secure access to
virtual desktops. With this all-in-one solution, easily deploy virtual 
desktops for less than the cost of PCs and save 60% on VDI infrastructure 
costs. Try it free! http://p.sf.net/sfu/Citrix-VDIinabox
_______________________________________________
Bibdesk-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit

Reply via email to