// // AppController.m // Rat // // Created by Curtis Jones on 2009.11.10. // Copyright 2009 __MyCompanyName__. All rights reserved. // #import "AppController.h" @implementation AppController /** * * */ - (void)dealloc { [mazeView release]; [scrollView release]; [super dealloc]; } /** * * */ - (void)awakeFromNib { CFDataRef pixelData; CGImageRef image; CGDataProviderRef dataProvider; // initialize the ratlib library. this only needs to be done once. ratlib_init(); if (NULL == (dataProvider = CGDataProviderCreateWithFilename( [[[NSBundle mainBundle] pathForResource:@"maze" ofType:@"png"] UTF8String] ))) { NSLog(@"%s.. failed to CGDataProviderCreateWithFilename\n", __PRETTY_FUNCTION__); return; } if (NULL == (image = CGImageCreateWithPNGDataProvider(dataProvider, NULL, NO, kCGRenderingIntentDefault))) { NSLog(@"%s.. failed to CGImageCreateWithPNGDataProvider\n", __PRETTY_FUNCTION__); return; } if (NULL == (pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image)))) { NSLog(@"%s.. failed to CGDataProviderCopyData\n", __PRETTY_FUNCTION__); return; } // create a new image with some image data and parameters. mImage = ratlib_image(CFDataGetBytePtr(pixelData), 0, CGImageGetBitsPerPixel(image)/8, CGImageGetWidth(image), CGImageGetHeight(image)); // create a new session. ratlib supports multiple simultaneous sessions. each session has a single // image associated with it. the image data is not modified and can be shared between multiple // sessions mSession = ratlib_session(mImage); mazeView = [[MazeView alloc] initWithFrame:CGRectMake(0., 0., 100., 100.)]; mazeView.target = self; mazeView.selector = @selector(mouseDown:); mazeView.session = mSession; mazeView.image = image; // the scroll view is in the main window and holds the maze image scrollView = [[NSScrollView alloc] initWithFrame:[[theWindow contentView] frame]]; [scrollView setHasVerticalScroller:YES]; [scrollView setHasHorizontalScroller:YES]; [scrollView setBorderType:NSNoBorder]; [scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; [scrollView setDocumentView:mazeView]; [theWindow setContentView:scrollView]; [theWindow makeKeyAndOrderFront:nil]; /* CGImageRelease(image); CGDataProviderRelease(dataProvider); */ } #pragma mark - #pragma mark UI Callbacks /** * * */ - (IBAction)setBegPoint:(id)sender { mTargetModeBeg = TRUE; mTargetModeEnd = FALSE; [mazeView setTargetCursor:TRUE]; } /** * * */ - (IBAction)setEndPoint:(id)sender { mTargetModeBeg = FALSE; mTargetModeEnd = TRUE; [mazeView setTargetCursor:TRUE]; } /** * * */ - (IBAction)doActionSolve:(id)sender { if (mSession->begpoint == NULL || mSession->endpoint == NULL) { NSLog(@"%s.. must set a begin and end point before solving.", __PRETTY_FUNCTION__); return; } NSLog(@"%s.. starting thread...", __PRETTY_FUNCTION__); [NSThread detachNewThreadSelector:@selector(solveThread:) toTarget:self withObject:self]; } /** * * */ - (IBAction)doActionSave:(id)sender { uint32_t bytes; CGContextRef context; CGColorSpaceRef colorSpace; CGImageRef image; colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); bytes = 4 * mSession->image->width * mSession->image->height; if (NULL == (context = CGBitmapContextCreate(NULL, mSession->image->width, mSession->image->height, 8, 4*mSession->image->width, colorSpace, kCGImageAlphaPremultipliedLast))) { NSLog(@"%s.. failed to CGBitmapContextCreate. Sorry.", __PRETTY_FUNCTION__); return; } [mazeView drawRect:NSMakeRect(0, 0, mSession->image->width, mSession->image->height) inContext:context]; if (NULL == (image = CGBitmapContextCreateImage(context))) { NSLog(@"%s.. failed to CGBitmapContextCreateImage. Sorry.", __PRETTY_FUNCTION__); return; } NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:image]; NSData *imageData = [imageRep representationUsingType:NSPNGFileType properties:nil]; [imageData writeToFile:[@"~/Desktop/Solution.png" stringByExpandingTildeInPath] atomically:TRUE]; [imageRep release]; CGImageRelease(image); CGContextRelease(context); CGColorSpaceRelease(colorSpace); } #pragma mark - #pragma mark NSResponder - (void)mouseDown:(NSEvent*)theEvent { NSLog(@"%s..", __PRETTY_FUNCTION__); if (!mTargetModeBeg && !mTargetModeEnd) return; NSPoint point = [mazeView convertPoint:[theEvent locationInWindow] fromView:nil]; ratlibpoint_t *point2 = ratlib_point(point.x, mSession->image->height - point.y - 1); if (mTargetModeBeg) { ratlibsession_setbeg(mSession, point2); [[NSNotificationCenter defaultCenter] postNotificationName:@"MazeBeginPointSet" object:nil]; } else if (mTargetModeEnd) { ratlibsession_setend(mSession, point2); [[NSNotificationCenter defaultCenter] postNotificationName:@"MazeEndPointSet" object:nil]; } mTargetModeBeg = FALSE; mTargetModeEnd = FALSE; [mazeView setTargetCursor:FALSE]; ratlibpoint_release(point2); } #pragma mark - #pragma mark Solver - (void)solveThread:(id)arg { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ratlibsession_t *session = mSession; [self performSelectorOnMainThread:@selector(disableSolveMenuItem) withObject:nil waitUntilDone:FALSE]; ratlibsession_solve(session); [mazeView setNeedsDisplay:TRUE]; [self performSelectorOnMainThread:@selector(enableSolveMenuItem) withObject:nil waitUntilDone:FALSE]; [pool release]; } - (void)disableSolveMenuItem { [solveItem setEnabled:FALSE]; } - (void)enableSolveMenuItem { [solveItem setEnabled:TRUE]; } @end