project_files/HedgewarsMobile/Classes/MapConfigViewController.m
changeset 3697 d5b30d6373fc
parent 3670 4c673e57f0d7
child 3703 12d17c6e8855
equal deleted inserted replaced
3695:c11abf387a7d 3697:d5b30d6373fc
    26 
    26 
    27 #pragma mark -
    27 #pragma mark -
    28 #pragma mark Preview Handling
    28 #pragma mark Preview Handling
    29 -(int) sendToEngine: (NSString *)string {
    29 -(int) sendToEngine: (NSString *)string {
    30     unsigned char length = [string length];
    30     unsigned char length = [string length];
    31     
    31 
    32     SDLNet_TCP_Send(csd, &length , 1);
    32     SDLNet_TCP_Send(csd, &length , 1);
    33     return SDLNet_TCP_Send(csd, [string UTF8String], length);
    33     return SDLNet_TCP_Send(csd, [string UTF8String], length);
    34 }
    34 }
    35 
    35 
    36 -(const uint8_t *)engineProtocol:(NSInteger) port {
    36 -(const uint8_t *)engineProtocol:(NSInteger) port {
    37     IPaddress ip;
    37     IPaddress ip;
    38     BOOL serverQuit = NO;
    38     BOOL serverQuit = NO;
    39     static uint8_t map[128*32];
    39     static uint8_t map[128*32];
    40     
    40 
    41     if (SDLNet_Init() < 0) {
    41     if (SDLNet_Init() < 0) {
    42         DLog(@"SDLNet_Init: %s", SDLNet_GetError());
    42         DLog(@"SDLNet_Init: %s", SDLNet_GetError());
    43         serverQuit = YES;
    43         serverQuit = YES;
    44     }
    44     }
    45     
    45 
    46     // Resolving the host using NULL make network interface to listen
    46     // Resolving the host using NULL make network interface to listen
    47     if (SDLNet_ResolveHost(&ip, NULL, port) < 0) {
    47     if (SDLNet_ResolveHost(&ip, NULL, port) < 0) {
    48         DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
    48         DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
    49         serverQuit = YES;
    49         serverQuit = YES;
    50     }
    50     }
    51     
    51 
    52     // Open a connection with the IP provided (listen on the host's port)
    52     // Open a connection with the IP provided (listen on the host's port)
    53     if (!(sd = SDLNet_TCP_Open(&ip))) {
    53     if (!(sd = SDLNet_TCP_Open(&ip))) {
    54         DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), port);
    54         DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), port);
    55         serverQuit = YES;
    55         serverQuit = YES;
    56     }
    56     }
    57     
    57 
    58     // launch the preview here so that we're sure the tcp channel is open
    58     // launch the preview here so that we're sure the tcp channel is open
    59     pthread_t thread_id;
    59     pthread_t thread_id;
    60     pthread_create(&thread_id, NULL, (void *)GenLandPreview, (void *)port);
    60     pthread_create(&thread_id, NULL, (void *)GenLandPreview, (void *)port);
    61     pthread_detach(thread_id);
    61     pthread_detach(thread_id);
    62     
    62 
    63     DLog(@"Waiting for a client on port %d", port);
    63     DLog(@"Waiting for a client on port %d", port);
    64     while (!serverQuit) {
    64     while (!serverQuit) {
    65         /* This check the sd if there is a pending connection.
    65         /* This check the sd if there is a pending connection.
    66          * If there is one, accept that, and open a new socket for communicating */
    66          * If there is one, accept that, and open a new socket for communicating */
    67         csd = SDLNet_TCP_Accept(sd);
    67         csd = SDLNet_TCP_Accept(sd);
    68         if (NULL != csd) {          
    68         if (NULL != csd) {
    69             DLog(@"Client found");
    69             DLog(@"Client found");
    70             
    70 
    71             [self sendToEngine:self.seedCommand];
    71             [self sendToEngine:self.seedCommand];
    72             [self sendToEngine:self.templateFilterCommand];
    72             [self sendToEngine:self.templateFilterCommand];
    73             [self sendToEngine:self.mapGenCommand];
    73             [self sendToEngine:self.mapGenCommand];
    74             [self sendToEngine:self.mazeSizeCommand];
    74             [self sendToEngine:self.mazeSizeCommand];
    75             [self sendToEngine:@"!"];
    75             [self sendToEngine:@"!"];
    76                 
    76 
    77             memset(map, 0, 128*32);
    77             memset(map, 0, 128*32);
    78             SDLNet_TCP_Recv(csd, map, 128*32);
    78             SDLNet_TCP_Recv(csd, map, 128*32);
    79             SDLNet_TCP_Recv(csd, &maxHogs, sizeof(uint8_t));
    79             SDLNet_TCP_Recv(csd, &maxHogs, sizeof(uint8_t));
    80 
    80 
    81             SDLNet_TCP_Close(csd);
    81             SDLNet_TCP_Close(csd);
    82             serverQuit = YES;
    82             serverQuit = YES;
    83         }
    83         }
    84     }
    84     }
    85     
    85 
    86     SDLNet_TCP_Close(sd);
    86     SDLNet_TCP_Close(sd);
    87     SDLNet_Quit();
    87     SDLNet_Quit();
    88     return map;
    88     return map;
    89 }
    89 }
    90 
    90 
    91 -(void) drawingThread {
    91 -(void) drawingThread {
    92     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    92     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    93     
    93 
    94     // select the port for IPC and launch the preview generation through engineProtocol:
    94     // select the port for IPC and launch the preview generation through engineProtocol:
    95     int port = randomPort();
    95     int port = randomPort();
    96     const uint8_t *map = [self engineProtocol:port];
    96     const uint8_t *map = [self engineProtocol:port];
    97     uint8_t mapExp[128*32*8];
    97     uint8_t mapExp[128*32*8];
    98 
    98 
   112         }
   112         }
   113     }
   113     }
   114     CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
   114     CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
   115     CGContextRef bitmapImage = CGBitmapContextCreate(mapExp, 256, 128, 8, 256, colorspace, kCGImageAlphaNone);
   115     CGContextRef bitmapImage = CGBitmapContextCreate(mapExp, 256, 128, 8, 256, colorspace, kCGImageAlphaNone);
   116     CGColorSpaceRelease(colorspace);
   116     CGColorSpaceRelease(colorspace);
   117     
   117 
   118     CGImageRef previewCGImage = CGBitmapContextCreateImage(bitmapImage);
   118     CGImageRef previewCGImage = CGBitmapContextCreateImage(bitmapImage);
   119     CGContextRelease(bitmapImage);
   119     CGContextRelease(bitmapImage);
   120     UIImage *previewImage = [[UIImage alloc] initWithCGImage:previewCGImage];
   120     UIImage *previewImage = [[UIImage alloc] initWithCGImage:previewCGImage];
   121     CGImageRelease(previewCGImage);
   121     CGImageRelease(previewCGImage);
   122     previewCGImage = nil;
   122     previewCGImage = nil;
   123 
   123 
   124     // set the preview image (autoreleased) in the button and the maxhog label on the main thread to prevent a leak
   124     // set the preview image (autoreleased) in the button and the maxhog label on the main thread to prevent a leak
   125     [self performSelectorOnMainThread:@selector(setButtonImage:) withObject:[previewImage makeRoundCornersOfSize:CGSizeMake(12, 12)] waitUntilDone:NO];
   125     [self performSelectorOnMainThread:@selector(setButtonImage:) withObject:[previewImage makeRoundCornersOfSize:CGSizeMake(12, 12)] waitUntilDone:NO];
   126     [previewImage release];
   126     [previewImage release];
   127     [self performSelectorOnMainThread:@selector(setLabelText:) withObject:[NSString stringWithFormat:@"%d", maxHogs] waitUntilDone:NO];
   127     [self performSelectorOnMainThread:@selector(setLabelText:) withObject:[NSString stringWithFormat:@"%d", maxHogs] waitUntilDone:NO];
   128     
   128 
   129     // restore functionality of button and remove the spinning wheel on the main thread to prevent a leak
   129     // restore functionality of button and remove the spinning wheel on the main thread to prevent a leak
   130     [self performSelectorOnMainThread:@selector(turnOnWidgets) withObject:nil waitUntilDone:NO];
   130     [self performSelectorOnMainThread:@selector(turnOnWidgets) withObject:nil waitUntilDone:NO];
   131     
   131 
   132     [pool release];
   132     [pool release];
   133     //Invoking this method should be avoided as it does not give your thread a chance to clean up any resources it allocated during its execution.
   133     //Invoking this method should be avoided as it does not give your thread a chance to clean up any resources it allocated during its execution.
   134     //[NSThread exit];
   134     //[NSThread exit];
   135 
   135 
   136     /*
   136     /*
   137     // http://developer.apple.com/mac/library/qa/qa2001/qa1037.html
   137     // http://developer.apple.com/mac/library/qa/qa2001/qa1037.html
   138     UIGraphicsBeginImageContext(CGSizeMake(256,128));      
   138     UIGraphicsBeginImageContext(CGSizeMake(256,128));
   139     CGContextRef context = UIGraphicsGetCurrentContext();       
   139     CGContextRef context = UIGraphicsGetCurrentContext();
   140     UIGraphicsPushContext(context);  
   140     UIGraphicsPushContext(context);
   141 
   141 
   142     CGContextSetRGBFillColor(context, 0.5, 0.5, 0.7, 1.0);
   142     CGContextSetRGBFillColor(context, 0.5, 0.5, 0.7, 1.0);
   143     CGContextFillRect(context,CGRectMake(xc,yc,1,1));
   143     CGContextFillRect(context,CGRectMake(xc,yc,1,1));
   144     
   144 
   145     UIGraphicsPopContext();
   145     UIGraphicsPopContext();
   146     UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext();
   146     UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext();
   147     UIGraphicsEndImageContext();
   147     UIGraphicsEndImageContext();
   148     */
   148     */
   149 }
   149 }
   150 
   150 
   151 -(IBAction) updatePreview {
   151 -(IBAction) updatePreview {
   152     // don't generate a new preview while it's already generating one
   152     // don't generate a new preview while it's already generating one
   153     if (busy)
   153     if (busy)
   154         return;
   154         return;
   155     
   155 
   156     // generate a seed
   156     // generate a seed
   157     CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
   157     CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
   158     NSString *seed = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuid);
   158     NSString *seed = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuid);
   159     CFRelease(uuid);
   159     CFRelease(uuid);
   160     NSString *seedCmd = [[NSString alloc] initWithFormat:@"eseed {%@}", seed];
   160     NSString *seedCmd = [[NSString alloc] initWithFormat:@"eseed {%@}", seed];
   161     [seed release];
   161     [seed release];
   162     self.seedCommand = seedCmd;
   162     self.seedCommand = seedCmd;
   163     [seedCmd release];
   163     [seedCmd release];
   164     
   164 
   165     NSIndexPath *theIndex;
   165     NSIndexPath *theIndex;
   166     if (segmentedControl.selectedSegmentIndex != 1) {
   166     if (segmentedControl.selectedSegmentIndex != 1) {
   167         // remove the current preview and title
   167         // remove the current preview and title
   168         [self.previewButton setImage:nil forState:UIControlStateNormal];
   168         [self.previewButton setImage:nil forState:UIControlStateNormal];
   169         [self.previewButton setTitle:nil forState:UIControlStateNormal];
   169         [self.previewButton setTitle:nil forState:UIControlStateNormal];
   170         
   170 
   171         // don't display preview on slower device, too slow and memory hog
   171         // don't display preview on slower device, too slow and memory hog
   172         NSString *modelId = modelType();
   172         NSString *modelId = modelType();
   173         if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"]) {
   173         if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"]) {
   174             busy = NO;
   174             busy = NO;
   175             [self.previewButton setTitle:NSLocalizedString(@"Preview not available",@"") forState:UIControlStateNormal];
   175             [self.previewButton setTitle:NSLocalizedString(@"Preview not available",@"") forState:UIControlStateNormal];
   176         } else {
   176         } else {
   177             // prevent other events and add an activity while the preview is beign generated
   177             // prevent other events and add an activity while the preview is beign generated
   178             [self turnOffWidgets];
   178             [self turnOffWidgets];
   179             
   179 
   180             // add a very nice spinning wheel
   180             // add a very nice spinning wheel
   181             UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] 
   181             UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]
   182                                                   initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
   182                                                   initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
   183             indicator.center = CGPointMake(previewButton.bounds.size.width / 2, previewButton.bounds.size.height / 2);
   183             indicator.center = CGPointMake(previewButton.bounds.size.width / 2, previewButton.bounds.size.height / 2);
   184             indicator.tag = INDICATOR_TAG;
   184             indicator.tag = INDICATOR_TAG;
   185             [indicator startAnimating];
   185             [indicator startAnimating];
   186             [self.previewButton addSubview:indicator];
   186             [self.previewButton addSubview:indicator];
   187             [indicator release];
   187             [indicator release];
   188             
   188 
   189             // let's draw in a separate thread so the gui can work; at the end it restore other widgets
   189             // let's draw in a separate thread so the gui can work; at the end it restore other widgets
   190             [NSThread detachNewThreadSelector:@selector(drawingThread) toTarget:self withObject:nil];
   190             [NSThread detachNewThreadSelector:@selector(drawingThread) toTarget:self withObject:nil];
   191         }
   191         }
   192         
   192 
   193         theIndex = [NSIndexPath indexPathForRow:(random()%[self.themeArray count]) inSection:0];
   193         theIndex = [NSIndexPath indexPathForRow:(random()%[self.themeArray count]) inSection:0];
   194     } else {
   194     } else {
   195         theIndex = [NSIndexPath indexPathForRow:(random()%[self.mapArray count]) inSection:0];
   195         theIndex = [NSIndexPath indexPathForRow:(random()%[self.mapArray count]) inSection:0];
   196     }
   196     }
   197     [self.tableView reloadData];
   197     [self.tableView reloadData];
   205     NSString *fileImage = [[NSString alloc] initWithFormat:@"%@/%@/preview.png", MAPS_DIRECTORY(),[self.mapArray objectAtIndex:index]];
   205     NSString *fileImage = [[NSString alloc] initWithFormat:@"%@/%@/preview.png", MAPS_DIRECTORY(),[self.mapArray objectAtIndex:index]];
   206     UIImage *image = [[UIImage alloc] initWithContentsOfFile:fileImage];
   206     UIImage *image = [[UIImage alloc] initWithContentsOfFile:fileImage];
   207     [fileImage release];
   207     [fileImage release];
   208     [self.previewButton setImage:[image makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal];
   208     [self.previewButton setImage:[image makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal];
   209     [image release];
   209     [image release];
   210     
   210 
   211     // update label
   211     // update label
   212     maxHogs = 18;
   212     maxHogs = 18;
   213     NSString *fileCfg = [[NSString alloc] initWithFormat:@"%@/%@/map.cfg", MAPS_DIRECTORY(),[self.mapArray objectAtIndex:index]];
   213     NSString *fileCfg = [[NSString alloc] initWithFormat:@"%@/%@/map.cfg", MAPS_DIRECTORY(),[self.mapArray objectAtIndex:index]];
   214     NSString *contents = [[NSString alloc] initWithContentsOfFile:fileCfg encoding:NSUTF8StringEncoding error:NULL];
   214     NSString *contents = [[NSString alloc] initWithContentsOfFile:fileCfg encoding:NSUTF8StringEncoding error:NULL];
   215     [fileCfg release];
   215     [fileCfg release];
   217     [contents release];
   217     [contents release];
   218 
   218 
   219     // set the theme and map here
   219     // set the theme and map here
   220     self.themeCommand = [NSString stringWithFormat:@"etheme %@", [split objectAtIndex:0]];
   220     self.themeCommand = [NSString stringWithFormat:@"etheme %@", [split objectAtIndex:0]];
   221     self.staticMapCommand = [NSString stringWithFormat:@"emap %@", [self.mapArray objectAtIndex:index]];
   221     self.staticMapCommand = [NSString stringWithFormat:@"emap %@", [self.mapArray objectAtIndex:index]];
   222     
   222 
   223     // if the number is not set we keep 18 standard; 
   223     // if the number is not set we keep 18 standard;
   224     // sometimes it's not set but there are trailing characters, we get around them with the second equation
   224     // sometimes it's not set but there are trailing characters, we get around them with the second equation
   225     if ([split count] > 1 && [[split objectAtIndex:1] intValue] > 0)
   225     if ([split count] > 1 && [[split objectAtIndex:1] intValue] > 0)
   226         maxHogs = [[split objectAtIndex:1] intValue];
   226         maxHogs = [[split objectAtIndex:1] intValue];
   227     NSString *max = [[NSString alloc] initWithFormat:@"%d",maxHogs];
   227     NSString *max = [[NSString alloc] initWithFormat:@"%d",maxHogs];
   228     self.maxLabel.text = max;
   228     self.maxLabel.text = max;
   242     self.previewButton.alpha = 1.0f;
   242     self.previewButton.alpha = 1.0f;
   243     self.previewButton.enabled = YES;
   243     self.previewButton.enabled = YES;
   244     self.segmentedControl.enabled = YES;
   244     self.segmentedControl.enabled = YES;
   245     self.slider.enabled = YES;
   245     self.slider.enabled = YES;
   246     busy = NO;
   246     busy = NO;
   247     
   247 
   248     UIActivityIndicatorView *indicator = (UIActivityIndicatorView *)[self.previewButton viewWithTag:INDICATOR_TAG];
   248     UIActivityIndicatorView *indicator = (UIActivityIndicatorView *)[self.previewButton viewWithTag:INDICATOR_TAG];
   249     if (indicator) {
   249     if (indicator) {
   250         [indicator stopAnimating];
   250         [indicator stopAnimating];
   251         [indicator removeFromSuperview];
   251         [indicator removeFromSuperview];
   252     }
   252     }
   253 }
   253 }
   254  
   254 
   255 -(void) setLabelText:(NSString *)str {
   255 -(void) setLabelText:(NSString *)str {
   256     self.maxLabel.text = str;
   256     self.maxLabel.text = str;
   257 }
   257 }
   258 
   258 
   259 -(void) setButtonImage:(UIImage *)img {
   259 -(void) setButtonImage:(UIImage *)img {
   260     [self.previewButton setBackgroundImage:img forState:UIControlStateNormal];
   260     [self.previewButton setBackgroundImage:img forState:UIControlStateNormal];
   261 }
   261 }
   262 
   262 
   263 -(void) restoreBackgroundImage {
   263 -(void) restoreBackgroundImage {
   264     // white rounded rectangle as background image for previewButton
   264     // white rounded rectangle as background image for previewButton
   265     UIGraphicsBeginImageContext(CGSizeMake(256,128));      
   265     UIGraphicsBeginImageContext(CGSizeMake(256,128));
   266     CGContextRef context = UIGraphicsGetCurrentContext();       
   266     CGContextRef context = UIGraphicsGetCurrentContext();
   267     UIGraphicsPushContext(context);  
   267     UIGraphicsPushContext(context);
   268 
   268 
   269     CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
   269     CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
   270     CGContextFillRect(context,CGRectMake(0,0,256,128));
   270     CGContextFillRect(context,CGRectMake(0,0,256,128));
   271     
   271 
   272     UIGraphicsPopContext();
   272     UIGraphicsPopContext();
   273     UIImage *bkgImg = UIGraphicsGetImageFromCurrentImageContext();
   273     UIImage *bkgImg = UIGraphicsGetImageFromCurrentImageContext();
   274     UIGraphicsEndImageContext();
   274     UIGraphicsEndImageContext();
   275     [self.previewButton setBackgroundImage:[bkgImg makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal];
   275     [self.previewButton setBackgroundImage:[bkgImg makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal];
   276 }
   276 }
   289 }
   289 }
   290 
   290 
   291 -(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   291 -(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   292     static NSString *CellIdentifier = @"Cell";
   292     static NSString *CellIdentifier = @"Cell";
   293     NSInteger row = [indexPath row];
   293     NSInteger row = [indexPath row];
   294     
   294 
   295     UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
   295     UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
   296     if (cell == nil) 
   296     if (cell == nil)
   297         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
   297         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
   298     
   298 
   299     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
   299     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
   300         cell.textLabel.textColor = [UIColor colorWithRed:(CGFloat)0xFE/255 green:(CGFloat)0xCB/255 blue:0 alpha:1 ];
   300         cell.textLabel.textColor = [UIColor colorWithRed:(CGFloat)0xFE/255 green:(CGFloat)0xCB/255 blue:0 alpha:1 ];
   301     }
   301     }
   302     
   302 
   303     if (self.segmentedControl.selectedSegmentIndex != 1) {
   303     if (self.segmentedControl.selectedSegmentIndex != 1) {
   304         // the % prevents a strange bug that occurs sporadically
   304         // the % prevents a strange bug that occurs sporadically
   305         NSString *themeName = [self.themeArray objectAtIndex:row % [self.themeArray count]];
   305         NSString *themeName = [self.themeArray objectAtIndex:row % [self.themeArray count]];
   306         cell.textLabel.text = themeName;
   306         cell.textLabel.text = themeName;
   307         UIImage *image = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@/icon.png",THEMES_DIRECTORY(),themeName]];
   307         UIImage *image = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@/icon.png",THEMES_DIRECTORY(),themeName]];
   309         [image release];
   309         [image release];
   310     } else {
   310     } else {
   311         cell.textLabel.text = [self.mapArray objectAtIndex:row];
   311         cell.textLabel.text = [self.mapArray objectAtIndex:row];
   312         cell.imageView.image = nil;
   312         cell.imageView.image = nil;
   313     }
   313     }
   314     
   314 
   315     if (row == [self.lastIndexPath row]) 
   315     if (row == [self.lastIndexPath row])
   316         cell.accessoryType = UITableViewCellAccessoryCheckmark;
   316         cell.accessoryType = UITableViewCellAccessoryCheckmark;
   317     else
   317     else
   318         cell.accessoryType = UITableViewCellAccessoryNone;
   318         cell.accessoryType = UITableViewCellAccessoryNone;
   319 
   319 
   320     return cell;
   320     return cell;
   324 #pragma mark -
   324 #pragma mark -
   325 #pragma mark Table view delegate
   325 #pragma mark Table view delegate
   326 -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
   326 -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
   327     int newRow = [indexPath row];
   327     int newRow = [indexPath row];
   328     int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;
   328     int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;
   329     
   329 
   330     if (newRow != oldRow) {
   330     if (newRow != oldRow) {
   331         if (self.segmentedControl.selectedSegmentIndex != 1) {
   331         if (self.segmentedControl.selectedSegmentIndex != 1) {
   332             NSString *theme = [self.themeArray objectAtIndex:newRow];                
   332             NSString *theme = [self.themeArray objectAtIndex:newRow];
   333             self.themeCommand = [NSString stringWithFormat:@"etheme %@", theme];
   333             self.themeCommand = [NSString stringWithFormat:@"etheme %@", theme];
   334         } else {
   334         } else {
   335             // theme and map are set in the function below
   335             // theme and map are set in the function below
   336             [self updatePreviewWithMap:newRow];
   336             [self updatePreviewWithMap:newRow];
   337         }
   337         }
   338         
   338 
   339         UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath]; 
   339         UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath];
   340         newCell.accessoryType = UITableViewCellAccessoryCheckmark;
   340         newCell.accessoryType = UITableViewCellAccessoryCheckmark;
   341         UITableViewCell *oldCell = [aTableView cellForRowAtIndexPath:self.lastIndexPath];
   341         UITableViewCell *oldCell = [aTableView cellForRowAtIndexPath:self.lastIndexPath];
   342         oldCell.accessoryType = UITableViewCellAccessoryNone;
   342         oldCell.accessoryType = UITableViewCellAccessoryNone;
   343 
   343 
   344         self.lastIndexPath = indexPath;
   344         self.lastIndexPath = indexPath;
   353 // no methods are called by this routine and you can pass nil to it
   353 // no methods are called by this routine and you can pass nil to it
   354 -(IBAction) sliderChanged:(id) sender {
   354 -(IBAction) sliderChanged:(id) sender {
   355     NSString *labelText;
   355     NSString *labelText;
   356     NSString *templateCommand;
   356     NSString *templateCommand;
   357     NSString *mazeCommand;
   357     NSString *mazeCommand;
   358     
   358 
   359     switch ((int)(self.slider.value*100)) {
   359     switch ((int)(self.slider.value*100)) {
   360         case 0:
   360         case 0:
   361             if (self.segmentedControl.selectedSegmentIndex == 0) {
   361             if (self.segmentedControl.selectedSegmentIndex == 0) {
   362                 labelText = NSLocalizedString(@"Wacky",@"");
   362                 labelText = NSLocalizedString(@"Wacky",@"");
   363             } else {
   363             } else {
   415             labelText = nil;
   415             labelText = nil;
   416             templateCommand = nil;
   416             templateCommand = nil;
   417             mazeCommand = nil;
   417             mazeCommand = nil;
   418             break;
   418             break;
   419     }
   419     }
   420     
   420 
   421     self.sizeLabel.text = labelText;
   421     self.sizeLabel.text = labelText;
   422     self.templateFilterCommand = templateCommand;
   422     self.templateFilterCommand = templateCommand;
   423     self.mazeSizeCommand = mazeCommand;
   423     self.mazeSizeCommand = mazeCommand;
   424 }
   424 }
   425 
   425 
   430         [self updatePreview];
   430         [self updatePreview];
   431         oldValue = num;
   431         oldValue = num;
   432     }
   432     }
   433 }
   433 }
   434 
   434 
   435 // perform actions based on the activated section, then call updatePreview to visually update the selection 
   435 // perform actions based on the activated section, then call updatePreview to visually update the selection
   436 // updatePreview will call didSelectRowAtIndexPath which will call the right update routine)
   436 // updatePreview will call didSelectRowAtIndexPath which will call the right update routine)
   437 // and if necessary update the table with a slide animation
   437 // and if necessary update the table with a slide animation
   438 -(IBAction) segmentedControlChanged:(id) sender {
   438 -(IBAction) segmentedControlChanged:(id) sender {
   439     NSString *mapgen, *staticmap;
   439     NSString *mapgen, *staticmap;
   440     NSInteger newPage = self.segmentedControl.selectedSegmentIndex;
   440     NSInteger newPage = self.segmentedControl.selectedSegmentIndex;
   441     
   441 
   442     switch (newPage) {
   442     switch (newPage) {
   443         case 0: // Random
   443         case 0: // Random
   444             mapgen = @"e$mapgen 0";
   444             mapgen = @"e$mapgen 0";
   445             staticmap = @"";
   445             staticmap = @"";
   446             [self sliderChanged:nil];
   446             [self sliderChanged:nil];
   447             self.slider.enabled = YES;
   447             self.slider.enabled = YES;
   448             break;
   448             break;
   449             
   449 
   450         case 1: // Map
   450         case 1: // Map
   451             mapgen = @"e$mapgen 0";
   451             mapgen = @"e$mapgen 0";
   452             // dummy value, everything is set by -updatePreview -> -didSelectRowAtIndexPath -> -updatePreviewWithMap
   452             // dummy value, everything is set by -updatePreview -> -didSelectRowAtIndexPath -> -updatePreviewWithMap
   453             staticmap = @"map Bamboo";
   453             staticmap = @"map Bamboo";
   454             self.slider.enabled = NO;
   454             self.slider.enabled = NO;
   455             self.sizeLabel.text = @".";
   455             self.sizeLabel.text = @".";
   456             [self restoreBackgroundImage];
   456             [self restoreBackgroundImage];
   457             break;
   457             break;
   458             
   458 
   459         case 2: // Maze
   459         case 2: // Maze
   460             mapgen = @"e$mapgen 1";
   460             mapgen = @"e$mapgen 1";
   461             staticmap = @"";
   461             staticmap = @"";
   462             [self sliderChanged:nil];
   462             [self sliderChanged:nil];
   463             self.slider.enabled = YES;
   463             self.slider.enabled = YES;
   464             break;
   464             break;
   465         
   465 
   466         default:
   466         default:
   467             mapgen = nil;
   467             mapgen = nil;
   468             staticmap = nil;
   468             staticmap = nil;
   469             break;
   469             break;
   470     }
   470     }
   471     self.mapGenCommand = mapgen;
   471     self.mapGenCommand = mapgen;
   472     self.staticMapCommand = staticmap;
   472     self.staticMapCommand = staticmap;
   473     [self updatePreview];
   473     [self updatePreview];
   474     
   474 
   475     // nice animation for updating the table when appropriate (on iphone)
   475     // nice animation for updating the table when appropriate (on iphone)
   476     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
   476     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
   477         if (((oldPage == 0 || oldPage == 2) && newPage == 1) ||
   477         if (((oldPage == 0 || oldPage == 2) && newPage == 1) ||
   478             (oldPage == 1 && (newPage == 0 || newPage == 2))) {
   478             (oldPage == 1 && (newPage == 0 || newPage == 2))) {
   479             [UIView beginAnimations:@"moving out table" context:NULL];
   479             [UIView beginAnimations:@"moving out table" context:NULL];
   485 }
   485 }
   486 
   486 
   487 // update data when table is not visible and then show it
   487 // update data when table is not visible and then show it
   488 -(void) moveTable {
   488 -(void) moveTable {
   489     [self.tableView reloadData];
   489     [self.tableView reloadData];
   490     
   490 
   491     [UIView beginAnimations:@"moving in table" context:NULL];
   491     [UIView beginAnimations:@"moving in table" context:NULL];
   492     self.tableView.frame = CGRectMake(295, 0, 185, 276);
   492     self.tableView.frame = CGRectMake(295, 0, 185, 276);
   493     [UIView commitAnimations];
   493     [UIView commitAnimations];
   494 }
   494 }
   495 
   495 
   496 #pragma mark -
   496 #pragma mark -
   497 #pragma mark view management
   497 #pragma mark view management
   498 -(void) viewDidLoad {
   498 -(void) viewDidLoad {
   499     [super viewDidLoad];
   499     [super viewDidLoad];
   500     
   500 
   501     srandom(time(NULL));
   501     srandom(time(NULL));
   502     
   502 
   503     CGSize screenSize = [[UIScreen mainScreen] bounds].size;
   503     CGSize screenSize = [[UIScreen mainScreen] bounds].size;
   504     self.view.frame = CGRectMake(0, 0, screenSize.height, screenSize.width - 44);
   504     self.view.frame = CGRectMake(0, 0, screenSize.height, screenSize.width - 44);
   505 
   505 
   506     // themes.cfg contains all the user-selectable themes
   506     // themes.cfg contains all the user-selectable themes
   507     NSString *string = [[NSString alloc] initWithContentsOfFile:[THEMES_DIRECTORY() stringByAppendingString:@"/themes.cfg"]
   507     NSString *string = [[NSString alloc] initWithContentsOfFile:[THEMES_DIRECTORY() stringByAppendingString:@"/themes.cfg"]
   508                                                        encoding:NSUTF8StringEncoding 
   508                                                        encoding:NSUTF8StringEncoding
   509                                                           error:NULL];
   509                                                           error:NULL];
   510     NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[string componentsSeparatedByString:@"\n"]];
   510     NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[string componentsSeparatedByString:@"\n"]];
   511     [string release];
   511     [string release];
   512     // remove a trailing "" element
   512     // remove a trailing "" element
   513     [array removeLastObject];
   513     [array removeLastObject];
   515     [array release];
   515     [array release];
   516     self.mapArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:MAPS_DIRECTORY() error:NULL];
   516     self.mapArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:MAPS_DIRECTORY() error:NULL];
   517 
   517 
   518     self.tableView.rowHeight = 42;
   518     self.tableView.rowHeight = 42;
   519     busy = NO;
   519     busy = NO;
   520     
   520 
   521     // draw a white background
   521     // draw a white background
   522     [self restoreBackgroundImage];
   522     [self restoreBackgroundImage];
   523     
   523 
   524     // initialize some "default" values
   524     // initialize some "default" values
   525     self.sizeLabel.text = NSLocalizedString(@"All",@"");
   525     self.sizeLabel.text = NSLocalizedString(@"All",@"");
   526     self.slider.value = 0.05f;
   526     self.slider.value = 0.05f;
   527     
   527 
   528     // on slower device we show directly the static map
   528     // on slower device we show directly the static map
   529     NSString *modelId = modelType();
   529     NSString *modelId = modelType();
   530     if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"])
   530     if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"])
   531         self.segmentedControl.selectedSegmentIndex = 1;
   531         self.segmentedControl.selectedSegmentIndex = 1;
   532     else
   532     else
   534 
   534 
   535     self.templateFilterCommand = @"e$template_filter 0";
   535     self.templateFilterCommand = @"e$template_filter 0";
   536     self.mazeSizeCommand = @"e$maze_size 0";
   536     self.mazeSizeCommand = @"e$maze_size 0";
   537     self.mapGenCommand = @"e$mapgen 0";
   537     self.mapGenCommand = @"e$mapgen 0";
   538     self.staticMapCommand = @"";
   538     self.staticMapCommand = @"";
   539     
   539 
   540     self.lastIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
   540     self.lastIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
   541     
   541 
   542     oldValue = 5;
   542     oldValue = 5;
   543     oldPage = 0;
   543     oldPage = 0;
   544 }
   544 }
   545 
   545 
   546 -(void) viewDidAppear:(BOOL) animated {
   546 -(void) viewDidAppear:(BOOL) animated {
   560     self.templateFilterCommand = nil;
   560     self.templateFilterCommand = nil;
   561     self.mapGenCommand = nil;
   561     self.mapGenCommand = nil;
   562     self.mazeSizeCommand = nil;
   562     self.mazeSizeCommand = nil;
   563     self.themeCommand = nil;
   563     self.themeCommand = nil;
   564     self.staticMapCommand = nil;
   564     self.staticMapCommand = nil;
   565     
   565 
   566     self.previewButton = nil;
   566     self.previewButton = nil;
   567     self.tableView = nil;
   567     self.tableView = nil;
   568     self.maxLabel = nil;
   568     self.maxLabel = nil;
   569     self.sizeLabel = nil;
   569     self.sizeLabel = nil;
   570     self.segmentedControl = nil;
   570     self.segmentedControl = nil;
   571     self.slider = nil;
   571     self.slider = nil;
   572     
   572 
   573     self.lastIndexPath = nil;
   573     self.lastIndexPath = nil;
   574     self.themeArray = nil;
   574     self.themeArray = nil;
   575     self.mapArray = nil;
   575     self.mapArray = nil;
   576     
   576 
   577     MSG_DIDUNLOAD();
   577     MSG_DIDUNLOAD();
   578     [super viewDidUnload];
   578     [super viewDidUnload];
   579 }
   579 }
   580 
   580 
   581 -(void) dealloc {
   581 -(void) dealloc {
   583     [templateFilterCommand release];
   583     [templateFilterCommand release];
   584     [mapGenCommand release];
   584     [mapGenCommand release];
   585     [mazeSizeCommand release];
   585     [mazeSizeCommand release];
   586     [themeCommand release];
   586     [themeCommand release];
   587     [staticMapCommand release];
   587     [staticMapCommand release];
   588     
   588 
   589     [previewButton release];
   589     [previewButton release];
   590     [tableView release];
   590     [tableView release];
   591     [maxLabel release];
   591     [maxLabel release];
   592     [sizeLabel release];
   592     [sizeLabel release];
   593     [segmentedControl release];
   593     [segmentedControl release];
   594     [slider release];
   594     [slider release];
   595     
   595 
   596     [lastIndexPath release];
   596     [lastIndexPath release];
   597     [themeArray release];
   597     [themeArray release];
   598     [mapArray release];
   598     [mapArray release];
   599     
   599 
   600     [super dealloc];
   600     [super dealloc];
   601 }
   601 }
   602 
   602 
   603 
   603 
   604 @end
   604 @end