home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / Rhapsody / Graphics / Morph-2.0a / MorphDocument.m < prev    next >
Encoding:
Text File  |  1998-03-02  |  17.5 KB  |  529 lines

  1. // MorphDocument.m 
  2. //
  3. // created by Martin Wennerberg on Sun 12-Nov-1995 
  4. //
  5. // when        who    modification
  6.  
  7. #import "MorphDocument.h"
  8. #import "AppController.h"
  9. #import "MorphLine.h"
  10. #import "Morpher.h"
  11. #import "Editor.h"
  12. #import "NSBitmapImageRep_editing.h"
  13. #import "algebra.h"
  14. #import "PreviewCell.h"
  15. #import "InspectorController.h"
  16. #import "MorphLineInspector.h"
  17.  
  18. #define NIB_NAME @"MorphDocument.nib"
  19.  
  20. @implementation MorphDocument
  21. + (NSSet *) readableFileTypes;
  22. {
  23.     return [NSSet setWithObject:MORPH_DOC_EXTENTION];
  24. }
  25.  
  26. + (void) load
  27. {
  28.     [[NSApp delegate] registerDocumentClass:[self class]];
  29. }
  30.  
  31. - (void) dealloc
  32. {
  33.     [firstImage release];
  34.     [lastImage release];
  35.     [morphLines release];
  36.     [super dealloc];
  37. }
  38.  
  39. - initWithContentsOfFile:(NSString *)path
  40. {
  41.     NSString        *filename;
  42.     NSString        *fullPath;
  43.     NSImage        *image;
  44.     NSArray        *lineDefs;
  45.     int             i;
  46.     MorphLine        *morphLine;
  47.     NSDictionary        *infoDict;
  48.     NSDictionary        *morphLineDict;
  49.     NSSize                interCellSpacing = {2, 2};
  50.     
  51.     self = [super initWithContentsOfFile:path];
  52.     morphLines = [[NSMutableArray allocWithZone:[self zone]] initWithCapacity:20];
  53.     selectedLines = [[NSMutableArray allocWithZone:[self zone]] initWithCapacity:20];
  54.  
  55.     if (![NSBundle loadNibNamed:NIB_NAME owner: self])
  56.     {
  57.             [self autorelease];
  58.             return nil;
  59.     }
  60.  
  61.     previewMatrix = [[NSMatrix allocWithZone:[self zone]] initWithFrame:[previewBox bounds]
  62.                                                                    mode:0 
  63.                                                               cellClass:[PreviewCell class] 
  64.                                                            numberOfRows:1 
  65.                                                         numberOfColumns:5];
  66.     [previewMatrix setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
  67.     [previewMatrix setAutosizesCells:YES];
  68.     [previewMatrix setDelegate:self];
  69.     [previewMatrix setIntercellSpacing:interCellSpacing];
  70.     [(NSBox *)previewBox setContentView:previewMatrix];
  71.     
  72.     [firstEditor setDelta:0.0];
  73.     [lastEditor setDelta:1.0];
  74.  
  75.     [[InspectorController sharedInspectorController] registerInspector:[MorphLineInspector sharedInspector]];
  76.     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(selectionChanged:) name:NOTIFICATION_SELECTION_CHANGED object:nil];
  77.  
  78.    if (!filePath)
  79.         return self;
  80.  
  81.     [[self window] setTitle:[NSLocalizedString (@"Opening file ", @"Opening window title") stringByAppendingString:filePath]];
  82.  
  83.     infoDict = [[[NSDictionary allocWithZone:[self zone]] initWithContentsOfFile:[filePath stringByAppendingPathComponent:DICT_PATHCOMPONENT]] autorelease];
  84.     if (!infoDict)
  85.     {
  86.         [self autorelease];
  87.         return nil;
  88.     }
  89.     
  90.     filename = [infoDict objectForKey:DICT_IMAGE0_PATH_KEY];
  91.     if ([filename characterAtIndex:0] == '/')
  92.         fullPath = filename;
  93.     else
  94.         fullPath = [filePath stringByAppendingPathComponent:filename];
  95.  
  96.     image = [[[NSImage allocWithZone:[self zone]] initWithContentsOfFile:fullPath] autorelease];
  97.     [self setImage:image atDelta:0.0];
  98.  
  99.     filename = [infoDict objectForKey:DICT_IMAGE1_PATH_KEY];
  100.     if ([filename characterAtIndex:0] == '/')
  101.         fullPath = filename;
  102.     else
  103.         fullPath = [filePath stringByAppendingPathComponent:filename];
  104.  
  105.     image = [[[NSImage allocWithZone:[self zone]] initWithContentsOfFile:fullPath] autorelease];
  106.     [self setImage:image atDelta:1.0];
  107.  
  108.     if ([infoDict objectForKey:@"frameWidth"])
  109.         [frameWidthField setStringValue:[infoDict objectForKey:@"frameWidth"]];
  110.     if ([infoDict objectForKey:@"frameHeight"])
  111.         [frameHeightField setStringValue:[infoDict objectForKey:@"frameHeight"]];
  112.  
  113.     lineDefs = [infoDict objectForKey:DICT_MORPHLINES_KEY];
  114.  
  115.     for (i = 0; i < [lineDefs count]; ++i)
  116.     {
  117.         morphLineDict = [lineDefs objectAtIndex:i];
  118.         morphLine = [[MorphLine allocWithZone:[self zone]] initWithValuesInDict:morphLineDict];
  119.         if (morphLine != nil)
  120.             [self addMorphLine:morphLine];
  121.     }
  122.     [[self window] setRepresentedFilename:path];
  123.     [[self window] setDocumentEdited:NO];
  124.     [self calcPreview:nil];
  125.  
  126.     if (filePath)
  127.         [[self window] setTitleWithRepresentedFilename:filePath];
  128.  
  129.     return self;
  130. }
  131.  
  132. - (void) selectionChanged:(NSNotification *)sender
  133. {
  134.     [firstEditor setNeedsDisplay:YES];
  135.     [lastEditor setNeedsDisplay:YES];
  136.     [previewMatrix setNeedsDisplay:YES];
  137. }
  138.  
  139. - (NSArray *) morphLines
  140. {
  141.     return morphLines;
  142. }
  143.  
  144. - (void) addMorphLine:(MorphLine *)morphLine
  145. {
  146.     [morphLines addObject:morphLine];
  147.     [firstEditor setNeedsDisplay:YES];
  148.     [lastEditor setNeedsDisplay:YES];
  149.     [[self window] setDocumentEdited:YES];
  150. }
  151.  
  152. - (void) deleteMorphLine:(MorphLine *)morphLine
  153. {
  154.     [morphLines removeObject:morphLine];
  155.     [firstEditor setNeedsDisplay:YES];
  156.     [lastEditor setNeedsDisplay:YES];
  157.     [selectedLines removeObject:morphLine];
  158.     [[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:NOTIFICATION_SELECTION_CHANGED object:self]
  159.                                 postingStyle:NSPostASAP coalesceMask:NSNotificationCoalescingOnName forModes:nil];
  160.  
  161.     [[self window] setDocumentEdited:YES];
  162. }
  163.  
  164. // Access methods
  165. - (void) setImage:(NSImage *)image atDelta:(float) delta
  166. {
  167.     NSSize    size = [image size];
  168.     
  169.     if (delta < 0.5)
  170.     {
  171.         [firstImage release];
  172.         firstImage = [image retain];
  173.     }
  174.     else
  175.     {
  176.         [lastImage release];
  177.         lastImage = [image retain];
  178.     }
  179.     [image setScalesWhenResized:YES];
  180.     [frameWidthField setIntValue:size.width];
  181.     [frameHeightField setIntValue:size.height];
  182.     [[self window] setDocumentEdited:YES];
  183. }
  184.  
  185. - (NSImage *) imageAtDelta:(float)delta
  186. {
  187.     if (delta < 0.5)
  188.         return firstImage;
  189.     else
  190.         return lastImage;
  191. }
  192.  
  193. - (NSWindow *)window
  194. {
  195.     return [firstEditor window];
  196. }
  197.  
  198. // Actions
  199. - (void) save:sender
  200. {
  201.     NSFileManager    *fileManager;
  202.     NSString            *dirPath;
  203.     NSString        *fullPath;
  204.     NSMutableDictionary *dict;
  205.     NSImageRep          *rep;
  206.     NSEnumerator        *repEnum;
  207.     NSImage             *im0;
  208.     NSImage             *im1;
  209.     NSData              *im0Data = nil;
  210.     NSData              *im1Data = nil;
  211.  
  212.     if (filePath == nil)
  213.         return [self saveAs:sender];
  214.  
  215.     // Create the info dict
  216.     dict = [NSMutableDictionary dictionaryWithCapacity:10];
  217.     
  218.     // Add the morph lines to the dict
  219.     [dict setObject:[self morphLines] forKey: DICT_MORPHLINES_KEY];
  220.  
  221.     // Get the NSData for the images
  222.     im0 = [self imageAtDelta:0.0];
  223.     im1 = [self imageAtDelta:1.0];
  224.  
  225.     repEnum = [[im0 representations] objectEnumerator];
  226.     while ((rep = [repEnum nextObject]))
  227.     {
  228.         if ([rep respondsToSelector:@selector(EPSRepresentation)])
  229.         {
  230.             im0Data = [rep performSelector:@selector(EPSRepresentation)];
  231.             [dict setObject:@"Image_0.eps"  forKey: DICT_IMAGE0_PATH_KEY];
  232.             break;
  233.         }
  234.     }
  235.     repEnum = [[im1 representations] objectEnumerator];
  236.     while ((rep = [repEnum nextObject]))
  237.     {
  238.         if ([rep respondsToSelector:@selector(EPSRepresentation)])
  239.         {
  240.             im1Data = [rep performSelector:@selector(EPSRepresentation)];
  241.             [dict setObject:@"Image_0.eps"  forKey: DICT_IMAGE1_PATH_KEY];
  242.             break;
  243.         }
  244.     }
  245.     if (im0Data == nil)
  246.     {
  247.         [dict setObject:@"Image_0.tiff"  forKey: DICT_IMAGE0_PATH_KEY];
  248.         im0Data = [im0 TIFFRepresentation];
  249.     }
  250.     if (im1Data == nil)
  251.     {
  252.         [dict setObject:@"Image_1.tiff"  forKey: DICT_IMAGE1_PATH_KEY];
  253.         im1Data = [im1 TIFFRepresentation];
  254.     }
  255.  
  256.     [dict setObject:[NSString stringWithFormat:@"%i", [frameHeightField intValue]] forKey:@"frameHeight"];
  257.     [dict setObject:[NSString stringWithFormat:@"%i", [frameWidthField intValue]] forKey:@"frameWidth"];
  258.     
  259.     // (Re)create the file package
  260.     dirPath = [self filePath];
  261.     fileManager = [NSFileManager defaultManager];
  262.     [fileManager removeFileAtPath:filePath handler:nil];
  263.     [fileManager createDirectoryAtPath:filePath attributes:nil];
  264.  
  265.     // Save the info plist
  266.     fullPath = [filePath stringByAppendingPathComponent:DICT_PATHCOMPONENT];
  267.     NSAssert1 ( [dict writeToFile:fullPath atomically:NO], @"Failed to write info dict %@", fullPath);
  268.  
  269.     // Save the image data
  270.     fullPath = [dirPath stringByAppendingPathComponent:[dict objectForKey: DICT_IMAGE0_PATH_KEY]];
  271.     NSAssert1 ( [im0Data writeToFile:fullPath atomically:NO], @"Failed to write image %@", fullPath);
  272.     fullPath = [dirPath stringByAppendingPathComponent:[dict objectForKey: DICT_IMAGE1_PATH_KEY]];
  273.     NSAssert1 ( [im1Data writeToFile:fullPath atomically:NO], @"Failed to write image %@", fullPath);
  274.  
  275.     [[self window] setDocumentEdited:NO];
  276. }
  277.  
  278. - (void) saveAs:sender
  279. {
  280.     NSSavePanel *sp;
  281.     NSString    *path;
  282.     NSString    *fname;
  283.     NSString    *dname;
  284.     int          result;
  285.  
  286.     [[self window] setDocumentEdited:NO];
  287.     path = [self filePath];
  288.     if (path)
  289.     {
  290.         dname = [path stringByDeletingLastPathComponent];
  291.         fname = [path lastPathComponent];
  292.     }
  293.     else
  294.     {
  295.         dname = NSHomeDirectory();
  296.         fname = nil;
  297.     }
  298.     sp = [NSSavePanel savePanel];
  299.     [sp setRequiredFileType: MORPH_DOC_EXTENTION];
  300.     result = [sp runModalForDirectory:dname file:fname];
  301.     if (result == NSOKButton)
  302.     {
  303.         path = [sp filename];
  304.         [self setFilePath:[sp filename]];
  305.         [self save:self];
  306.     }
  307. }
  308.  
  309. - (void) saveTo:sender
  310. {
  311.     [[self window] setDocumentEdited:NO];
  312.     return;
  313. }
  314.  
  315. - (void) saveFrames:sender
  316. {
  317.     NSString    *path;
  318.     NSString    *fullPath;
  319.     NSSavePanel *sp;
  320.     NSString    *dname;
  321.     NSString    *fname;
  322.     NSMutableDictionary *dict;
  323.     int             result;
  324.     NSFileManager    *fileManager;
  325.     int          frameCount;
  326.     NSSize         frameSize;
  327.     
  328.     path = [self filePath];
  329.     if (path)
  330.     {
  331.         dname = [path stringByDeletingLastPathComponent];
  332.         fname = [[path lastPathComponent] stringByDeletingPathExtension];
  333.     }
  334.     else
  335.     {
  336.         dname = NSHomeDirectory();
  337.         fname = nil;
  338.     }
  339.  
  340.     sp = [NSSavePanel savePanel];
  341.     [sp setRequiredFileType: XMOVIE_EXTENTION];
  342.     [sp setAccessoryView:frameSettingsView];
  343.     result = [sp runModalForDirectory:dname file:fname];
  344.     if (result != NSOKButton)
  345.         return;
  346.     
  347.     path = [sp filename];
  348.     frameCount = [frameCountField intValue];
  349.     frameSize.width = [frameWidthField floatValue];
  350.     frameSize.height = [frameHeightField floatValue];
  351.     
  352.     // (Re)create the file package
  353.     fileManager = [NSFileManager defaultManager];
  354.     [fileManager removeFileAtPath:path handler:nil];
  355.     [fileManager createDirectoryAtPath:path attributes:nil];
  356.  
  357.     // Save the info plist
  358.     fullPath = [path stringByAppendingPathComponent:DICT_PATHCOMPONENT];
  359.     dict = [NSMutableDictionary dictionaryWithCapacity:10];
  360.     // Insert code to fill the dictionary with usefull information
  361.     NSAssert1 ( [dict writeToFile:fullPath atomically:NO], @"Failed to write info dict %@", fullPath);
  362.  
  363.     [[self window] display];
  364.     
  365.     [self calcFramesAndSaveToPath:path count:frameCount size:frameSize];
  366.     [[[NSApplication sharedApplication] delegate] application:[NSApplication sharedApplication] openFile:path];
  367. }
  368.  
  369. - (void) selectAll:sender
  370. {
  371.     [selectedLines removeAllObjects];
  372.     [selectedLines addObjectsFromArray:[self morphLines]];
  373.     [[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:NOTIFICATION_SELECTION_CHANGED object:self]
  374.                                 postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:nil];
  375. }
  376.  
  377. - (void) selectNone:sender
  378. {
  379.     [selectedLines removeAllObjects];
  380.     [[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:NOTIFICATION_SELECTION_CHANGED object:self]
  381.                                 postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:nil];
  382. }
  383.  
  384. - (void) addToCurrentSelection:(id)obj
  385. {
  386.     if (obj != nil && ![selectedLines containsObject:obj])
  387.         [selectedLines addObject:obj];
  388.     [[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:NOTIFICATION_SELECTION_CHANGED object:self]
  389.                                 postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:nil];
  390. }
  391.  
  392. - (void) removeFromCurrentSelection:(id)obj
  393. {
  394.     if (obj != nil && [selectedLines containsObject:obj])
  395.     {
  396.         [selectedLines removeObject:obj];
  397.         [[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:NOTIFICATION_SELECTION_CHANGED object:self]
  398.                                     postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:nil];
  399.     }
  400. }
  401.  
  402. - (NSArray *) currentSelection
  403. {
  404.     return selectedLines;
  405. }
  406.  
  407. - (void) calcPreview:sender
  408. {
  409.     NSBitmapImageRep    *firstBitmap;
  410.     NSBitmapImageRep    *lastBitmap;
  411.     NSBitmapImageRep    *bitmap;
  412.     Morpher                *morpher;
  413.     float                  delta;
  414.     NSArray                *cells;
  415.     PreviewCell            *cell;
  416.     int                     i;
  417.     NSSize                size;
  418.     NSSize                winSize;
  419.  
  420.     firstBitmap = [[[self imageAtDelta:0] representations] lastObject];
  421.     lastBitmap = [[[self imageAtDelta:1] representations] lastObject];
  422.     cells = [previewMatrix cells];
  423.     size = [previewMatrix cellSize];
  424.  
  425.     [progressIndicator setDoubleValue:0];
  426.     winSize = size;
  427.     winSize.height += 20;
  428.     [progressIndicator setDoubleValue:0];
  429.     [[progressIndicator window] setContentSize:winSize];
  430.     [[progressIndicator window] makeKeyAndOrderFront:nil];
  431.     [[progressIndicator window] display];
  432.  
  433.     morpher = [[Morpher allocWithZone:[self zone]] initWithFirstBitmap:firstBitmap lastBitmap:lastBitmap morphLines:morphLines];
  434.     for (i = 0; i < [cells count]; ++i)
  435.     {
  436.         cell = [cells objectAtIndex:i];
  437.         delta = i / (float) ([cells count] - 1.0);
  438.  
  439.         [cell setShouldDrawLines:YES];
  440.         
  441.         [progressIndicator setDoubleValue:delta];
  442.         [progressIndicator display];
  443.         
  444.         bitmap = [[NSBitmapImageRep allocWithZone:[self zone]] initWithBitmapDataPlanes:NULL
  445.                                                                              pixelsWide:size.width
  446.                                                                              pixelsHigh:size.height
  447.                                                                           bitsPerSample:8
  448.                                                                         samplesPerPixel:3
  449.                                                                                hasAlpha:NO
  450.                                                                                isPlanar:NO
  451.                                                                          colorSpaceName:NSDeviceRGBColorSpace
  452.                                                                             bytesPerRow:(size.width + 1) * 3
  453.                                                                            bitsPerPixel:24];
  454.  
  455.         [morpher calcMorphBitmap:bitmap atDelta:delta];
  456.         [cell setBitmap:bitmap];
  457.         [cell setDelta:delta];
  458.         [cell setDelegate:self];
  459.         [previewMatrix display];
  460.  
  461.         [progressView lockFocus];
  462.         [bitmap draw];
  463.         [progressView unlockFocus];
  464.         [[progressView window] flushWindow];
  465.         [[NSDPSContext currentContext] flush];
  466.  
  467.         [bitmap release];
  468.     }
  469.     [morpher release];
  470.     [[progressIndicator window] orderOut:nil];
  471.  
  472.     return;
  473. }
  474.  
  475. - (void) calcFramesAndSaveToPath:(NSString *)dirPath count:(unsigned int)frameCount size:(NSSize)frameSize
  476. {
  477.     NSBitmapImageRep    *firstBitmap;
  478.     NSBitmapImageRep    *lastBitmap;
  479.     NSBitmapImageRep    *bitmap;
  480.     NSData                *data;
  481.     Morpher                *morpher;
  482.     float                 delta;
  483.     NSString            *path;
  484.     int                     frameNum = 0;
  485.     NSSize                 winSize;
  486.  
  487.     winSize = frameSize;
  488.     winSize.height += 20;
  489.     [progressIndicator setDoubleValue:0];
  490.     [[progressIndicator window] setContentSize:winSize];
  491.     [[progressIndicator window] makeKeyAndOrderFront:nil];
  492.     [[progressIndicator window] display];
  493.  
  494.     bitmap = [[NSBitmapImageRep allocWithZone:[self zone]] initWithBitmapDataPlanes:NULL pixelsWide:frameSize.width pixelsHigh:frameSize.height bitsPerSample:8 samplesPerPixel:3 hasAlpha:NO isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:(frameSize.width + 1) * 3 bitsPerPixel:24];
  495.     firstBitmap = [[[self imageAtDelta:0] representations] lastObject];
  496.     lastBitmap = [[[self imageAtDelta:1] representations] lastObject];
  497.  
  498.     morpher = [[Morpher allocWithZone:[self zone]] initWithFirstBitmap:firstBitmap lastBitmap:lastBitmap morphLines:morphLines];
  499.  
  500.     for (frameNum = 0; frameNum < frameCount; ++frameNum)
  501.     {
  502.         delta = frameNum / (float) (frameCount - 1.0);
  503.         [progressIndicator setDoubleValue:delta];
  504.         [progressIndicator display];
  505.  
  506.         [morpher calcMorphBitmap:bitmap atDelta:delta];
  507.  
  508.         [progressView lockFocus];
  509.         [bitmap draw];
  510.         [progressView unlockFocus];
  511.         [[progressView window] flushWindow];
  512.         [[NSDPSContext currentContext] flush];
  513.  
  514.         
  515.         data = [bitmap TIFFRepresentationUsingCompression:NSTIFFCompressionLZW factor:20];
  516.         path = [dirPath stringByAppendingPathComponent:[NSString stringWithFormat:@"Image_%d.tiff", frameNum]];
  517.         [data writeToFile:path atomically:NO];
  518.     }
  519.     [morpher release];
  520.     [[progressIndicator window] orderOut:nil];
  521. }
  522.  
  523. - (void)windowDidBecomeMain:(NSNotification *)notification
  524. {
  525.     [[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:NOTIFICATION_SELECTION_CHANGED object:self]
  526.                                 postingStyle:NSPostASAP coalesceMask:NSNotificationCoalescingOnName forModes:nil];
  527. }
  528. @end
  529.