This is SlideShowView.m in view mode; [Download] [Up]
#import "SlideShowView.h"
#import "Thinker.h"
#import <appkit/TextField.h>
#import <appkit/Slider.h>
#import <appkit/Button.h>
#import <appkit/NXImage.h>
#import <math.h>
#import <libc.h>
#import <dpsclient/wraps.h>
#import <appkit/OpenPanel.h>
#import <appkit/Panel.h>
#import <appkit/publicWraps.h>
#import <c.h>
#import <defaults/defaults.h>
#import <sys/file.h>
@implementation SlideShowView
#define DOBOUNCE "ssSlideShowDoBounce"
#define SECSPERSLIDE "ssSlideShowSecsPerSlide"
#define SLIDESPATH "ssSlideShowSlidesFile"
#define FILEEXTENSION "anim"
// x & y periods in milliseconds
#define X_PERIOD 20000.0
#define Y_PERIOD 19000.0
#define PI 3.1415926535
#define SCREEN_WIDTH 1120
#define SCREEN_HEIGHT 832
#define MAX_IMAGE_WIDTH 1120
#define MAX_IMAGE_HEIGHT 832
#define MAX_X_SPEED (26)
#define MAX_Y_SPEED (26)
#define BUFFER_WIDTH (MAX_IMAGE_WIDTH + MAX_X_SPEED + 1)
#define BUFFER_HEIGHT (MAX_IMAGE_HEIGHT + MAX_Y_SPEED + 1)
// do the next image if the time is right
- oneStep
{
NXRect black = {0,0,0,0};
NXRect imageRect;
BRECT new;
then = now;
now = currentTimeInMs();
/* animate by selecting a new image to blit */
[self incrementImageNumber];
if ( bounce ) {
// calculate new image x & y position
xpos = ((1 + sin(((float)now) / X_PERIOD * 2. * PI))/2.0)
* maxCoord.x;
ypos = ((1 + sin(((float)now) / Y_PERIOD * 2. * PI))/2.0)
* maxCoord.y;
if (xpos < (old.l - MAX_X_SPEED)) xpos = old.l - MAX_X_SPEED;
else if (xpos > (old.l + MAX_X_SPEED)) xpos = old.l + MAX_X_SPEED;
if (ypos < (old.b - MAX_Y_SPEED)) ypos = old.b - MAX_Y_SPEED;
else if (ypos > (old.b + MAX_Y_SPEED)) ypos = old.b + MAX_Y_SPEED;
}
else {
NXRect vRect;
[self getVisibleRect:&vRect];
xpos = ( vRect.size.width - currentImageSize.width ) / 2;
ypos = ( vRect.size.height - currentImageSize.height ) / 2;
}
/* animate new image to blit */
new.l = floor(xpos);
new.b = floor(ypos);
new.r = new.l + currentImageSize.width;
new.t = new.b + currentImageSize.height;
imageRect.origin.x = 0;
imageRect.origin.y = 0;
imageRect.size.width = currentImageSize.width;
imageRect.size.height = currentImageSize.height;
redrawTo.x = MIN(new.l, old.l);
redrawTo.y = MIN(new.b, old.b);
redraw.origin.x = 0;
redraw.origin.y = 0;
redraw.size.width = (MAX(new.r, old.r)) - redrawTo.x + 1;
redraw.size.height = (MAX(new.t, old.t)) - redrawTo.y + 1;
black.size= redraw.size;
imageTo.x = new.l - redrawTo.x;
imageTo.y = new.b - redrawTo.y;
[buffer lockFocus];
PSsetgray(0);
NXRectFill(&black);
[currentImage composite:NX_SOVER fromRect:&imageRect toPoint:&imageTo];
[buffer unlockFocus];
// Now bring it onto the screen
[buffer composite:NX_COPY fromRect:&redraw toPoint:&redrawTo];
old = new;
return self;
}
static BOOL noSSSlidesFile = FALSE;
- initFrame:(const NXRect *)frameRect
{
const char *ssSlideShowDoBounce,
*ssSlideShowSecsPerSlide,
*slidesPath;
static char moduleDirectory[MAXPATHLEN];
NXRect black = {0, 0, BUFFER_WIDTH, BUFFER_HEIGHT };
[super initFrame:frameRect];
[self allocateGState]; // For faster lock/unlockFocus
[self setClipping:NO]; // even faster...
//in this case, I only need one buffer for several Views
if (!(buffer = [NXImage findImageNamed:"worldBuffer"]))
{
buffer = [[NXImage alloc] initSize:&black.size];
[buffer setName:"worldBuffer"];
}
if ([buffer lockFocus])
{
PSsetgray(0);
NXRectFill(&black);
[buffer unlockFocus];
}
ssSlideShowDoBounce = NXGetDefaultValue([NXApp appName], DOBOUNCE);
if (ssSlideShowDoBounce == NULL) bounce = YES;
else { bounce = (!strcmp(ssSlideShowDoBounce,"1")) ? YES : NO; }
ssSlideShowSecsPerSlide = NXGetDefaultValue([NXApp appName], SECSPERSLIDE);
if (ssSlideShowSecsPerSlide == NULL) secsPerSlide = 5;
else secsPerSlide = atoi(ssSlideShowSecsPerSlide);
ssslidesPath = (char *)malloc(sizeof(char)*MAXPATHLEN);
slidesPath = NXGetDefaultValue([NXApp appName], SLIDESPATH);
if (slidesPath != NULL) strcpy(ssslidesPath, slidesPath);
if ( (![self readSlidesFromFile:ssslidesPath]) || (slidesPath == NULL) )
{
sprintf(moduleDirectory,"%s/SlideShow.%s", [(BSThinker()) moduleDirectory:"SlideShow"], FILEEXTENSION);
strcpy(ssslidesPath, moduleDirectory);
[self readSlidesFromFile:ssslidesPath];
}
return self;
}
- readSlidesFromFile:(const char *)slidesPath
{
int i, f;
id local_image;
NXSize localImageSize,
newMaxImageSize;
id newImageList;
char slideFrame[MAXPATHLEN];
// construct the image list
newImageList = [[List alloc] init];
for (i=0; ; i++)
{
sprintf(slideFrame, "%s/%d.tiff", slidesPath, i+1);
if (!(local_image = [NXImage findImageNamed:slideFrame]))
{
if ((f=open(slideFrame, O_RDONLY)) < 0) break;
close(f);
local_image = [[NXImage alloc] initFromFile:slideFrame];
if (local_image == NULL) break; // never null, even if no file
[local_image setName:slideFrame];
}
[newImageList addObject:local_image];
[local_image getSize: &localImageSize];
newMaxImageSize.width = MAX(newMaxImageSize.width, localImageSize.width);
newMaxImageSize.height = MAX(newMaxImageSize.height, localImageSize.height);
}
if (i == 0)
{
if (!slidesPath) NXRunAlertPanel([NXApp appName], "Could not open %s", NULL, NULL, NULL, slidesPath);
noSSSlidesFile = TRUE;
NXBeep();
[[pathTextField selectText:self] setStringValue:ssslidesPath];
return nil;
}
else {
maxImageSize = newMaxImageSize;
numberOfFrames = i;
currentFrame = 0;
[[imageList freeObjects] free];
imageList = newImageList;
if (ssslidesPath != slidesPath) strcpy(ssslidesPath, slidesPath);
[[pathTextField selectText:self] setStringValue:ssslidesPath];
NXWriteDefault([NXApp appName], SLIDESPATH, ssslidesPath);
}
nextRotationTime = 0;
[self newViewSize];
return self;
}
- sizeTo:(NXCoord)width :(NXCoord)height
{
[super sizeTo:width :height];
[self newViewSize];
return self;
}
- drawSelf:(const NXRect *)rects :(int)rectCount
{
return self;
}
- newViewSize
{
//this is called every time View size changes
NXRect black = {0, 0, BUFFER_WIDTH, BUFFER_HEIGHT };
then = now = currentTimeInMs();
if (oldSize.width == bounds.size.width &&
oldSize.height == bounds.size.height)
return self;
else
{
oldSize.width = bounds.size.width;
oldSize.height = bounds.size.height;
}
maxCoord.x = bounds.size.width - maxImageSize.width;
maxCoord.y = bounds.size.height - maxImageSize.height;
if (maxCoord.x < 0) maxCoord.x = 0;
if (maxCoord.y < 0) maxCoord.y = 0;
old.l = old.r = maxCoord.x/2;
old.b = old.t = maxCoord.y/2;
imageTo.x = imageTo.y = 0;
if ([buffer lockFocus])
{
PSsetgray(0);
NXRectFill(&black);
[buffer unlockFocus];
}
return self;
}
- incrementImageNumber
{
if (now > nextRotationTime)
{
if (++currentFrame >= numberOfFrames) currentFrame = 0;
currentImage = [imageList objectAt:currentFrame];
[currentImage getSize:¤tImageSize];
nextRotationTime = now + (850 * secsPerSlide);
}
return self;
}
- (const char *)windowTitle
{
return "SlideShow View by Kamlesh Trivedi";
}
- didLockFocus
{
return self;
}
- inspector:sender
{
char buf[MAXPATHLEN];
if (!inspectorView)
{
sprintf(buf,"%s/SlideShow.nib",[sender moduleDirectory:"SlideShow"]);
[NXApp loadNibFile:buf owner:self withNames:NO];
[bounceButton setState:bounce];
[secsPerSlideSlider setIntValue:secsPerSlide];
[secsPerSlideTextField setIntValue:secsPerSlide];
[[pathTextField selectText:self] setStringValue:ssslidesPath];
}
return inspectorView;
}
//--------------------------------
- bounceButtonHit:sender
{
bounce = [sender state];
NXWriteDefault([NXApp appName], DOBOUNCE, (bounce) ? "1" : "0");
nextRotationTime = now;
return self;
}
- setSecsPerSlide:sender
{
char spsStr[10];
secsPerSlide = [sender intValue];
[secsPerSlideTextField takeIntValueFrom:sender];
sprintf(spsStr, "%d", secsPerSlide);
NXWriteDefault([NXApp appName], SECSPERSLIDE, spsStr);
nextRotationTime = now;
return self;
}
- pathButtonHit:sender;
{
id openPanel;
const char* types[] = { FILEEXTENSION, (const char*)0 };
openPanel = [OpenPanel new];
[openPanel setTitle:"Open Slides"];
[openPanel allowMultipleFiles:NO];
if ( [openPanel runModalForTypes:types] ) {
const char* const *filenames;
for ( filenames = [openPanel filenames]; *filenames; filenames ++ ) {
char pathname[MAXPATHLEN];
sprintf(pathname, "%s/%s", [openPanel directory], *filenames);
[self readSlidesFromFile:pathname];
}
}
nextRotationTime = now;
return self;
}
- pathSet:sender
{
const char *filenames;
filenames = [sender stringValue];
[self readSlidesFromFile:filenames];
nextRotationTime = now;
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.