You need to log in to create posts and topics.
TextView_LineNumbers
1,678 Posts
#1 · November 6, 2012, 9:07 pm
Quote from Forum Archives on November 6, 2012, 9:07 pmPosted by: svanvoorst <svanvoorst@...>
This demo gives the illusion of line numbers in a text view by utilizing two synchronized scroll views; one containing text and the other containing line numbers. Both are embedded into a single view to make it easier to 'group' the components and move them en masse. The window is resizable.'------- start ----------/*Adds line numbers to an NSTextView by utilizing synchronized NSScrollViews.Reference: Apple Doc "Scroll View Programming Guide for Mac", 2010-06-19, pp. 17-20.Adapted for FB by S.Van Voorst {20121024} Modifications by Bernie Wylde.*/BeginCDeclaration@interface EmbedderView : NSView//methods automatically called@end //interfaceEndCBeginCFunction@implementation EmbedderView : NSView;- (id)initWithFrame:(NSRect)frameRect{if ((self = [super initWithFrame:frameRect]) != nil){self = [super initWithFrame:frameRect];// Add initialization code here}return self;}- (void)drawRect:(NSRect)rect{// ****** Background ***** //[[NSColor orangeColor] set];[NSBezierPath fillRect:rect];}// ----- Use this if you want 0,0 (origin) to be top, left ---- //// ----- Otherwise origin will be at bottom, left (Unflipped) ----- //-(BOOL)isFlipped{return YES;}@end //implementationEndCBeginCDeclaration@interface MyDelegate : NSObject{NSWindow *window;NSScrollView *rightScrollView;NSScrollView *leftScrollView;NSTextView *txtView1;NSTextView *txtView2;NSRect embedderR;}- (void) createMenu;- (void) createWindow;- (void) calcLineNumbers;@endEndCBeginCFunction@implementation MyDelegate : NSObject- (void) dealloc{[window release];[super dealloc];}- (void)calcLineNumbers{NSMutableString *txtView1String = [[NSMutableString alloc] initWithCapacity:0];NSLayoutManager *layoutManager = [txtView2 layoutManager];unsigned numberOfLines, index, numberOfGlyphs = [layoutManager numberOfGlyphs];NSRange lineRange;for (numberOfLines = 0, index = 0; index < numberOfGlyphs; numberOfLines++){(void) [layoutManager lineFragmentRectForGlyphAtIndex:index effectiveRange: &lineRange];index = NSMaxRange(lineRange);[txtView1String appendFormat:@"%dn", numberOfLines+1];[txtView1 setString:txtView1String];}[txtView1String release];}- (void)textDidChange:(NSNotification *)notification{[self calcLineNumbers];}- (void)scrollViewContentBoundsDidChange:(NSNotification *)notification{NSPoint leftOrigin = [[leftScrollView contentView] bounds].origin;NSPoint rightOrigin = [[rightScrollView contentView] bounds].origin;if ( [notification object] == [rightScrollView contentView] ) {leftOrigin.y = rightOrigin.y;[[leftScrollView contentView] scrollToPoint:leftOrigin];} else {rightOrigin.y = leftOrigin.y;[[rightScrollView contentView] scrollToPoint:rightOrigin];[rightScrollView reflectScrolledClipView:[rightScrollView contentView]];}}- (void) createMenu{// ******** Menu and menubar ********//id menubar = [[NSMenu new] autorelease];id appMenuItem = [[NSMenuItem new] autorelease];[menubar addItem:appMenuItem];[NSApp setMainMenu:menubar];id appMenu = [[NSMenu new] autorelease];id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Quit"action:@selector(terminate:) keyEquivalent:@"q"] autorelease];[appMenu addItem:quitMenuItem];[appMenuItem setSubmenu:appMenu];}- (void) createWindow{// ***** window ***** //#define _wndW 600#define _wndH 550window = [[NSWindow alloc] initWithContentRect: NSMakeRect( 0, 0, _wndW, _wndH )styleMask: NSTitledWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask | NSResizableWindowMaskbacking: NSBackingStoreBuffereddefer: NO];[window center];[window setMinSize:NSMakeSize(152,220)];[window setTitle: @"NSTextView with line numbers."];// ------- Create an instance of EmbedderView (NSView) ------ //embedderR = NSMakeRect( 20, 80, _wndW - 40, _wndH - 100 );EmbedderView *baseView = [[EmbedderView alloc]initWithFrame:embedderR];[baseView setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];[baseView setAutoresizesSubviews:YES];[[window contentView] addSubview:baseView];[baseView release];// ****** Left NSTextView with Scroll ****** //NSRect leftScrollViewR = NSMakeRect( 10, 10, 50, embedderR.size.height - 20 );leftScrollView = [[NSScrollView alloc] initWithFrame: leftScrollViewR];[baseView addSubview:leftScrollView];[leftScrollView setHasVerticalScroller:NO];[leftScrollView setAutoresizingMask:NSViewHeightSizable];txtView1 = [[NSTextView alloc] initWithFrame:NSMakeRect( 0, 0, leftScrollViewR.size.width, leftScrollViewR.size.height )];[txtView1 setEditable:NO];[txtView1 setAlignment:NSRightTextAlignment];[txtView1 setBackgroundColor:[NSColor lightGrayColor]];[txtView1 setHorizontallyResizable:NO];[txtView1 setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];[leftScrollView setDocumentView: txtView1];[leftScrollView release];[txtView1 release];// ****** Right NSTextView with Scroll ****** //NSRect rightScrollViewR = NSMakeRect( 62, 10, embedderR.size.width - 72, embedderR.size.height - 20 );rightScrollView = [[NSScrollView alloc] initWithFrame: rightScrollViewR];[baseView addSubview:rightScrollView];[rightScrollView setHasVerticalScroller: YES];[rightScrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];txtView2 = [[NSTextView alloc] initWithFrame:NSMakeRect( 0, 0, rightScrollViewR.size.width, rightScrollViewR.size.height )];[txtView2 setMinSize:NSMakeSize( 0.0, [rightScrollView contentSize].height)];[txtView2 setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];[txtView2 setVerticallyResizable:YES];[txtView2 setHorizontallyResizable:YES];[txtView2 setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ];[[txtView2 textContainer]setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)];[[txtView2 textContainer] setWidthTracksTextView:NO];[txtView2 setDelegate:[NSApp delegate]];[rightScrollView setDocumentView: txtView2];[[txtView2 enclosingScrollView] setHasHorizontalScroller:YES];[txtView2 insertText:@"Enter text - Right click for menu."];[rightScrollView release];[txtView2 release];// ******* Synchronize the two Scroll Views ******** //[[rightScrollView contentView] setPostsBoundsChangedNotifications:YES];[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(scrollViewContentBoundsDidChange:)name:NSViewBoundsDidChangeNotificationobject:[rightScrollView contentView]];[[leftScrollView contentView] setPostsBoundsChangedNotifications:YES];[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(scrollViewContentBoundsDidChange:)name:NSViewBoundsDidChangeNotificationobject:[leftScrollView contentView]];[window setInitialFirstResponder:txtView2];// ***** Quit btn ***** //NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect( _wndW - 130, 30, 95, 30 )];[quitBtn setBezelStyle:NSRoundedBezelStyle ];[quitBtn setAutoresizingMask:NSViewMinXMargin];[quitBtn setTitle: @"Quit" ];[quitBtn setAction:@selector(terminate:)];[[window contentView] addSubview: quitBtn];[quitBtn release];}- (void) applicationWillFinishLaunching: (NSNotification *)notification{[self createMenu];[self createWindow];}- (void) applicationDidFinishLaunching: (NSNotification *)notification{[window makeKeyAndOrderFront: nil];}@endEndCBeginCCodeNSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];[NSApplication sharedApplication];[NSApp setDelegate: [MyDelegate new]];[NSApp run];[pool drain];EndC'-------- end ----------Steve Van Voorst
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
Posted by: svanvoorst <svanvoorst@...>
This demo gives the illusion of line numbers in a text view by utilizing two synchronized scroll views; one containing text and the other containing line numbers. Both are embedded into a single view to make it easier to 'group' the components and move them en masse. The window is resizable.
'------- start ----------
/*
Adds line numbers to an NSTextView by utilizing synchronized NSScrollViews.
Reference: Apple Doc "Scroll View Programming Guide for Mac", 2010-06-19, pp. 17-20.
Adapted for FB by S.Van Voorst {20121024} Modifications by Bernie Wylde.
*/
BeginCDeclaration
@interface EmbedderView : NSView
//methods automatically called
@end //interface
EndC
BeginCFunction
@implementation EmbedderView : NSView;
- (id)initWithFrame:(NSRect)frameRect
{
if ((self = [super initWithFrame:frameRect]) != nil)
{
self = [super initWithFrame:frameRect];
// Add initialization code here
}
return self;
}
- (void)drawRect:(NSRect)rect
{
// ****** Background ***** //
[[NSColor orangeColor] set];
[NSBezierPath fillRect:rect];
}
// ----- Use this if you want 0,0 (origin) to be top, left ---- //
// ----- Otherwise origin will be at bottom, left (Unflipped) ----- //
-(BOOL)isFlipped
{
return YES;
}
@end //implementation
EndC
BeginCDeclaration
@interface MyDelegate : NSObject
{
NSWindow *window;
NSScrollView *rightScrollView;
NSScrollView *leftScrollView;
NSTextView *txtView1;
NSTextView *txtView2;
NSRect embedderR;
}
- (void) createMenu;
- (void) createWindow;
- (void) calcLineNumbers;
@end
EndC
BeginCFunction
@implementation MyDelegate : NSObject
- (void) dealloc
{
[window release];
[super dealloc];
}
- (void)calcLineNumbers
{
NSMutableString *txtView1String = [[NSMutableString alloc] initWithCapacity:0];
NSLayoutManager *layoutManager = [txtView2 layoutManager];
unsigned numberOfLines, index, numberOfGlyphs = [layoutManager numberOfGlyphs];
NSRange lineRange;
for (numberOfLines = 0, index = 0; index < numberOfGlyphs; numberOfLines++)
{
(void) [layoutManager lineFragmentRectForGlyphAtIndex:index effectiveRange: &lineRange];
index = NSMaxRange(lineRange);
[txtView1String appendFormat:@"%dn", numberOfLines+1];
[txtView1 setString:txtView1String];
}
[txtView1String release];
}
- (void)textDidChange:(NSNotification *)notification
{
[self calcLineNumbers];
}
- (void)scrollViewContentBoundsDidChange:(NSNotification *)notification
{
NSPoint leftOrigin = [[leftScrollView contentView] bounds].origin;
NSPoint rightOrigin = [[rightScrollView contentView] bounds].origin;
if ( [notification object] == [rightScrollView contentView] ) {
leftOrigin.y = rightOrigin.y;
[[leftScrollView contentView] scrollToPoint:leftOrigin];
} else {
rightOrigin.y = leftOrigin.y;
[[rightScrollView contentView] scrollToPoint:rightOrigin];
[rightScrollView reflectScrolledClipView:[rightScrollView contentView]];
}
}
- (void) createMenu
{
// ******** Menu and menubar ********//
id menubar = [[NSMenu new] autorelease];
id appMenuItem = [[NSMenuItem new] autorelease];
[menubar addItem:appMenuItem];
[NSApp setMainMenu:menubar];
id appMenu = [[NSMenu new] autorelease];
id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Quit"
action:@selector(terminate:) keyEquivalent:@"q"] autorelease];
[appMenu addItem:quitMenuItem];
[appMenuItem setSubmenu:appMenu];
}
- (void) createWindow
{
// ***** window ***** //
#define _wndW 600
#define _wndH 550
window = [[NSWindow alloc] initWithContentRect: NSMakeRect( 0, 0, _wndW, _wndH )
styleMask: NSTitledWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask | NSResizableWindowMask
backing: NSBackingStoreBuffered
defer: NO];
[window center];
[window setMinSize:NSMakeSize(152,220)];
[window setTitle: @"NSTextView with line numbers."];
// ------- Create an instance of EmbedderView (NSView) ------ //
embedderR = NSMakeRect( 20, 80, _wndW - 40, _wndH - 100 );
EmbedderView *baseView = [[EmbedderView alloc]initWithFrame:embedderR];
[baseView setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
[baseView setAutoresizesSubviews:YES];
[[window contentView] addSubview:baseView];
[baseView release];
// ****** Left NSTextView with Scroll ****** //
NSRect leftScrollViewR = NSMakeRect( 10, 10, 50, embedderR.size.height - 20 );
leftScrollView = [[NSScrollView alloc] initWithFrame: leftScrollViewR];
[baseView addSubview:leftScrollView];
[leftScrollView setHasVerticalScroller:NO];
[leftScrollView setAutoresizingMask:NSViewHeightSizable];
txtView1 = [[NSTextView alloc] initWithFrame:NSMakeRect( 0, 0, leftScrollViewR.size.width, leftScrollViewR.size.height )];
[txtView1 setEditable:NO];
[txtView1 setAlignment:NSRightTextAlignment];
[txtView1 setBackgroundColor:[NSColor lightGrayColor]];
[txtView1 setHorizontallyResizable:NO];
[txtView1 setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[leftScrollView setDocumentView: txtView1];
[leftScrollView release];
[txtView1 release];
// ****** Right NSTextView with Scroll ****** //
NSRect rightScrollViewR = NSMakeRect( 62, 10, embedderR.size.width - 72, embedderR.size.height - 20 );
rightScrollView = [[NSScrollView alloc] initWithFrame: rightScrollViewR];
[baseView addSubview:rightScrollView];
[rightScrollView setHasVerticalScroller: YES];
[rightScrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
txtView2 = [[NSTextView alloc] initWithFrame:NSMakeRect( 0, 0, rightScrollViewR.size.width, rightScrollViewR.size.height )];
[txtView2 setMinSize:NSMakeSize( 0.0, [rightScrollView contentSize].height)];
[txtView2 setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[txtView2 setVerticallyResizable:YES];
[txtView2 setHorizontallyResizable:YES];
[txtView2 setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ];
[[txtView2 textContainer]setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[[txtView2 textContainer] setWidthTracksTextView:NO];
[txtView2 setDelegate:[NSApp delegate]];
[rightScrollView setDocumentView: txtView2];
[[txtView2 enclosingScrollView] setHasHorizontalScroller:YES];
[txtView2 insertText:@"Enter text - Right click for menu."];
[rightScrollView release];
[txtView2 release];
// ******* Synchronize the two Scroll Views ******** //
[[rightScrollView contentView] setPostsBoundsChangedNotifications:YES];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(scrollViewContentBoundsDidChange:)
name:NSViewBoundsDidChangeNotification
object:[rightScrollView contentView]];
[[leftScrollView contentView] setPostsBoundsChangedNotifications:YES];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(scrollViewContentBoundsDidChange:)
name:NSViewBoundsDidChangeNotification
object:[leftScrollView contentView]];
[window setInitialFirstResponder:txtView2];
// ***** Quit btn ***** //
NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect( _wndW - 130, 30, 95, 30 )];
[quitBtn setBezelStyle:NSRoundedBezelStyle ];
[quitBtn setAutoresizingMask:NSViewMinXMargin];
[quitBtn setTitle: @"Quit" ];
[quitBtn setAction:@selector(terminate:)];
[[window contentView] addSubview: quitBtn];
[quitBtn release];
}
- (void) applicationWillFinishLaunching: (NSNotification *)notification
{
[self createMenu];
[self createWindow];
}
- (void) applicationDidFinishLaunching: (NSNotification *)notification
{
[window makeKeyAndOrderFront: nil];
}
@end
EndC
BeginCCode
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
[NSApplication sharedApplication];
[NSApp setDelegate: [MyDelegate new]];
[NSApp run];
[pool drain];
EndC
'-------- end ----------
Steve Van Voorst
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
Click for thumbs down.0Click for thumbs up.0