[ios][search] Display compass for near features in search results

This commit is contained in:
Alex Zolotarev 2012-02-16 13:51:44 +03:00 committed by Alex Zolotarev
parent 90d2a193ec
commit 51fe3127bd
6 changed files with 94 additions and 51 deletions

View file

@ -4,4 +4,6 @@
@interface CompassView : UIView
// Rotation angle in radians (decart system)
@property (nonatomic, assign) float angle;
// Image to display instead of compass arrow
@property (nonatomic, retain) UIImage * image;
@end

View file

@ -3,6 +3,7 @@
@implementation CompassView
@synthesize angle;
@synthesize image;
- (id)initWithFrame:(CGRect)frame
{
@ -21,29 +22,44 @@
[self setNeedsDisplay];
}
// Draws an arrow looking to the right like this:
// =>
// and rotates it to given angle
- (void)setImage:(UIImage *)aImage
{
[image release];
image = aImage;
[image retain];
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
UIBezierPath * aPath = [UIBezierPath bezierPath];
float const w = rect.size.width;
float const w2 = w / 2.0;
float const w3 = w / 3.0;
[aPath moveToPoint:CGPointMake(w3, w2)];
[aPath addLineToPoint:CGPointMake(0, w2 - w3)];
[aPath addLineToPoint:CGPointMake(w, w2)];
[aPath addLineToPoint:CGPointMake(0, w2 + w3)];
[aPath closePath];
CGAffineTransform matrix = CGAffineTransformMakeTranslation(w2, w2);
matrix = CGAffineTransformRotate(matrix, -angle);
matrix = CGAffineTransformTranslate(matrix, -w2, -w2);
[aPath applyTransform:matrix];
[[UIColor blueColor] setFill];
[aPath fill];
if (image)
{
[image drawInRect:rect];
}
else
{
// Draws an arrow looking to the right like this:
// =>
// and rotates it to given angle
UIBezierPath * aPath = [UIBezierPath bezierPath];
float const w = rect.size.width;
float const w2 = w / 2.0;
float const w3 = w / 3.0;
[aPath moveToPoint:CGPointMake(w3, w2)];
[aPath addLineToPoint:CGPointMake(0, w2 - w3)];
[aPath addLineToPoint:CGPointMake(w, w2)];
[aPath addLineToPoint:CGPointMake(0, w2 + w3)];
[aPath closePath];
CGAffineTransform matrix = CGAffineTransformMakeTranslation(w2, w2);
matrix = CGAffineTransformRotate(matrix, -angle);
matrix = CGAffineTransformTranslate(matrix, -w2, -w2);
[aPath applyTransform:matrix];
[[UIColor blueColor] setFill];
[aPath fill];
}
}
@end

View file

@ -19,7 +19,6 @@ namespace search { class Result; }
UIButton * m_radarButton;
UISearchBar * m_searchBar;
UITableView * m_table;
string m_currentCountryFlagCode;
}
- (id)initWithFramework:(Framework *)framework andLocationManager:(LocationManager *)lm;

View file

@ -13,6 +13,10 @@
#include "../../map/measurement_utils.hpp"
#include "../../search/result.hpp"
/// When to display compass instead of country flags
#define MIN_COMPASS_DISTANCE 25000.0
SearchVC * g_searchVC = nil;
volatile int g_queryId = 0;
@ -434,23 +438,52 @@ static void OnSearchResultCallback(search::Results const & res, int queryId)
cell.featureName.text = [NSString stringWithUTF8String:r.GetString()];
cell.featureCountry.text = [NSString stringWithUTF8String:r.GetRegionString()];
cell.featureType.text = [NSString stringWithUTF8String:r.GetFeatureType()];
cell.featureDistance.text = [SearchVC formatDistance:r.GetDistanceFromCenter()];
if (m_radarButton.isSelected)
cell.accessoryView = nil;
double const distance = r.GetDistanceFromCenter();
cell.featureDistance.text = [SearchVC formatDistance:distance];
// Show flags only if feature is too far away and it has the flag
if (r.GetRegionFlag() && (distance < 0. || distance > MIN_COMPASS_DISTANCE))
{
UIImage * flagImage = [UIImage imageNamed:[NSString stringWithFormat:@"%s.png", r.GetRegionFlag()]];
UIImageView * imgView = [[UIImageView alloc] initWithImage:flagImage];
cell.accessoryView = imgView;
[imgView release];
}
else
{ // Show flags only when radar mode is disabled and feature is not in the same country as the user
char const * flagCode = r.GetRegionFlag();
if (flagCode && m_currentCountryFlagCode != flagCode)
{
CompassView * compass;
// Try to reuse existing compass view
if ([cell.accessoryView isKindOfClass:[CompassView class]])
compass = (CompassView *)cell.accessoryView;
else
{
UIImage * flagImage = [UIImage imageNamed:[NSString stringWithFormat:@"%s.png", flagCode]];
UIImageView * imgView = [[UIImageView alloc] initWithImage:flagImage];
cell.accessoryView = imgView;
[imgView release];
// Create compass view
float const h = (int)(m_table.rowHeight * 0.6);
compass = [[CompassView alloc] initWithFrame:CGRectMake(0, 0, h, h)];
cell.accessoryView = compass;
[compass release];
}
// Separate case for continents
if (!r.GetRegionFlag())
{
// @TODO add valid icon
compass.image = [UIImage imageNamed:@"downloader"];
}
else
{
// Reset cached flag for reused cell
cell.accessoryView = nil;
CLLocation * loc = [m_locationManager lastLocation];
CLHeading * heading = [m_locationManager lastHeading];
if (loc == nil || heading == nil)
{
compass.image = [UIImage imageNamed:@"location"];
}
else
{
double const northDeg = (heading.trueHeading < 0) ? heading.magneticHeading : heading.trueHeading;
m2::PointD const center = r.GetFeatureCenter();
compass.angle = ang::AngleTo(m2::PointD(MercatorBounds::LonToX(loc.coordinate.longitude),
MercatorBounds::LatToY(loc.coordinate.latitude)), center) + northDeg / 180. * math::pi;
}
}
}
return cell;
@ -489,6 +522,8 @@ static void OnSearchResultCallback(search::Results const & res, int queryId)
case search::Result::RESULT_SUGGESTION:
char const * s = res.GetSuggestionString();
[m_searchBar setText: [NSString stringWithUTF8String:s]];
// Remove blue selection from the row
[tableView deselectRowAtIndexPath: indexPath animated:YES];
break;
}
}
@ -517,10 +552,6 @@ static void OnSearchResultCallback(search::Results const & res, int queryId)
- (void)onGpsUpdate:(location::GpsInfo const &)info
{
// Update current country code only once after Search View was opened
if (m_currentCountryFlagCode.empty())
m_currentCountryFlagCode = m_framework->GetCountryCodeByPosition(info.m_latitude, info.m_longitude);
// Refresh search results with newer location, but
// do not search if text is not entered
NSString * queryString = m_searchBar.text;
@ -547,20 +578,9 @@ static void OnSearchResultCallback(search::Results const & res, int queryId)
if (res.GetResultType() == search::Result::RESULT_FEATURE)
{
// Show compass only for cells without flags
CompassView * compass = nil;
if (cell.accessoryView == nil)
{
// Create compass view if it wasn't already created
float const h = m_table.rowHeight * 0.6;
compass = [[CompassView alloc] initWithFrame:CGRectMake(0, 0, h, h)];
cell.accessoryView = compass;
[compass release];
}
else if ([cell.accessoryView isKindOfClass:[CompassView class]])
compass = (CompassView *)cell.accessoryView;
if (compass)
if ([cell.accessoryView isKindOfClass:[CompassView class]])
{
CompassView * compass = (CompassView *)cell.accessoryView;
m2::PointD const center = res.GetFeatureCenter();
compass.angle = ang::AngleTo(m2::PointD(MercatorBounds::LonToX(loc.coordinate.longitude),
MercatorBounds::LatToY(loc.coordinate.latitude)), center) + northDeg / 180. * math::pi;

View file

@ -23,6 +23,7 @@
- (void)start:(id <LocationObserver>)observer;
- (void)stop:(id <LocationObserver>)observer;
- (CLLocation *)lastLocation;
- (CLHeading *)lastHeading;
// Fixes compass angle orientation when rotating screen to landscape
- (void)setOrientation:(UIInterfaceOrientation)orientation;
@end

View file

@ -86,6 +86,11 @@
return m_locationManager.location;
}
- (CLHeading *)lastHeading
{
return m_locationManager.heading;
}
- (void)location:(CLLocation *)location toGpsInfo:(location::GpsInfo &)info
{
info.m_horizontalAccuracy = location.horizontalAccuracy;