This is AppController.m in view mode; [Download] [Up]
#import "AppController.h" #import "ImageView.h" #import "Thumber.h" #define THUMBSIZE 80 NSConditionLock *globalLock; TransferData global; @interface AppController(PrivateMethods) - (BOOL)_internalOpenGigernail:(NSString *)filename; - (BOOL)_internalOpenGigerwww:(NSString *)filename; - (BOOL)_internalOpenGiger:(NSString *)filename; - (BOOL)_internalSaveGigernail:(NSString *)filename; - (BOOL)_internalSaveGigerwww:(NSString *)filename; - (BOOL)_internalSaveGiger:(NSString *)filename; @end @implementation AppController(PrivateMethods) - (BOOL)_internalSaveGiger:(NSString *)filename { NSArray *cells; if(!numberOfThumbnails) return NO; cells = [thumbView cells]; if(![NSArchiver archiveRootObject:cells toFile:filename]) return NO; return YES; } - (BOOL)_internalOpenGiger:(NSString *)filename { NSArray *cells; cells = [NSUnarchiver unarchiveObjectWithFile:filename]; if(cells){ [thumbView removeRow:0]; [thumbView renewRows:0 columns:[cells count]]; [thumbView addRowWithCells:cells]; [thumbView sizeToCells]; [[thumbView window] display]; numberOfThumbnails = [cells count]; return YES; } else return NO; } - (BOOL)_internalOpenGigernail:(NSString *)filename { NSString *componentName; NSArray *cells, *thumbNames; unsigned int i,n; NSImage *image; NSButtonCell *cell; componentName = [NSString stringWithFormat:@"%@/Thumbs.plist",filename]; thumbNames = [NSArray arrayWithContentsOfFile:componentName]; if(thumbNames){ n = [thumbNames count]; [thumbView removeRow:0]; [thumbView renewRows:1 columns:n]; cells = [thumbView cells]; for(i = 0; i < n; i++){ componentName = [NSString stringWithFormat:@"%@/t%d.tiff", filename, i]; cell = [cells objectAtIndex:i]; image = [[NSImage alloc] initWithContentsOfFile:componentName]; [cell setImage:image]; [image release]; [cell setRepresentedObject:[thumbNames objectAtIndex:i]]; } [thumbView sizeToCells]; [[thumbView window] display]; numberOfThumbnails = n; return YES; } else return NO; } - (BOOL)_internalOpenGigerwww:(NSString *)filename { NSString *componentName; NSArray *cells, *thumbNames; unsigned int i,n; NSImage *image; NSBitmapImageRep *bitmap; NSButtonCell *cell; componentName = [NSString stringWithFormat:@"%@/Thumbs.plist",filename]; thumbNames = [NSArray arrayWithContentsOfFile:componentName]; if(thumbNames){ n = [thumbNames count]; [thumbView removeRow:0]; [thumbView renewRows:1 columns:n]; cells = [thumbView cells]; for(i = 0; i < n; i++){ componentName = [NSString stringWithFormat:@"%@/t%d.gif", filename, i]; cell = [cells objectAtIndex:i]; bitmap = [imageDecoder decodeFromFile:componentName]; if(bitmap){ image = [[NSImage alloc] init]; [image addRepresentation:bitmap]; [cell setImage:image]; [image release]; } [cell setRepresentedObject:[thumbNames objectAtIndex:i]]; } [thumbView sizeToCells]; [[thumbView window] display]; numberOfThumbnails = n; return YES; } else return NO; } - (BOOL)_internalSaveGigernail:(NSString *)filename { NSString *fileComponentName; NSData *tiffData; NSFileManager *fm = [NSFileManager defaultManager]; BOOL isDir; NSMutableString *plistString; NSArray *cells; NSButtonCell *cell; unsigned int i; if(!numberOfThumbnails) return NO; if([fm fileExistsAtPath:filename isDirectory:&isDir]){ if(![fm removeFileAtPath:filename handler:nil]){ NSLog(@"Could not remove old directory %@", filename); NSBeep(); return NO; } } if(![fm createDirectoryAtPath:filename attributes:nil]){ NSLog(@"Could not create directory %@", filename); NSBeep(); return NO; } plistString = [[NSMutableString alloc] init]; [plistString appendString:@"(\n"]; cells = [thumbView cells]; for(i = 0; i < numberOfThumbnails; i++){ cell = [cells objectAtIndex:i]; fileComponentName = [NSString stringWithFormat:@"%@/t%d.tiff", filename, i]; tiffData = [[cell image] TIFFRepresentation]; if(![tiffData writeToFile:fileComponentName atomically:YES]){ NSLog(@"Could not write thumbnail %@", fileComponentName); NSBeep(); } [plistString appendFormat:@"\t\"%@\",\n", [cell representedObject]]; } [plistString appendString:@")\n"]; fileComponentName = [NSString stringWithFormat:@"%@/Thumbs.plist", filename]; if(![plistString writeToFile:fileComponentName atomically:YES]){ NSLog(@"Could not write plist"); NSBeep(); } [plistString release]; return YES; } - (BOOL)_internalSaveGigerwww:(NSString *)filename { NSString *fileComponentName; NSData *tiffData, *gifData; NSFileManager *fm = [NSFileManager defaultManager]; BOOL isDir; NSMutableString *plistString; NSArray *cells; NSButtonCell *cell; unsigned int i; NSAutoreleasePool *pool; NSPasteboard *filterPB; if(!numberOfThumbnails) return NO; if([fm fileExistsAtPath:filename isDirectory:&isDir]){ if(![fm removeFileAtPath:filename handler:nil]){ NSLog(@"Could not remove old directory %@", filename); NSBeep(); return NO; } } if(![fm createDirectoryAtPath:filename attributes:nil]){ NSLog(@"Could not create directory %@", filename); NSBeep(); return NO; } plistString = [[NSMutableString alloc] init]; [plistString appendString:@"(\n"]; cells = [thumbView cells]; for(i = 0; i < numberOfThumbnails; i++){ pool = [[NSAutoreleasePool alloc] init]; cell = [cells objectAtIndex:i]; fileComponentName = [NSString stringWithFormat:@"%@/t%d.gif", filename, i]; tiffData = [[cell image] TIFFRepresentation]; filterPB = [NSPasteboard pasteboardByFilteringData:tiffData ofType:NSTIFFPboardType]; gifData = [filterPB dataForType:@"image format gif"]; if(gifData && ![gifData writeToFile:fileComponentName atomically:YES]){ NSLog(@"Could not write thumbnail %@", fileComponentName); NSBeep(); } [plistString appendFormat:@"\t\"%@\",\n", [cell representedObject]]; [filterPB releaseGlobally]; [pool release]; } [plistString appendString:@")\n"]; fileComponentName = [NSString stringWithFormat:@"%@/Thumbs.plist", filename]; if(![plistString writeToFile:fileComponentName atomically:YES]){ NSLog(@"Could not write plist"); NSBeep(); } [plistString release]; return YES; } @end @implementation AppController - (oneway void)provideGlobalData { NSAutoreleasePool *subpool; NSBitmapImageRep *bitmap; [globalLock lock]; if(global.full){ NSZoneFree(NSDefaultMallocZone(),global.imagePlanes); [global.bitmap release]; [global.image release]; [global.filename release]; global.full = NO; } if(isRunning && currentJob < [filenames count]){ global.filename = [[filenames objectAtIndex:currentJob] retain]; global.image = [[NSImage alloc] init]; bitmap = [imageDecoder decodeFromFile:global.filename]; if(!global.image || !bitmap){ [global.filename release]; global.full = NO; [globalLock unlockWithCondition:HAS_DATA]; return; } [global.image addRepresentation:bitmap]; subpool = [[NSAutoreleasePool alloc] init]; global.bitmap = [[NSBitmapImageRep alloc] initWithData:[global.image TIFFRepresentation]]; [subpool release]; if(!global.bitmap){ [global.filename release]; [global.image release]; global.full = NO; [globalLock unlockWithCondition:HAS_DATA]; return; } global.imageInfo.bitsPerPixel = [global.bitmap bitsPerPixel]; global.imageInfo.samplesPerPixel = [global.bitmap samplesPerPixel]; global.imageInfo.bitsPerSample = [global.bitmap bitsPerSample]; global.imageInfo.isPlanar = [global.bitmap isPlanar]; global.imageInfo.hasAlpha = [global.bitmap hasAlpha]; global.imageInfo.numberOfPlanes = [global.bitmap numberOfPlanes]; global.imageInfo.bytesPerPlane = [global.bitmap bytesPerPlane]; global.imageInfo.bytesPerRow = [global.bitmap bytesPerRow]; global.imageInfo.pixelsHigh = [global.bitmap pixelsHigh]; global.imageInfo.pixelsWide = [global.bitmap pixelsWide]; // normally it should be global.imageInfo.samplesPerPixel // but due to a bug ?? it only works with something greater like 10 // global.imagePlanes = NSZoneMalloc(NSDefaultMallocZone(), // global.imageInfo.samplesPerPixel * sizeof(unsigned char *)); global.imagePlanes = NSZoneMalloc(NSDefaultMallocZone(), 10 * sizeof(unsigned char *)); [global.bitmap getBitmapDataPlanes:global.imagePlanes]; global.imageData = [global.bitmap bitmapData]; global.full = YES; } [globalLock unlockWithCondition:HAS_DATA]; } - (oneway void)displayGlobalData { NSButtonCell *cell; NSWindow *window = [thumbView window]; NSImage *thumbnail, *thumbSharpenedNail; NSBitmapImageRep *thumbBitmap, *thumbSharpenedBitmap; [globalLock lock]; if(!global.full){ [globalLock unlockWithCondition:NO_DATA]; currentJob++; if(isRunning && currentJob < [filenames count]) [thumber thumbWithSize:THUMBSIZE]; else { job = NO; isRunning = NO; [statusTextField setStringValue:@""]; [window display]; [NSApp updateWindows]; } return; } if(global.thumbnailPlanes){ thumbBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:global.thumbnailPlanes pixelsWide:global.thumbnailInfo.pixelsWide pixelsHigh:global.thumbnailInfo.pixelsHigh bitsPerSample:global.thumbnailInfo.bitsPerSample samplesPerPixel:global.thumbnailInfo.samplesPerPixel hasAlpha:global.thumbnailInfo.hasAlpha isPlanar:global.thumbnailInfo.isPlanar colorSpaceName:[global.bitmap colorSpaceName] bytesPerRow:global.thumbnailInfo.bytesPerRow bitsPerPixel:global.thumbnailInfo.bitsPerPixel]; thumbSharpenedBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:global.thumbnailSharpenedPlanes pixelsWide:global.thumbnailInfo.pixelsWide pixelsHigh:global.thumbnailInfo.pixelsHigh bitsPerSample:global.thumbnailInfo.bitsPerSample samplesPerPixel:global.thumbnailInfo.samplesPerPixel hasAlpha:global.thumbnailInfo.hasAlpha isPlanar:global.thumbnailInfo.isPlanar colorSpaceName:[global.bitmap colorSpaceName] bytesPerRow:global.thumbnailInfo.bytesPerRow bitsPerPixel:global.thumbnailInfo.bitsPerPixel]; thumbnail = [[NSImage alloc] init]; [thumbnail addRepresentation:thumbBitmap]; thumbSharpenedNail = [[NSImage alloc] init]; [thumbSharpenedNail addRepresentation:thumbSharpenedBitmap]; [thumbBitmap release]; [thumbSharpenedBitmap release]; [thumbnail lockFocus]; [thumbSharpenedNail compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver]; [thumbnail unlockFocus]; [thumbSharpenedNail release]; } else thumbnail = [global.image retain]; [thumbView addColumn]; cell = (NSButtonCell *)[[thumbView cells] lastObject]; [cell setImage:thumbnail]; [thumbnail release]; [cell setRepresentedObject:global.filename]; [globalLock unlockWithCondition:NO_DATA]; [thumbView sizeToCells]; [thumbView scrollCellToVisibleAtRow:0 column:[[thumbView cells] count] - 1]; [window display]; numberOfThumbnails++; currentJob++; if(isRunning && currentJob < [filenames count]) [thumber thumbWithSize:THUMBSIZE]; else { job = NO; isRunning = NO; [statusTextField setStringValue:@""]; [window display]; [NSApp updateWindows]; } } - (BOOL)isRunning { return isRunning; } - (void)setThumber:(id)aThumber { if(thumber == aThumber) return; [thumber release]; thumber = [aThumber retain]; [thumber setProtocolForProxy:@protocol(ThumberMethods)]; } - (void)stopThumbs:(id)sender { isRunning = NO; } - (void)addDirectory:(id)sender { NSWindow *window = [thumbView window]; NSString *filename, *dirname; NSFileManager *fm = [NSFileManager defaultManager]; NSDirectoryEnumerator *dir; NSArray *imageFileTypes = [imageDecoder imageUnfilteredFileTypes]; NSMutableArray *fn; [openPanel setAllowsMultipleSelection:NO]; [openPanel setCanChooseDirectories:YES]; [openPanel setCanChooseFiles:NO]; [openPanel setTitle:@"Add Images from"]; if([openPanel runModal]){ [statusTextField setStringValue:@"Making thumbnails"]; [thumbView deselectAllCells]; [window display]; [window flushWindow]; PSWait(); dirname = [[openPanel filenames] objectAtIndex:0]; dir = [fm enumeratorAtPath:dirname]; if(filenames) [filenames release]; fn = [[NSMutableArray alloc] init]; while(filename = [dir nextObject]){ if([imageFileTypes containsObject:[filename pathExtension]]){ filename = [NSString stringWithFormat:@"%@/%@",dirname,filename]; [fn addObject:filename]; } } filenames = [fn copy]; [fn release]; isRunning = YES; job = YES; currentJob = 0; [thumber thumbWithSize:THUMBSIZE]; } } - (void)addImages:(id)sender { NSWindow *window = [thumbView window]; [openPanel setAllowsMultipleSelection:YES]; [openPanel setCanChooseDirectories:NO]; [openPanel setCanChooseFiles:YES]; [openPanel setTitle:@"Add Images"]; if([openPanel runModalForTypes:[imageDecoder imageUnfilteredFileTypes]]){ [statusTextField setStringValue:@"Making thumbnails"]; [thumbView deselectAllCells]; [window display]; [window flushWindow]; PSWait(); if(filenames) [filenames release]; filenames = [[openPanel filenames] copy]; isRunning = YES; job = YES; currentJob = 0; [thumber thumbWithSize:THUMBSIZE]; } } - (void)showImage:(id)sender { NSImage *image; NSBitmapImageRep *bitmap; NSButtonCell *cell; NSString *filename; cell = (NSButtonCell *)[thumbView selectedCell]; filename = (NSString *)[cell representedObject]; if(!filename){ NSBeep(); return; } bitmap = [imageDecoder decodeFromFile:filename]; if(bitmap){ image = [[NSImage alloc] init]; [image addRepresentation:bitmap]; } else { NSBeep(); return; } [statusTextField setStringValue:filename]; [imageView setImage:image]; [imageView setImageName:filename]; [[imageView window] display]; [image release]; } static BOOL alreadyAwake = NO; - (void)awakeFromNib { NSScrollView *ms; NSSize msSize; if(alreadyAwake) return; alreadyAwake = YES; numberOfThumbnails = 0; [thumbView setAllowsEmptySelection:YES]; [thumbView removeRow:0]; [thumbView renewRows:1 columns:0]; [thumbView setCellSize:NSMakeSize(THUMBSIZE + 5, THUMBSIZE + 5)]; [thumbView setAutoresizingMask:0]; [thumbView sizeToCells]; [thumbView setDoubleAction:@selector(showImage:)]; [thumbView setTarget:self]; [thumbView setPostsFrameChangedNotifications:YES]; [thumbView deselectAllCells]; ms = [thumbView enclosingScrollView]; msSize = [NSScrollView frameSizeForContentSize:[thumbView frame].size hasHorizontalScroller:[ms hasHorizontalScroller] hasVerticalScroller:[ms hasVerticalScroller] borderType:[ms borderType]]; [ms setFrameSize:msSize]; [self splitView:splitView resizeSubviewsWithOldSize:[splitView frame].size]; savePanel = [NSSavePanel savePanel]; openPanel = [NSOpenPanel openPanel]; } - (void)applicationDidFinishLaunching:(NSNotification *)notification { NSPort *port1; NSPort *port2; NSArray *portArray; isRunning = NO; job = NO; filenames = nil; currentJob = 0; global.full = NO; globalLock = [[NSConditionLock alloc] initWithCondition:NO_DATA]; imageDecoder = [[MiscImageDecoderController alloc] init]; port1 = [NSPort port]; port2 = [NSPort port]; serverConnection = [[NSConnection alloc] initWithReceivePort:port1 sendPort:port2]; [serverConnection setRootObject:self]; portArray = [NSArray arrayWithObjects:port2, port1, nil]; [NSThread detachNewThreadSelector:@selector(connectWithPorts:) toTarget:[Thumber class] withObject:portArray]; [[imageView window] makeKeyAndOrderFront:self]; } - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { NSString *extension; extension = [filename pathExtension]; if([extension isEqualToString:@"giger"]){ return [self _internalOpenGiger:filename]; } else if([extension isEqualToString:@"gigernail"]){ return [self _internalOpenGigernail:filename]; } else if([extension isEqualToString:@"gigerwww"]){ return [self _internalOpenGigerwww:filename]; } return NO; } - (void)saveDocument:(id)sender { NSString *filename; NSString *extension; if(!numberOfThumbnails) return; [savePanel setRequiredFileType:@"giger"]; [savePanel setTitle:@"Save"]; [savePanel setAccessoryView:saveFileTypeMatrix]; if([savePanel runModal]){ filename = [savePanel filename]; extension = [filename pathExtension]; if([extension isEqualToString:@"giger"]) [self _internalSaveGiger:filename]; else if([extension isEqualToString:@"gigernail"]) [self _internalSaveGigernail:filename]; else [self _internalSaveGigerwww:filename]; } } - (void)saveChangeFileType:(id)sender { int tag = [sender selectedTag]; if(tag == 0) [savePanel setRequiredFileType:@"giger"]; else if(tag == 1) [savePanel setRequiredFileType:@"gigernail"]; else [savePanel setRequiredFileType:@"gigerwww"]; } - (void)openDocument:(id)sender { NSString *filename; NSString *extension; [openPanel setAllowsMultipleSelection:NO]; [openPanel setCanChooseDirectories:NO]; [openPanel setCanChooseFiles:YES]; [openPanel setTitle:@"Open"]; if([openPanel runModalForTypes:[NSArray arrayWithObjects:@"giger",@"gigernail",@"gigerwww",nil]]){ filename = [[openPanel filenames] objectAtIndex:0]; extension = [filename pathExtension]; if([extension isEqualToString:@"giger"]) [self _internalOpenGiger:filename]; else if([extension isEqualToString:@"gigernail"]) [self _internalOpenGigernail:filename]; else [self _internalOpenGigerwww:filename]; } } - (void)showInfo:(id)sender { if(!infoPanel){ [NSBundle loadNibNamed:@"Info" owner:self]; [infoPanel setBecomesKeyOnlyIfNeeded:YES]; } [infoPanel orderFront:self]; } - (void)saveImage:(id)sender { NSString *filename; NSData *tiffData; if(![imageView image]) return; [savePanel setRequiredFileType:@"tiff"]; [savePanel setTitle:@"Save Image"]; if([savePanel runModal]){ filename = [savePanel filename]; tiffData = [[imageView image] TIFFRepresentation]; if(![tiffData writeToFile:filename atomically:YES]) NSBeep(); } } - (void)openImage:(id)sender { NSString *filename; NSImage *image; NSBitmapImageRep *bitmap; [openPanel setAllowsMultipleSelection:NO]; [openPanel setCanChooseDirectories:NO]; [openPanel setCanChooseFiles:YES]; [openPanel setTitle:@"Open Image"]; if([openPanel runModalForTypes:[imageDecoder imageUnfilteredFileTypes]]){ filename = [[openPanel filenames] objectAtIndex:0]; bitmap = [imageDecoder decodeFromFile:filename]; if(bitmap){ image = [[NSImage alloc] init]; [image addRepresentation:bitmap]; } else { NSBeep(); return; } [statusTextField setStringValue:filename]; [imageView setImage:image]; [imageView setImageName:filename]; [[imageView window] display]; [image release]; } } - (void)remove:(id)sender { NSArray *selectedCells; NSMutableArray *cells; selectedCells = [thumbView selectedCells]; if([selectedCells count] == 0) return; cells = [[thumbView cells] mutableCopy]; [cells removeObjectsInArray:selectedCells]; [thumbView removeRow:0]; numberOfThumbnails = [cells count]; if(numberOfThumbnails == 0){ [thumbView renewRows:1 columns:0]; } else { [thumbView renewRows:0 columns:[cells count]]; [thumbView addRowWithCells:cells]; } [thumbView sizeToCells]; [[thumbView window] display]; } - (void)newDocument:(id)sender; { if(numberOfThumbnails == 0) return; numberOfThumbnails = 0; [thumbView removeRow:0]; [thumbView renewRows:1 columns:0]; [thumbView sizeToCells]; [[thumbView window] display]; } - (void)splitView:(NSSplitView *)sender resizeSubviewsWithOldSize:(NSSize)oldSize { NSRect upper,lower; NSView *upperView; NSView *lowerView; float delta, thumbHeight; upperView = (NSView *)[[sender subviews] objectAtIndex:0]; lowerView = (NSView *)[[sender subviews] objectAtIndex:1]; upper = [upperView frame]; thumbHeight = upper.size.height; [sender adjustSubviews]; upper = [upperView frame]; lower = [lowerView frame]; if(upper.size.height > thumbHeight){ delta = upper.size.height - thumbHeight; upper.size.height = thumbHeight; lower.size.height += delta; [upperView setFrame:upper]; [lowerView setFrame:lower]; } else if (upper.size.height < thumbHeight){ delta = thumbHeight - upper.size.height; upper.size.height = thumbHeight; lower.size.height -= delta; if(lower.size.height < 0) lower.size.height = 0; [upperView setFrame:upper]; [lowerView setFrame:lower]; } } - (void)splitView:(NSSplitView *)sender constrainMinCoordinate:(float *)min maxCoordinate:(float *)max ofSubviewAt:(int)offset { NSScrollView *ms; NSSize msSize; if(offset == 0){ ms = [thumbView enclosingScrollView]; msSize = [NSScrollView frameSizeForContentSize:[thumbView frame].size hasHorizontalScroller:[ms hasHorizontalScroller] hasVerticalScroller:[ms hasVerticalScroller] borderType:[ms borderType]]; *min = 0.0; *max = msSize.height; } } - (BOOL)validateMenuItem:(NSMenuItem *)anItem { NSString *menuTitle = [anItem title]; if([menuTitle isEqualToString:@"New"]){ if(isRunning || numberOfThumbnails == 0) return NO; else return YES; } if([menuTitle isEqualToString:@"Open..."]){ if(isRunning) return NO; else return YES; } if([menuTitle isEqualToString:@"Save..."]){ if(isRunning || numberOfThumbnails == 0) return NO; else return YES; } if([menuTitle isEqualToString:@"Add Images..."]){ if(isRunning) return NO; else return YES; } if([menuTitle isEqualToString:@"Add Directory..."]){ if(isRunning) return NO; else return YES; } if([menuTitle isEqualToString:@"Remove"]){ if(isRunning || [[thumbView selectedCells] count] == 0) return NO; else return YES; } if([menuTitle isEqualToString:@"Stop Thumbnails"]){ if(!isRunning) return NO; else return YES; } if([menuTitle isEqualToString:@"Save Image..."]){ if(![imageView image]) return NO; else return YES; } return YES; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.