forked from organicmaps/organicmaps
[ios][search] Display compass for near features in search results
This commit is contained in:
parent
90d2a193ec
commit
51fe3127bd
6 changed files with 94 additions and 51 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue