[ios] Downloader UI

This commit is contained in:
Igor Khmurets 2014-10-10 17:05:32 +03:00 committed by Alex Zolotarev
parent 545aaaafec
commit e5f65a930e
38 changed files with 2071 additions and 757 deletions

View file

@ -0,0 +1,7 @@
#import <UIKit/UIKit.h>
#import "DownloaderParentVC.h"
@interface ActiveMapsVC : DownloaderParentVC
@end

371
iphone/Maps/ActiveMapsVC.mm Normal file
View file

@ -0,0 +1,371 @@
#import "ActiveMapsVC.h"
#import "CustomAlertView.h"
#import "Statistics.h"
#import "MapCell.h"
#import "BadgeView.h"
@interface ActiveMapsVC () <ActiveMapsObserverProtocol>
@property (nonatomic) BadgeView * outOfDateBadge;
@property (nonatomic) ActiveMapsLayout::TGroup selectedGroup;
@end
@implementation ActiveMapsVC
{
ActiveMapsObserver * m_mapsObserver;
int m_mapsObserverSlotId;
}
- (id)init
{
self = [super init];
self.title = L(@"downloader_downloaded_maps");
__weak ActiveMapsVC * weakSelf = self;
m_mapsObserver = new ActiveMapsObserver(weakSelf);
m_mapsObserverSlotId = self.mapsLayout.AddListener(m_mapsObserver);
return self;
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if (self.isMovingFromParentViewController)
self.mapsLayout.RemoveListener(m_mapsObserverSlotId);
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self refreshTopRightButton];
}
- (void)outOfDateCountriesCountChanged:(NSNotification *)notification
{
self.outOfDateBadge.value = [[notification userInfo][@"OutOfDate"] integerValue];
}
- (void)refreshTopRightButton
{
UIBarButtonItem * item;
if (self.mapsLayout.IsDownloadingActive())
item = [[UIBarButtonItem alloc] initWithTitle:L(@"downloader_cancel_all") style:UIBarButtonItemStylePlain target:self action:@selector(cancelAllMaps:)];
else if (self.mapsLayout.GetCountInGroup(ActiveMapsLayout::TGroup::EOutOfDate) > 0)
item = [[UIBarButtonItem alloc] initWithTitle:L(@"downloader_update_all") style:UIBarButtonItemStylePlain target:self action:@selector(updateAllMaps:)];
[self.navigationItem setRightBarButtonItem:item animated:YES];
}
- (void)updateAllMaps:(id)sender
{
self.mapsLayout.UpdateAll();
}
- (void)cancelAllMaps:(id)sender
{
self.mapsLayout.CancelAll();
}
#pragma mark - Helpers
- (ActiveMapsLayout &)mapsLayout
{
return GetFramework().GetCountryTree().GetActiveMapLayout();
}
- (ActiveMapsLayout::TGroup)groupWithSection:(NSInteger)section
{
ASSERT(section < (NSInteger)ActiveMapsLayout::TGroup::EGroupCount, ());
return static_cast<ActiveMapsLayout::TGroup>(section);
}
- (MapCell *)cellAtPosition:(int)position inGroup:(ActiveMapsLayout::TGroup const &)group
{
return (MapCell *)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:position inSection:(NSInteger)group]];
}
- (void)markSelectedMapIndexPath:(NSIndexPath *)indexPath
{
self.selectedPosition = indexPath.row;
self.selectedGroup = [self groupWithSection:indexPath.section];
}
#pragma mark - DownloaderParentVC virtual methods implementation
- (NSString *)parentTitle
{
return nil;
}
- (NSString *)selectedMapName
{
return [NSString stringWithUTF8String:self.mapsLayout.GetCountryName(self.selectedGroup, self.selectedPosition).c_str()];
}
- (NSString *)selectedMapGuideName
{
guides::GuideInfo info;
if (self.mapsLayout.GetGuideInfo(self.selectedGroup, self.selectedPosition, info))
{
string const lang = languages::GetCurrentNorm();
return [NSString stringWithUTF8String:info.GetAdTitle(lang).c_str()];
}
return nil;
}
- (size_t)selectedMapSizeWithOptions:(storage::TMapOptions)options
{
return self.mapsLayout.GetCountrySize(self.selectedGroup, self.selectedPosition, options).second;
}
- (TStatus)selectedMapStatus
{
return self.mapsLayout.GetCountryStatus(self.selectedGroup, self.selectedPosition);
}
- (TMapOptions)selectedMapOptions
{
return self.mapsLayout.GetCountryOptions(self.selectedGroup, self.selectedPosition);
}
- (void)performAction:(DownloaderAction)action
{
switch (action)
{
case DownloaderActionDownloadAll:
case DownloaderActionDownloadMap:
case DownloaderActionDownloadCarRouting:
if ([self canDownloadSelectedMap])
self.mapsLayout.DownloadMap(self.selectedGroup, self.selectedPosition, self.selectedInActionSheetOptions);
break;
case DownloaderActionDeleteAll:
case DownloaderActionDeleteMap:
case DownloaderActionDeleteCarRouting:
self.mapsLayout.DeleteMap(self.selectedGroup, self.selectedPosition, self.selectedInActionSheetOptions);
break;
case DownloaderActionCancelDownloading:
self.mapsLayout.CancelDownloading(self.selectedGroup, self.selectedPosition);
break;
case DownloaderActionZoomToCountry:
self.mapsLayout.ShowMap(self.selectedGroup, self.selectedPosition);
[[Statistics instance] logEvent:@"Show Map From Download Countries Screen"];
[self.navigationController popToRootViewControllerAnimated:YES];
break;
case DownloaderActionShowGuide:
guides::GuideInfo info;
if (self.mapsLayout.GetGuideInfo(self.selectedGroup, self.selectedPosition, info))
[self openGuideWithInfo:info];
break;
}
}
#pragma mark - TableView
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
ActiveMapsLayout::TGroup const group = [self groupWithSection:section];
if (group == ActiveMapsLayout::TGroup::ENewMap)
return nil;
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 40)];
view.clipsToBounds = YES;
UILabel * label = [[UILabel alloc] initWithFrame:view.bounds];
label.font = [UIFont fontWithName:@"HelveticaNeue" size:13];
label.backgroundColor = [UIColor clearColor];
if (group == ActiveMapsLayout::TGroup::EOutOfDate)
label.text = L(@"downloader_outdated_maps").uppercaseString;
else if (group == ActiveMapsLayout::TGroup::EUpToDate)
label.text = L(@"downloader_uptodate_maps").uppercaseString;
[label sizeToFit];
[view addSubview:label];
label.minX = 13;
label.maxY = view.height - 5;
if (group == ActiveMapsLayout::TGroup::EOutOfDate)
{
BadgeView * badge = [[BadgeView alloc] init];
badge.value = self.mapsLayout.GetCountInGroup(ActiveMapsLayout::TGroup::EOutOfDate);
badge.center = CGPointMake(label.maxX + badge.width - 2, label.midY);
[view addSubview:badge];
self.outOfDateBadge = badge;
}
return view;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
ActiveMapsLayout::TGroup const group = [self groupWithSection:section];
if (group == ActiveMapsLayout::TGroup::EOutOfDate || group == ActiveMapsLayout::TGroup::EUpToDate)
return self.mapsLayout.GetCountInGroup(group) == 0 ? 0.001 : 42;
else
return 0.001;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 0.001;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return (NSInteger)ActiveMapsLayout::TGroup::EGroupCount;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.mapsLayout.GetCountInGroup([self groupWithSection:section]);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MapCell * cell = [tableView dequeueReusableCellWithIdentifier:[MapCell className]];
if (!cell)
cell = [[MapCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[MapCell className]];
int const position = indexPath.row;
ActiveMapsLayout::TGroup const group = [self groupWithSection:indexPath.section];
TStatus const status = self.mapsLayout.GetCountryStatus(group, position);
TMapOptions const options = self.mapsLayout.GetCountryOptions(group, position);
cell.titleLabel.text = [NSString stringWithUTF8String:self.mapsLayout.GetCountryName(group, position).c_str()];
cell.parentMode = NO;
cell.status = status;
cell.options = options;
cell.delegate = self;
cell.badgeView.value = 0;
NSString * sizeString;
if (status == TStatus::ENotDownloaded)
{
LocalAndRemoteSizeT const size = self.mapsLayout.GetRemoteCountrySizes(position);
sizeString = [NSString stringWithFormat:@"%@ / %@", [self formattedMapSize:size.first], [self formattedMapSize:size.second]];
}
else if (status == TStatus::EOnDisk || status == TStatus::EOnDiskOutOfDate)
{
size_t const size = self.mapsLayout.GetCountrySize(position, options).second;
sizeString = [self formattedMapSize:size];
}
else if (status == TStatus::EOutOfMemFailed || status == TStatus::EDownloadFailed || status == TStatus::EDownloading || status == TStatus::EInQueue)
{
LocalAndRemoteSizeT const size = self.mapsLayout.GetDownloadableCountrySize(position);
sizeString = [self formattedMapSize:size.second];
cell.downloadProgress = (double)size.first / size.second;
}
cell.sizeLabel.text = sizeString;
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
TStatus const status = self.mapsLayout.GetCountryStatus([self groupWithSection:indexPath.section], indexPath.row);
return status == TStatus::EOnDisk || status == TStatus::EOnDiskOutOfDate;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
int const position = indexPath.row;
ActiveMapsLayout::TGroup const group = [self groupWithSection:position];
TMapOptions const options = self.mapsLayout.GetCountryOptions(group, position);
self.mapsLayout.DeleteMap(group, position, options);
[tableView setEditing:NO animated:YES];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self markSelectedMapIndexPath:indexPath];
MapCell * cell = [self cellAtPosition:self.selectedPosition inGroup:self.selectedGroup];
UIActionSheet * actionSheet = [self actionSheetToPerformActionOnSelectedMap];
[actionSheet showFromRect:cell.frame inView:cell.superview animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [MapCell cellHeight];
}
#pragma mark - MapCellDelegate
- (void)mapCellDidStartDownloading:(MapCell *)cell
{
[self markSelectedMapIndexPath:[self.tableView indexPathForCell:cell]];
TStatus const status = [self selectedMapStatus];
if (status == TStatus::EDownloadFailed || status == TStatus::EOutOfMemFailed)
if ([self canDownloadSelectedMap])
self.mapsLayout.RetryDownloading(self.selectedGroup, self.selectedPosition);
}
- (void)mapCellDidCancelDownloading:(MapCell *)cell
{
NSIndexPath * indexPath = [self.tableView indexPathForCell:cell];
self.selectedPosition = indexPath.row;
self.selectedGroup = [self groupWithSection:indexPath.section];
[[self actionSheetToDeleteSelectedMap] showFromRect:cell.frame inView:cell.superview animated:YES];
}
#pragma mark - ActiveMaps core callbacks
- (void)countryStatusChangedAtPosition:(int)position inGroup:(ActiveMapsLayout::TGroup const &)group
{
[self refreshTopRightButton];
MapCell * cell = [self cellAtPosition:position inGroup:group];
[cell setStatus:self.mapsLayout.GetCountryStatus(group, position) options:self.mapsLayout.GetCountryOptions(group, position) animated:YES];
self.outOfDateBadge.value = self.mapsLayout.GetCountInGroup(ActiveMapsLayout::TGroup::EOutOfDate);
}
- (void)countryOptionsChangedAtPosition:(int)position inGroup:(ActiveMapsLayout::TGroup const &)group
{
MapCell * cell = [self cellAtPosition:position inGroup:group];
[cell setStatus:self.mapsLayout.GetCountryStatus(group, position) options:self.mapsLayout.GetCountryOptions(group, position) animated:YES];
}
- (void)countryGroupChangedFromPosition:(int)oldPosition inGroup:(ActiveMapsLayout::TGroup const &)oldGroup toPosition:(int)newPosition inGroup:(ActiveMapsLayout::TGroup const &)newGroup
{
if (oldGroup == newGroup && oldPosition == -1)
{
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:newPosition inSection:(NSInteger)newGroup];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
else if (oldGroup == newGroup && newPosition == -1)
{
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:oldPosition inSection:(NSInteger)oldGroup];
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
else if (oldGroup != newGroup && oldPosition >= 0 && newPosition >= 0)
{
NSIndexPath * oldIndexPath = [NSIndexPath indexPathForRow:oldPosition inSection:(NSInteger)oldGroup];
NSIndexPath * newIndexPath = [NSIndexPath indexPathForRow:newPosition inSection:(NSInteger)newGroup];
[self.tableView moveRowAtIndexPath:oldIndexPath toIndexPath:newIndexPath];
}
}
- (void)countryDownloadingProgressChanged:(LocalAndRemoteSizeT const &)progress atPosition:(int)position inGroup:(ActiveMapsLayout::TGroup const &)group
{
MapCell * cell = [self cellAtPosition:position inGroup:group];
[cell setDownloadProgress:((double)progress.first / progress.second) animated:YES];
}
@end

View file

@ -0,0 +1,8 @@
#import <UIKit/UIKit.h>
@interface BadgeView : UIImageView
@property (nonatomic) NSInteger value;
@end

View file

@ -0,0 +1,33 @@
#import "BadgeView.h"
#import "UIKitCategories.h"
@implementation BadgeView
- (void)setValue:(NSInteger)value
{
[self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
self.hidden = value == 0;
UIFont * font = [UIFont fontWithName:@"HelveticaNeue-Light" size:12];
UIImage * image = [UIImage imageNamed:@"Badge"];
CGFloat const textWidth = [@(value).stringValue sizeWithDrawSize:CGSizeMake(100, 20) font:font].width;
CGFloat const offset = 4;
CGFloat const imageDiameter = 17;
self.size = CGSizeMake(MAX(textWidth + 2 * offset, imageDiameter), imageDiameter);
self.image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(imageDiameter / 2, imageDiameter / 2, imageDiameter / 2, imageDiameter / 2)];
UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(offset, 0, textWidth, self.height)];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.font = font;
label.text = @(value).stringValue;
label.center = CGPointMake(self.width / 2, self.height / 2);
[self addSubview:label];
_value = value;
}
@end

View file

@ -6,6 +6,8 @@
#include "../../../platform/settings.hpp"
#import "AppInfo.h"
#import "ImageDownloader.h"
#import "MapsAppDelegate.h"
#import "Framework.h"
@interface BottomMenu () <UITableViewDataSource, UITableViewDelegate, ImageDownloaderDelegate>
@ -23,8 +25,8 @@
self = [super initWithFrame:frame];
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:self.fadeView];
[self addSubview:self.fadeView];
[self addSubview:self.tableView];
_menuHidden = YES;
@ -32,10 +34,20 @@
self.imageDownloaders = [[NSMutableDictionary alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appInfoSynced:) name:AppInfoSyncedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(outOfDateCountriesCountChanged:) name:MapsStatusChangedNotification object:nil];
return self;
}
- (void)outOfDateCountriesCountChanged:(NSNotification *)notification
{
NSInteger const row = [self.items indexOfObjectPassingTest:^(id obj, NSUInteger i, BOOL *stop){
return [obj[@"Id"] isEqualToString:@"Maps"];
}];
BottomMenuCell * cell = (BottomMenuCell *)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0]];
cell.badgeView.value = [[notification userInfo][@"OutOfDate"] integerValue];
}
- (NSArray *)generateItems
{
NSMutableArray * items = [[NSMutableArray alloc] init];
@ -154,6 +166,11 @@
cell.titleLabel.text = title;
}
if ([item[@"Id"] isEqualToString:@"Maps"])
cell.badgeView.value = GetFramework().GetCountryTree().GetActiveMapLayout().GetCountInGroup(storage::ActiveMapsLayout::TGroup::EOutOfDate);
else
cell.badgeView.value = 0;
return cell;
}

View file

@ -1,10 +1,12 @@
#import <UIKit/UIKit.h>
#import "BadgeView.h"
@interface BottomMenuCell : UITableViewCell
@property (nonatomic) UIImageView * iconImageView;
@property (nonatomic) UILabel * titleLabel;
@property (nonatomic, readonly) UIImageView * iconImageView;
@property (nonatomic, readonly) UILabel * titleLabel;
@property (nonatomic, readonly) BadgeView * badgeView;
+ (CGFloat)cellHeight;

View file

@ -5,6 +5,9 @@
@interface BottomMenuCell ()
@property (nonatomic) UIImageView * separator;
@property (nonatomic) UIImageView * iconImageView;
@property (nonatomic) UILabel * titleLabel;
@property (nonatomic) BadgeView * badgeView;
@end
@ -23,6 +26,7 @@
[self.contentView addSubview:self.titleLabel];
[self.contentView addSubview:self.iconImageView];
[self.contentView addSubview:self.separator];
[self.contentView addSubview:self.badgeView];
return self;
}
@ -41,7 +45,14 @@
self.separator.width = self.width - 2 * shift;
self.separator.maxY = self.height;
self.titleLabel.frame = CGRectMake(53, -2, self.width - 70, self.height);
self.titleLabel.size = CGSizeMake(self.width - 70, self.height);
[self.titleLabel sizeToFit];
self.titleLabel.minX = 53;
self.titleLabel.midY = self.height / 2 - 2;
self.badgeView.minX = self.titleLabel.maxX + 4;
self.badgeView.minY = self.titleLabel.minY - 5;
self.iconImageView.origin = CGPointMake(11, 4.5);
}
@ -50,7 +61,7 @@
if (!_separator)
{
UIImage * separatorImage = [[UIImage imageNamed:@"SearchCellSeparator"] resizableImageWithCapInsets:UIEdgeInsetsZero];
_separator = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.width, separatorImage.size.height)];
_separator = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.width, 1)];
_separator.image = separatorImage;
}
return _separator;
@ -77,4 +88,11 @@
return _titleLabel;
}
- (BadgeView *)badgeView
{
if (!_badgeView)
_badgeView = [[BadgeView alloc] init];
return _badgeView;
}
@end

View file

@ -0,0 +1,39 @@
#import <UIKit/UIKit.h>
#import "ProgressView.h"
#import "BadgeView.h"
#include "../../storage/storage_defines.hpp"
using namespace storage;
@class MapCell;
@protocol MapCellDelegate <NSObject>
@optional
- (void)mapCellDidStartDownloading:(MapCell *)cell;
- (void)mapCellDidCancelDownloading:(MapCell *)cell;
@end
@interface MapCell : UITableViewCell
@property (nonatomic, readonly) UILabel * titleLabel;
@property (nonatomic, readonly) UILabel * subtitleLabel;
@property (nonatomic, readonly) UILabel * sizeLabel;
@property (nonatomic, readonly) BadgeView * badgeView;
@property (nonatomic) BOOL parentMode;
@property (nonatomic) TStatus status;
@property (nonatomic) TMapOptions options;
@property (nonatomic) double downloadProgress;
@property (nonatomic, weak) id <MapCellDelegate> delegate;
- (void)setStatus:(TStatus)status options:(TMapOptions)options animated:(BOOL)animated;
- (void)setDownloadProgress:(double)downloadProgress animated:(BOOL)animated;
+ (CGFloat)cellHeight;
@end

View file

@ -0,0 +1,336 @@
#import "MapCell.h"
#import "UIKitCategories.h"
@interface MapCell () <ProgressViewDelegate>
@property (nonatomic) UILabel * titleLabel;
@property (nonatomic) UILabel * subtitleLabel;
@property (nonatomic) UILabel * statusLabel;
@property (nonatomic) UILabel * sizeLabel;
@property (nonatomic) ProgressView * progressView;
@property (nonatomic) UIView * rightTapZone;
@property (nonatomic) UIImageView * arrowView;
@property (nonatomic) BadgeView * badgeView;
@property (nonatomic) UIImageView * routingImageView;
@property (nonatomic) UIImageView * separator;
@property (nonatomic, readonly) BOOL progressMode;
@end
@implementation MapCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
NSArray * subviews = @[self.titleLabel, self.subtitleLabel, self.statusLabel, self.sizeLabel, self.progressView, self.arrowView, self.badgeView, self.routingImageView, self.separator];
for (UIView * subview in subviews)
[self.contentView addSubview:subview];
return self;
}
- (void)setStatus:(TStatus)status options:(TMapOptions)options animated:(BOOL)animated
{
self.status = status;
self.options = options;
self.rightTapZone.userInteractionEnabled = NO;
self.progressView.failedMode = NO;
if (options == TMapOptions::EMapOnly)
self.routingImageView.image = [UIImage imageNamed:@"DownloadRoutingButton"];
else
self.routingImageView.image = [UIImage imageNamed:@"RoutingDownloadedButton"];
switch (status)
{
case TStatus::ENotDownloaded:
case TStatus::EOnDiskOutOfDate:
if (status == TStatus::ENotDownloaded)
self.statusLabel.text = L(@"download").uppercaseString;
else
self.statusLabel.text = L(@"downloader_status_outdated").uppercaseString;
self.statusLabel.textColor = [UIColor colorWithColorCode:@"179E4D"];
self.rightTapZone.userInteractionEnabled = YES;
[self setProgressMode:NO withAnimatedLayout:animated];
break;
case TStatus::EInQueue:
self.statusLabel.text = L(@"downloader_queued").uppercaseString;
self.statusLabel.textColor = [UIColor colorWithColorCode:@"999999"];
[self.progressView setProgress:0 animated:animated];
[self setProgressMode:YES withAnimatedLayout:animated];
break;
case TStatus::EDownloading:
self.statusLabel.textColor = [UIColor colorWithColorCode:@"999999"];
[self.progressView setProgress:self.downloadProgress animated:animated];
[self setProgressMode:YES withAnimatedLayout:animated];
break;
case TStatus::EOnDisk:
{
self.statusLabel.text = L(@"downloader_downloaded").uppercaseString;
self.statusLabel.textColor = [UIColor colorWithColorCode:@"999999"];
if (animated)
{
[self alignSubviews];
[self performAfterDelay:0.3 block:^{
[self setProgressMode:NO withAnimatedLayout:YES];
}];
}
else
{
[self setProgressMode:NO withAnimatedLayout:NO];
}
break;
}
case TStatus::EOutOfMemFailed:
case TStatus::EDownloadFailed:
self.progressView.failedMode = YES;
self.statusLabel.text = L(@"downloader_retry").uppercaseString;
self.statusLabel.textColor = [UIColor colorWithColorCode:@"FF4436"];
self.rightTapZone.userInteractionEnabled = YES;
[self setProgressMode:YES withAnimatedLayout:animated];
break;
case TStatus::EUnknown:
break;
}
}
- (void)setDownloadProgress:(double)downloadProgress animated:(BOOL)animated
{
self.downloadProgress = downloadProgress;
self.statusLabel.text = [NSString stringWithFormat:@"%i%%", NSInteger(downloadProgress * 100)];
[self.progressView setProgress:downloadProgress animated:animated];
if (!self.progressMode)
[self setProgressMode:YES withAnimatedLayout:animated];
}
- (void)setProgressMode:(BOOL)progressMode withAnimatedLayout:(BOOL)withLayout
{
_progressMode = progressMode;
if (withLayout)
{
if (progressMode)
self.progressView.hidden = NO;
[UIView animateWithDuration:0.5 delay:0 damping:0.9 initialVelocity:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
[self alignProgressView];
[self alignSubviews];
} completion:^(BOOL finished) {
if (!progressMode)
self.progressView.hidden = YES;
}];
}
else
{
[self alignSubviews];
}
}
- (void)alignProgressView
{
self.progressView.minX = self.progressMode ? self.width - [self rightOffset] + 2 : self.width;
}
- (void)alignSubviews
{
self.progressView.hidden = self.parentMode || !self.progressMode;
self.progressView.midY = self.height / 2;
self.arrowView.center = CGPointMake(self.width - [self minimumRightOffset] - 4, self.height / 2);
self.arrowView.hidden = !self.parentMode;
[self.statusLabel sizeToFit];
self.statusLabel.width = MAX(self.statusLabel.width, 60);
[self.sizeLabel sizeToFit];
self.statusLabel.frame = CGRectMake(self.width - [self rightOffset] - self.statusLabel.width, 14, self.statusLabel.width, 16);
self.statusLabel.hidden = self.parentMode;
CGFloat const sizeLabelMinY = self.statusLabel.maxY;
self.sizeLabel.frame = CGRectMake(self.width - [self rightOffset] - self.sizeLabel.width, sizeLabelMinY, self.sizeLabel.width, 16);
self.sizeLabel.textColor = [UIColor colorWithColorCode:@"999999"];
self.sizeLabel.hidden = self.parentMode;
CGFloat const rightLabelsMaxWidth = self.parentMode ? 10 : MAX(self.statusLabel.width, self.sizeLabel.width);
CGFloat const leftLabelsWith = self.width - [self leftOffset] - [self betweenSpace] - rightLabelsMaxWidth - [self rightOffset];
self.titleLabel.frame = CGRectMake([self leftOffset], self.subtitleLabel.text == nil ? 19 : 10, leftLabelsWith, 20);
self.subtitleLabel.frame = CGRectMake([self leftOffset], self.titleLabel.maxY + 1, leftLabelsWith, 18);
self.subtitleLabel.hidden = self.subtitleLabel.text == nil;
CGFloat const rightTapWidth = rightLabelsMaxWidth + [self rightOffset] + [self betweenSpace];
self.rightTapZone.frame = CGRectMake(self.width - rightTapWidth, 0, rightTapWidth - [self rightOffset] + 4, self.height);
if (self.parentMode)
self.rightTapZone.userInteractionEnabled = NO;
self.routingImageView.center = CGPointMake(self.width - 25, self.height / 2 - 1);
self.routingImageView.alpha = [self shouldShowRoutingView];
}
- (BOOL)shouldShowRoutingView
{
return !self.progressMode && !self.parentMode && self.status != TStatus::ENotDownloaded;
}
- (void)layoutSubviews
{
[self alignProgressView];
[self setStatus:self.status options:self.options animated:NO];
self.badgeView.minX = self.titleLabel.maxX + 4;
self.badgeView.minY = self.titleLabel.minY - 5;
self.separator.minX = self.titleLabel.minX;
self.separator.size = CGSizeMake(self.width - 2 * self.separator.minX, 1);
self.separator.maxY = self.height + 0.5;
}
- (CGFloat)leftOffset
{
return 12;
}
- (CGFloat)betweenSpace
{
return 10;
}
- (CGFloat)rightOffset
{
return self.progressMode || [self shouldShowRoutingView] ? 50 : [self minimumRightOffset];
}
- (CGFloat)minimumRightOffset
{
return 12;
}
+ (CGFloat)cellHeight
{
return 59;
}
- (void)rightTap:(id)sender
{
[self.delegate mapCellDidStartDownloading:self];
}
- (void)progressViewDidStart:(ProgressView *)progress
{
[self.delegate mapCellDidStartDownloading:self];
}
- (void)progressViewDidCancel:(ProgressView *)progress
{
[self.delegate mapCellDidCancelDownloading:self];
}
- (UIImageView *)arrowView
{
if (!_arrowView)
_arrowView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"AccessoryView"]];
return _arrowView;
}
- (ProgressView *)progressView
{
if (!_progressView)
{
_progressView = [[ProgressView alloc] init];
_progressView.delegate = self;
}
return _progressView;
}
- (UILabel *)titleLabel
{
if (!_titleLabel)
{
_titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_titleLabel.backgroundColor = [UIColor clearColor];
_titleLabel.textColor = [UIColor blackColor];
_titleLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:17];
}
return _titleLabel;
}
- (UILabel *)subtitleLabel
{
if (!_subtitleLabel)
{
_subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_subtitleLabel.backgroundColor = [UIColor clearColor];
_subtitleLabel.textColor = [UIColor colorWithColorCode:@"999999"];
_subtitleLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:13];
}
return _subtitleLabel;
}
- (UILabel *)statusLabel
{
if (!_statusLabel)
{
_statusLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_statusLabel.backgroundColor = [UIColor clearColor];
_statusLabel.textAlignment = NSTextAlignmentRight;
_statusLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:13];
}
return _statusLabel;
}
- (UILabel *)sizeLabel
{
if (!_sizeLabel)
{
_sizeLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_sizeLabel.backgroundColor = [UIColor clearColor];
_sizeLabel.textAlignment = NSTextAlignmentRight;
_sizeLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:13];
}
return _sizeLabel;
}
- (UIView *)rightTapZone
{
if (!_rightTapZone)
{
_rightTapZone = [[UIView alloc] initWithFrame:CGRectZero];
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(rightTap:)];
[_rightTapZone addGestureRecognizer:tap];
}
return _rightTapZone;
}
- (UIImageView *)routingImageView
{
if (!_routingImageView)
_routingImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"DownloadRoutingButton"]];
return _routingImageView;
}
- (BadgeView *)badgeView
{
if (!_badgeView)
_badgeView = [[BadgeView alloc] init];
return _badgeView;
}
- (UIImageView *)separator
{
if (!_separator)
{
UIImage * separatorImage = [[UIImage imageNamed:@"MapCellSeparator"] resizableImageWithCapInsets:UIEdgeInsetsZero];
_separator = [[UIImageView alloc] initWithFrame:CGRectZero];
_separator.image = separatorImage;
}
return _separator;
}
@end

View file

@ -35,7 +35,8 @@
#define ALERT_VIEW_FACEBOOK 1
#define ALERT_VIEW_APPSTORE 2
#define ALERT_VIEW_BOOKMARKS 4
#define ALERT_VIEW_ERROR 5
#define ALERT_VIEW_DOWNLOADER 5
#define ALERT_VIEW_PRO_VERSION_ROUTING 6
#define FACEBOOK_URL @"http://www.facebook.com/MapsWithMe"
#define FACEBOOK_SCHEME @"fb://profile/111923085594432"
@ -513,10 +514,6 @@
[self.view addSubview:self.containerView];
[self.view addSubview:self.bottomMenu];
// [self performAfterDelay:0.3 block:^{
// [self bottomMenu:self.bottomMenu didPressItemWithName:@"Maps" appURL:nil webURL:nil];
// }];
}
- (void)viewDidAppear:(BOOL)animated
@ -606,19 +603,23 @@
f.SetRouteBuildingListener([self, &f](bool isSuccess, string const & message, bool openDownloader)
{
[self.containerView.placePage showBuildingRoutingActivity:NO];
if (isSuccess)
{
f.GetBalloonManager().RemovePin();
f.GetBalloonManager().Dismiss();
[self.containerView.placePage setState:PlacePageStateHidden animated:YES withCallback:YES];
[self.searchView setState:SearchViewStateHidden animated:YES withCallback:YES];
[self performAfterDelay:0.3 block:^{
[self.routeView setVisible:YES animated:YES];
}];
}
else
{
/// if openDownloader == true than we need show dialog with 2 button. On positive button - open downloader
[self showDialogWithMessageID:message];
if (openDownloader)
[self showDownloaderDialogWithMessageID:message];
else
[self showDialogWithMessageID:message];
}
});
@ -633,16 +634,24 @@
}
#pragma mark - ShowDialog callback
- (void)showDialogWithMessageID:(string const &)message
{
///@TODO for goga.
[[[UIAlertView alloc] initWithTitle:[NSString stringWithUTF8String:message.c_str()] message:nil delegate:self cancelButtonTitle:NSLocalizedString(@"ok", nil) otherButtonTitles:nil] show];
}
- (void)showDownloaderDialogWithMessageID:(string const &)message
{
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithUTF8String:message.c_str()] message:nil delegate:self cancelButtonTitle:NSLocalizedString(@"cancel", nil) otherButtonTitles:NSLocalizedString(@"ok", nil), nil];
alertView.tag = ALERT_VIEW_DOWNLOADER;
[alertView show];
}
- (void)showBuyProDialog
{
///@TODO for goga. Show buy pro dialog with text [routing_failed_buy_pro]
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"routing_failed_buy_pro", nil) message:nil delegate:self cancelButtonTitle:NSLocalizedString(@"ok", nil) otherButtonTitles:nil] show];
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"routing_failed_buy_pro", nil) message:nil delegate:self cancelButtonTitle:NSLocalizedString(@"cancel", nil) otherButtonTitles:NSLocalizedString(@"get_it_now", nil), nil];
alert.tag = ALERT_VIEW_PRO_VERSION_ROUTING;
[alert show];
}
#pragma mark - Getters
@ -753,6 +762,8 @@
return _apiTitleLabel;
}
#pragma mark - Api methods
- (void)clearApiMode:(id)sender
{
[self setApiMode:NO animated:YES];
@ -765,17 +776,14 @@
[[UIApplication sharedApplication] openURL:url];
}
#pragma mark - ToolbarView delegate
- (void)toolbar:(ToolbarView *)toolbar didPressItemWithName:(NSString *)itemName
{
if ([itemName isEqualToString:@"Location"])
{
// [self onMyPositionClicked:nil];
[self.routeView setVisible:!self.routeView.visible animated:YES];
}
[self onMyPositionClicked:nil];
else if ([itemName isEqualToString:@"Search"])
{
[self.searchView setState:SearchViewStateFullscreen animated:YES withCallback:YES];
}
else if ([itemName isEqualToString:@"Bookmarks"])
{
if (GetPlatform().IsPro())
@ -791,14 +799,15 @@
}
}
else if ([itemName isEqualToString:@"Menu"])
{
[self.bottomMenu setMenuHidden:NO animated:YES];
}
}
- (void)routeViewDidStartRouting:(RouteView *)routeView
{
#pragma mark - Routing
- (void)routeViewDidStartFollowing:(RouteView *)routeView
{
[routeView hideFollowButton];
GetFramework().FollowRoute();
}
- (void)routeViewDidCancelRouting:(RouteView *)routeView
@ -811,6 +820,7 @@
- (void)placePageViewDidStartRouting:(PlacePageView *)placePage
{
[placePage showBuildingRoutingActivity:YES];
GetFramework().BuildRoute([placePage pinPoint]);
}
@ -988,11 +998,24 @@
[[UIApplication sharedApplication] openProVersionFrom:@"ios_toolabar_bookmarks"];
}
}
case ALERT_VIEW_ERROR:
case ALERT_VIEW_DOWNLOADER:
{
if (buttonIndex != alertView.cancelButtonIndex)
{
CountryTreeVC * vc = [[CountryTreeVC alloc] initWithNodePosition:-1];
[self.navigationController pushViewController:vc animated:YES];
}
}
case ALERT_VIEW_PRO_VERSION_ROUTING:
{
if (buttonIndex == alertView.cancelButtonIndex)
{
[[Statistics instance] logProposalReason:@"Routing Menu" withAnswer:@"NO"];
}
else
{
[[UIApplication sharedApplication] openProVersionFrom:@"ios_routing_alert"];
[[Statistics instance] logProposalReason:@"Routing Menu" withAnswer:@"YES"];
}
}
default:
@ -1017,7 +1040,8 @@
[UIView animateWithDuration:0.3 animations:^{
self.toolbarView.maxY = self.view.height;
self.routeView.alpha = 1;
if (GetFramework().IsRoutingActive())
self.routeView.minY = 0;
}];
break;
}
@ -1045,11 +1069,11 @@
framework.SetViewportCenterAnimated(framework.GetViewportCenter() + offset);
}
}
[UIView animateWithDuration:0.3 animations:^{
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.toolbarView.maxY = self.view.height;
self.routeView.alpha = 0;
}];
if (GetFramework().IsRoutingActive())
self.routeView.minY = self.containerView.placePage.maxY - 20;
} completion:^(BOOL finished) {}];
break;
}
@ -1071,6 +1095,20 @@
GetFramework().ActivateUserMark(NULL);
[self.containerView.placePage setState:PlacePageStateHidden animated:YES withCallback:NO];
}
else if (self.searchView.state == SearchViewStateResults)
{
[UIView animateWithDuration:0.3 animations:^{
if (GetFramework().IsRoutingActive())
self.routeView.minY = self.searchView.searchBar.maxY - 14;
}];
}
else if (self.searchView.state == SearchViewStateHidden)
{
[UIView animateWithDuration:0.3 animations:^{
if (GetFramework().IsRoutingActive())
self.routeView.minY = 0;
}];
}
}
}

View file

@ -1,13 +1,15 @@
#import <UIKit/UIKit.h>
#import "NavigationController.h"
#import "MapsObservers.h"
@class MapViewController;
@class SettingsManager;
@class LocationManager;
@interface MapsAppDelegate : NSObject <UIApplicationDelegate, UIAlertViewDelegate>
extern NSString * const MapsStatusChangedNotification;
@interface MapsAppDelegate : NSObject <UIApplicationDelegate, UIAlertViewDelegate, ActiveMapsObserverProtocol>
{
SettingsManager * m_settingsManager;
NSInteger m_standbyCounter;
NSInteger m_activeDownloadsCounter;
UIBackgroundTaskIdentifier m_backgroundTask;
@ -21,8 +23,6 @@
+ (MapsAppDelegate *)theApp;
- (SettingsManager *)settingsManager;
- (void)disableStandby;
- (void)enableStandby;

View file

@ -1,6 +1,5 @@
#import "MapsAppDelegate.h"
#import "MapViewController.h"
#import "SettingsManager.h"
#import "Preferences.h"
#import "LocationManager.h"
#import "Statistics.h"
@ -15,14 +14,13 @@
#import <FacebookSDK/FacebookSDK.h>
#include "Framework.h"
#include "../../../storage/storage_defines.hpp"
#include "../../../platform/settings.hpp"
#include "../../../platform/platform.hpp"
#include "../../../platform/preferred_languages.hpp"
NSString * const MapsStatusChangedNotification = @"MapsStatusChangedNotification";
#define NOTIFICATION_ALERT_VIEW_TAG 665
@ -67,6 +65,7 @@ void InitLocalizedStrings()
NSString * m_scheme;
NSString * m_sourceApplication;
ActiveMapsObserver * m_mapsObserver;
}
+ (MapsAppDelegate *)theApp
@ -229,7 +228,7 @@ void InitLocalizedStrings()
UIPasteboard * pasteboard = [UIPasteboard generalPasteboard];
if ([pasteboard.string length])
{
if (GetFramework().ShowMapForURL([pasteboard.string UTF8String]))
if (f.ShowMapForURL([pasteboard.string UTF8String]))
{
[self showMap];
pasteboard.string = @"";
@ -255,17 +254,13 @@ void InitLocalizedStrings()
#ifdef OMIM_FULL
[[AccountManager sharedManager] applicationDidBecomeActive:application];
#endif
}
- (SettingsManager *)settingsManager
{
if (!m_settingsManager)
m_settingsManager = [[SettingsManager alloc] init];
return m_settingsManager;
f.GetLocationState()->InvalidatePosition();
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
// Global cleanup
DeleteFramework();
}
@ -424,36 +419,38 @@ void InitLocalizedStrings()
- (void)subscribeToStorage
{
typedef void (*TChangeFunc)(id, SEL, storage::TIndex const &);
SEL changeSel = @selector(OnCountryChange:);
TChangeFunc changeImpl = (TChangeFunc)[self methodForSelector:changeSel];
__weak MapsAppDelegate * weakSelf = self;
m_mapsObserver = new ActiveMapsObserver(weakSelf);
GetFramework().GetCountryTree().GetActiveMapLayout().AddListener(m_mapsObserver);
typedef void (*TProgressFunc)(id, SEL, storage::TIndex const &, pair<int64_t, int64_t> const &);
SEL emptySel = @selector(EmptyFunction:withProgress:);
TProgressFunc progressImpl = (TProgressFunc)[self methodForSelector:emptySel];
GetFramework().Storage().Subscribe(bind(changeImpl, self, changeSel, _1),
bind(progressImpl, self, emptySel, _1, _2));
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(outOfDateCountriesCountChanged:) name:MapsStatusChangedNotification object:nil];
}
- (void)OnCountryChange:(storage::TIndex const &)index
- (void)countryStatusChangedAtPosition:(int)position inGroup:(storage::ActiveMapsLayout::TGroup const &)group
{
Framework const & f = GetFramework();
guides::GuideInfo guide;
if (f.GetCountryStatus(index) == storage::TStatus::EOnDisk && f.GetGuideInfo(index, guide))
[self ShowNotificationWithGuideInfo:guide];
ActiveMapsLayout & l = GetFramework().GetCountryTree().GetActiveMapLayout();
TStatus const & status = l.GetCountryStatus(group, position);
guides::GuideInfo info;
if (status == storage::TStatus::EOnDisk && l.GetGuideInfo(group, position, info))
[self showNotificationWithGuideInfo:info];
int const outOfDateCount = l.GetCountInGroup(storage::ActiveMapsLayout::TGroup::EOutOfDate);
[[NSNotificationCenter defaultCenter] postNotificationName:MapsStatusChangedNotification object:nil userInfo:@{@"OutOfDate" : @(outOfDateCount)}];
}
- (void)EmptyFunction:(storage::TIndex const &)index withProgress:(pair<int64_t, int64_t> const &)progress {}
- (void)outOfDateCountriesCountChanged:(NSNotification *)notification
{
[UIApplication sharedApplication].applicationIconBadgeNumber = [[notification userInfo][@"OutOfDate"] integerValue];
}
- (BOOL)ShowNotificationWithGuideInfo:(guides::GuideInfo const &)guide
- (void)showNotificationWithGuideInfo:(guides::GuideInfo const &)guide
{
guides::GuidesManager & guidesManager = GetFramework().GetGuidesManager();
string const appID = guide.GetAppID();
if (guidesManager.WasAdvertised(appID) ||
[[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:[NSString stringWithUTF8String:appID.c_str()]]])
return NO;
return;
UILocalNotification * notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:0];
@ -474,8 +471,6 @@ void InitLocalizedStrings()
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
guidesManager.SetWasAdvertised(appID);
return YES;
}
@end

View file

@ -0,0 +1,54 @@
#include "Framework.h"
#include "../../storage/storage_defines.hpp"
using namespace storage;
@protocol ActiveMapsObserverProtocol <NSObject>
- (void)countryStatusChangedAtPosition:(int)position inGroup:(ActiveMapsLayout::TGroup const &)group;
@optional
- (void)countryGroupChangedFromPosition:(int)oldPosition inGroup:(ActiveMapsLayout::TGroup const &)oldGroup toPosition:(int)newPosition inGroup:(ActiveMapsLayout::TGroup const &)newGroup;
- (void)countryOptionsChangedAtPosition:(int)position inGroup:(ActiveMapsLayout::TGroup const &)group;
- (void)countryDownloadingProgressChanged:(LocalAndRemoteSizeT const &)progress atPosition:(int)position inGroup:(ActiveMapsLayout::TGroup const &)group;
@end
@protocol CountryTreeObserverProtocol <NSObject>
- (void)countryStatusChangedAtPositionInNode:(int)position;
- (void)countryDownloadingProgressChanged:(LocalAndRemoteSizeT const &)progress atPositionInNode:(int)position;
@end
class ActiveMapsObserver : public ActiveMapsLayout::ActiveMapsListener
{
public:
ActiveMapsObserver(id<ActiveMapsObserverProtocol> delegateObject);
virtual void CountryGroupChanged(ActiveMapsLayout::TGroup const & oldGroup, int oldPosition,
ActiveMapsLayout::TGroup const & newGroup, int newPosition);
virtual void CountryStatusChanged(ActiveMapsLayout::TGroup const & group, int position,
TStatus const & oldStatus, TStatus const & newStatus);
virtual void CountryOptionsChanged(ActiveMapsLayout::TGroup const & group, int position,
TMapOptions const & oldOpt, TMapOptions const & newOpt);
virtual void DownloadingProgressUpdate(ActiveMapsLayout::TGroup const & group, int position, LocalAndRemoteSizeT const & progress);
private:
id<ActiveMapsObserverProtocol> m_delegateObject;
};
class CountryTreeObserver : public CountryTree::CountryTreeListener
{
public:
CountryTreeObserver(id<CountryTreeObserverProtocol> delegateObject);
virtual void ItemStatusChanged(int childPosition);
virtual void ItemProgressChanged(int childPosition, LocalAndRemoteSizeT const & sizes);
private:
id<CountryTreeObserverProtocol> m_delegateObject;
};

View file

@ -0,0 +1,52 @@
#import <Foundation/Foundation.h>
#import "MapsObservers.h"
ActiveMapsObserver::ActiveMapsObserver(id<ActiveMapsObserverProtocol> delegateObject)
: m_delegateObject(delegateObject)
{
}
void ActiveMapsObserver::CountryGroupChanged(ActiveMapsLayout::TGroup const & oldGroup, int oldPosition,
ActiveMapsLayout::TGroup const & newGroup, int newPosition)
{
if ([m_delegateObject respondsToSelector:@selector(countryGroupChangedFromPosition:inGroup:toPosition:inGroup:)])
[m_delegateObject countryGroupChangedFromPosition:oldPosition inGroup:oldGroup toPosition:newPosition inGroup:newGroup];
}
void ActiveMapsObserver::CountryStatusChanged(ActiveMapsLayout::TGroup const & group, int position,
TStatus const & oldStatus, TStatus const & newStatus)
{
if ([m_delegateObject respondsToSelector:@selector(countryStatusChangedAtPosition:inGroup:)])
[m_delegateObject countryStatusChangedAtPosition:position inGroup:group];
}
void ActiveMapsObserver::CountryOptionsChanged(ActiveMapsLayout::TGroup const & group, int position, TMapOptions const & oldOpt, TMapOptions const & newOpt)
{
if ([m_delegateObject respondsToSelector:@selector(countryOptionsChangedAtPosition:inGroup:)])
[m_delegateObject countryOptionsChangedAtPosition:position inGroup:group];
}
void ActiveMapsObserver::DownloadingProgressUpdate(ActiveMapsLayout::TGroup const & group, int position, LocalAndRemoteSizeT const & progress)
{
if ([m_delegateObject respondsToSelector:@selector(countryDownloadingProgressChanged:atPosition:inGroup:)])
[m_delegateObject countryDownloadingProgressChanged:progress atPosition:position inGroup:group];
}
CountryTreeObserver::CountryTreeObserver(id<CountryTreeObserverProtocol> delegateObject)
: m_delegateObject(delegateObject)
{
}
void CountryTreeObserver::ItemStatusChanged(int childPosition)
{
if ([m_delegateObject respondsToSelector:@selector(countryStatusChangedAtPositionInNode:)])
[m_delegateObject countryStatusChangedAtPositionInNode:childPosition];
}
void CountryTreeObserver::ItemProgressChanged(int childPosition, storage::LocalAndRemoteSizeT const & sizes)
{
if ([m_delegateObject respondsToSelector:@selector(countryDownloadingProgressChanged:atPositionInNode:)])
[m_delegateObject countryDownloadingProgressChanged:sizes atPositionInNode:childPosition];
}

View file

@ -38,4 +38,6 @@ typedef NS_ENUM(NSUInteger, PlacePageState) {
@property (nonatomic, readonly) NSString * temporaryTitle;
@property (nonatomic) BOOL statusBarIncluded;
- (void)showBuildingRoutingActivity:(BOOL)buiding;
@end

View file

@ -32,6 +32,7 @@ typedef NS_ENUM(NSUInteger, CellRow)
@property (nonatomic) CopyLabel * titleLabel;
@property (nonatomic) UIButton * bookmarkButton;
@property (nonatomic) UIButton * routeButton;
@property (nonatomic) UIActivityIndicatorView * routingActivity;
@property (nonatomic) UILabel * typeLabel;
@property (nonatomic) UIButton * shareButton;
@property (nonatomic) UIImageView * editImageView;
@ -342,6 +343,7 @@ typedef NS_ENUM(NSUInteger, CellRow)
self.bookmarkButton.midY = 36;
}
self.routeButton.midY = self.bookmarkButton.midY - 1;
self.routeButton.hidden = [self isMyPosition];
}
- (CGFloat)headerHeight
@ -812,6 +814,23 @@ typedef NS_ENUM(NSUInteger, CellRow)
m_bookmarkData = NULL;
}
- (void)showBuildingRoutingActivity:(BOOL)building
{
if (building)
{
self.routeButton.hidden = YES;
self.routingActivity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.routingActivity.center = CGPointMake(self.routeButton.midX, self.routeButton.midY + 2);
[self.routeButton.superview addSubview:self.routingActivity];
[self.routingActivity startAnimating];
}
else
{
self.routeButton.hidden = NO;
[self.routingActivity removeFromSuperview];
}
}
- (BOOL)isMarkOfType:(UserMark::Type)type
{
return m_mark ? [self userMark]->GetMarkType() == type : NO;

View file

@ -0,0 +1,20 @@
#import <UIKit/UIKit.h>
@class ProgressView;
@protocol ProgressViewDelegate <NSObject>
- (void)progressViewDidCancel:(ProgressView *)progress;
- (void)progressViewDidStart:(ProgressView *)progress;
@end
@interface ProgressView : UIView
@property (nonatomic) BOOL failedMode;
@property (nonatomic) double progress;
- (void)setProgress:(double)progress animated:(BOOL)animated;
@property (nonatomic, weak) id <ProgressViewDelegate> delegate;
@end

View file

@ -0,0 +1,169 @@
#import "ProgressView.h"
#import "UIKitCategories.h"
@interface ProgressView ()
@property (nonatomic) CAShapeLayer * progressLayer;
@property (nonatomic) CAShapeLayer * backgroundCircleLayer;
@property (nonatomic) CAShapeLayer * stopRectLayer;
@property (nonatomic) UIImageView * startTriangleView;
@property (nonatomic) UIButton * button;
@property (nonatomic) NSNumber * nextProgressToAnimate;
@end
@implementation ProgressView
#define CIRCLE_RADIUS 18
- (instancetype)init
{
self = [super initWithFrame:CGRectMake(0, 0, 44, 44)];
[self.layer addSublayer:self.backgroundCircleLayer];
[self.layer addSublayer:self.progressLayer];
[self.layer addSublayer:self.stopRectLayer];
[self addSubview:self.startTriangleView];
self.startTriangleView.center = CGPointMake(self.width / 2 + 1, self.height / 2);
[self addSubview:self.button];
[self setProgress:0 animated:NO];
return self;
}
- (void)buttonPressed:(id)sender
{
if (self.failedMode)
[self.delegate progressViewDidStart:self];
else
[self.delegate progressViewDidCancel:self];
}
- (CGFloat)angleWithProgress:(double)progress
{
return 2 * M_PI * progress - M_PI_2;
}
NSString * const CircleAnimationKey = @"CircleAnimation";
- (void)setProgress:(double)progress animated:(BOOL)animated
{
if ([self.progressLayer animationForKey:CircleAnimationKey])
{
self.nextProgressToAnimate = @(progress);
}
else
{
self.nextProgressToAnimate = nil;
CGPoint const center = CGPointMake(self.width / 2, self.height / 2);
CGFloat const radius = CIRCLE_RADIUS - self.progressLayer.lineWidth;
UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:[self angleWithProgress:0] endAngle:[self angleWithProgress:progress] clockwise:YES];
if (animated)
{
self.progressLayer.path = path.CGPath;
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.duration = 0.3;
animation.repeatCount = 1;
animation.fromValue = @(_progress / progress);
animation.toValue = @1;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.delegate = self;
[self.progressLayer addAnimation:animation forKey:CircleAnimationKey];
}
else
{
self.progressLayer.path = path.CGPath;
}
_progress = progress;
}
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
if (self.nextProgressToAnimate)
[self setProgress:[self.nextProgressToAnimate doubleValue] animated:YES];
}
- (CGColorRef)redColor
{
return [UIColor colorWithColorCode:@"FF4436"].CGColor;
}
- (CGColorRef)blueColor
{
return [UIColor colorWithColorCode:@"0585FF"].CGColor;
}
- (void)setFailedMode:(BOOL)failedMode
{
_failedMode = failedMode;
self.progressLayer.strokeColor = failedMode ? [self redColor] : [self blueColor];
self.stopRectLayer.hidden = failedMode;
self.startTriangleView.hidden = !failedMode;
}
- (UIButton *)button
{
if (!_button)
{
_button = [[UIButton alloc] initWithFrame:self.bounds];
[_button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
}
return _button;
}
- (CAShapeLayer *)stopRectLayer
{
if (!_stopRectLayer)
{
_stopRectLayer = [CAShapeLayer layer];
CGFloat const side = 11;
CGRect const rect = CGRectMake((self.width - side) / 2, (self.width - side) / 2, side, side);
_stopRectLayer.fillColor = [self blueColor];
_stopRectLayer.path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:2].CGPath;
}
return _stopRectLayer;
}
- (UIImageView *)startTriangleView
{
if (!_startTriangleView)
_startTriangleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"ProgressTriangle"]];
return _startTriangleView;
}
- (CAShapeLayer *)backgroundCircleLayer
{
if (!_backgroundCircleLayer)
{
_backgroundCircleLayer = [CAShapeLayer layer];
_backgroundCircleLayer.fillColor = [UIColor clearColor].CGColor;
_backgroundCircleLayer.lineWidth = 2;
_backgroundCircleLayer.strokeColor = [[UIColor colorWithColorCode:@"F0F0F0"] CGColor];
_backgroundCircleLayer.shouldRasterize = YES;
_backgroundCircleLayer.rasterizationScale = 2 * [UIScreen mainScreen].scale;
CGRect rect = CGRectMake(self.width / 2 - CIRCLE_RADIUS, self.height / 2 - CIRCLE_RADIUS, 2 * CIRCLE_RADIUS, 2 * CIRCLE_RADIUS);
rect = CGRectInset(rect, _backgroundCircleLayer.lineWidth, _backgroundCircleLayer.lineWidth);
_backgroundCircleLayer.path = [UIBezierPath bezierPathWithOvalInRect:rect].CGPath;
}
return _backgroundCircleLayer;
}
- (CAShapeLayer *)progressLayer
{
if (!_progressLayer)
{
_progressLayer = [CAShapeLayer layer];
_progressLayer.fillColor = [UIColor clearColor].CGColor;
_progressLayer.lineWidth = 3;
_progressLayer.shouldRasterize = YES;
_progressLayer.rasterizationScale = 2 * [UIScreen mainScreen].scale;
}
return _progressLayer;
}
@end

View file

@ -6,13 +6,14 @@
@protocol RouteViewDelegate <NSObject>
- (void)routeViewDidCancelRouting:(RouteView *)routeView;
- (void)routeViewDidStartRouting:(RouteView *)routeView;
- (void)routeViewDidStartFollowing:(RouteView *)routeView;
@end
@interface RouteView : UIView
- (void)setVisible:(BOOL)visible animated:(BOOL)animated;
- (void)hideFollowButton;
- (void)updateDistance:(NSString *)distance withMetrics:(NSString *)metrics;

View file

@ -19,6 +19,7 @@
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
[self addSubview:self.distanceView];
[self.distanceView addSubview:self.wrapView];
@ -38,7 +39,7 @@
- (void)updateDistance:(NSString *)distance withMetrics:(NSString *)metrics
{
self.distanceLabel.text = distance;
self.metricsLabel.text = metrics;
self.metricsLabel.text = metrics.uppercaseString;
[self layoutSubviews];
}
@ -51,13 +52,14 @@
CGFloat const betweenOffset = 0;
self.wrapView.size = CGSizeMake(self.distanceLabel.width + betweenOffset + self.metricsLabel.width, 40);
self.distanceLabel.midY = self.wrapView.height / 2;
self.metricsLabel.maxY = self.distanceLabel.maxY - 4;
self.wrapView.center = CGPointMake(self.wrapView.superview.width / 2, self.wrapView.superview.height / 2);
self.distanceLabel.minX = 0;
self.metricsLabel.minX = self.distanceLabel.minX + self.distanceLabel.width + betweenOffset;
self.distanceLabel.midY = self.wrapView.height / 2;
self.metricsLabel.maxY = self.distanceLabel.maxY - 4;
self.distanceView.size = CGSizeMake(self.wrapView.width + 24, BUTTON_HEIGHT);
self.wrapView.center = CGPointMake(self.wrapView.superview.width / 2, self.wrapView.superview.height / 2);
}
- (void)didMoveToSuperview
@ -73,7 +75,15 @@
- (void)startButtonPressed:(id)sender
{
[self.delegate routeViewDidStartRouting:self];
[self.delegate routeViewDidStartFollowing:self];
}
- (void)hideFollowButton
{
self.startButton.userInteractionEnabled = NO;
[UIView animateWithDuration:0.5 delay:0.1 damping:0.83 initialVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.startButton.maxY = -30;
} completion:nil];
}
- (void)setVisible:(BOOL)visible animated:(BOOL)animated
@ -82,9 +92,11 @@
CGFloat const offsetInnerX = 3;
CGFloat const offsetBetweenX = 0;
CGFloat const offsetOuterX = 18;
[UIView animateWithDuration:(animated ? 0.5 : 0) delay:0 damping:0.8 initialVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[UIView animateWithDuration:(animated ? 0.5 : 0) delay:0 damping:0.83 initialVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
if (visible)
{
self.startButton.userInteractionEnabled = YES;
self.startButton.minY = self.closeButton.minY;
self.distanceView.minX = offsetInnerX;
self.closeButton.maxX = self.width - offsetInnerX;
self.startButton.maxX = self.closeButton.minX - offsetBetweenX;
@ -126,7 +138,7 @@
if (!_startButton)
{
UIImageView * imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"StartRoutingButton"]];
NSString * title = @"Поехали!";
NSString * title = NSLocalizedString(@"routing_go", nil);
UIFont * font = [UIFont fontWithName:@"HelveticaNeue-Light" size:14];
CGFloat const width = [title sizeWithDrawSize:CGSizeMake(200, 30) font:font].width + imageView.width + 40;
@ -180,7 +192,6 @@
UIImage * image = [[UIImage imageNamed:@"RoutingButtonBackground"] resizableImageWithCapInsets:UIEdgeInsetsMake(5, 5, 5, 5)];
_distanceView.image = image;
_distanceView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
[_distanceView addSubview:self.wrapView];
}
return _distanceView;
}

View file

@ -1,11 +1,15 @@
#import "ToolbarView.h"
#import "MapsAppDelegate.h"
#import "Framework.h"
#import "BadgeView.h"
@interface ToolbarView ()
@property (nonatomic) UIButton * searchButton;
@property (nonatomic) UIButton * bookmarkButton;
@property (nonatomic) UIButton * menuButton;
@property (nonatomic) BadgeView * menuBadge;
@property (nonatomic) UIImageView * backgroundImageView;
@end
@ -32,9 +36,30 @@
[self layoutButtons];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(outOfDateCountriesCountChanged:) name:MapsStatusChangedNotification object:nil];
[self updateMenuBadgeWithCount:GetFramework().GetCountryTree().GetActiveMapLayout().GetCountInGroup(storage::ActiveMapsLayout::TGroup::EOutOfDate)];
return self;
}
- (void)outOfDateCountriesCountChanged:(NSNotification *)notification
{
[self updateMenuBadgeWithCount:[[notification userInfo][@"OutOfDate"] integerValue]];
}
- (void)updateMenuBadgeWithCount:(NSInteger)count
{
[self.menuBadge removeFromSuperview];
if (count > 0)
{
BadgeView * badge = [[BadgeView alloc] init];
badge.value = count;
badge.minY = 4;
badge.minX = self.menuButton.width / 2 + 10;
[self.menuButton addSubview:badge];
self.menuBadge = badge;
}
}
- (void)locationButtonPressed:(id)sender
{
[self.delegate toolbar:self didPressItemWithName:@"Location"];
@ -106,4 +131,9 @@
return _backgroundImageView;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end

View file

@ -0,0 +1,9 @@
#import <UIKit/UIKit.h>
#import "DownloaderParentVC.h"
@interface CountryTreeVC : DownloaderParentVC
- (id)initWithNodePosition:(int)position;
@end

View file

@ -0,0 +1,329 @@
#import "CountryTreeVC.h"
#import "ActiveMapsVC.h"
#import "CustomAlertView.h"
#import "Statistics.h"
@interface CountryTreeVC () <CountryTreeObserverProtocol>
@end
@implementation CountryTreeVC
{
CountryTreeObserver * m_treeObserver;
}
- (id)initWithNodePosition:(int)position
{
self = [super init];
if (position == -1)
{
self.tree.SetDefaultRoot();
self.title = L(@"download_maps");
}
else
{
ASSERT(position < self.tree.GetChildCount(), ());
self.title = [NSString stringWithUTF8String:self.tree.GetChildName(position).c_str()];
self.tree.SetChildAsRoot(position);
}
__weak CountryTreeVC * weakSelf = self;
m_treeObserver = new CountryTreeObserver(weakSelf);
self.tree.SetListener(m_treeObserver);
return self;
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if (self.isMovingFromParentViewController)
{
if (self.tree.HasParent())
self.tree.SetParentAsRoot();
else
self.tree.ResetListener();
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView reloadData];
}
#define TOP_ROWS_COUNT 1
- (NSIndexPath *)downloadedCountriesIndexPath
{
return [NSIndexPath indexPathForRow:0 inSection:0];
}
- (void)outOfDateCountriesCountChanged:(NSNotification *)notification
{
NSInteger const count = [[notification userInfo][@"OutOfDate"] integerValue];
if ([self isRootScreen])
{
MapCell * cell = (MapCell *)[self.tableView cellForRowAtIndexPath:[self downloadedCountriesIndexPath]];
cell.badgeView.value = count;
}
}
#pragma mark - Helpers
- (BOOL)isRootScreen
{
return !self.tree.HasParent();
}
- (CountryTree &)tree
{
return GetFramework().GetCountryTree();
}
- (MapCell *)cellAtPositionInNode:(int)position
{
NSInteger const section = [self isRootScreen] ? [self downloadedCountriesIndexPath].section + 1 : 0;
return (MapCell *)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:position inSection:section]];
}
- (BOOL)isActiveMapsIndexPath:(NSIndexPath *)indexPath
{
return [self isRootScreen] && [indexPath isEqual:[self downloadedCountriesIndexPath]];
}
#pragma mark - DownloaderParentVC virtual methods implementation
- (NSString *)parentTitle
{
return self.tree.IsCountryRoot() ? [NSString stringWithUTF8String:self.tree.GetRootName().c_str()] : nil;
}
- (NSString *)selectedMapName
{
return [NSString stringWithUTF8String:self.tree.GetChildName(self.selectedPosition).c_str()];
}
- (NSString *)selectedMapGuideName
{
guides::GuideInfo info;
if (self.tree.GetLeafGuideInfo(self.selectedPosition, info))
{
string const lang = languages::GetCurrentNorm();
return [NSString stringWithUTF8String:info.GetAdTitle(lang).c_str()];
}
return nil;
}
- (size_t)selectedMapSizeWithOptions:(storage::TMapOptions)options
{
return self.tree.GetLeafSize(self.selectedPosition, options).second;
}
- (TStatus)selectedMapStatus
{
return self.tree.GetLeafStatus(self.selectedPosition);
}
- (TMapOptions)selectedMapOptions
{
return self.tree.GetLeafOptions(self.selectedPosition);
}
- (void)performAction:(DownloaderAction)action
{
switch (action)
{
case DownloaderActionDownloadAll:
case DownloaderActionDownloadMap:
case DownloaderActionDownloadCarRouting:
if ([self canDownloadSelectedMap])
self.tree.DownloadCountry(self.selectedPosition, self.selectedInActionSheetOptions);
break;
case DownloaderActionDeleteAll:
case DownloaderActionDeleteMap:
case DownloaderActionDeleteCarRouting:
self.tree.DeleteCountry(self.selectedPosition, self.selectedInActionSheetOptions);
break;
case DownloaderActionCancelDownloading:
self.tree.CancelDownloading(self.selectedPosition);
break;
case DownloaderActionZoomToCountry:
self.tree.ShowLeafOnMap(self.selectedPosition);
[[Statistics instance] logEvent:@"Show Map From Download Countries Screen"];
[self.navigationController popToRootViewControllerAnimated:YES];
break;
case DownloaderActionShowGuide:
guides::GuideInfo info;
if (self.tree.GetLeafGuideInfo(self.selectedPosition, info))
[self openGuideWithInfo:info];
break;
}
}
#pragma mark - TableView
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 13;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 0.001;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self isRootScreen] ? 1 + TOP_ROWS_COUNT : 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self isRootScreen] && section == [self downloadedCountriesIndexPath].section)
return TOP_ROWS_COUNT;
else
return self.tree.GetChildCount();
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MapCell * cell = [tableView dequeueReusableCellWithIdentifier:[MapCell className]];
if (!cell)
cell = [[MapCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[MapCell className]];
if ([self isActiveMapsIndexPath:indexPath])
{
cell.titleLabel.text = L(@"downloader_downloaded_maps");
cell.subtitleLabel.text = nil;
cell.parentMode = YES;
cell.badgeView.value = self.tree.GetActiveMapLayout().GetCountInGroup(ActiveMapsLayout::TGroup::EOutOfDate);
}
else
{
int const position = indexPath.row;
bool const isLeaf = self.tree.IsLeaf(position);
cell.titleLabel.text = [NSString stringWithUTF8String:self.tree.GetChildName(position).c_str()];
cell.subtitleLabel.text = [self parentTitle];
cell.delegate = self;
cell.badgeView.value = 0;
cell.parentMode = !isLeaf;
if (isLeaf)
{
TMapOptions const options = self.tree.GetLeafOptions(position);
TStatus const status = self.tree.GetLeafStatus(position);
NSString * sizeString;
if (status == TStatus::ENotDownloaded)
{
LocalAndRemoteSizeT const size = self.tree.GetRemoteLeafSizes(position);
sizeString = [NSString stringWithFormat:@"%@ / %@", [self formattedMapSize:size.first], [self formattedMapSize:size.second]];
}
else if (status == TStatus::EOnDisk || status == TStatus::EOnDiskOutOfDate)
{
size_t const size = self.tree.GetLeafSize(position, options).second;
sizeString = [self formattedMapSize:size];
}
else if (status == TStatus::EOutOfMemFailed || status == TStatus::EDownloadFailed || status == TStatus::EDownloading || status == TStatus::EInQueue)
{
LocalAndRemoteSizeT const size = self.tree.GetDownloadableLeafSize(position);
sizeString = [self formattedMapSize:size.second];
cell.downloadProgress = (double)size.first / size.second;
}
cell.sizeLabel.text = sizeString;
cell.status = status;
cell.options = options;
}
}
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
TStatus const status = self.tree.GetLeafStatus(indexPath.row);
return status == TStatus::EOnDisk || status == TStatus::EOnDiskOutOfDate;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
self.tree.DeleteCountry(indexPath.row, TMapOptions::EMapWithCarRouting);
[tableView setEditing:NO animated:YES];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self isActiveMapsIndexPath:indexPath])
{
ActiveMapsVC * vc = [[ActiveMapsVC alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
else
{
self.selectedPosition = indexPath.row;
if (self.tree.IsLeaf(self.selectedPosition))
{
MapCell * cell = [self cellAtPositionInNode:self.selectedPosition];
UIActionSheet * actionSheet = [self actionSheetToPerformActionOnSelectedMap];
[actionSheet showFromRect:cell.frame inView:cell.superview animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
else
{
CountryTreeVC * vc = [[CountryTreeVC alloc] initWithNodePosition:self.selectedPosition];
[self.navigationController pushViewController:vc animated:YES];
}
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [MapCell cellHeight];
}
#pragma mark - MapCellDelegate
- (void)mapCellDidStartDownloading:(MapCell *)cell
{
self.selectedPosition = [self.tableView indexPathForCell:cell].row;
TStatus const status = [self selectedMapStatus];
if (status == TStatus::EDownloadFailed || status == TStatus::EOutOfMemFailed)
if ([self canDownloadSelectedMap])
self.tree.RetryDownloading(self.selectedPosition);
}
- (void)mapCellDidCancelDownloading:(MapCell *)cell
{
self.selectedPosition = [self.tableView indexPathForCell:cell].row;
[[self actionSheetToDeleteSelectedMap] showFromRect:cell.frame inView:cell.superview animated:YES];
}
#pragma mark - CountryTree core callbacks
- (void)countryStatusChangedAtPositionInNode:(int)position
{
MapCell * cell = [self cellAtPositionInNode:position];
[cell setStatus:self.tree.GetLeafStatus(position) options:self.tree.GetLeafOptions(position) animated:YES];
}
- (void)countryDownloadingProgressChanged:(LocalAndRemoteSizeT const &)progress atPositionInNode:(int)position
{
MapCell * cell = [self cellAtPositionInNode:position];
[cell setDownloadProgress:((double)progress.first / progress.second) animated:YES];
}
@end

View file

@ -0,0 +1,50 @@
#import <UIKit/UIKit.h>
#import "MapsObservers.h"
#import "MapCell.h"
#import "UIKitCategories.h"
#include "../../storage/storage_defines.hpp"
#include "../../platform/preferred_languages.hpp"
typedef NS_ENUM(NSUInteger, DownloaderAction)
{
DownloaderActionDownloadAll,
DownloaderActionDownloadMap,
DownloaderActionDownloadCarRouting,
DownloaderActionDeleteAll,
DownloaderActionDeleteMap,
DownloaderActionDeleteCarRouting,
DownloaderActionCancelDownloading,
DownloaderActionZoomToCountry,
DownloaderActionShowGuide
};
using namespace storage;
@interface DownloaderParentVC : UITableViewController <MapCellDelegate, UIActionSheetDelegate, UIAlertViewDelegate>
- (NSString *)formattedMapSize:(size_t)size;
- (void)openGuideWithInfo:(guides::GuideInfo const &)info;
- (BOOL)canDownloadSelectedMap;
- (UIActionSheet *)actionSheetToDeleteSelectedMap;
- (UIActionSheet *)actionSheetToCancelDownloadingSelectedMap;
- (UIActionSheet *)actionSheetToPerformActionOnSelectedMap;
@property (nonatomic) NSInteger selectedPosition;
@property (nonatomic) TMapOptions selectedInActionSheetOptions;
@property (nonatomic) NSMutableDictionary * actionSheetActions;
// virtual
- (NSString *)parentTitle;
- (NSString *)selectedMapName;
- (NSString *)selectedMapGuideName;
- (size_t)selectedMapSizeWithOptions:(TMapOptions)options;
- (TStatus)selectedMapStatus;
- (TMapOptions)selectedMapOptions;
- (void)performAction:(DownloaderAction)action;
@end

View file

@ -0,0 +1,282 @@
#import "DownloaderParentVC.h"
#import "CustomAlertView.h"
#import "DiskFreeSpace.h"
#import "Statistics.h"
#import "Reachability.h"
#import "MapsAppDelegate.h"
@interface DownloaderParentVC ()
@end
@implementation DownloaderParentVC
- (id)init
{
self = [super initWithStyle:UITableViewStyleGrouped];
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(outOfDateCountriesCountChanged:) name:MapsStatusChangedNotification object:nil];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != alertView.cancelButtonIndex)
{
if (self.selectedInActionSheetOptions == TMapOptions::EMapOnly)
[self performAction:DownloaderActionDownloadMap];
else if (self.selectedInActionSheetOptions == TMapOptions::ECarRouting)
[self performAction:DownloaderActionDownloadCarRouting];
else if (self.selectedInActionSheetOptions == TMapOptions::EMapWithCarRouting)
[self performAction:DownloaderActionDownloadAll];
}
}
- (BOOL)allButtonsInActionSheetAreAboutDownloading:(TStatus const)status
{
return status == TStatus::ENotDownloaded;
}
#pragma mark - Virtual methods
- (void)performAction:(DownloaderAction)action {}
- (NSString *)parentTitle { return nil; }
- (NSString *)selectedMapName { return nil; }
- (NSString *)selectedMapGuideName { return nil; }
- (size_t)selectedMapSizeWithOptions:(TMapOptions)options { return 0; }
- (TStatus)selectedMapStatus { return TStatus::EUnknown; }
- (TMapOptions)selectedMapOptions { return TMapOptions::EMapOnly; }
#pragma mark - Public methods for successors
#define MB (1024 * 1024)
- (NSString *)formattedMapSize:(size_t)size
{
NSString * sizeString;
if (size > MB)
sizeString = [NSString stringWithFormat:@"%ld %@", (size + 512 * 1024) / MB, L(@"mb")];
else
sizeString = [NSString stringWithFormat:@"%ld %@", (size + 1023) / 1024, L(@"kb")];
return [sizeString uppercaseString];
}
- (BOOL)canDownloadSelectedMap
{
size_t const size = [self selectedMapSizeWithOptions:self.selectedInActionSheetOptions];
NSString * name = [self selectedMapName];
Reachability * reachability = [Reachability reachabilityForInternetConnection];
if ([reachability isReachable])
{
if ([reachability isReachableViaWWAN] && size > 50 * MB)
{
NSString * title = [NSString stringWithFormat:L(@"no_wifi_ask_cellular_download"), name];
[[[CustomAlertView alloc] initWithTitle:title message:nil delegate:self cancelButtonTitle:L(@"cancel") otherButtonTitles:L(@"use_cellular_data"), nil] show];
}
else
return YES;
}
else
{
[[[CustomAlertView alloc] initWithTitle:L(@"no_internet_connection_detected") message:L(@"use_wifi_recommendation_text") delegate:nil cancelButtonTitle:L(@"ok") otherButtonTitles:nil] show];
}
return NO;
}
- (void)openGuideWithInfo:(const guides::GuideInfo &)info
{
string const lang = languages::GetCurrentNorm();
NSURL * guideUrl = [NSURL URLWithString:[NSString stringWithUTF8String:info.GetAppID().c_str()]];
[[Statistics instance] logEvent:@"Open Guide Country" withParameters:@{@"Country Name" : [self selectedMapName]}];
UIApplication * application = [UIApplication sharedApplication];
if ([application canOpenURL:guideUrl])
{
[application openURL:guideUrl];
[[Statistics instance] logEvent:@"Open Guide Button" withParameters:@{@"Guide downloaded" : @"YES"}];
}
else
{
[application openURL:[NSURL URLWithString:[NSString stringWithUTF8String:info.GetURL().c_str()]]];
[[Statistics instance] logEvent:@"Open Guide Button" withParameters:@{@"Guide downloaded" : @"NO"}];
}
}
#define ROUTING_SYMBOL @"\xF0\x9F\x9A\x97"
- (UIActionSheet *)actionSheetToPerformActionOnSelectedMap
{
TStatus const status = [self selectedMapStatus];
TMapOptions const options = [self selectedMapOptions];
[self.actionSheetActions removeAllObjects];
NSString * title;
if ([self allButtonsInActionSheetAreAboutDownloading:status])
title = [NSString stringWithFormat:@"%@ %@", L(@"download").uppercaseString, [self actionSheetTitle]];
else
title = [self actionSheetTitle];
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
if (status == TStatus::EOnDisk || status == TStatus::EOnDiskOutOfDate)
{
if ([self selectedMapGuideName])
[self addButtonWithTitle:[self selectedMapGuideName] action:DownloaderActionShowGuide toActionSheet:actionSheet];
[self addButtonWithTitle:L(@"zoom_to_country") action:DownloaderActionZoomToCountry toActionSheet:actionSheet];
}
if (status == TStatus::ENotDownloaded || status == TStatus::EOutOfMemFailed || status == TStatus::EDownloadFailed)
{
NSString * size = [self formattedMapSize:[self selectedMapSizeWithOptions:TMapOptions::EMapOnly]];
NSString * title;
if ([self allButtonsInActionSheetAreAboutDownloading:status])
title = [NSString stringWithFormat:@"%@, %@", L(@"downloader_map_only"), size];
else
title = [NSString stringWithFormat:@"%@, %@", L(@"downloader_download_map"), size];
[self addButtonWithTitle:title action:DownloaderActionDownloadMap toActionSheet:actionSheet];
}
if (status == TStatus::ENotDownloaded || status == TStatus::EOutOfMemFailed || status == TStatus::EDownloadFailed)
{
NSString * size = [self formattedMapSize:[self selectedMapSizeWithOptions:TMapOptions::EMapWithCarRouting]];
NSString * title;
if ([self allButtonsInActionSheetAreAboutDownloading:status])
title = [NSString stringWithFormat:@"%@%@, %@", L(@"downloader_map_and_routing"), ROUTING_SYMBOL, size];
else
title = [NSString stringWithFormat:@"%@%@, %@", L(@"downloader_download_map_and_routing"), ROUTING_SYMBOL, size];
[self addButtonWithTitle:title action:DownloaderActionDownloadAll toActionSheet:actionSheet];
}
if (status == TStatus::EOnDiskOutOfDate && options == TMapOptions::EMapWithCarRouting)
{
NSString * size = [self formattedMapSize:[self selectedMapSizeWithOptions:TMapOptions::EMapWithCarRouting]];
NSString * title = [NSString stringWithFormat:@"%@%@, %@", L(@"downloader_update_map_and_routing"), ROUTING_SYMBOL, size];
[self addButtonWithTitle:title action:DownloaderActionDownloadAll toActionSheet:actionSheet];
}
if (status == TStatus::EOnDisk && options == TMapOptions::EMapOnly)
{
NSString * size = [self formattedMapSize:[self selectedMapSizeWithOptions:TMapOptions::ECarRouting]];
NSString * title = [NSString stringWithFormat:@"%@, %@", L(@"downloader_download_routing"), size];
[self addButtonWithTitle:title action:DownloaderActionDownloadCarRouting toActionSheet:actionSheet];
}
if (status == TStatus::EOnDiskOutOfDate && options == TMapOptions::EMapOnly)
{
NSString * size = [self formattedMapSize:[self selectedMapSizeWithOptions:TMapOptions::EMapOnly]];
NSString * title = [NSString stringWithFormat:@"%@, %@", L(@"downloader_update_map"), size];
[self addButtonWithTitle:title action:DownloaderActionDownloadMap toActionSheet:actionSheet];
}
if (status == TStatus::EOnDisk || status == TStatus::EOnDiskOutOfDate)
{
if (options == TMapOptions::EMapWithCarRouting)
[self addButtonWithTitle:L(@"downloader_delete_routing") action:DownloaderActionDeleteCarRouting toActionSheet:actionSheet];
[self addButtonWithTitle:L(@"downloader_delete_map") action:DownloaderActionDeleteMap toActionSheet:actionSheet];
actionSheet.destructiveButtonIndex = actionSheet.numberOfButtons - 1;
}
if (status == TStatus::EDownloading)
{
[self addButtonWithTitle:L(@"cancel_download") action:DownloaderActionCancelDownloading toActionSheet:actionSheet];
actionSheet.destructiveButtonIndex = actionSheet.numberOfButtons - 1;
}
if (!IPAD)
{
[actionSheet addButtonWithTitle:L(@"cancel")];
actionSheet.cancelButtonIndex = actionSheet.numberOfButtons - 1;
}
return actionSheet;
}
- (UIActionSheet *)actionSheetToDeleteSelectedMap
{
[self.actionSheetActions removeAllObjects];
self.actionSheetActions[@0] = @(DownloaderActionDeleteAll);
return [[UIActionSheet alloc] initWithTitle:[self actionSheetTitle] delegate:self cancelButtonTitle:L(@"cancel") destructiveButtonTitle:L(@"downloader_delete_map") otherButtonTitles:nil];
}
- (UIActionSheet *)actionSheetToCancelDownloadingSelectedMap
{
[self.actionSheetActions removeAllObjects];
self.actionSheetActions[@0] = @(DownloaderActionCancelDownloading);
return [[UIActionSheet alloc] initWithTitle:[self actionSheetTitle] delegate:self cancelButtonTitle:L(@"cancel") destructiveButtonTitle:L(@"cancel_download") otherButtonTitles:nil];
}
#pragma mark -
- (NSString *)actionSheetTitle
{
if ([self parentTitle])
return [NSString stringWithFormat:@"%@, %@", [self selectedMapName].uppercaseString, [self parentTitle].uppercaseString];
else
return [self selectedMapName].uppercaseString;
}
- (void)addButtonWithTitle:(NSString *)title action:(DownloaderAction)action toActionSheet:(UIActionSheet *)actionSheet
{
[actionSheet addButtonWithTitle:title];
self.actionSheetActions[@(actionSheet.numberOfButtons - 1)] = @(action);
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != actionSheet.cancelButtonIndex)
{
DownloaderAction const action = (DownloaderAction)[self.actionSheetActions[@(buttonIndex)] integerValue];
switch (action)
{
case DownloaderActionDownloadAll:
case DownloaderActionDeleteAll:
self.selectedInActionSheetOptions = TMapOptions::EMapWithCarRouting;
break;
case DownloaderActionDownloadMap:
case DownloaderActionDeleteMap:
self.selectedInActionSheetOptions = TMapOptions::EMapOnly;
break;
case DownloaderActionDownloadCarRouting:
case DownloaderActionDeleteCarRouting:
self.selectedInActionSheetOptions = TMapOptions::ECarRouting;
break;
default:
break;
}
[self performAction:action];
}
}
#pragma mark -
- (NSMutableDictionary *)actionSheetActions
{
if (!_actionSheetActions)
_actionSheetActions = [[NSMutableDictionary alloc] init];
return _actionSheetActions;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end

View file

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "MapCellSeparator@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "MapCellSeparator@3x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -3,25 +3,21 @@
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "drive.png"
"filename" : "ProgressTriangle.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "drive@2x.png"
"filename" : "ProgressTriangle@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "drive@3x.png"
"filename" : "ProgressTriangle@3x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
<<<<<<< HEAD
}
=======
}
>>>>>>> 56a28db... [ios] Downloader UI
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 B

View file

@ -23,8 +23,8 @@
974386DA1934CBAD00FD5659 /* FacebookSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 974386D81934CBAC00FD5659 /* FacebookSDK.framework */; };
974386DD19373EA400FD5659 /* ToastView.m in Sources */ = {isa = PBXBuildFile; fileRef = 974386DC19373EA400FD5659 /* ToastView.m */; };
974386DE19373EA400FD5659 /* ToastView.m in Sources */ = {isa = PBXBuildFile; fileRef = 974386DC19373EA400FD5659 /* ToastView.m */; };
9746492718EEE2F8004B4658 /* ToolbarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9746492618EEE2F8004B4658 /* ToolbarView.m */; };
9746492818EEE2F8004B4658 /* ToolbarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9746492618EEE2F8004B4658 /* ToolbarView.m */; };
9746492718EEE2F8004B4658 /* ToolbarView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9746492618EEE2F8004B4658 /* ToolbarView.mm */; };
9746492818EEE2F8004B4658 /* ToolbarView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9746492618EEE2F8004B4658 /* ToolbarView.mm */; };
9747264318323080006B7CB7 /* UIKitCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 9747264118323080006B7CB7 /* UIKitCategories.m */; };
9747264418323080006B7CB7 /* UIKitCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 9747264118323080006B7CB7 /* UIKitCategories.m */; };
9747278418338F0C006B7CB7 /* UIViewController+Navigation.m in Sources */ = {isa = PBXBuildFile; fileRef = 9747278318338F0C006B7CB7 /* UIViewController+Navigation.m */; };
@ -47,6 +47,10 @@
9767702519B718D800402693 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 9767701D19B718D700402693 /* LICENSE */; };
9769D6EF1912BF3000CA6158 /* ContainerView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9769D6EE1912BF3000CA6158 /* ContainerView.mm */; };
9769D6F01912BF3000CA6158 /* ContainerView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9769D6EE1912BF3000CA6158 /* ContainerView.mm */; };
976D86EC19C8697700C920EF /* ProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 976D86EB19C8697700C920EF /* ProgressView.m */; };
976D86ED19C8697700C920EF /* ProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 976D86EB19C8697700C920EF /* ProgressView.m */; };
976D86F119C877E600C920EF /* MapCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = 976D86F019C877E600C920EF /* MapCell.mm */; };
976D86F219C877E600C920EF /* MapCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = 976D86F019C877E600C920EF /* MapCell.mm */; };
976D86F519CB21BD00C920EF /* RouteView.m in Sources */ = {isa = PBXBuildFile; fileRef = 976D86F419CB21BD00C920EF /* RouteView.m */; };
976D86F619CB21BD00C920EF /* RouteView.m in Sources */ = {isa = PBXBuildFile; fileRef = 976D86F419CB21BD00C920EF /* RouteView.m */; };
97719D451843B6DC00BDD815 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 97719D441843B6DC00BDD815 /* MessageUI.framework */; };
@ -63,6 +67,14 @@
9778E9A2191A663700AD850A /* BookmarkNameVC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9778E9A0191A663700AD850A /* BookmarkNameVC.mm */; };
9778E9A5191A86D800AD850A /* SelectedColorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9778E9A4191A86D800AD850A /* SelectedColorView.m */; };
9778E9A6191A86D800AD850A /* SelectedColorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9778E9A4191A86D800AD850A /* SelectedColorView.m */; };
977E26B919E2E64200BA2219 /* MapsObservers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 977E26B819E2E64200BA2219 /* MapsObservers.mm */; };
977E26BA19E2E64200BA2219 /* MapsObservers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 977E26B819E2E64200BA2219 /* MapsObservers.mm */; };
977E26BE19E31BBE00BA2219 /* CountryTreeVC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 977E26BD19E31BBE00BA2219 /* CountryTreeVC.mm */; };
977E26BF19E31BBE00BA2219 /* CountryTreeVC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 977E26BD19E31BBE00BA2219 /* CountryTreeVC.mm */; };
977E26C219E31BCC00BA2219 /* ActiveMapsVC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 977E26C119E31BCC00BA2219 /* ActiveMapsVC.mm */; };
977E26C319E31BCC00BA2219 /* ActiveMapsVC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 977E26C119E31BCC00BA2219 /* ActiveMapsVC.mm */; };
977E26C619E31BDF00BA2219 /* DownloaderParentVC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 977E26C519E31BDF00BA2219 /* DownloaderParentVC.mm */; };
977E26C719E31BDF00BA2219 /* DownloaderParentVC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 977E26C519E31BDF00BA2219 /* DownloaderParentVC.mm */; };
9789DB56188D5E2A007C6FAE /* InAppMessagesManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9789DB55188D5E2A007C6FAE /* InAppMessagesManager.mm */; };
9789DB57188D5E2A007C6FAE /* InAppMessagesManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9789DB55188D5E2A007C6FAE /* InAppMessagesManager.mm */; };
9789DB5A188D94F9007C6FAE /* InterstitialView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9789DB59188D94F9007C6FAE /* InterstitialView.mm */; };
@ -89,8 +101,8 @@
97908B31196591FB003DD7C6 /* SearchShowOnMapCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 97908B2F196591F7003DD7C6 /* SearchShowOnMapCell.m */; };
97A0EEFA192F3B43009B2779 /* BottomMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 97A0EEF7192F3B43009B2779 /* BottomMenu.mm */; };
97A0EEFB192F3B43009B2779 /* BottomMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 97A0EEF7192F3B43009B2779 /* BottomMenu.mm */; };
97A0EEFC192F3B43009B2779 /* BottomMenuCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 97A0EEF9192F3B43009B2779 /* BottomMenuCell.m */; };
97A0EEFD192F3B43009B2779 /* BottomMenuCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 97A0EEF9192F3B43009B2779 /* BottomMenuCell.m */; };
97A0EEFC192F3B43009B2779 /* BottomMenuCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = 97A0EEF9192F3B43009B2779 /* BottomMenuCell.mm */; };
97A0EEFD192F3B43009B2779 /* BottomMenuCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = 97A0EEF9192F3B43009B2779 /* BottomMenuCell.mm */; };
97A5967F19B9CD47007A963F /* copyright.html in Resources */ = {isa = PBXBuildFile; fileRef = 97A5967E19B9CD47007A963F /* copyright.html */; };
97A5968019B9CD47007A963F /* copyright.html in Resources */ = {isa = PBXBuildFile; fileRef = 97A5967E19B9CD47007A963F /* copyright.html */; };
97A8000C18B21363000C07A2 /* SearchView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 97A8000B18B21363000C07A2 /* SearchView.mm */; };
@ -151,6 +163,8 @@
97ECD881183674CA00F77A46 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 97ECD87718362B3D00F77A46 /* CoreTelephony.framework */; };
97ECD8821836751100F77A46 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 97ECD87918362B5400F77A46 /* MobileCoreServices.framework */; };
97EDDCE518A299C000AEFB7A /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 97EDDCE418A299C000AEFB7A /* Twitter.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
97F0817E19AF72590098FB0B /* BadgeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 97F0817D19AF72590098FB0B /* BadgeView.m */; };
97F0817F19AF72590098FB0B /* BadgeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 97F0817D19AF72590098FB0B /* BadgeView.m */; };
97F61781183E6172009919E2 /* LocationButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = 97F6177F183E6172009919E2 /* LocationButton.mm */; };
97F61782183E6172009919E2 /* LocationButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = 97F6177F183E6172009919E2 /* LocationButton.mm */; };
97F61794183E7445009919E2 /* LinkCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 97F61793183E7445009919E2 /* LinkCell.m */; };
@ -238,8 +252,6 @@
FA34BECA1338D72F00FFB2A7 /* CustomAlertView.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA34BEC81338D72F00FFB2A7 /* CustomAlertView.mm */; };
FA36B80D15403A4F004560CC /* BookmarksVC.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA36B80615403A4F004560CC /* BookmarksVC.mm */; };
FA36B80E15403A4F004560CC /* BookmarksVC.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA36B80615403A4F004560CC /* BookmarksVC.mm */; };
FA4135EA120A263C0062D5B4 /* CountriesViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA4135E2120A263C0062D5B4 /* CountriesViewController.mm */; };
FA4135ED120A263C0062D5B4 /* SettingsManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA4135E7120A263C0062D5B4 /* SettingsManager.mm */; };
FA459EB414327AF700B5BB3C /* WorldCoasts.mwm in Resources */ = {isa = PBXBuildFile; fileRef = FA459EB314327AF700B5BB3C /* WorldCoasts.mwm */; };
FA46DA2C12D4166E00968C36 /* countries.txt in Resources */ = {isa = PBXBuildFile; fileRef = FA46DA2B12D4166E00968C36 /* countries.txt */; };
FA64D9A913F975AD00350ECF /* types.txt in Resources */ = {isa = PBXBuildFile; fileRef = FA64D9A813F975AD00350ECF /* types.txt */; };
@ -1297,8 +1309,6 @@
FAFB08EA151215EE0041901D /* MapsAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* MapsAppDelegate.mm */; };
FAFB08EB151215EE0041901D /* EAGLView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 46F26CD710F623BA00ECCA39 /* EAGLView.mm */; };
FAFB08EC151215EE0041901D /* MapViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = EED10A4411F78D120095FAD4 /* MapViewController.mm */; };
FAFB08ED151215EE0041901D /* CountriesViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA4135E2120A263C0062D5B4 /* CountriesViewController.mm */; };
FAFB08EE151215EE0041901D /* SettingsManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA4135E7120A263C0062D5B4 /* SettingsManager.mm */; };
FAFB08EF151215EE0041901D /* RenderBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = EE7F297D1219ECA300EB67A9 /* RenderBuffer.mm */; };
FAFB08F0151215EE0041901D /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = EE7F297E1219ECA300EB67A9 /* RenderContext.mm */; };
FAFB08F1151215EE0041901D /* WebViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = FAFCB63513366E78001A5C59 /* WebViewController.mm */; };
@ -1345,7 +1355,7 @@
974386DB19373EA400FD5659 /* ToastView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ToastView.h; sourceTree = "<group>"; };
974386DC19373EA400FD5659 /* ToastView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ToastView.m; sourceTree = "<group>"; };
9746492518EEE2F8004B4658 /* ToolbarView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ToolbarView.h; sourceTree = "<group>"; };
9746492618EEE2F8004B4658 /* ToolbarView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ToolbarView.m; sourceTree = "<group>"; };
9746492618EEE2F8004B4658 /* ToolbarView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ToolbarView.mm; sourceTree = "<group>"; };
9747264118323080006B7CB7 /* UIKitCategories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UIKitCategories.m; path = Categories/UIKitCategories.m; sourceTree = "<group>"; };
9747264218323080006B7CB7 /* UIKitCategories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UIKitCategories.h; path = Categories/UIKitCategories.h; sourceTree = "<group>"; };
9747278218338F0C006B7CB7 /* UIViewController+Navigation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIViewController+Navigation.h"; path = "Classes/UIViewController+Navigation.h"; sourceTree = "<group>"; };
@ -1365,6 +1375,10 @@
9767701F19B718D700402693 /* LocalyticsSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalyticsSession.h; sourceTree = "<group>"; };
9769D6ED1912BF3000CA6158 /* ContainerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContainerView.h; sourceTree = "<group>"; };
9769D6EE1912BF3000CA6158 /* ContainerView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContainerView.mm; sourceTree = "<group>"; };
976D86EA19C8697700C920EF /* ProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressView.h; path = Classes/ProgressView.h; sourceTree = "<group>"; };
976D86EB19C8697700C920EF /* ProgressView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressView.m; path = Classes/ProgressView.m; sourceTree = "<group>"; };
976D86EF19C877E600C920EF /* MapCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MapCell.h; path = Classes/MapCell.h; sourceTree = "<group>"; };
976D86F019C877E600C920EF /* MapCell.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MapCell.mm; path = Classes/MapCell.mm; sourceTree = "<group>"; };
976D86F319CB21BD00C920EF /* RouteView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RouteView.h; sourceTree = "<group>"; };
976D86F419CB21BD00C920EF /* RouteView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RouteView.m; sourceTree = "<group>"; };
97719D441843B6DC00BDD815 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
@ -1378,6 +1392,14 @@
9778E9A0191A663700AD850A /* BookmarkNameVC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BookmarkNameVC.mm; sourceTree = "<group>"; };
9778E9A3191A86D800AD850A /* SelectedColorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectedColorView.h; sourceTree = "<group>"; };
9778E9A4191A86D800AD850A /* SelectedColorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SelectedColorView.m; sourceTree = "<group>"; };
977E26B819E2E64200BA2219 /* MapsObservers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MapsObservers.mm; path = Classes/MapsObservers.mm; sourceTree = "<group>"; };
977E26BB19E2E65E00BA2219 /* MapsObservers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MapsObservers.h; path = Classes/MapsObservers.h; sourceTree = "<group>"; };
977E26BC19E31BBE00BA2219 /* CountryTreeVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountryTreeVC.h; sourceTree = "<group>"; };
977E26BD19E31BBE00BA2219 /* CountryTreeVC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CountryTreeVC.mm; sourceTree = "<group>"; };
977E26C019E31BCC00BA2219 /* ActiveMapsVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActiveMapsVC.h; sourceTree = "<group>"; };
977E26C119E31BCC00BA2219 /* ActiveMapsVC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ActiveMapsVC.mm; sourceTree = "<group>"; };
977E26C419E31BDF00BA2219 /* DownloaderParentVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DownloaderParentVC.h; sourceTree = "<group>"; };
977E26C519E31BDF00BA2219 /* DownloaderParentVC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DownloaderParentVC.mm; sourceTree = "<group>"; };
9789DB54188D5E2A007C6FAE /* InAppMessagesManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppMessagesManager.h; sourceTree = "<group>"; };
9789DB55188D5E2A007C6FAE /* InAppMessagesManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InAppMessagesManager.mm; sourceTree = "<group>"; };
9789DB58188D94F9007C6FAE /* InterstitialView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterstitialView.h; sourceTree = "<group>"; };
@ -1403,7 +1425,7 @@
97A0EEF6192F3B43009B2779 /* BottomMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BottomMenu.h; sourceTree = "<group>"; };
97A0EEF7192F3B43009B2779 /* BottomMenu.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BottomMenu.mm; sourceTree = "<group>"; };
97A0EEF8192F3B43009B2779 /* BottomMenuCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BottomMenuCell.h; sourceTree = "<group>"; };
97A0EEF9192F3B43009B2779 /* BottomMenuCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BottomMenuCell.m; sourceTree = "<group>"; };
97A0EEF9192F3B43009B2779 /* BottomMenuCell.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BottomMenuCell.mm; sourceTree = "<group>"; };
97A5967E19B9CD47007A963F /* copyright.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = copyright.html; path = ../../data/copyright.html; sourceTree = "<group>"; };
97A8000A18B21363000C07A2 /* SearchView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SearchView.h; sourceTree = "<group>"; };
97A8000B18B21363000C07A2 /* SearchView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SearchView.mm; sourceTree = "<group>"; };
@ -1458,6 +1480,8 @@
97ECD87918362B5400F77A46 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
97ECD87E1836594400F77A46 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
97EDDCE418A299C000AEFB7A /* Twitter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Twitter.framework; path = System/Library/Frameworks/Twitter.framework; sourceTree = SDKROOT; };
97F0817C19AF72590098FB0B /* BadgeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BadgeView.h; path = Classes/BadgeView.h; sourceTree = "<group>"; };
97F0817D19AF72590098FB0B /* BadgeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BadgeView.m; path = Classes/BadgeView.m; sourceTree = "<group>"; };
97F6177F183E6172009919E2 /* LocationButton.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocationButton.mm; sourceTree = "<group>"; };
97F61780183E6172009919E2 /* LocationButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocationButton.h; sourceTree = "<group>"; };
97F6178F183E742E009919E2 /* LinkCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LinkCell.h; path = Settings/LinkCell.h; sourceTree = "<group>"; };
@ -1557,10 +1581,6 @@
FA34BEC91338D72F00FFB2A7 /* CustomAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomAlertView.h; sourceTree = "<group>"; };
FA36B80515403A4F004560CC /* BookmarksVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BookmarksVC.h; path = Bookmarks/BookmarksVC.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
FA36B80615403A4F004560CC /* BookmarksVC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = BookmarksVC.mm; path = Bookmarks/BookmarksVC.mm; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
FA4135E1120A263C0062D5B4 /* CountriesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = CountriesViewController.h; path = Settings/CountriesViewController.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
FA4135E2120A263C0062D5B4 /* CountriesViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = CountriesViewController.mm; path = Settings/CountriesViewController.mm; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
FA4135E6120A263C0062D5B4 /* SettingsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SettingsManager.h; path = Settings/SettingsManager.h; sourceTree = SOURCE_ROOT; };
FA4135E7120A263C0062D5B4 /* SettingsManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = SettingsManager.mm; path = Settings/SettingsManager.mm; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
FA459EB314327AF700B5BB3C /* WorldCoasts.mwm */ = {isa = PBXFileReference; lastKnownFileType = file; name = WorldCoasts.mwm; path = ../../data/WorldCoasts.mwm; sourceTree = "<group>"; };
FA46DA2B12D4166E00968C36 /* countries.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = countries.txt; path = ../../data/countries.txt; sourceTree = SOURCE_ROOT; };
FA5940D2171C964D0045C9BB /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -2224,6 +2244,7 @@
CB252D6816FF82C8001E41E9 /* Statistics */,
FA36B8011540388B004560CC /* Bookmarks */,
FA34BEC71338D6DB00FFB2A7 /* Common */,
976D86EE19C8777500C920EF /* Downloader */,
97354B6B196EDCE200352536 /* Login & sharing */,
FA6E1F1B124E6B2800F59149 /* Platform */,
080E96DDFE201D6D7F000001 /* Classes */,
@ -2334,6 +2355,27 @@
path = Localitycs;
sourceTree = "<group>";
};
976D86EE19C8777500C920EF /* Downloader */ = {
isa = PBXGroup;
children = (
97F0817C19AF72590098FB0B /* BadgeView.h */,
97F0817D19AF72590098FB0B /* BadgeView.m */,
976D86EA19C8697700C920EF /* ProgressView.h */,
976D86EB19C8697700C920EF /* ProgressView.m */,
976D86EF19C877E600C920EF /* MapCell.h */,
976D86F019C877E600C920EF /* MapCell.mm */,
977E26BB19E2E65E00BA2219 /* MapsObservers.h */,
977E26B819E2E64200BA2219 /* MapsObservers.mm */,
977E26C419E31BDF00BA2219 /* DownloaderParentVC.h */,
977E26C519E31BDF00BA2219 /* DownloaderParentVC.mm */,
977E26BC19E31BBE00BA2219 /* CountryTreeVC.h */,
977E26BD19E31BBE00BA2219 /* CountryTreeVC.mm */,
977E26C019E31BCC00BA2219 /* ActiveMapsVC.h */,
977E26C119E31BCC00BA2219 /* ActiveMapsVC.mm */,
);
name = Downloader;
sourceTree = "<group>";
};
9770A04618AD19D300126E5C /* More Apps */ = {
isa = PBXGroup;
children = (
@ -2375,7 +2417,7 @@
97A0EEF6192F3B43009B2779 /* BottomMenu.h */,
97A0EEF7192F3B43009B2779 /* BottomMenu.mm */,
97A0EEF8192F3B43009B2779 /* BottomMenuCell.h */,
97A0EEF9192F3B43009B2779 /* BottomMenuCell.m */,
97A0EEF9192F3B43009B2779 /* BottomMenuCell.mm */,
9750841D199501F100A7457D /* ImageDownloader.h */,
9750841E199501F100A7457D /* ImageDownloader.m */,
);
@ -2410,7 +2452,7 @@
97D092AD190A67CA00FF645B /* Place Page */,
97A8000918B210DC000C07A2 /* Search */,
9746492518EEE2F8004B4658 /* ToolbarView.h */,
9746492618EEE2F8004B4658 /* ToolbarView.m */,
9746492618EEE2F8004B4658 /* ToolbarView.mm */,
976D86F319CB21BD00C920EF /* RouteView.h */,
976D86F419CB21BD00C920EF /* RouteView.m */,
974386DB19373EA400FD5659 /* ToastView.h */,
@ -2603,10 +2645,6 @@
isa = PBXGroup;
children = (
978F924D183BB5D6000D6C7C /* Cells */,
FA4135E1120A263C0062D5B4 /* CountriesViewController.h */,
FA4135E2120A263C0062D5B4 /* CountriesViewController.mm */,
FA4135E6120A263C0062D5B4 /* SettingsManager.h */,
FA4135E7120A263C0062D5B4 /* SettingsManager.mm */,
978F923F183B660F000D6C7C /* SettingsViewController.h */,
978F9239183B660F000D6C7C /* SettingsViewController.mm */,
97508421199522D300A7457D /* SettingsAndMoreVC.h */,
@ -4469,26 +4507,29 @@
978D4A291996C17300D72CA7 /* RichTextVC.m in Sources */,
9747278418338F0C006B7CB7 /* UIViewController+Navigation.m in Sources */,
97908B30196591F7003DD7C6 /* SearchShowOnMapCell.m in Sources */,
976D86F119C877E600C920EF /* MapCell.mm in Sources */,
977E26C219E31BCC00BA2219 /* ActiveMapsVC.mm in Sources */,
1D3623260D0F684500981E51 /* MapsAppDelegate.mm in Sources */,
9746492718EEE2F8004B4658 /* ToolbarView.m in Sources */,
9746492718EEE2F8004B4658 /* ToolbarView.mm in Sources */,
46F26CD810F623BA00ECCA39 /* EAGLView.mm in Sources */,
EED10A4511F78D120095FAD4 /* MapViewController.mm in Sources */,
FA4135EA120A263C0062D5B4 /* CountriesViewController.mm in Sources */,
FA4135ED120A263C0062D5B4 /* SettingsManager.mm in Sources */,
EE7F29811219ECA300EB67A9 /* RenderBuffer.mm in Sources */,
97D092B5190A6E1D00FF645B /* PlacePageEditCell.mm in Sources */,
9750841F199501F100A7457D /* ImageDownloader.m in Sources */,
978F9253183BD530000D6C7C /* NavigationController.mm in Sources */,
974386DD19373EA400FD5659 /* ToastView.m in Sources */,
97C9851E186AE3C500AF7E9E /* Reachability.m in Sources */,
977E26B919E2E64200BA2219 /* MapsObservers.mm in Sources */,
EE7F29821219ECA300EB67A9 /* RenderContext.mm in Sources */,
FAFCB63613366E78001A5C59 /* WebViewController.mm in Sources */,
FA34BECA1338D72F00FFB2A7 /* CustomAlertView.mm in Sources */,
97F61781183E6172009919E2 /* LocationButton.mm in Sources */,
9747264318323080006B7CB7 /* UIKitCategories.m in Sources */,
97A0EEFC192F3B43009B2779 /* BottomMenuCell.m in Sources */,
977E26BE19E31BBE00BA2219 /* CountryTreeVC.mm in Sources */,
97A0EEFC192F3B43009B2779 /* BottomMenuCell.mm in Sources */,
97D092B9190AA69700FF645B /* SmallCompassView.mm in Sources */,
97A8001418B2140A000C07A2 /* SearchResultCell.m in Sources */,
97F0817E19AF72590098FB0B /* BadgeView.m in Sources */,
97A8002718B2741C000C07A2 /* SearchCell.m in Sources */,
97908B2C19658767003DD7C6 /* SearchCategoryCell.m in Sources */,
9778E9A5191A86D800AD850A /* SelectedColorView.m in Sources */,
@ -4509,6 +4550,7 @@
97CC93BB19599F4700369B42 /* SearchSuggestCell.m in Sources */,
FA054612155C465E001F4E37 /* SelectSetVC.mm in Sources */,
FAA614B8155F16950031C345 /* AddSetVC.mm in Sources */,
977E26C619E31BDF00BA2219 /* DownloaderParentVC.mm in Sources */,
FAAEA7D5161D8D3100CCD661 /* BookmarksRootVC.mm in Sources */,
F785EB4016386FC4003A38A8 /* BookmarkCell.mm in Sources */,
9789DB56188D5E2A007C6FAE /* InAppMessagesManager.mm in Sources */,
@ -4524,6 +4566,7 @@
9773DB8F198652E600C4A9E9 /* PlacePageBookmarkDescriptionCell.m in Sources */,
97ABBA4518C8DF620079333C /* PlacePageView.mm in Sources */,
97F61794183E7445009919E2 /* LinkCell.m in Sources */,
976D86EC19C8697700C920EF /* ProgressView.m in Sources */,
97D092B1190A681F00FF645B /* PlacePageInfoCell.mm in Sources */,
97A8001018B21395000C07A2 /* SearchBar.mm in Sources */,
EDC5C543175F2CA600420E92 /* ShareActionSheet.mm in Sources */,
@ -4543,26 +4586,29 @@
978D4A2A1996C17300D72CA7 /* RichTextVC.m in Sources */,
FAFB08EA151215EE0041901D /* MapsAppDelegate.mm in Sources */,
97908B31196591FB003DD7C6 /* SearchShowOnMapCell.m in Sources */,
976D86F219C877E600C920EF /* MapCell.mm in Sources */,
977E26C319E31BCC00BA2219 /* ActiveMapsVC.mm in Sources */,
FAFB08EB151215EE0041901D /* EAGLView.mm in Sources */,
97A8001118B21395000C07A2 /* SearchBar.mm in Sources */,
FAFB08EC151215EE0041901D /* MapViewController.mm in Sources */,
FAFB08ED151215EE0041901D /* CountriesViewController.mm in Sources */,
FAFB08EE151215EE0041901D /* SettingsManager.mm in Sources */,
FAFB08EF151215EE0041901D /* RenderBuffer.mm in Sources */,
97DEA09718D75BB000C5F963 /* ContextViews.mm in Sources */,
978F9254183BD530000D6C7C /* NavigationController.mm in Sources */,
97508420199501F100A7457D /* ImageDownloader.m in Sources */,
97A0EEFD192F3B43009B2779 /* BottomMenuCell.m in Sources */,
97A0EEFD192F3B43009B2779 /* BottomMenuCell.mm in Sources */,
97C9851F186AE3C500AF7E9E /* Reachability.m in Sources */,
97ABBA4618C8DF620079333C /* PlacePageView.mm in Sources */,
977E26BA19E2E64200BA2219 /* MapsObservers.mm in Sources */,
9789DB5B188D94F9007C6FAE /* InterstitialView.mm in Sources */,
FAFB08F0151215EE0041901D /* RenderContext.mm in Sources */,
FAFB08F1151215EE0041901D /* WebViewController.mm in Sources */,
9769D6F01912BF3000CA6158 /* ContainerView.mm in Sources */,
FAFB08F2151215EE0041901D /* CustomAlertView.mm in Sources */,
977E26BF19E31BBE00BA2219 /* CountryTreeVC.mm in Sources */,
97F61782183E6172009919E2 /* LocationButton.mm in Sources */,
9747264418323080006B7CB7 /* UIKitCategories.m in Sources */,
FAFB08F5151215EE0041901D /* Preferences.mm in Sources */,
97F0817F19AF72590098FB0B /* BadgeView.m in Sources */,
97D807BD18A933FB00D416E0 /* MoreAppsCell.m in Sources */,
97908B2D1965876C003DD7C6 /* SearchCategoryCell.m in Sources */,
FAFB08F6151215EE0041901D /* LocationManager.mm in Sources */,
@ -4583,6 +4629,7 @@
97CC93BC19599F4700369B42 /* SearchSuggestCell.m in Sources */,
FAA614B9155F16950031C345 /* AddSetVC.mm in Sources */,
FAAEA7D6161D8D3100CCD661 /* BookmarksRootVC.mm in Sources */,
977E26C719E31BDF00BA2219 /* DownloaderParentVC.mm in Sources */,
97D092B6190A6E1D00FF645B /* PlacePageEditCell.mm in Sources */,
F785EB4116386FC4003A38A8 /* BookmarkCell.mm in Sources */,
97C98523186AE3CF00AF7E9E /* AppInfo.mm in Sources */,
@ -4598,11 +4645,12 @@
9773DB90198652E600C4A9E9 /* PlacePageBookmarkDescriptionCell.m in Sources */,
97F61795183E7445009919E2 /* LinkCell.m in Sources */,
EDC5C544175F2CA600420E92 /* ShareActionSheet.mm in Sources */,
976D86ED19C8697700C920EF /* ProgressView.m in Sources */,
9778E9A6191A86D800AD850A /* SelectedColorView.m in Sources */,
97A8000D18B21363000C07A2 /* SearchView.mm in Sources */,
ED48BBBB17C2B1E2003E7E92 /* CircleView.mm in Sources */,
97D092B2190A681F00FF645B /* PlacePageInfoCell.mm in Sources */,
9746492818EEE2F8004B4658 /* ToolbarView.m in Sources */,
9746492818EEE2F8004B4658 /* ToolbarView.mm in Sources */,
ED48BBC417C3B3BF003E7E92 /* ColorPickerView.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View file

@ -1,24 +0,0 @@
#import <UIKit/UIKit.h>
#include "../../../storage/storage.hpp"
@interface CountriesViewController
: UIViewController <UINavigationBarDelegate, UITableViewDelegate, UITableViewDataSource,
UIActionSheetDelegate, UIAlertViewDelegate>
{
storage::TIndex m_index;
/// Params for using self as delegate in confirmations.
storage::TStatus m_countryStatus;
storage::TIndex m_clickedIndex;
uint64_t m_downloadSize;
UITableViewCell * m_clickedCell;
}
- (id)initWithIndex:(storage::TIndex const &)index andHeader:(NSString *)header;
- (void)OnCountryChange:(storage::TIndex const &)index;
- (void)OnDownload:(storage::TIndex const &)index withProgress:(pair<int64_t, int64_t> const &)progress;
- (void)TryDownloadCountry;
@end

View file

@ -1,499 +0,0 @@
#import "CountriesViewController.h"
#import "SettingsManager.h"
#import "MapsAppDelegate.h"
#import "MapViewController.h"
#import "WebViewController.h"
#import "CustomAlertView.h"
#import "DiskFreeSpace.h"
#import "Statistics.h"
#import "Reachability.h"
#import "UIKitCategories.h"
#include "Framework.h"
#include "../../storage/storage_defines.hpp"
#include "../../platform/platform.hpp"
#include "../../platform/preferred_languages.hpp"
#define MAX_3G_MEGABYTES (50)
#define MB (1024*1024)
#define BAG_TAG 664
using namespace storage;
static TIndex CalculateIndex(TIndex const & parentIndex, NSIndexPath * indexPath)
{
TIndex index = parentIndex;
if (index.m_group == TIndex::INVALID)
index.m_group = indexPath.row;
else if (index.m_country == TIndex::INVALID)
index.m_country = indexPath.row;
else
index.m_region = indexPath.row;
return index;
}
static NSInteger RowFromIndex(TIndex const & index)
{
if (index.m_region != TIndex::INVALID)
return index.m_region;
else if (index.m_country != TIndex::INVALID)
return index.m_country;
else
return index.m_group;
}
static bool IsOurIndex(TIndex const & theirs, TIndex const & ours)
{
TIndex theirsFixed = theirs;
if (theirsFixed.m_region != -1)
theirsFixed.m_region = -1;
else if (theirsFixed.m_country != -1)
theirsFixed.m_country = -1;
else
theirsFixed.m_group = -1;
return ours == theirsFixed;
}
static bool getGuideName(string & name, TIndex const & index)
{
guides::GuideInfo info;
Framework & f = GetFramework();
if ((f.Storage().CountriesCount(index) == 0) && f.GetGuideInfo(index, info))
{
string const lang = languages::GetCurrentNorm();
name = info.GetAdTitle(lang);
return true;
}
return false;
}
@implementation CountriesViewController
- (void)onCloseButton:(id)sender
{
[[[MapsAppDelegate theApp] settingsManager] hide];
}
- (id)initWithIndex:(TIndex const &)index andHeader:(NSString *)header
{
m_index = index;
if ((self = [super initWithNibName:nil bundle:nil]))
{
self.navigationItem.title = header;
// Show Close button only on the first page
}
return self;
}
- (void)loadView
{
CGRect appRect = [UIScreen mainScreen].applicationFrame;
UITableView * countriesTableView = [[UITableView alloc] initWithFrame:appRect style:UITableViewStylePlain];
countriesTableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
countriesTableView.delegate = self;
countriesTableView.dataSource = self;
self.view = countriesTableView;
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
TIndex const index = CalculateIndex(m_index, indexPath);
Framework & frm = GetFramework();
TStatus const status = frm.GetCountryStatus(index);
if (status == TStatus::EOnDisk || status == TStatus::EOnDiskOutOfDate)
{
frm.ShowCountry(index);
[[[MapsAppDelegate theApp] settingsManager] hide];
[[Statistics instance] logEvent:@"Show Map From Download Countries Screen"];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return GetFramework().Storage().CountriesCount(m_index);
}
- (NSString *)GetStringForSize: (size_t)size
{
if (size > MB)
{
// do the correct rounding of Mb
return [NSString stringWithFormat:@"%ld %@", (size + 512 * 1024) / MB, NSLocalizedString(@"mb", nil)];
}
else
{
// get upper bound size for Kb
return [NSString stringWithFormat:@"%ld %@", (size + 1023) / 1024, NSLocalizedString(@"kb", nil)];
}
}
// @TODO Refactor UI to use good icon for "zoom to the country" action
- (UITableViewCellAccessoryType)getZoomIconType
{
static const UITableViewCellAccessoryType iconType =
[UIDevice currentDevice].systemVersion.floatValue < 7.0 ? UITableViewCellAccessoryDetailDisclosureButton
: UITableViewCellAccessoryDetailButton;
return iconType;
}
/// @todo Pass correct options from UI.
TMapOptions const g_mapOptions = TMapOptions::EMapWithCarRouting;
- (void)UpdateCell:(UITableViewCell *)cell forCountry:(TIndex const &)countryIndex
{
cell.accessoryView = nil;
Framework & frm = GetFramework();
Storage & s = frm.Storage();
string const & flag = s.CountryFlag(countryIndex);
guides::GuideInfo info;
if (flag.empty())
cell.imageView.image = nil;
else
cell.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%s.png", flag.c_str()]];
// do not show status for parent categories
if (![cell.reuseIdentifier isEqual:@"ParentCell"])
{
TStatus const st = frm.GetCountryStatus(countryIndex);
switch (st)
{
case TStatus::EOnDisk:
cell.textLabel.textColor = [UIColor colorWithRed:0.f/255.f
green:161.f/255.f
blue:68.f/255.f
alpha:1.f];
cell.detailTextLabel.text = [NSString stringWithFormat:NSLocalizedString(@"downloaded_touch_to_delete", nil), [self GetStringForSize: s.CountrySizeInBytes(countryIndex, g_mapOptions).first]];
// also add "sight" icon for centering on the country
cell.accessoryType = [self getZoomIconType];
break;
case TStatus::EOnDiskOutOfDate:
cell.textLabel.textColor = [UIColor colorWithRed:1.f
green:105.f/255.f
blue:180.f/255.f
alpha:1.f];
cell.detailTextLabel.text = [NSString stringWithFormat:NSLocalizedString(@"downloaded_touch_to_update", nil), [self GetStringForSize: s.CountrySizeInBytes(countryIndex, g_mapOptions).first]];
// also add "sight" icon for centering on the country
cell.accessoryType = [self getZoomIconType];
break;
case TStatus::EDownloading:
{
cell.textLabel.textColor = [UIColor colorWithRed:52.f/255.f
green:43.f/255.f
blue:182.f/255.f
alpha:1.f];
cell.detailTextLabel.text = NSLocalizedString(@"downloading", nil);
UIActivityIndicatorView * indicator = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleGray];
cell.accessoryView = indicator;
[indicator startAnimating];
break;
}
case TStatus::EOutOfMemFailed:
/// @TODO show specific message for EOutOfMemFailed
case TStatus::EDownloadFailed:
cell.textLabel.textColor = [UIColor redColor];
cell.detailTextLabel.text = NSLocalizedString(@"download_has_failed", nil);
break;
case TStatus::EInQueue:
{
cell.textLabel.textColor = [UIColor colorWithRed:91.f/255.f
green:148.f/255.f
blue:222.f/255.f
alpha:1.f];
cell.detailTextLabel.text = NSLocalizedString(@"marked_for_downloading", nil);
}
break;
case TStatus::ENotDownloaded:
cell.textLabel.textColor = [UIColor blackColor];
cell.detailTextLabel.text = NSLocalizedString(@"touch_to_download", nil);
break;
case TStatus::EUnknown:
break;
}
}
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TIndex index = CalculateIndex(m_index, indexPath);
Storage & s = GetFramework().Storage();
bool const hasChildren = s.CountriesCount(index) != 0;
NSString * cellId = hasChildren ? @"ParentCell" : @"DetailCell";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: cellId];
if (cell == nil)
{
if (hasChildren)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
else
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId];
}
if (hasChildren)
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
else
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.text = [NSString stringWithUTF8String:s.CountryName(index).c_str()];
[self UpdateCell:cell forCountry:index];
return cell;
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != actionSheet.cancelButtonIndex)
{
Framework & f = GetFramework();
NSString * title = [actionSheet buttonTitleAtIndex:buttonIndex];
guides::GuideInfo info;
BOOL isGuideAvailable = f.GetGuideInfo(m_clickedIndex, info);
string const lang = languages::GetCurrentNorm();
if (isGuideAvailable && [title isEqualToString:[NSString stringWithUTF8String:info.GetAdTitle(lang).c_str()]])
{
NSURL * guideUrl = [NSURL URLWithString:[NSString stringWithUTF8String:info.GetAppID().c_str()]];
NSString * countryName = [NSString stringWithUTF8String:f.Storage().CountryName(m_clickedIndex).c_str()];
[[Statistics instance] logEvent:@"Open Guide Country" withParameters:@{@"Country Name" : countryName}];
UIApplication * application = [UIApplication sharedApplication];
if ([application canOpenURL:guideUrl])
{
[application openURL:guideUrl];
[[Statistics instance] logEvent:@"Open Guide Button" withParameters:@{@"Guide downloaded" : @"YES"}];
}
else
{
[application openURL:[NSURL URLWithString:[NSString stringWithUTF8String:info.GetURL().c_str()]]];
[[Statistics instance] logEvent:@"Open Guide Button" withParameters:@{@"Guide downloaded" : @"NO"}];
}
}
else if ([title rangeOfString:[NSString stringWithFormat:NSLocalizedString(@"download_mb_or_kb", nil), @""]].location != NSNotFound
|| [title rangeOfString:[NSString stringWithFormat:NSLocalizedString(@"update_mb_or_kb", nil), @""]].location != NSNotFound)
[self TryDownloadCountry];
else if ([title isEqualToString:NSLocalizedString(@"cancel_download", nil)] || [title isEqualToString:NSLocalizedString(@"delete", nil)])
{
f.DeleteCountry(m_clickedIndex, g_mapOptions);
m_clickedCell.accessoryType = UITableViewCellAccessoryNone;
}
else
ASSERT ( false, () );
}
}
- (void)DoDownloadCountry
{
GetFramework().DownloadCountry(m_clickedIndex, g_mapOptions);
}
// 3G warning confirmation handler
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex != alertView.cancelButtonIndex)
{
[self DoDownloadCountry];
}
}
- (void) TryDownloadCountry
{
NSString * countryName = m_clickedCell.textLabel.text;
if (FreeDiskSpaceInBytes() < (m_downloadSize + MB))
{
// No enough disk space - display warning dialog
NSString * message = [NSString stringWithFormat:NSLocalizedString(@"free_space_for_country", nil), [self GetStringForSize: m_downloadSize], countryName];
[[[CustomAlertView alloc] initWithTitle:NSLocalizedString(@"not_enough_disk_space", nil)
message:message
delegate:nil
cancelButtonTitle:NSLocalizedString(@"ok", nil)
otherButtonTitles:nil] show];
}
else
{
Reachability * reachability = [Reachability reachabilityForInternetConnection];
if (![reachability isReachable])
{
// No any connection - skip downloading
[[[CustomAlertView alloc] initWithTitle:NSLocalizedString(@"no_internet_connection_detected", nil)
message:NSLocalizedString(@"use_wifi_recommendation_text", nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"ok", nil)
otherButtonTitles:nil] show];
}
else
{
if ([reachability isReachableViaWWAN] && m_downloadSize > MAX_3G_MEGABYTES * MB)
{
// If user uses 3G, show warning before downloading
[[[CustomAlertView alloc] initWithTitle:[NSString stringWithFormat:NSLocalizedString(@"no_wifi_ask_cellular_download", nil), countryName]
message:nil
delegate:self
cancelButtonTitle:NSLocalizedString(@"cancel", nil)
otherButtonTitles:NSLocalizedString(@"use_cellular_data", nil), nil] show];
}
else
[self DoDownloadCountry];
}
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// deselect the current row (don't keep the table selection persistent)
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell * cell = [tableView cellForRowAtIndexPath: indexPath];
// Push the new table view on the stack
TIndex const index = CalculateIndex(m_index, indexPath);
Framework & frm = GetFramework();
Storage & s = frm.Storage();
if (s.CountriesCount(index))
{
CountriesViewController * newController = [[CountriesViewController alloc] initWithIndex:index andHeader:cell.textLabel.text];
[self.navigationController pushViewController:newController animated:YES];
}
else
[self createActionSheetForCountry:indexPath];
}
- (void)OnCountryChange:(TIndex const &)index
{
if (IsOurIndex(index, m_index))
{
UITableView * tableView = (UITableView *)self.view;
UITableViewCell * cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:RowFromIndex(index) inSection:0]];
if (cell)
[self UpdateCell:cell forCountry:index];
}
}
- (void)OnDownload:(TIndex const &)index withProgress:(pair<int64_t, int64_t> const &)progress
{
if (IsOurIndex(index, m_index))
{
UITableView * tableView = (UITableView *)self.view;
UITableViewCell * cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:RowFromIndex(index) inSection:0]];
if (cell)
cell.detailTextLabel.text = [NSString stringWithFormat:NSLocalizedString(@"downloading_touch_to_cancel", nil), progress.first * 100 / progress.second];
}
}
- (void)createActionSheetForCountry:(NSIndexPath *)indexPath
{
UITableView * table = (UITableView *)(self.view);
UITableViewCell * cell = [table cellForRowAtIndexPath:indexPath];
Framework & frm = GetFramework();
m_clickedIndex = CalculateIndex(m_index, indexPath);
m_countryStatus = frm.GetCountryStatus(m_clickedIndex);
m_clickedCell = cell;
Storage & s = GetFramework().Storage();
m_downloadSize = s.CountrySizeInBytes(m_clickedIndex, g_mapOptions).second;
NSMutableArray * buttonNames = [[NSMutableArray alloc] init];
bool canDelete = NO;
switch (m_countryStatus)
{
case TStatus::EOnDisk:
canDelete = YES;
break;
case TStatus::EOnDiskOutOfDate:
canDelete = YES;
[buttonNames addObject:[NSString stringWithFormat:NSLocalizedString(@"update_mb_or_kb", nil), [self GetStringForSize:m_downloadSize]]];
break;
case TStatus::ENotDownloaded:
[buttonNames addObject:[NSString stringWithFormat:NSLocalizedString(@"download_mb_or_kb", nil), [self GetStringForSize:m_downloadSize]]];
break;
case TStatus::EDownloadFailed:
case TStatus::EOutOfMemFailed:
[self DoDownloadCountry];
return;
case TStatus::EDownloading:
{
// special one, with destructive button
string guideAdevertiseString;
NSString * guideAd = nil;
if (getGuideName(guideAdevertiseString, m_clickedIndex))
guideAd = [NSString stringWithUTF8String:guideAdevertiseString.c_str()];
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:cell.textLabel.text
delegate:self
cancelButtonTitle:NSLocalizedString(@"do_nothing", nil)
destructiveButtonTitle:NSLocalizedString(@"cancel_download", nil)
otherButtonTitles:guideAd, nil];
[actionSheet showFromRect:cell.frame inView:table animated:YES];
return;
}
case TStatus::EInQueue:
{
frm.DeleteCountry(m_clickedIndex, g_mapOptions);
return;
}
default:
ASSERT ( false, () );
}
UIActionSheet * as = [[UIActionSheet alloc] initWithTitle:cell.textLabel.text
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
for (NSString * str in buttonNames)
[as addButtonWithTitle:str];
size_t numOfButtons = [buttonNames count];
if (canDelete)
{
[as addButtonWithTitle:NSLocalizedString(@"delete", nil)];
as.destructiveButtonIndex = numOfButtons++;
}
string guideAdevertiseString;
if (getGuideName(guideAdevertiseString, m_clickedIndex))
{
[as addButtonWithTitle:[NSString stringWithUTF8String:guideAdevertiseString.c_str()]];
++numOfButtons;
}
if (!IPAD)
{
[as addButtonWithTitle:NSLocalizedString(@"cancel", nil)];
as.cancelButtonIndex = numOfButtons;
}
[as showFromRect:cell.frame inView:(UITableView *)self.view animated: YES];
}
@end

View file

@ -1,14 +0,0 @@
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
/// Responsible for all settings dialogs
@interface SettingsManager : NSObject <UIActionSheetDelegate>
{
UINavigationController * m_navigationController;
int m_slotID;
}
- (void)show:(UIViewController *)prevController;
- (void)hide;
@end

View file

@ -1,106 +0,0 @@
#import "SettingsManager.h"
#import "CountriesViewController.h"
#import "MapViewController.h"
#import "MapsAppDelegate.h"
#include "Framework.h"
#include "../../../std/bind.hpp"
using namespace storage;
// Settings are always present globally
@implementation SettingsManager
/// Get right controller from the stack
- (UIViewController *)ControllerByIndex:(TIndex const &)index
{
NSArray * controllers = m_navigationController.viewControllers;
NSInteger count = [controllers count] - 1;
if (index.m_region != TIndex::INVALID && count >= 3)
return controllers[3];
else if (index.m_country != TIndex::INVALID && count >= 2)
return controllers[2];
else if (index.m_group != TIndex::INVALID && count >= 1)
return controllers[1];
return nil;
}
- (void)OnCountryChange:(TIndex const &)index
{
UIViewController * controller = [self ControllerByIndex:index];
if (controller && [controller respondsToSelector:@selector(OnCountryChange:)])
[(CountriesViewController *)controller OnCountryChange: index];
}
- (void)OnCountryDownload:(TIndex const &)index withProgress:(pair<int64_t, int64_t> const &)progress
{
UIViewController * controller = [self ControllerByIndex:index];
if (controller && [controller respondsToSelector:@selector(OnDownload:withProgress:)])
[(CountriesViewController *)controller OnDownload:index withProgress:progress];
}
- (void)show:(UIViewController *)prevController
{
NSString * header = NSLocalizedString(@"download_maps", @"Settings/Downloader - Main downloader window title");
CountriesViewController * countriesController = [[CountriesViewController alloc] initWithIndex:TIndex() andHeader:header];
// m_navigationController = [[UINavigationController alloc] initWithRootViewController:countriesController];
Framework & f = GetFramework();
// Subscribe to storage callbacks AND load country names after calling Storage::Subscribe()
{
// tricky boost::bind for objC class methods
typedef void (*TChangeFunc)(id, SEL, TIndex const &);
SEL changeSel = @selector(OnCountryChange:);
TChangeFunc changeImpl = (TChangeFunc)[self methodForSelector:changeSel];
typedef void (*TProgressFunc)(id, SEL, TIndex const &, pair<int64_t, int64_t> const &);
SEL progressSel = @selector(OnCountryDownload:withProgress:);
TProgressFunc progressImpl = (TProgressFunc)[self methodForSelector:progressSel];
m_slotID = f.Storage().Subscribe(bind(changeImpl, self, changeSel, _1),
bind(progressImpl, self, progressSel, _1, _2));
}
// display controller only when countries are loaded
m_navigationController = prevController.navigationController;
[m_navigationController pushViewController:countriesController animated:YES];
// We do force delete of old maps at startup from this moment.
/*
// display upgrade/delete old maps dialog if necessary
if (f.NeedToDeleteOldMaps())
{
UIActionSheet * dialog = [[UIActionSheet alloc]
initWithTitle:NSLocalizedString(@"new_map_data_format_upgrade_dialog", @"Downloader/Upgrade dialog title")
delegate:self
cancelButtonTitle:NSLocalizedString(@"cancel", @"Downloader/Upgrade Cancel button")
destructiveButtonTitle:NSLocalizedString(@"delete_old_maps", @"Downloader/Upgrade OK button")
otherButtonTitles:nil];
[dialog showInView:m_navigationController.view];
[dialog release];
}
*/
}
// Hides all opened settings windows
- (void)hide
{
GetFramework().Storage().Unsubscribe(m_slotID);
[m_navigationController popToRootViewControllerAnimated:YES];
}
/*
// Called from Upgrade/Delete old maps dialog
- (void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{ // delete old maps and show downloader
GetFramework().DeleteOldMaps();
}
else
{ // User don't want to upgrade at the moment - so be it.
[self hide];
}
}
*/
@end

View file

@ -395,13 +395,12 @@ void ActiveMapsLayout::StatusChangedCallback(TIndex const & index)
int newPosition = MoveItemToGroup(group, position, TGroup::EUpToDate);
NotifyMove(group, position, TGroup::EUpToDate, newPosition);
}
else
else if (item.m_options != options)
{
// Here we handle
// "Actual map without routing" -> "Actual map with routing"
// "Actual map with routing" -> "Actual map without routing"
ASSERT(item.m_options != options, ());
TMapOptions requestOpt = item.m_downloadRequest;
TMapOptions requestOpt = item.m_downloadRequest;
item.m_options = item.m_downloadRequest = options;
NotifyOptionsChanged(group, position, item.m_options, requestOpt);
}