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.