This is MiscAutoTextScroller.m in view mode; [Download] [Up]
/* MiscAutoTextScroller.m created by stark on Fri 04-Apr-1997 */ #import "MiscAutoTextScroller.h" // Private methods @interface MiscAutoTextScroller(Private) - (void)_reset; - (void)_nextStep:sender; // I'm not sure of the case :-) @end // Public methods implementation @implementation MiscAutoTextScroller - (NSTextStorage *)textStorage { return [itsSourceText textStorage]; } - (void)setTextStorage:(NSTextStorage *)aTextStorage { [[itsSourceText layoutManager] replaceTextStorage:aTextStorage]; [self _reset]; [self display]; } - (BOOL)setTextFromRTFDPath:(NSString *)anRtfdPath { if (anRtfdPath) { NSTextStorage *theStorage = [[[NSTextStorage alloc] initWithPath:anRtfdPath documentAttributes:NULL] autorelease]; if (theStorage) { [self setTextStorage:theStorage]; return YES; } } return NO; } - (void)startScroll:sender { if ([self isScrolling]) [self stopScroll:sender]; [self _nextStep:nil]; } - (void)stopScroll:sender { [self _reset]; [self display]; } - (BOOL)isScrolling { return itsState<=1; } - (NSTimeInterval)scrollTime { return itsScrollTime; } - (void)setScrollTime:(NSTimeInterval)aTotalTime { itsScrollTime = aTotalTime; } - (float)frameCountPerSecond { return itsFrameCountPerSeconds; } - (void)setFrameCountPerSecond:(float)aFrameCountPerSeconds { itsFrameCountPerSeconds = aFrameCountPerSeconds; } @end // Private implementation @implementation MiscAutoTextScroller(Private) - initWithFrame:(NSRect)aFrame { [super initWithFrame:aFrame]; itsScrollTime = 2; // 50 pixels/seconds itsFrameCountPerSeconds = 25; // 25 images/seconds (crappy) itsSourceText = [[NSTextView alloc] initWithFrame:[self frame]]; // We use the class name for enabling each subclass having a different RTFD by default // We use the mainBundle because MiscKit is living in its own framework // but the user want to put its info file in its own directory // Not that this have the 'sad' side-effect of diabling a subclass that come from // a framework to have its own auto-comment. // I suppose this is too much magic... [self setTextFromRTFDPath:[[NSBundle mainBundle] pathForResource:[[self class] description] ofType:@"rtfd"]]; return self; } - (void)dealloc { [itsBgImage release]; [itsTextImage release]; [itsSourceText release]; [super dealloc]; } - (void)_reset { [itsTextImage release]; itsTextImage = 0; [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_nextStep:) object:nil]; itsState = 0; } - (void)_buildImgCache { NSRect theCover = [self convertRect:[self bounds] toView:nil]; [[self window] disableFlushWindow]; itsfIsBuildingCache = YES; [self display]; itsfIsBuildingCache = NO; itsBgImage = [[NSImage alloc] initWithSize:theCover.size]; [itsBgImage lockFocus]; NSCopyBits( [[self window] gState], theCover, NSMakePoint(0,0) ); [itsBgImage unlockFocus]; [[self window] enableFlushWindow]; } - (void)_buildTextCache { NSRect theCover = [self convertRect:[self bounds] toView:nil]; [itsTextImage release]; itsTextImage = nil; // Grab the content of the text [itsSourceText setDrawsBackground:NO]; [itsSourceText setFrame:NSMakeRect(0,0,NSWidth(theCover),0)]; [itsSourceText sizeToFit]; itsTextImage = [[NSImage alloc] initWithSize:[itsSourceText bounds].size]; [itsTextImage setFlipped:YES]; [itsTextImage lockFocus]; PSsetalpha( 0 ); NSRectFill( [itsSourceText bounds] ); [itsSourceText drawRect:[itsSourceText bounds]]; [itsTextImage unlockFocus]; } - (void)drawRect:(NSRect)aRect { // If we are building our background cache, we do not draw if (itsfIsBuildingCache) return; // Get the background if we don't already have if (!itsBgImage) [self _buildImgCache]; // Get the text if we don't already have if (!itsTextImage) [self _buildTextCache]; // If scrolling, show the current position if ([self isScrolling]) { NSRect theRect = [self bounds]; [itsBgImage compositeToPoint:[self bounds].origin operation:NSCompositeCopy]; theRect.origin.y = ([itsTextImage size].height)*(1-itsState)-NSHeight(theRect); // NSLog( @"%@ %@", NSStringFromPoint( [self bounds].origin ), NSStringFromRect( theRect ) ); [itsTextImage compositeToPoint:[self bounds].origin fromRect:theRect operation:NSCompositeSourceOver]; } } - (void)_nextStep:sender { if (itsState>1) { [self _reset]; [self display]; } else { [self performSelector:@selector(_nextStep:) withObject:nil afterDelay:1.0/itsFrameCountPerSeconds]; [self display]; itsState += 1.0/(itsFrameCountPerSeconds*itsScrollTime*[itsTextImage size].height/100); } } - (void)setFrame:(NSRect)aFrame { [super setFrame:aFrame]; [itsBgImage release]; itsBgImage = nil; [itsTextImage release]; itsTextImage = nil; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.