// // SingleCache.m // Geopher OpenCaching // // Created by Jeremy on 12/11/10. // Copyright 2010 Stone Software. All rights reserved. // #import "SingleCache.h" #import "JSON.h" #import "Geopher_OpenCachingAppDelegate.h" #import "LocatorModel.h" #import "CompassViewController.h" @implementation SingleCache @synthesize spinner, textView, setTargetButton, cacheName, cacheDescription, cacheID, cacheType, cacheHint, cacheOxcode, cacheOwnerName, cacheActive, cacheTags, cacheLogs, cacheAwesomeness, cacheSize, cacheLastUpdated, cacheDifficultyRating, cacheHiddenDate, cacheOwnerID, cacheLatitude, cacheLongitude, cacheTerrain, tableView; @synthesize size = _size; @synthesize rating = _rating; @synthesize terrain = _terrain; @synthesize difficulty = _difficulty; @synthesize description = _description; @synthesize logText = _logTextView; @synthesize info = _info; @synthesize name = _name; @synthesize logName = _logName; @synthesize logDate = _logDate; #pragma mark - - (IBAction) sendToNavigon:(id)sender { NSString* scheme = @"navigon"; // urlAsString = [NSString stringWithFormat:@"%@://%@|%@|%@|%@|%@|%@|%@|%f|%f", NSString* urlAsString = [NSString stringWithFormat:@"%@://%@|%@||||||%f|%f", scheme, @"OpenCaching", // Field1/AppName:Application or Company Name (e.g. AroundMe) cacheName, // Field2/NameOfPOI: Name of POI (e.g. Navigon AG Würzburg) // @"FRA", // Field3/Country: ISO 3166-1 alpha-3 code for country (http://unstats.un.org/unsd/methods/m49/m49alpha.htm) (e.g. DEU) // @"", // Field4/ZipCode: Postalcode, ZIP code of the POIs city (e.g. 97080) // @"", // Field5/City: Name of POIs city (e.g. Würzburg) // thePOI.location.streetAddress, // Field6/Street:POIs street name (e.g. Berliner Platz) // @"", // Field7/HouseNumber: POIs street/house number (e.g. 11) [cacheLongitude doubleValue], // Field8/Longitude: Longitude in WGS84 (e.g. 9.870) [cacheLatitude doubleValue]]; // Field9/Latitude: Latitude in WGS84 (e.g. 49.938) urlAsString = [urlAsString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; // NSLog(@"Starting Navigon app with %@", urlAsString); NSURL*url = [[[NSURL alloc] initWithString:urlAsString] autorelease]; [[UIApplication sharedApplication ]openURL:url]; } - (IBAction) setTargetLocation:(id)sender { Geopher_OpenCachingAppDelegate* del = GetAppDelegate(); [del setNewTargetWithLatitude:[self.cacheLatitude stringValue] longitude:[self.cacheLongitude stringValue]]; // set target from lat/lon here CLLocation* location = [[[CLLocation alloc] initWithLatitude:[self.cacheLatitude doubleValue] longitude:[self.cacheLongitude doubleValue]] autorelease]; [[LocatorModel sharedInstance] setTargetLocation:location]; CompassViewController* navController = [GetAppDelegate() compassScreen]; // auto-swap to the compass view CGContextRef context = UIGraphicsGetCurrentContext(); [UIView beginAnimations:nil context:context]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDuration:1.0]; [UIView transitionFromView:self.navigationController.view toView:navController.view duration:0.75 options:UIViewAnimationOptionTransitionCurlDown completion:^(BOOL finished) { [self.tabBarController setSelectedIndex:[self.tabBarController.viewControllers indexOfObject:navController]]; }]; [UIView commitAnimations]; } - (void) loadCacheWithCode:(NSString*)cache { NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/api/geocache/%@?%@", kOpenCachingURL, cache, kDeveloperSiteAuthenticationKey]]]; [[NSURLConnection alloc] initWithRequest:request delegate:self]; [self.spinner startAnimating]; self.setTargetButton.enabled = NO; self.navigationItem.backBarButtonItem.enabled = NO; } - (NSString*) removeHTML:(NSString*)inString { #warning html stripping not done! // OC.com supports these codes: BR, P, B, I, OL, UL, LI, PRE, BLOCKQUOTE, STRONG, EM, H1, H2, H3, H4, H5, H6 //
and

to returns? // now strip all other HTML out: NSScanner *theScanner; NSString *text = nil; theScanner = [NSScanner scannerWithString:inString]; while ([theScanner isAtEnd] == NO) { NSString* replaceStr = @" "; // find start of tag [theScanner scanUpToString:@"<" intoString:nil] ; // find end of tag [theScanner scanUpToString:@">" intoString:&text] ; // replace certain tags with text equivalent if ([@"", text] withString:replaceStr]; } // while // return inString; } //#pragma mark - //#pragma mark Table View // //- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath //{ //} #pragma mark - #pragma mark Table View data source - (NSInteger)tableView:(UITableView *)inTableView numberOfRowsInSection:(NSInteger)section { return kStandardRows + [cacheLogs count]; } - (UITableViewCell *)tableView:(UITableView *)inTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // get the appropriate cell NSString* cellIdentifier; switch (indexPath.row) { case kStatsRow: cellIdentifier = @"StatsRowCell"; break; case kNameRow: cellIdentifier = @"NameRow"; break; case kDescriptionRow: cellIdentifier = @"DescriptionRow"; break; case kHintRow: cellIdentifier = @"HintRow"; break; case kInfoRow: cellIdentifier = @"MiscInfoRow"; break; case kLogRow: default: cellIdentifier = @"LogRow"; break; } // get the cached cell object if it exists // otherwise create a cell UITableViewCell *cell = [inTableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { // this loads the cell from the xib and links it to our outlet, since we are the owner. [[NSBundle mainBundle] loadNibNamed:@"SingleCacheTableCells" owner:self options:nil]; } // fill the cell's details. switch (indexPath.row) { case kStatsRow: cell = statsCell; // set up the height, size, etc of the row. self.difficulty.text = [NSString stringWithFormat:@"%.1f Difficulty", [self.cacheDifficultyRating doubleValue]]; self.rating.text = [NSString stringWithFormat:@"%.1f Awesomeness", [self.cacheAwesomeness doubleValue]]; self.terrain.text = [NSString stringWithFormat:@"%.1f Terrain", [self.cacheTerrain doubleValue]]; self.size.text = [NSString stringWithFormat:@"%.1f Cache Size", [self.cacheSize doubleValue]]; break; case kNameRow: cell = nameCell; self.name.text = self.cacheName; self.name.textColor = kEveningBlueColor; break; case kDescriptionRow: cell = descriptionCell; self.description.text = [self removeHTML:self.cacheDescription]; break; case kHintRow: hintButton.layer.cornerRadius = kButtonCornerRadius; hintButton.layer.masksToBounds = YES; hintButton.layer.borderWidth = kButtonBorderWidth; [hintButton setTitleColor:kButtonTextColor forState:UIControlStateNormal]; hintButton.layer.borderColor = [kDirtBrownColor CGColor]; navigonButton.layer.cornerRadius = kButtonCornerRadius; navigonButton.layer.masksToBounds = YES; navigonButton.layer.borderWidth = kButtonBorderWidth; [navigonButton setTitleColor:kButtonTextColor forState:UIControlStateNormal]; navigonButton.layer.borderColor = [kDirtBrownColor CGColor]; cell = hintCell; break; case kInfoRow: cell = infoCell; #warning not yet done, what do we want here? break; default: cell = logCell; // logs row if (indexPath.row) { NSDictionary* dict = [cacheLogs objectAtIndex:indexPath.row - kTotalNumberOfSetRowTypes]; self.logText.text = [dict objectForKey:kLogCommentOXKey]; self.logName.text = [[dict objectForKey:kLogCommentUserOXKey] objectForKey:kLogCommentUserNameOXKey]; self.logName.textColor = kEveningBlueColor; self.logDate.text = @" "; } break; } cell.backgroundColor = [UIColor clearColor]; return cell; } - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { return nil; } - (CGFloat)tableView:(UITableView *)inTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { CGFloat height = ([self tableView:inTableView cellForRowAtIndexPath:indexPath]).frame.size.height; if (indexPath.row >= kTotalNumberOfSetRowTypes) { NSDictionary* dict = [cacheLogs objectAtIndex:indexPath.row - kTotalNumberOfSetRowTypes]; NSString* text = [dict objectForKey:kLogCommentOXKey]; if (text) { // calc the size of the text for the log CGFloat preHeight = [_logTextView.text sizeWithFont:_logTextView.font].height; CGSize sz = [_logTextView.text sizeWithFont:_logTextView.font constrainedToSize:CGSizeMake(_logTextView.bounds.size.width-20, preHeight * 20)]; height = sz.height + lrint(preHeight * 2.5); height += 10 + _logName.frame.size.height; } } return height; } #pragma mark - #pragma mark request delegate - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { [responseData setLength:0]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [responseData appendData:data]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSLog(@"Connection failed: %@", [error description]); [self.spinner stopAnimating]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { [connection release]; NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; [responseData release]; NSError *error; SBJSON *json = [[SBJSON new] autorelease]; NSDictionary *cacheResults = [json objectWithString:responseString error:&error]; [responseString autorelease]; if (cacheResults == nil) { NSLog(@"JSON parsing failed: %@", [error localizedDescription]); UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[self removeHTML:responseString] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [alert release]; } else { NSMutableString *text = [NSMutableString string]; NSArray* allKeys = [cacheResults allKeys]; for (id key in allKeys) { [text appendFormat:@"%@: %@", key, [[cacheResults objectForKey:key] description]]; [text appendString:@"\r"]; textView.text = text; } self.cacheName = [cacheResults objectForKey:kNameOXKey]; self.cacheDescription = [cacheResults objectForKey:kDescriptionOXKey]; self.cacheID = [cacheResults objectForKey:kIDOXKey]; self.cacheType = [cacheResults objectForKey:kTypeOXKey]; self.cacheHint = [cacheResults objectForKey:kHintOXKey]; self.cacheOxcode = [cacheResults objectForKey:kOXCodeOXKey]; self.cacheActive = [cacheResults objectForKey:kActiveOXKey]; self.cacheTags = [cacheResults objectForKey:kTagsOXKey]; self.cacheLogs = [cacheResults objectForKey:kLogsOXKey]; self.cacheAwesomeness = [cacheResults objectForKey:kAwesomenessOXKey]; self.cacheSize = [cacheResults objectForKey:kSizeOXKey]; self.cacheLastUpdated = [cacheResults objectForKey:kLastUpdatedOXKey]; self.cacheDifficultyRating = [cacheResults objectForKey:kDifficultyOXKey]; self.cacheHiddenDate = [cacheResults objectForKey:kHiddenDateOXKey]; self.cacheTerrain = [cacheResults objectForKey:kTerrainOXKey]; self.cacheOwnerID = [[cacheResults objectForKey:kHiddenByOXKey] objectForKey:kIDOXKey]; self.cacheOwnerName = [[cacheResults objectForKey:kHiddenByOXKey] objectForKey:kHiddenByNameOXKey]; self.cacheLatitude = [[cacheResults objectForKey:kLocationOXKey] objectForKey:kLatitudeOXKey]; self.cacheLongitude = [[cacheResults objectForKey:kLocationOXKey] objectForKey:kLongitudeOXKey]; [tableView reloadData]; tableView.hidden = NO; } // save the results to disk here, later we will read these results if we don't have a current connection. [self.spinner stopAnimating]; self.setTargetButton.enabled = YES; self.navigationItem.backBarButtonItem.enabled = YES; } #pragma mark - - (void) loadCacheWithInfo:(NSDictionary*)info { self.cacheName = [info objectForKey:kNameOXKey]; self.cacheDescription = [info objectForKey:kDescriptionOXKey]; self.cacheID = [info objectForKey:kIDOXKey]; self.cacheType = [info objectForKey:kTypeOXKey]; self.cacheHint = [info objectForKey:kHintOXKey]; self.cacheOxcode = [info objectForKey:kOXCodeOXKey]; self.cacheActive = [info objectForKey:kActiveOXKey]; self.cacheTags = [info objectForKey:kTagsOXKey]; self.cacheLogs = [info objectForKey:kLogsOXKey]; self.cacheAwesomeness = [info objectForKey:kAwesomenessOXKey]; self.cacheSize = [info objectForKey:kSizeOXKey]; self.cacheLastUpdated = [info objectForKey:kLastUpdatedOXKey]; self.cacheDifficultyRating = [info objectForKey:kDifficultyOXKey]; self.cacheHiddenDate = [info objectForKey:kHiddenDateOXKey]; self.cacheTerrain = [info objectForKey:kTerrainOXKey]; self.cacheOwnerID = [[info objectForKey:kHiddenByOXKey] objectForKey:kIDOXKey]; self.cacheOwnerName = [[info objectForKey:kHiddenByOXKey] objectForKey:kHiddenByNameOXKey]; self.cacheLatitude = [[info objectForKey:kLocationOXKey] objectForKey:kLatitudeOXKey]; self.cacheLongitude = [[info objectForKey:kLocationOXKey] objectForKey:kLongitudeOXKey]; [tableView reloadData]; } #pragma mark - #pragma mark view lifecycle // The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization. responseData = [[NSMutableData alloc] init]; self.cacheName = nil; self.cacheDescription = nil; self.cacheID = nil; self.cacheType = nil; self.cacheHint = nil; self.cacheOxcode = nil; self.cacheActive = nil; self.cacheTags = nil; self.cacheLogs = nil; self.cacheAwesomeness = nil; self.cacheSize = nil; self.cacheLastUpdated = nil; self.cacheDifficultyRating = nil; self.cacheHiddenDate = nil; self.cacheTerrain = nil; self.cacheOwnerID = nil; self.cacheOwnerName = nil; self.cacheLatitude = nil; self.cacheLongitude = nil; } return self; } // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { [super viewDidLoad]; // setup buttons. In the GUI someday. Maybe. setTargetButton.layer.cornerRadius = kButtonCornerRadius; setTargetButton.layer.masksToBounds = YES; setTargetButton.layer.borderWidth = kButtonBorderWidth; setTargetButton.layer.borderColor = [kDirtBrownColor CGColor]; [setTargetButton setTitleColor:kButtonTextColor forState:UIControlStateNormal]; [self.spinner startAnimating]; } /* // Override to allow orientations other than the default portrait orientation. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations. return (interfaceOrientation == UIInterfaceOrientationPortrait); } */ - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc. that aren't in use. } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (void)dealloc { [textView release]; [setTargetButton release]; [spinner release]; [tableView release]; // cells [statsCell release]; [nameCell release]; [descriptionCell release]; [hintCell release]; [infoCell release]; [logCell release]; // UI details [_difficulty release]; [_size release]; [_rating release]; [_terrain release]; [_description release]; [_logTextView release]; [_info release]; [_logName release]; [_logDate release]; // cache items [cacheName release]; [cacheDescription release]; [cacheID release]; [cacheType release]; [cacheHint release]; [cacheOxcode release]; [cacheOwnerName release]; [cacheActive release]; [cacheTags release]; [cacheLogs release]; [cacheAwesomeness release]; [cacheSize release]; [cacheLastUpdated release]; [cacheDifficultyRating release]; [cacheHiddenDate release]; [cacheOwnerID release]; [cacheTerrain release]; [cacheLatitude release]; [cacheLongitude release]; [super dealloc]; } @end