[MAPSME-5030] [ios] Refactored app for routing manager.

This commit is contained in:
Ilya Grechuhin 2017-08-01 18:17:26 +03:00 committed by Sergey Yershov
parent e024bafd45
commit 55b0d067b7
73 changed files with 2766 additions and 3192 deletions

View file

@ -237,8 +237,7 @@ extern NSString * const kBookmarkDeletedNotification = @"BookmarkDeletedNotifica
{
[Statistics logEvent:kStatEventName(kStatBookmarks, kStatShowOnMap)];
// Same as "Close".
MapViewController * mapVC = self.navigationController.viewControllers.firstObject;
mapVC.controlsManager.searchHidden = YES;
[MWMSearchManager manager].state = MWMSearchManagerStateHidden;
f.ShowBookmark({static_cast<size_t>(indexPath.row), m_categoryIndex});
[self.navigationController popToRootViewControllerAnimated:YES];
}

View file

@ -10,12 +10,15 @@
#import "MoPub-Bridging-Header.h"
#import "MPNativeAd.h"
#import "MPNativeAd+MWM.h"
#import "MWMTypes.h"
#import "UIKitCategories.h"
#import "private.h"
#import "AppInfo.h"
#import "MWMAvailableAreaAffectDirection.h"
#import "MWMBanner.h"
#import "MWMBottomMenuViewController.h"
#import "MWMCollectionViewController.h"
#import "MWMConsts.h"
#import "MWMController.h"
@ -23,25 +26,30 @@
#import "MWMKeyboard.h"
#import "MWMLocationManager.h"
#import "MWMMapWidgetsHelper.h"
#import "MWMNavigationDashboardEntity.h"
#import "MWMNavigationDashboardManager.h"
#import "MWMNoMapsViewController.h"
#import "MWMPlacePageButtonsProtocol.h"
#import "MWMPlacePageCellUpdateProtocol.h"
#import "MWMPlacePageManagerHelper.h"
#import "MWMPlacePageTaxiProvider.h"
#import "MWMPushNotifications.h"
#import "MWMRoutePreviewTaxiCellType.h"
#import "MWMRouter.h"
#import "MWMSearchItemType.h"
#import "MWMSearchNoResults.h"
#import "MWMSettings.h"
#import "MWMSideButtons.h"
#import "MWMTableViewCell.h"
#import "MWMTextToSpeech.h"
#import "MWMTextToSpeechObserver.h"
#import "MWMTextView.h"
#import "MWMTrafficButtonViewController.h"
#import "MWMTypes.h"
#import "MWMTrafficManager.h"
#import "MWMViewController.h"
#import "Statistics.h"
#import "UIButton+RuntimeAttributes.h"
#import "UIColor+MapsMeColor.h"
#import "UIFont+MapsMeFonts.h"
#import "UIKitCategories.h"
#import "UIViewController+Navigation.h"

View file

@ -0,0 +1,6 @@
extension String {
init(coreFormat: String, arguments: [CVarArg]) {
let format = coreFormat.replacingOccurrences(of: "%s", with: "%@")
self.init(format: format, arguments: arguments)
}
}

View file

@ -0,0 +1,43 @@
@objc(MWMDimBackground)
final class DimBackground: SolidTouchView {
private let mainView: UIView
private var tapAction: (() -> Void)!
init(mainView: UIView) {
self.mainView = mainView
super.init(frame: mainView.superview!.bounds)
backgroundColor = UIColor.fadeBackground()
autoresizingMask = [.flexibleWidth, .flexibleHeight];
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onTap)))
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc
func setVisible(_ visible: Bool, tapAction: @escaping () -> Void) {
self.tapAction = tapAction
if visible {
let sv = mainView.superview!
frame = sv.bounds
sv.insertSubview(self, belowSubview: mainView)
alpha = 0
} else {
alpha = 0.8
}
UIView.animate(withDuration: kDefaultAnimationDuration,
animations: { self.alpha = visible ? 0.8 : 0 },
completion: { _ in
if !visible {
self.removeFromSuperview()
}
})
}
@objc
private func onTap() {
tapAction()
}
}

View file

@ -1,17 +1,9 @@
#import "MWMButton.h"
#import "MWMCircularProgressState.h"
#import "UIImageView+Coloring.h"
#include "std/vector.hpp"
typedef NS_ENUM(NSInteger, MWMCircularProgressState) {
MWMCircularProgressStateNormal,
MWMCircularProgressStateSelected,
MWMCircularProgressStateProgress,
MWMCircularProgressStateSpinner,
MWMCircularProgressStateFailed,
MWMCircularProgressStateCompleted
};
using MWMCircularProgressStateVec = vector<MWMCircularProgressState>;
@class MWMCircularProgress;

View file

@ -0,0 +1,8 @@
typedef NS_ENUM(NSInteger, MWMCircularProgressState) {
MWMCircularProgressStateNormal,
MWMCircularProgressStateSelected,
MWMCircularProgressStateProgress,
MWMCircularProgressStateSpinner,
MWMCircularProgressStateFailed,
MWMCircularProgressStateCompleted
};

View file

@ -2,7 +2,7 @@
#import "MWMNavigationDashboardManager.h"
#import "MWMSearchManager.h"
#include "map/user_mark.hpp"
#include "map/place_page_info.hpp"
@class MapViewController;
@protocol MWMFeatureHolder;
@ -18,8 +18,6 @@
@property(nonatomic) BOOL trafficButtonHidden;
@property(nonatomic) MWMBottomMenuState menuState;
@property(nonatomic) MWMBottomMenuState menuRestoreState;
@property(nonatomic, readonly) MWMNavigationDashboardState navigationState;
@property(nonatomic) BOOL searchHidden;
@property(nonatomic) BOOL isDirectionViewHidden;
- (instancetype)init __attribute__((unavailable("init is not available")));
@ -52,9 +50,7 @@
#pragma mark - MWMSearchManager
- (void)searchViewDidEnterState:(MWMSearchManagerState)state;
- (void)actionDownloadMaps:(mwm::DownloaderMode)mode;
- (void)searchFrameUpdated:(CGRect)frame;
- (BOOL)searchText:(NSString *)text forInputLocale:(NSString *)locale;
- (void)searchTextOnMap:(NSString *)text forInputLocale:(NSString *)locale;

View file

@ -5,6 +5,7 @@
#import "MWMAlertViewController.h"
#import "MWMAlertViewController.h"
#import "MWMAuthorizationCommon.h"
#import "MWMBottomMenuControllerProtocol.h"
#import "MWMBottomMenuViewController.h"
#import "MWMButton.h"
#import "MWMCommon.h"
@ -12,11 +13,9 @@
#import "MWMNetworkPolicy.h"
#import "MWMObjectsCategorySelectorController.h"
#import "MWMPlacePageManager.h"
#import "MWMRoutePreview.h"
#import "MWMRouter.h"
#import "MWMSearchManager.h"
#import "MWMSideButtons.h"
#import "MWMTaxiPreviewDataSource.h"
#import "MWMToast.h"
#import "MWMTrafficButtonViewController.h"
#import "MapViewController.h"
@ -40,8 +39,7 @@ NSString * const kMapToCategorySelectorSegue = @"MapToCategorySelectorSegue";
extern NSString * const kAlohalyticsTapEventKey;
@interface MWMMapViewControlsManager ()<MWMNavigationDashboardManagerProtocol,
MWMBottomMenuControllerProtocol>
@interface MWMMapViewControlsManager ()<MWMBottomMenuControllerProtocol, MWMSearchManagerObserver>
@property(nonatomic) MWMSideButtons * sideButtons;
@property(nonatomic) MWMTrafficButtonViewController * trafficButton;
@ -54,9 +52,6 @@ extern NSString * const kAlohalyticsTapEventKey;
@property(nonatomic) BOOL disableStandbyOnRouteFollowing;
@property(nonatomic) CGFloat topBound;
@property(nonatomic) CGFloat leftBound;
@end
@implementation MWMMapViewControlsManager
@ -74,7 +69,6 @@ extern NSString * const kAlohalyticsTapEventKey;
self.sideButtonsHidden = NO;
self.trafficButtonHidden = NO;
self.isDirectionViewHidden = YES;
self.menuState = MWMBottomMenuStateInactive;
self.menuRestoreState = MWMBottomMenuStateInactive;
return self;
}
@ -84,12 +78,11 @@ extern NSString * const kAlohalyticsTapEventKey;
if ([MWMToast affectsStatusBar])
return [MWMToast preferredStatusBarStyle];
BOOL const isSearchUnderStatusBar = !self.searchHidden;
BOOL const isSearchUnderStatusBar = (self.searchManager.state != MWMSearchManagerStateHidden);
BOOL const isNavigationUnderStatusBar =
self.navigationManager.state != MWMNavigationDashboardStateHidden &&
self.navigationManager.state != MWMNavigationDashboardStateNavigation;
BOOL const isMenuViewUnderStatusBar = self.menuState == MWMBottomMenuStateActive ||
self.menuState == MWMBottomMenuStateRoutingExpanded;
BOOL const isMenuViewUnderStatusBar = self.menuState == MWMBottomMenuStateActive;
BOOL const isDirectionViewUnderStatusBar = !self.isDirectionViewHidden;
BOOL const isAddPlaceUnderStatusBar =
[self.ownerController.view hasSubviewWithViewClass:[MWMAddPlaceNavigationBar class]];
@ -123,11 +116,6 @@ extern NSString * const kAlohalyticsTapEventKey;
[self.trafficButton viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[self.menuController viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[self.searchManager viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:^(
id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
self.navigationManager.leftBound = self.leftBound;
}
completion:nil];
}
#pragma mark - MWMPlacePageViewManager
@ -158,30 +146,6 @@ extern NSString * const kAlohalyticsTapEventKey;
}
}
- (void)searchViewDidEnterState:(MWMSearchManagerState)state
{
if (state == MWMSearchManagerStateMapSearch)
{
[self.navigationManager setMapSearch];
}
if (state == MWMSearchManagerStateHidden)
{
if (!IPAD)
{
self.hidden = NO;
self.leftBound = self.topBound = 0.0;
}
}
[self.ownerController setNeedsStatusBarAppearanceUpdate];
}
- (void)searchFrameUpdated:(CGRect)frame
{
CGSize const s = frame.size;
self.leftBound = s.width;
self.topBound = s.height;
}
- (void)searchTextOnMap:(NSString *)text forInputLocale:(NSString *)locale
{
if (![self searchText:text forInputLocale:locale])
@ -226,23 +190,6 @@ extern NSString * const kAlohalyticsTapEventKey;
}
}
- (void)closeInfoScreens
{
if (IPAD)
{
if (!self.searchHidden)
self.searchManager.state = MWMSearchManagerStateHidden;
else
[MWMRouter stopRouting];
}
else
{
CGSize const ownerViewSize = self.ownerController.view.size;
if (ownerViewSize.width > ownerViewSize.height)
[self dismissPlacePage];
}
}
- (void)didFinishAddingPlace
{
self.trafficButtonHidden = NO;
@ -280,12 +227,6 @@ extern NSString * const kAlohalyticsTapEventKey;
#pragma mark - MWMNavigationDashboardManager
- (void)routePreviewDidChangeFrame:(CGRect)newFrame
{
if (IPAD)
self.navigationManager.leftBound = newFrame.origin.x + newFrame.size.width;
}
- (void)setDisableStandbyOnRouteFollowing:(BOOL)disableStandbyOnRouteFollowing
{
if (_disableStandbyOnRouteFollowing == disableStandbyOnRouteFollowing)
@ -297,9 +238,13 @@ extern NSString * const kAlohalyticsTapEventKey;
[[MapsAppDelegate theApp] enableStandby];
}
- (MWMTaxiCollectionView *)taxiCollectionView
#pragma mark - MWMSearchManagerObserver
- (void)onSearchManagerStateChanged
{
return self.menuController.taxiCollectionView;
auto state = [MWMSearchManager manager].state;
if (!IPAD && state == MWMSearchManagerStateHidden)
self.hidden = NO;
}
#pragma mark - Routing
@ -307,7 +252,6 @@ extern NSString * const kAlohalyticsTapEventKey;
- (void)onRoutePrepare
{
self.navigationManager.state = MWMNavigationDashboardStatePrepare;
self.menuController.p2pButton.selected = YES;
[self onRoutePointsUpdated];
}
@ -321,7 +265,11 @@ extern NSString * const kAlohalyticsTapEventKey;
- (void)onRouteError
{
self.navigationManager.state = MWMNavigationDashboardStateError;
if ([MWMRouter isTaxi])
return;
auto nm = self.navigationManager;
nm.errorMessage = L(@"routing_planning_error");
nm.state = MWMNavigationDashboardStateError;
}
- (void)onRouteReady
@ -331,10 +279,10 @@ extern NSString * const kAlohalyticsTapEventKey;
{
dispatch_async(dispatch_get_main_queue(), ^{
[MWMRouter disableFollowMode];
[self.navigationManager updateDashboard];
});
}
if (self.navigationManager.state != MWMNavigationDashboardStateNavigation)
[MWMSearchManager manager].state = MWMSearchManagerStateHidden;
if (self.navigationManager.state != MWMNavigationDashboardStateNavigation && ![MWMRouter isTaxi])
self.navigationManager.state = MWMNavigationDashboardStateReady;
}
@ -354,7 +302,6 @@ extern NSString * const kAlohalyticsTapEventKey;
self.navigationManager.state = MWMNavigationDashboardStateHidden;
self.disableStandbyOnRouteFollowing = NO;
self.trafficButtonHidden = NO;
self.menuState = MWMBottomMenuStateInactive;
}
- (void)onRoutePointsUpdated { [self.navigationManager onRoutePointsUpdated]; }
@ -393,19 +340,18 @@ extern NSString * const kAlohalyticsTapEventKey;
- (MWMNavigationDashboardManager *)navigationManager
{
if (!_navigationManager)
{
_navigationManager =
[[MWMNavigationDashboardManager alloc] initWithParentView:self.ownerController.view
delegate:self];
[_navigationManager addInfoDisplay:self.menuController];
}
[[MWMNavigationDashboardManager alloc] initWithParentView:self.ownerController.view];
return _navigationManager;
}
- (MWMSearchManager *)searchManager
{
if (!_searchManager)
{
_searchManager = [[MWMSearchManager alloc] init];
[MWMSearchManager addObserver:self];
}
return _searchManager;
}
@ -446,11 +392,6 @@ extern NSString * const kAlohalyticsTapEventKey;
self.menuController.state = self.hidden ? MWMBottomMenuStateHidden : menuState;
}
- (void)setRoutingErrorMessage:(NSString *)message
{
[self.menuController setRoutingErrorMessage:message];
}
- (MWMBottomMenuState)menuState
{
MWMBottomMenuState const state = self.menuController.state;
@ -459,36 +400,6 @@ extern NSString * const kAlohalyticsTapEventKey;
return _menuState;
}
- (MWMNavigationDashboardState)navigationState { return self.navigationManager.state; }
- (void)setTopBound:(CGFloat)topBound
{
if (IPAD)
return;
_topBound = topBound;
self.navigationManager.topBound = topBound;
}
- (void)setLeftBound:(CGFloat)leftBound
{
if (!IPAD)
return;
if ([MWMRouter isRoutingActive])
return;
_leftBound = self.navigationManager.leftBound = self.menuController.leftBound = leftBound;
}
- (BOOL)searchHidden
{
if (!_searchManager)
return YES;
return self.searchManager.state == MWMSearchManagerStateHidden;
}
- (void)setSearchHidden:(BOOL)searchHidden
{
self.searchManager.state =
searchHidden ? MWMSearchManagerStateHidden : MWMSearchManagerStateDefault;
}
#pragma mark - MWMFeatureHolder
- (id<MWMFeatureHolder>)featureHolder { return self.placePageManager; }

View file

@ -123,43 +123,37 @@ NSArray<UIImage *> * imagesWithName(NSString * name)
[iv stopAnimating];
switch ([MWMTrafficManager state])
{
case TrafficManager::TrafficState::Disabled:
btn.imageName = @"btn_traffic_off";
break;
case TrafficManager::TrafficState::Enabled:
btn.imageName = @"btn_traffic_on";
break;
case TrafficManager::TrafficState::WaitingData:
case MWMTrafficManagerStateDisabled: btn.imageName = @"btn_traffic_off"; break;
case MWMTrafficManagerStateEnabled: btn.imageName = @"btn_traffic_on"; break;
case MWMTrafficManagerStateWaitingData:
iv.animationImages = imagesWithName(@"btn_traffic_update");
iv.animationDuration = 0.8;
[iv startAnimating];
break;
case TrafficManager::TrafficState::Outdated:
btn.imageName = @"btn_traffic_outdated";
break;
case TrafficManager::TrafficState::NoData:
case MWMTrafficManagerStateOutdated: btn.imageName = @"btn_traffic_outdated"; break;
case MWMTrafficManagerStateNoData:
btn.imageName = @"btn_traffic_on";
[MWMToast showWithText:L(@"traffic_data_unavailable")];
break;
case TrafficManager::TrafficState::NetworkError:
case MWMTrafficManagerStateNetworkError:
btn.imageName = @"btn_traffic_off";
[MWMTrafficManager enableTraffic:NO];
[[MWMAlertViewController activeAlertController] presentNoConnectionAlert];
break;
case TrafficManager::TrafficState::ExpiredApp:
btn.imageName = @"btn_traffic_on";
[MWMToast showWithText:L(@"traffic_update_app_message")];
break;
case TrafficManager::TrafficState::ExpiredData:
case MWMTrafficManagerStateExpiredData:
btn.imageName = @"btn_traffic_on";
[MWMToast showWithText:L(@"traffic_update_maps_text")];
break;
case MWMTrafficManagerStateExpiredApp:
btn.imageName = @"btn_traffic_on";
[MWMToast showWithText:L(@"traffic_update_app_message")];
break;
}
}
- (IBAction)buttonTouchUpInside
{
if ([MWMTrafficManager state] == TrafficManager::TrafficState::Disabled)
if ([MWMTrafficManager state] == MWMTrafficManagerStateDisabled)
[MWMTrafficManager enableTraffic:YES];
else
[MWMTrafficManager enableTraffic:NO];

View file

@ -1,10 +1,6 @@
#include "platform/location.hpp"
#include "geometry/latlon.hpp"
@interface MWMNavigationDashboardEntity : NSObject
@property(nonatomic, readonly) ms::LatLon pedestrianDirectionPosition;
@property(nonatomic, readonly) CLLocation * pedestrianDirectionPosition;
@property(nonatomic, readonly) BOOL isValid;
@property(nonatomic, readonly) NSString * speed;
@property(nonatomic, readonly) NSString * speedUnits;
@ -16,14 +12,13 @@
@property(nonatomic, readonly) UIImage * turnImage;
@property(nonatomic, readonly) UIImage * nextTurnImage;
@property(nonatomic, readonly) NSUInteger roundExitNumber;
@property(nonatomic, readonly) NSUInteger timeToTarget;
@property(nonatomic, readonly) NSString * eta;
@property(nonatomic, readonly) NSString * arrival;
@property(nonatomic, readonly) CGFloat progress;
//@property (nonatomic, readonly) vector<location::FollowingInfo::SingleLaneInfoClient> lanes;
@property(nonatomic, readonly) BOOL isPedestrian;
@property(nonatomic, readonly) NSAttributedString * estimate;
- (void)updateFollowingInfo:(location::FollowingInfo const &)info;
+ (instancetype) new __attribute__((unavailable("init is not available")));
@end

View file

@ -1,111 +1,32 @@
#import "MWMNavigationDashboardEntity.h"
#import "MWMCommon.h"
#import "MWMCoreUnits.h"
#import "MWMLocationManager.h"
#import "MWMSettings.h"
#import "MapsAppDelegate.h"
#import "SwiftBridge.h"
#include "Framework.h"
#include "geometry/distance_on_sphere.hpp"
#include "platform/measurement_utils.hpp"
using namespace routing::turns;
@interface MWMNavigationDashboardEntity ()
@property(nonatomic, readwrite) CLLocation * pedestrianDirectionPosition;
@property(nonatomic, readwrite) BOOL isValid;
@property(nonatomic, readwrite) NSString * targetDistance;
@property(nonatomic, readwrite) NSString * targetUnits;
@property(nonatomic, readwrite) NSString * distanceToTurn;
@property(nonatomic, readwrite) NSString * turnUnits;
@property(nonatomic, readwrite) NSString * streetName;
@property(nonatomic, readwrite) UIImage * turnImage;
@property(nonatomic, readwrite) UIImage * nextTurnImage;
@property(nonatomic, readwrite) NSUInteger roundExitNumber;
@property(nonatomic, readwrite) NSUInteger timeToTarget;
@property(nonatomic, readwrite) CGFloat progress;
@property(nonatomic, readwrite) BOOL isPedestrian;
@property(nonatomic, readwrite) NSAttributedString * estimate;
@end
@implementation MWMNavigationDashboardEntity
- (void)updateFollowingInfo:(location::FollowingInfo const &)info
{
_isValid = info.IsValid();
_timeToTarget = info.m_time;
_targetDistance = @(info.m_distToTarget.c_str());
_targetUnits = @(info.m_targetUnitsSuffix.c_str());
_progress = info.m_completionPercent;
CLLocation * lastLocation = [MWMLocationManager lastLocation];
if (lastLocation && [MWMRouter type] == MWMRouterTypePedestrian)
{
_isPedestrian = YES;
string distance;
CLLocationCoordinate2D const & coordinate = lastLocation.coordinate;
_pedestrianDirectionPosition = info.m_pedestrianDirectionPos;
// TODO: Not the best solution, but this solution is temporary and will be replaced in future
measurement_utils::FormatDistance(
ms::DistanceOnEarth(coordinate.latitude, coordinate.longitude,
_pedestrianDirectionPosition.lat, _pedestrianDirectionPosition.lon),
distance);
istringstream is(distance);
string dist;
string units;
is >> dist;
is >> units;
_nextTurnImage = nil;
_distanceToTurn = @(dist.c_str());
_turnUnits = @(units.c_str());
_streetName = @"";
}
else
{
_isPedestrian = NO;
_distanceToTurn = @(info.m_distToTurn.c_str());
_turnUnits = @(info.m_turnUnitsSuffix.c_str());
_streetName = @(info.m_targetName.c_str());
_nextTurnImage = image(info.m_nextTurn, true);
}
NSDictionary * etaAttributes = @{
NSForegroundColorAttributeName : UIColor.blackPrimaryText,
NSFontAttributeName : UIFont.medium17
};
NSString * eta = [NSDateComponentsFormatter etaStringFrom:_timeToTarget];
NSString * resultString =
[NSString stringWithFormat:@"%@ • %@ %@", eta, _targetDistance, _targetUnits];
NSMutableAttributedString * result =
[[NSMutableAttributedString alloc] initWithString:resultString];
[result addAttributes:etaAttributes range:NSMakeRange(0, resultString.length)];
_estimate = [result copy];
CarDirection const turn = info.m_turn;
_turnImage = image(turn, false);
BOOL const isRound = turn == CarDirection::EnterRoundAbout ||
turn == CarDirection::StayOnRoundAbout ||
turn == CarDirection::LeaveRoundAbout;
if (isRound)
_roundExitNumber = info.m_exitNum;
else
_roundExitNumber = 0;
}
UIImage * image(routing::turns::CarDirection t, bool isNextTurn)
{
if ([MWMRouter type] == MWMRouterTypePedestrian)
return [UIImage imageNamed:@"ic_direction"];
NSString * imageName;
switch (t)
{
case CarDirection::TurnSlightRight: imageName = @"slight_right"; break;
case CarDirection::TurnRight: imageName = @"simple_right"; break;
case CarDirection::TurnSharpRight: imageName = @"sharp_right"; break;
case CarDirection::TurnSlightLeft: imageName = @"slight_left"; break;
case CarDirection::TurnLeft: imageName = @"simple_left"; break;
case CarDirection::TurnSharpLeft: imageName = @"sharp_left"; break;
case CarDirection::UTurnLeft: imageName = @"uturn_left"; break;
case CarDirection::UTurnRight: imageName = @"uturn_right"; break;
case CarDirection::ReachedYourDestination: imageName = @"finish_point"; break;
case CarDirection::LeaveRoundAbout:
case CarDirection::EnterRoundAbout: imageName = @"round"; break;
case CarDirection::GoStraight: imageName = @"straight"; break;
case CarDirection::StartAtEndOfStreet:
case CarDirection::StayOnRoundAbout:
case CarDirection::TakeTheExit:
case CarDirection::Count:
case CarDirection::None: imageName = isNextTurn ? nil : @"straight"; break;
}
if (!imageName)
return nil;
return [UIImage imageNamed:isNextTurn ? [imageName stringByAppendingString:@"_then"] : imageName];
}
- (NSString *)speed
{
CLLocation * lastLocation = [MWMLocationManager lastLocation];
@ -121,4 +42,13 @@ UIImage * image(routing::turns::CarDirection t, bool isNextTurn)
return @(measurement_utils::FormatSpeedUnits(units).c_str());
}
- (NSString *)eta { return [NSDateComponentsFormatter etaStringFrom:self.timeToTarget]; }
- (NSString *)arrival
{
auto arrivalDate = [[NSDate date] dateByAddingTimeInterval:self.timeToTarget];
return [NSDateFormatter localizedStringFromDate:arrivalDate
dateStyle:NSDateFormatterNoStyle
timeStyle:NSDateFormatterShortStyle];
}
@end

View file

@ -1,7 +0,0 @@
#import "MWMNavigationDashboardEntity.h"
@protocol MWMNavigationDashboardInfoProtocol
- (void)updateNavigationInfo:(MWMNavigationDashboardEntity *)info;
@end

View file

@ -0,0 +1,9 @@
#import "MWMNavigationDashboardManager.h"
#include "platform/location.hpp"
@interface MWMNavigationDashboardManager (Entity)
- (void)updateFollowingInfo:(location::FollowingInfo const &)info;
@end

View file

@ -0,0 +1,149 @@
#import "MWMLocationManager.h"
#import "MWMNavigationDashboardEntity.h"
#import "MWMNavigationDashboardManager+Entity.h"
#import "MWMRouter.h"
#import "SwiftBridge.h"
#include "geometry/distance_on_sphere.hpp"
#include "routing/turns.hpp"
namespace
{
UIImage * image(routing::turns::CarDirection t, bool isNextTurn)
{
if ([MWMRouter type] == MWMRouterTypePedestrian)
return [UIImage imageNamed:@"ic_direction"];
using namespace routing::turns;
NSString * imageName;
switch (t)
{
case CarDirection::TurnSlightRight: imageName = @"slight_right"; break;
case CarDirection::TurnRight: imageName = @"simple_right"; break;
case CarDirection::TurnSharpRight: imageName = @"sharp_right"; break;
case CarDirection::TurnSlightLeft: imageName = @"slight_left"; break;
case CarDirection::TurnLeft: imageName = @"simple_left"; break;
case CarDirection::TurnSharpLeft: imageName = @"sharp_left"; break;
case CarDirection::UTurnLeft: imageName = @"uturn_left"; break;
case CarDirection::UTurnRight: imageName = @"uturn_right"; break;
case CarDirection::ReachedYourDestination: imageName = @"finish_point"; break;
case CarDirection::LeaveRoundAbout:
case CarDirection::EnterRoundAbout: imageName = @"round"; break;
case CarDirection::GoStraight: imageName = @"straight"; break;
case CarDirection::StartAtEndOfStreet:
case CarDirection::StayOnRoundAbout:
case CarDirection::TakeTheExit:
case CarDirection::Count:
case CarDirection::None: imageName = isNextTurn ? nil : @"straight"; break;
}
if (!imageName)
return nil;
return [UIImage imageNamed:isNextTurn ? [imageName stringByAppendingString:@"_then"] : imageName];
}
} // namespace
@interface MWMNavigationDashboardEntity ()
@property(nonatomic, readwrite) CLLocation * pedestrianDirectionPosition;
@property(nonatomic, readwrite) BOOL isValid;
@property(nonatomic, readwrite) NSString * targetDistance;
@property(nonatomic, readwrite) NSString * targetUnits;
@property(nonatomic, readwrite) NSString * distanceToTurn;
@property(nonatomic, readwrite) NSString * turnUnits;
@property(nonatomic, readwrite) NSString * streetName;
@property(nonatomic, readwrite) UIImage * turnImage;
@property(nonatomic, readwrite) UIImage * nextTurnImage;
@property(nonatomic, readwrite) NSUInteger roundExitNumber;
@property(nonatomic, readwrite) NSUInteger timeToTarget;
@property(nonatomic, readwrite) CGFloat progress;
@property(nonatomic, readwrite) BOOL isPedestrian;
@property(nonatomic, readwrite) NSAttributedString * estimate;
@end
@interface MWMNavigationDashboardManager ()
@property(nonatomic) MWMNavigationDashboardEntity * entity;
- (void)onNavigationInfoUpdated;
@end
@implementation MWMNavigationDashboardManager (Entity)
- (void)updateFollowingInfo:(location::FollowingInfo const &)info
{
if ([MWMRouter isRouteFinished])
{
[MWMRouter stopRouting];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
return;
}
if (auto entity = self.entity)
{
entity.isValid = info.IsValid();
entity.timeToTarget = info.m_time;
entity.targetDistance = @(info.m_distToTarget.c_str());
entity.targetUnits = @(info.m_targetUnitsSuffix.c_str());
entity.progress = info.m_completionPercent;
CLLocation * lastLocation = [MWMLocationManager lastLocation];
if (lastLocation && [MWMRouter type] == MWMRouterTypePedestrian)
{
entity.isPedestrian = YES;
string distance;
CLLocationCoordinate2D const & coordinate = lastLocation.coordinate;
auto const lat = info.m_pedestrianDirectionPos.lat;
auto const lon = info.m_pedestrianDirectionPos.lon;
entity.pedestrianDirectionPosition = [[CLLocation alloc] initWithLatitude:lat longitude:lon];
// TODO: Not the best solution, but this solution is temporary and will be replaced in future
measurement_utils::FormatDistance(
ms::DistanceOnEarth(coordinate.latitude, coordinate.longitude, lat, lon), distance);
istringstream is(distance);
string dist;
string units;
is >> dist;
is >> units;
entity.nextTurnImage = nil;
entity.distanceToTurn = @(dist.c_str());
entity.turnUnits = @(units.c_str());
entity.streetName = @"";
}
else
{
entity.isPedestrian = NO;
entity.distanceToTurn = @(info.m_distToTurn.c_str());
entity.turnUnits = @(info.m_turnUnitsSuffix.c_str());
entity.streetName = @(info.m_targetName.c_str());
entity.nextTurnImage = image(info.m_nextTurn, true);
}
NSDictionary * etaAttributes = @{
NSForegroundColorAttributeName : UIColor.blackPrimaryText,
NSFontAttributeName : UIFont.medium17
};
NSString * eta = [NSDateComponentsFormatter etaStringFrom:entity.timeToTarget];
NSString * resultString =
[NSString stringWithFormat:@"%@ • %@ %@", eta, entity.targetDistance, entity.targetUnits];
NSMutableAttributedString * result =
[[NSMutableAttributedString alloc] initWithString:resultString];
[result addAttributes:etaAttributes range:NSMakeRange(0, resultString.length)];
entity.estimate = [result copy];
using namespace routing::turns;
CarDirection const turn = info.m_turn;
entity.turnImage = image(turn, false);
BOOL const isRound = turn == CarDirection::EnterRoundAbout ||
turn == CarDirection::StayOnRoundAbout ||
turn == CarDirection::LeaveRoundAbout;
if (isRound)
entity.roundExitNumber = info.m_exitNum;
else
entity.roundExitNumber = 0;
}
[self onNavigationInfoUpdated];
}
@end

View file

@ -1,15 +1,7 @@
#import "MWMBottomMenuView.h"
#import "MWMCircularProgress.h"
#import "MWMNavigationDashboardEntity.h"
#import "MWMNavigationDashboardInfoProtocol.h"
#import "MWMNavigationViewProtocol.h"
#import "MWMRoutePreview.h"
#import "MWMNavigationDashboardObserver.h"
#import "MWMTaxiPreviewDataSource.h"
#include "Framework.h"
#include "platform/location.hpp"
typedef NS_ENUM(NSUInteger, MWMNavigationDashboardState) {
MWMNavigationDashboardStateHidden,
MWMNavigationDashboardStatePrepare,
@ -19,40 +11,23 @@ typedef NS_ENUM(NSUInteger, MWMNavigationDashboardState) {
MWMNavigationDashboardStateNavigation
};
@protocol MWMNavigationDashboardManagerProtocol<MWMNavigationViewProtocol>
- (void)setMenuState:(MWMBottomMenuState)menuState;
- (void)setMenuRestoreState:(MWMBottomMenuState)menuState;
- (void)setRoutingErrorMessage:(NSString *)errorMessage;
- (MWMTaxiCollectionView *)taxiCollectionView;
@end
@interface MWMNavigationDashboardManager : NSObject
+ (MWMNavigationDashboardManager *)manager;
+ (void)addObserver:(id<MWMNavigationDashboardObserver>)observer;
+ (void)removeObserver:(id<MWMNavigationDashboardObserver>)observer;
@property(nonatomic, readonly) MWMNavigationDashboardEntity * entity;
@property(nonatomic, readonly) MWMRoutePreview * routePreview;
@property(nonatomic) MWMNavigationDashboardState state;
@property(nonatomic) MWMTaxiPreviewDataSource * taxiDataSource;
@property(weak, nonatomic, readonly) id<MWMNavigationDashboardManagerProtocol> delegate;
@property(nonatomic) CGFloat topBound;
@property(nonatomic) CGFloat leftBound;
@property(nonatomic, readonly) MWMTaxiPreviewDataSource * taxiDataSource;
@property(nonatomic) NSString * errorMessage;
- (instancetype)init __attribute__((unavailable("init is not available")));
- (instancetype)initWithParentView:(UIView *)view
delegate:(id<MWMNavigationDashboardManagerProtocol>)delegate;
- (void)updateFollowingInfo:(location::FollowingInfo const &)info;
- (void)updateDashboard;
- (instancetype)initWithParentView:(UIView *)view;
- (void)setRouteBuilderProgress:(CGFloat)progress;
- (void)mwm_refreshUI;
- (void)setMapSearch;
- (void)addInfoDisplay:(id<MWMNavigationDashboardInfoProtocol>)infoDisplay;
- (void)updateStartButtonTitle:(UIButton *)startButton;
- (void)onRoutePointsUpdated;
+ (void)updateNavigationInfoAvailableArea:(CGRect)frame;
@end

View file

@ -4,26 +4,32 @@
#import "MWMCommon.h"
#import "MWMLocationHelpers.h"
#import "MWMMapViewControlsManager.h"
#import "MWMNavigationDashboardEntity.h"
#import "MWMNavigationInfoView.h"
#import "MWMRoutePoint+CPP.h"
#import "MWMRoutePreview.h"
#import "MWMRouter.h"
#import "MWMTaxiPreviewDataSource.h"
#import "MWMSearchManager.h"
#import "MWMTextToSpeech.h"
#import "MWMTrafficManager.h"
#import "MapViewController.h"
#import "MapsAppDelegate.h"
#import "Statistics.h"
#import "SwiftBridge.h"
#include "platform/platform.hpp"
extern NSString * const kAlohalyticsTapEventKey;
namespace
{
NSString * const kRoutePreviewXibName = @"MWMRoutePreview";
NSString * const kRoutePreviewIPADXibName = @"MWMiPadRoutePreview";
NSString * const kRoutePreviewIPhoneXibName = @"MWMiPhoneRoutePreview";
NSString * const kNavigationInfoViewXibName = @"MWMNavigationInfoView";
NSString * const kNavigationControlViewXibName = @"NavigationControlView";
using TInfoDisplay = id<MWMNavigationDashboardInfoProtocol>;
using TInfoDisplays = NSHashTable<__kindof TInfoDisplay>;
using TObserver = id<MWMNavigationDashboardObserver>;
using TObservers = NSHashTable<__kindof TObserver>;
} // namespace
@interface MWMMapViewControlsManager ()
@ -32,16 +38,18 @@ using TInfoDisplays = NSHashTable<__kindof TInfoDisplay>;
@end
@interface MWMNavigationDashboardManager ()
@interface MWMNavigationDashboardManager ()<MWMSearchManagerObserver>
@property(nonatomic, readwrite) IBOutlet MWMRoutePreview * routePreview;
@property(nonatomic) IBOutlet MWMNavigationControlView * navigationControlView;
@property(nonatomic) IBOutlet MWMNavigationInfoView * navigationInfoView;
@property(nonatomic) TInfoDisplays * infoDisplays;
@property(weak, nonatomic) UIView * ownerView;
@property(nonatomic) IBOutlet MWMRoutePreview * routePreview;
@property(nonatomic) IBOutlet MWMRoutePreviewStatus * statusBox;
@property(nonatomic) IBOutlet MWMRouteStartButton * goButton;
@property(nonatomic) MWMNavigationDashboardEntity * entity;
@property(nonatomic) TObservers * observers;
@property(nonatomic, readwrite) MWMTaxiPreviewDataSource * taxiDataSource;
@property(weak, nonatomic) IBOutlet MWMTaxiCollectionView * taxiCollectionView;
@property(weak, nonatomic) UIView * ownerView;
@end
@ -53,46 +61,22 @@ using TInfoDisplays = NSHashTable<__kindof TInfoDisplay>;
}
- (instancetype)initWithParentView:(UIView *)view
delegate:(id<MWMNavigationDashboardManagerProtocol>)delegate
{
self = [super init];
if (self)
{
_ownerView = view;
_delegate = delegate;
_infoDisplays = [TInfoDisplays weakObjectsHashTable];
_observers = [TObservers weakObjectsHashTable];
}
return self;
}
- (void)updateFollowingInfo:(location::FollowingInfo const &)info
- (void)loadPreviewWithStatusBox
{
if ([MWMRouter isRouteFinished])
{
[MWMRouter stopRouting];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
return;
}
[self.entity updateFollowingInfo:info];
[self updateDashboard];
}
- (void)handleError
{
if ([MWMRouter isTaxi])
return;
[self.routePreview stateError];
[self.routePreview router:[MWMRouter type] setState:MWMCircularProgressStateFailed];
}
- (void)updateDashboard
{
if (!self.entity.isValid)
return;
for (TInfoDisplay infoDisplay in self.infoDisplays)
[infoDisplay updateNavigationInfo:self.entity];
[NSBundle.mainBundle loadNibNamed:IPAD ? kRoutePreviewIPADXibName : kRoutePreviewIPhoneXibName
owner:self
options:nil];
_statusBox.ownerView = self.ownerView;
}
#pragma mark - MWMRoutePreview
@ -102,63 +86,81 @@ using TInfoDisplays = NSHashTable<__kindof TInfoDisplay>;
[self.routePreview router:[MWMRouter type] setProgress:progress / 100.];
}
#pragma mark - MWMNavigationDashboard
- (IBAction)routingStopTouchUpInside
{
if (IPAD && self.state != MWMNavigationDashboardStateNavigation)
[self.delegate routePreviewDidChangeFrame:{}];
[MWMRouter stopRouting];
}
#pragma mark - MWMTaxiDataSource
- (MWMTaxiPreviewDataSource *)taxiDataSource
{
if (!_taxiDataSource)
{
_taxiDataSource = [[MWMTaxiPreviewDataSource alloc] initWithCollectionView:IPAD ?
self.routePreview.taxiCollectionView : self.delegate.taxiCollectionView];
}
return _taxiDataSource;
}
#pragma mark - MWMNavigationGo
- (IBAction)routingStartTouchUpInside { [MWMRouter startRouting]; }
- (void)updateGoButtonTitle
{
NSString * title = nil;
if ([MWMRouter isTaxi])
title = self.taxiDataSource.isTaxiInstalled ? L(@"taxi_order") : L(@"install_app");
else
title = L(@"p2p_start");
[self.goButton setTitle:title forState:UIControlStateNormal];
}
- (void)onRoutePointsUpdated { [self.navigationInfoView updateToastView]; }
- (void)mwm_refreshUI
{
[_routePreview mwm_refreshUI];
[_navigationInfoView mwm_refreshUI];
[_navigationControlView mwm_refreshUI];
[_statusBox mwm_refreshUI];
}
- (void)onNavigationInfoUpdated
{
auto entity = self.entity;
if (!entity.isValid)
return;
[_navigationInfoView onNavigationInfoUpdated:entity];
[_statusBox onNavigationInfoUpdated:entity];
[_navigationControlView onNavigationInfoUpdated:entity];
}
#pragma mark - State changes
- (void)hideState
- (void)stateHidden
{
self.taxiDataSource = nil;
[self.routePreview remove];
self.routePreview = nil;
self.navigationInfoView.state = MWMNavigationInfoViewStateHidden;
self.navigationInfoView = nil;
self.navigationControlView.isVisible = NO;
self.navigationControlView = nil;
[self.statusBox stateNavigation];
self.statusBox = nil;
}
- (void)showStatePrepare
- (void)statePrepare
{
self.navigationInfoView.state = MWMNavigationInfoViewStatePrepare;
[self.routePreview addToView:self.ownerView];
[self.routePreview statePrepare];
[self.routePreview selectRouter:[MWMRouter type]];
[self setMenuState:MWMBottomMenuStateHidden];
auto routePreview = self.routePreview;
[routePreview addToView:self.ownerView];
[routePreview statePrepare];
[routePreview selectRouter:[MWMRouter type]];
[self updateGoButtonTitle];
[self.goButton statePrepare];
[self.statusBox statePrepare];
}
- (void)showStatePlanning
- (void)statePlanning
{
[self showStatePrepare];
[self statePrepare];
[self.routePreview router:[MWMRouter type] setState:MWMCircularProgressStateSpinner];
[self setRouteBuilderProgress:0.];
if (![MWMRouter isTaxi])
return;
auto showError = ^(NSString * errorMessage)
{
[self.routePreview stateError];
[self.routePreview router:MWMRouterTypeTaxi setState:MWMCircularProgressStateFailed];
[self setMenuErrorStateWithErrorMessage:errorMessage];
__weak auto wSelf = self;
auto showError = ^(NSString * errorMessage) {
__strong auto self = wSelf;
if (!self)
return;
self.errorMessage = errorMessage;
self.state = MWMNavigationDashboardStateError;
};
auto pFrom = [MWMRouter startPoint];
@ -172,131 +174,151 @@ using TInfoDisplays = NSHashTable<__kindof TInfoDisplay>;
return;
}
[self.taxiDataSource requestTaxiFrom:pFrom
to:pTo
completion:^{
[self setMenuState:MWMBottomMenuStateGo];
[self.routePreview stateReady];
[self setRouteBuilderProgress:100.];
}
failure:^(NSString * errorMessage) {
showError(errorMessage);
}];
to:pTo
completion:^{
wSelf.state = MWMNavigationDashboardStateReady;
}
failure:^(NSString * errorMessage) {
showError(errorMessage);
}];
}
- (void)showStateReady
- (void)stateError
{
if ([MWMRouter isTaxi])
return;
[self setMenuState:MWMBottomMenuStateGo];
[self.routePreview stateReady];
NSAssert(_state == MWMNavigationDashboardStatePlanning, @"Invalid state change (error)");
auto routePreview = self.routePreview;
[routePreview router:[MWMRouter type] setState:MWMCircularProgressStateFailed];
[self updateGoButtonTitle];
[self.goButton stateError];
[self.statusBox stateErrorWithMessage:self.errorMessage];
}
- (void)showStateNavigation
- (void)stateReady
{
NSAssert(_state == MWMNavigationDashboardStatePlanning, @"Invalid state change (ready)");
[self setRouteBuilderProgress:100.];
[self updateGoButtonTitle];
[self.goButton stateReady];
[self.statusBox stateReady];
}
- (void)stateNavigation
{
[self setMenuState:MWMBottomMenuStateRouting];
[self.routePreview remove];
self.routePreview = nil;
self.navigationInfoView.state = MWMNavigationInfoViewStateNavigation;
self.navigationControlView.isVisible = YES;
[self.statusBox stateNavigation];
self.statusBox = nil;
}
- (void)updateStartButtonTitle:(UIButton *)startButton
#pragma mark - MWMNavigationControlView
- (IBAction)ttsButtonAction
{
auto t = self.startButtonTitle;
[startButton setTitle:t forState:UIControlStateNormal];
[startButton setTitle:t forState:UIControlStateDisabled];
BOOL const isEnabled = [MWMTextToSpeech tts].active;
[Statistics logEvent:kStatMenu withParameters:@{kStatTTS : isEnabled ? kStatOn : kStatOff}];
[MWMTextToSpeech tts].active = !isEnabled;
}
- (void)onRoutePointsUpdated { [self.navigationInfoView updateToastView]; }
- (void)setMenuErrorStateWithErrorMessage:(NSString *)message
- (IBAction)trafficButtonAction
{
[self.delegate setRoutingErrorMessage:message];
[self setMenuState:MWMBottomMenuStateRoutingError];
BOOL const switchOn = ([MWMTrafficManager state] == MWMTrafficManagerStateDisabled);
[Statistics logEvent:kStatMenu withParameters:@{kStatTraffic : switchOn ? kStatOn : kStatOff}];
[MWMTrafficManager enableTraffic:switchOn];
}
- (void)setMenuState:(MWMBottomMenuState)menuState
- (IBAction)settingsButtonAction
{
id<MWMNavigationDashboardManagerProtocol> delegate = self.delegate;
[delegate setMenuState:menuState];
[delegate setMenuRestoreState:menuState];
[Statistics logEvent:kStatMenu withParameters:@{kStatButton : kStatSettings}];
[Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"settingsAndMore"];
[[MapViewController controller] performSegueWithIdentifier:@"Map2Settings" sender:nil];
}
- (void)mwm_refreshUI
- (IBAction)stopRoutingButtonAction { [MWMRouter stopRouting]; }
#pragma mark - Add/Remove Observers
+ (void)addObserver:(id<MWMNavigationDashboardObserver>)observer
{
if (_routePreview)
[self.routePreview mwm_refreshUI];
if (_navigationInfoView)
[self.navigationInfoView mwm_refreshUI];
[[MWMNavigationDashboardManager manager].observers addObject:observer];
}
+ (void)removeObserver:(id<MWMNavigationDashboardObserver>)observer
{
[[MWMNavigationDashboardManager manager].observers removeObject:observer];
}
#pragma mark - MWMNavigationDashboardObserver
- (void)onNavigationDashboardStateChanged
{
for (TObserver observer in self.observers)
[observer onNavigationDashboardStateChanged];
}
#pragma mark - MWMSearchManagerObserver
- (void)onSearchManagerStateChanged
{
auto state = [MWMSearchManager manager].state;
if (state == MWMSearchManagerStateMapSearch)
[self setMapSearch];
}
#pragma mark - Available area
+ (void)updateNavigationInfoAvailableArea:(CGRect)frame
{
[[MWMNavigationDashboardManager manager] updateNavigationInfoAvailableArea:frame];
}
- (void)updateNavigationInfoAvailableArea:(CGRect)frame { _navigationInfoView.frame = frame; }
#pragma mark - Properties
- (void)setState:(MWMNavigationDashboardState)state
{
if (_state == state)
return;
if (state == MWMNavigationDashboardStateHidden)
[MWMSearchManager removeObserver:self];
else
[MWMSearchManager addObserver:self];
switch (state)
{
case MWMNavigationDashboardStateHidden: [self hideState]; break;
case MWMNavigationDashboardStatePrepare: [self showStatePrepare]; break;
case MWMNavigationDashboardStatePlanning: [self showStatePlanning]; break;
case MWMNavigationDashboardStateError:
NSAssert(
_state == MWMNavigationDashboardStatePlanning || _state == MWMNavigationDashboardStateReady,
@"Invalid state change (error)");
[self handleError];
break;
case MWMNavigationDashboardStateReady:
NSAssert(_state == MWMNavigationDashboardStatePlanning, @"Invalid state change (ready)");
[self showStateReady];
break;
case MWMNavigationDashboardStateNavigation: [self showStateNavigation]; break;
case MWMNavigationDashboardStateHidden: [self stateHidden]; break;
case MWMNavigationDashboardStatePrepare: [self statePrepare]; break;
case MWMNavigationDashboardStatePlanning: [self statePlanning]; break;
case MWMNavigationDashboardStateError: [self stateError]; break;
case MWMNavigationDashboardStateReady: [self stateReady]; break;
case MWMNavigationDashboardStateNavigation: [self stateNavigation]; break;
}
_state = state;
[[MapViewController controller] updateStatusBarStyle];
[self updateDashboard];
[self onNavigationDashboardStateChanged];
}
- (void)setTopBound:(CGFloat)topBound
- (MWMTaxiPreviewDataSource *)taxiDataSource
{
_topBound = topBound;
if (_routePreview)
self.routePreview.topBound = topBound;
if (_navigationInfoView)
self.navigationInfoView.topBound = topBound;
if (!_taxiDataSource)
_taxiDataSource =
[[MWMTaxiPreviewDataSource alloc] initWithCollectionView:self.taxiCollectionView];
return _taxiDataSource;
}
- (void)setLeftBound:(CGFloat)leftBound
{
_leftBound = leftBound;
if (_routePreview && IPAD)
self.routePreview.leftBound = leftBound;
if (_navigationInfoView)
self.navigationInfoView.leftBound = leftBound;
}
- (void)addInfoDisplay:(TInfoDisplay)infoDisplay { [self.infoDisplays addObject:infoDisplay]; }
- (NSString *)startButtonTitle
{
if (![MWMRouter isTaxi])
return L(@"p2p_start");
return self.taxiDataSource.isTaxiInstalled ? L(@"taxi_order") : L(@"install_app");
}
#pragma mark - Properties
- (MWMRoutePreview *)routePreview
{
if (!_routePreview)
{
[NSBundle.mainBundle loadNibNamed:IPAD ? kRoutePreviewIPADXibName : kRoutePreviewXibName
owner:self
options:nil];
_routePreview.dashboardManager = self;
_routePreview.delegate = self.delegate;
[self addInfoDisplay:_routePreview];
}
[self loadPreviewWithStatusBox];
return _routePreview;
}
- (MWMRoutePreviewStatus *)statusBox
{
if (!_statusBox)
[self loadPreviewWithStatusBox];
return _statusBox;
}
- (MWMNavigationInfoView *)navigationInfoView
{
if (!_navigationInfoView)
@ -304,11 +326,20 @@ using TInfoDisplays = NSHashTable<__kindof TInfoDisplay>;
[NSBundle.mainBundle loadNibNamed:kNavigationInfoViewXibName owner:self options:nil];
_navigationInfoView.state = MWMNavigationInfoViewStateHidden;
_navigationInfoView.ownerView = self.ownerView;
[self addInfoDisplay:_navigationInfoView];
}
return _navigationInfoView;
}
- (MWMNavigationControlView *)navigationControlView
{
if (!_navigationControlView)
{
[NSBundle.mainBundle loadNibNamed:kNavigationControlViewXibName owner:self options:nil];
_navigationControlView.ownerView = self.ownerView;
}
return _navigationControlView;
}
- (MWMNavigationDashboardEntity *)entity
{
if (!_entity)
@ -318,8 +349,7 @@ using TInfoDisplays = NSHashTable<__kindof TInfoDisplay>;
- (void)setMapSearch
{
if (_navigationInfoView)
[self.navigationInfoView setMapSearch];
[_navigationInfoView setMapSearch];
}
@end

View file

@ -0,0 +1,5 @@
@protocol MWMNavigationDashboardObserver<NSObject>
- (void)onNavigationDashboardStateChanged;
@end

View file

@ -1,5 +1,3 @@
#import "MWMNavigationDashboardInfoProtocol.h"
enum class NavigationSearchState
{
Maximized,
@ -18,14 +16,16 @@ typedef NS_ENUM(NSUInteger, MWMNavigationInfoViewState) {
MWMNavigationInfoViewStateNavigation
};
@interface MWMNavigationInfoView : UIView<MWMNavigationDashboardInfoProtocol>
@class MWMNavigationDashboardEntity;
@interface MWMNavigationInfoView : UIView
@property(nonatomic) CGFloat topBound;
@property(nonatomic) CGFloat leftBound;
@property(nonatomic, readonly) NavigationSearchState searchState;
@property(nonatomic) MWMNavigationInfoViewState state;
@property(weak, nonatomic) UIView * ownerView;
- (void)onNavigationInfoUpdated:(MWMNavigationDashboardEntity *)info;
- (void)setMapSearch;
- (void)updateToastView;

View file

@ -8,6 +8,7 @@
#import "MWMLocationObserver.h"
#import "MWMMapViewControlsManager.h"
#import "MWMMapWidgets.h"
#import "MWMNavigationDashboardEntity.h"
#import "MWMRouter.h"
#import "MWMSearch.h"
#import "MapViewController.h"
@ -77,6 +78,7 @@ BOOL defaultOrientation(CGSize const & size)
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * searchButtonsViewHeight;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * searchButtonsViewWidth;
@property(nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray * searchLandscapeConstraints;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * searchButtonsToastOffset;
@property(nonatomic) IBOutletCollection(UIButton) NSArray * searchButtons;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * searchButtonsSideSize;
@property(weak, nonatomic) IBOutlet MWMButton * searchGasButton;
@ -96,20 +98,12 @@ BOOL defaultOrientation(CGSize const & size)
@property(nonatomic) BOOL hasLocation;
@property(nonatomic) CGRect availableArea;
@end
@implementation MWMNavigationInfoView
- (void)layoutSubviews
{
[super layoutSubviews];
if (!CGRectEqualToRect(self.frame, self.defaultFrame))
{
self.frame = self.defaultFrame;
[self setNeedsLayout];
}
}
- (void)setMapSearch { [self setSearchState:NavigationSearchState::MinimizedSearch animated:YES]; }
- (void)updateToastView
{
@ -159,7 +153,7 @@ BOOL defaultOrientation(CGSize const & size)
BOOL const isStart = ([MWMRouter startPoint] == nil);
auto const type = isStart ? kStatRoutingPointTypeStart : kStatRoutingPointTypeFinish;
[Statistics logEvent:kStatRoutingTooltipClicked withParameters:@{kStatRoutingPointType : type}];
[MWMMapViewControlsManager manager].searchHidden = NO;
[MWMSearchManager manager].state = MWMSearchManagerStateDefault;
}
- (IBAction)addLocationRoutePoint
@ -187,14 +181,14 @@ BOOL defaultOrientation(CGSize const & size)
switch (self.searchState)
{
case NavigationSearchState::Maximized:
[MWMMapViewControlsManager manager].searchHidden = NO;
[MWMSearchManager manager].state = MWMSearchManagerStateDefault;
[self setSearchState:NavigationSearchState::MinimizedNormal animated:YES];
[Statistics logEvent:kStatRoutingSearchClicked withParameters:@{ kStatRoutingMode : kStatRoutingModeOnRoute }];
break;
case NavigationSearchState::MinimizedNormal:
if (self.state == MWMNavigationInfoViewStatePrepare)
{
[MWMMapViewControlsManager manager].searchHidden = NO;
[MWMSearchManager manager].state = MWMSearchManagerStateDefault;
[Statistics logEvent:kStatRoutingSearchClicked withParameters:@{ kStatRoutingMode : kStatRoutingModePlanning }];
}
else
@ -209,7 +203,7 @@ BOOL defaultOrientation(CGSize const & size)
case NavigationSearchState::MinimizedShop:
case NavigationSearchState::MinimizedATM:
[MWMSearch clear];
[MWMMapViewControlsManager manager].searchHidden = YES;
[MWMSearchManager manager].state = MWMSearchManagerStateHidden;
[self setSearchState:NavigationSearchState::MinimizedNormal animated:YES];
break;
}
@ -252,9 +246,38 @@ BOOL defaultOrientation(CGSize const & size)
[self setSearchState:NavigationSearchState::MinimizedNormal animated:YES];
}
#pragma mark - MWMNavigationDashboardInfoProtocol
- (void)layoutSearch
{
BOOL const defaultView = defaultOrientation(self.frame.size);
CGFloat alpha = 1;
CGFloat searchButtonsSideSize = kSearchButtonsSideSize;
if (self.searchState == NavigationSearchState::Maximized)
{
self.searchButtonsViewWidth.constant =
defaultView ? kSearchButtonsViewWidthPortrait : kSearchButtonsViewWidthLandscape;
self.searchButtonsViewHeight.constant =
defaultView ? kSearchButtonsViewHeightPortrait : kSearchButtonsViewHeightLandscape;
}
else
{
self.searchButtonsViewWidth.constant = 0;
self.searchButtonsViewHeight.constant = 0;
alpha = 0;
searchButtonsSideSize = 0;
}
for (UIButton * searchButton in self.searchButtons)
searchButton.alpha = alpha;
UILayoutPriority const priority =
defaultView ? UILayoutPriorityDefaultLow : UILayoutPriorityDefaultHigh;
for (NSLayoutConstraint * constraint in self.searchLandscapeConstraints)
constraint.priority = priority;
self.searchButtonsToastOffset.priority = priority + UILayoutPriorityFittingSizeLevel;
self.searchButtonsSideSize.constant = searchButtonsSideSize;
}
- (void)updateNavigationInfo:(MWMNavigationDashboardEntity *)info
#pragma mark - MWMNavigationDashboardManager
- (void)onNavigationInfoUpdated:(MWMNavigationDashboardEntity *)info
{
self.navigationInfo = info;
if (self.state != MWMNavigationInfoViewStateNavigation)
@ -320,34 +343,6 @@ BOOL defaultOrientation(CGSize const & size)
[self setNeedsLayout];
}
- (void)layoutSearch
{
BOOL const defaultView = defaultOrientation(self.frame.size);
CGFloat alpha = 1;
CGFloat searchButtonsSideSize = kSearchButtonsSideSize;
if (self.searchState == NavigationSearchState::Maximized)
{
self.searchButtonsViewWidth.constant =
defaultView ? kSearchButtonsViewWidthPortrait : kSearchButtonsViewWidthLandscape;
self.searchButtonsViewHeight.constant =
defaultView ? kSearchButtonsViewHeightPortrait : kSearchButtonsViewHeightLandscape;
}
else
{
self.searchButtonsViewWidth.constant = 0;
self.searchButtonsViewHeight.constant = 0;
alpha = 0;
searchButtonsSideSize = 0;
}
for (UIButton * searchButton in self.searchButtons)
searchButton.alpha = alpha;
UILayoutPriority const priority =
defaultView ? UILayoutPriorityDefaultLow : UILayoutPriorityDefaultHigh;
for (NSLayoutConstraint * constraint in self.searchLandscapeConstraints)
constraint.priority = priority;
self.searchButtonsSideSize.constant = searchButtonsSideSize;
}
#pragma mark - MWMLocationObserver
- (void)onLocationUpdate:(location::GpsInfo const &)gpsInfo
@ -364,10 +359,9 @@ BOOL defaultOrientation(CGSize const & size)
if (lastLocation && self.state == MWMNavigationInfoViewStateNavigation &&
[MWMRouter type] == MWMRouterTypePedestrian)
{
auto const mercator =
location_helpers::ToMercator(self.navigationInfo.pedestrianDirectionPosition);
auto const angle = ang::AngleTo(lastLocation.mercator, mercator) + info.m_bearing;
transform = CATransform3DMakeRotation(M_PI_2 - angle, 0, 0, 1);
auto const angle = ang::AngleTo(lastLocation.mercator,
self.navigationInfo.pedestrianDirectionPosition.mercator);
transform = CATransform3DMakeRotation(M_PI_2 - angle + info.m_bearing, 0, 0, 1);
}
self.nextTurnImageView.layer.transform = transform;
}
@ -408,14 +402,10 @@ BOOL defaultOrientation(CGSize const & size)
- (void)setFrame:(CGRect)frame
{
CGSize const & oldSize = self.frame.size;
CGSize const & size = frame.size;
if (CGRectEqualToRect(self.frame, frame) || (equalScreenDimensions(oldSize.width, size.width) &&
equalScreenDimensions(oldSize.height, size.height)))
return;
super.frame = frame;
[self layoutIfNeeded];
[self setNeedsLayout];
[self layoutSearch];
self.turnsTopOffset.constant = self.minY > 0 ? kShiftedTurnsTopOffset : kBaseTurnsTopOffset;
[UIView animateWithDuration:kDefaultAnimationDuration
animations:^{
self.searchButtonsView.layer.cornerRadius =
@ -463,11 +453,14 @@ BOOL defaultOrientation(CGSize const & size)
- (void)setState:(MWMNavigationInfoViewState)state
{
if (_state == state)
return;
_state = state;
switch (state)
{
case MWMNavigationInfoViewStateHidden:
self.isVisible = NO;
[self setToastViewHidden:YES];
[MWMLocationManager removeObserver:self];
break;
case MWMNavigationInfoViewStateNavigation:
@ -502,10 +495,10 @@ BOOL defaultOrientation(CGSize const & size)
- (void)setIsVisible:(BOOL)isVisible
{
[self setNeedsLayout];
if (_isVisible == isVisible)
return;
_isVisible = isVisible;
[self setNeedsLayout];
if (isVisible)
{
self.bookmarksButton.imageName = @"ic_routing_bookmark";
@ -517,29 +510,14 @@ BOOL defaultOrientation(CGSize const & size)
return;
[sv insertSubview:self atIndex:0];
}
else
{
[self removeFromSuperview];
}
}
- (CGRect)defaultFrame
{
return {{self.leftBound, self.topBound},
{self.superview.width - self.leftBound, self.superview.height - self.topBound}};
}
- (void)setTopBound:(CGFloat)topBound
{
_topBound = MAX(topBound, 0.0);
self.turnsTopOffset.constant = topBound > 0 ? kShiftedTurnsTopOffset : kBaseTurnsTopOffset;
[self setNeedsLayout];
}
- (void)setLeftBound:(CGFloat)leftBound
{
_leftBound = MAX(leftBound, 0.0);
[self setNeedsLayout];
[UIView animateWithDuration:kDefaultAnimationDuration
animations:^{
[self layoutIfNeeded];
}
completion:^(BOOL finished) {
if (!isVisible)
[self removeFromSuperview];
}];
}
- (void)setToastViewHidden:(BOOL)hidden
@ -548,14 +526,15 @@ BOOL defaultOrientation(CGSize const & size)
self.toastView.hidden = NO;
[self setNeedsLayout];
self.toastViewHideOffset.priority =
hidden ? UILayoutPriorityDefaultHigh : UILayoutPriorityDefaultLow;
(hidden ? UILayoutPriorityDefaultHigh : UILayoutPriorityDefaultLow) + 20;
[UIView animateWithDuration:kDefaultAnimationDuration
animations:^{
[self layoutIfNeeded];
} completion:^(BOOL finished) {
if (hidden)
self.toastView.hidden = YES;
}];
animations:^{
[self layoutIfNeeded];
}
completion:^(BOOL finished) {
if (hidden)
self.toastView.hidden = YES;
}];
}
@end

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
@ -367,7 +367,7 @@
<constraint firstItem="TMW-aw-1RT" firstAttribute="centerY" secondItem="Xna-Q1-7zW" secondAttribute="centerY" id="652-PO-iav"/>
<constraint firstItem="YYv-pG-Wkw" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="IBQ-gK-Cpe"/>
<constraint firstItem="Xna-Q1-7zW" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="6" id="J7x-54-WT5"/>
<constraint firstItem="Tzc-l6-Vvt" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="bottom" priority="750" id="JqF-da-c1k"/>
<constraint firstItem="Tzc-l6-Vvt" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="bottom" priority="770" id="JqF-da-c1k"/>
<constraint firstItem="Xna-Q1-7zW" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" priority="500" constant="32" id="KQb-ju-1bf"/>
<constraint firstItem="YYv-pG-Wkw" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" priority="500" id="Rd5-Hl-fSF"/>
<constraint firstItem="Tzc-l6-Vvt" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="TvX-b3-3Sa"/>
@ -378,14 +378,14 @@
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="Xna-Q1-7zW" secondAttribute="bottom" constant="48" id="btg-Xq-UVZ"/>
<constraint firstItem="TMW-aw-1RT" firstAttribute="centerX" secondItem="Xna-Q1-7zW" secondAttribute="centerX" priority="500" id="ctJ-SL-eKZ"/>
<constraint firstItem="Aa6-N8-acP" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="28" id="goU-O7-rpS"/>
<constraint firstItem="XMv-au-OYf" firstAttribute="top" relation="greaterThanOrEqual" secondItem="Aa6-N8-acP" secondAttribute="bottom" priority="740" constant="8" id="hiU-Sn-hG1"/>
<constraint firstItem="XMv-au-OYf" firstAttribute="top" relation="greaterThanOrEqual" secondItem="Aa6-N8-acP" secondAttribute="bottom" priority="800" id="hiU-Sn-hG1"/>
<constraint firstItem="ShI-bz-5g8" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Aa6-N8-acP" secondAttribute="trailing" priority="999" constant="8" id="mdA-B9-tvQ"/>
<constraint firstItem="Tzc-l6-Vvt" firstAttribute="top" relation="greaterThanOrEqual" secondItem="Xna-Q1-7zW" secondAttribute="bottom" priority="200" constant="12" id="pFP-r6-dGK"/>
<constraint firstItem="Tzc-l6-Vvt" firstAttribute="top" relation="greaterThanOrEqual" secondItem="Xna-Q1-7zW" secondAttribute="bottom" priority="740" constant="12" id="pFP-r6-dGK"/>
<constraint firstItem="Aa6-N8-acP" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" priority="610" constant="8" id="pXD-dk-ku2"/>
<constraint firstItem="Xna-Q1-7zW" firstAttribute="top" secondItem="XMv-au-OYf" secondAttribute="bottom" constant="8" id="tEP-Qf-uBZ"/>
<constraint firstAttribute="top" secondItem="YYv-pG-Wkw" secondAttribute="bottom" priority="250" id="xMz-Tm-KEn"/>
<constraint firstAttribute="leading" secondItem="Aa6-N8-acP" secondAttribute="trailing" priority="250" id="xO2-jM-2bk"/>
<constraint firstAttribute="bottom" secondItem="Tzc-l6-Vvt" secondAttribute="bottom" priority="500" id="yP1-ip-l24"/>
<constraint firstAttribute="bottom" secondItem="Tzc-l6-Vvt" secondAttribute="bottom" priority="760" id="yP1-ip-l24"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
@ -430,7 +430,6 @@
<outletCollection property="searchLandscapeConstraints" destination="NcX-Rf-Cvm" id="vwd-uF-iTf"/>
<outletCollection property="searchButtons" destination="RP3-01-Pj7" id="1nL-Ib-y49"/>
<outletCollection property="searchLandscapeConstraints" destination="Y9b-UG-buF" id="cjs-so-6PQ"/>
<outletCollection property="searchLandscapeConstraints" destination="pFP-r6-dGK" id="p6X-D7-oom"/>
<outletCollection property="searchLandscapeConstraints" destination="boQ-v0-PUh" id="cV7-rz-brS"/>
</connections>
<point key="canvasLocation" x="33.5" y="54.5"/>

View file

@ -1,17 +0,0 @@
#import "MWMNavigationViewProtocol.h"
@interface MWMNavigationView : SolidTouchView
@property (nonatomic) CGFloat topBound;
@property (nonatomic) CGFloat leftBound;
@property (nonatomic) CGFloat defaultHeight;
@property (nonatomic, readonly) BOOL isVisible;
@property (nonatomic) UIView * statusbarBackground;
@property (weak, nonatomic) id<MWMNavigationViewProtocol> delegate;
@property (weak, nonatomic, readonly) IBOutlet UIView * contentView;
- (void)addToView:(UIView *)superview;
- (void)remove;
- (CGRect)defaultFrame;
@end

View file

@ -1,87 +0,0 @@
#import "MWMNavigationView.h"
#import "MWMCommon.h"
@interface MWMNavigationView ()
@property(nonatomic) BOOL isVisible;
@property(weak, nonatomic, readwrite) IBOutlet UIView * contentView;
@end
@implementation MWMNavigationView
- (void)awakeFromNib
{
[super awakeFromNib];
self.statusbarBackground = [[UIView alloc] initWithFrame:CGRectZero];
self.statusbarBackground.backgroundColor = self.contentView.backgroundColor;
self.defaultHeight = self.height;
self.topBound = 0.0;
self.leftBound = 0.0;
}
- (void)addToView:(UIView *)superview
{
self.frame = self.defaultFrame;
self.isVisible = YES;
NSAssert(superview != nil, @"Superview can't be nil");
if ([superview.subviews containsObject:self])
return;
[superview addSubview:self];
}
- (void)remove { self.isVisible = NO; }
- (void)layoutSubviews
{
[super layoutSubviews];
[UIView animateWithDuration:kDefaultAnimationDuration
animations:^{
if (!CGRectEqualToRect(self.frame, self.defaultFrame))
self.frame = self.defaultFrame;
CGFloat const sbHeight = statusBarHeight();
self.statusbarBackground.frame = CGRectMake(0.0, -sbHeight, self.width, sbHeight);
}
completion:^(BOOL finished) {
if (!self.isVisible)
[self removeFromSuperview];
}];
}
#pragma mark - Properties
- (CGRect)defaultFrame
{
return CGRectMake(self.leftBound, self.isVisible ? self.topBound : -self.defaultHeight,
self.superview.width, self.defaultHeight);
}
- (void)setTopBound:(CGFloat)topBound
{
CGFloat const sbHeight = statusBarHeight();
_topBound = MAX(topBound, sbHeight);
if (_topBound <= sbHeight)
{
if (![self.statusbarBackground.superview isEqual:self])
[self addSubview:self.statusbarBackground];
}
else
{
[self.statusbarBackground removeFromSuperview];
}
[self setNeedsLayout];
}
- (void)setLeftBound:(CGFloat)leftBound
{
_leftBound = MAX(leftBound, 0.0);
[self setNeedsLayout];
}
- (void)setIsVisible:(BOOL)isVisible
{
_isVisible = isVisible;
[self setNeedsLayout];
}
@end

View file

@ -1,5 +0,0 @@
@protocol MWMNavigationViewProtocol <NSObject>
- (void)routePreviewDidChangeFrame:(CGRect)newFrame;
@end

View file

@ -0,0 +1,252 @@
@objc(MWMNavigationControlView)
final class NavigationControlView: SolidTouchView, MWMTextToSpeechObserver, MWMTrafficManagerObserver {
@IBOutlet private weak var distanceLabel: UILabel!
@IBOutlet private weak var distanceLegendLabel: UILabel!
@IBOutlet private weak var distanceWithLegendLabel: UILabel!
@IBOutlet private weak var progressView: UIView!
@IBOutlet private weak var routingProgress: NSLayoutConstraint!
@IBOutlet private weak var speedLabel: UILabel!
@IBOutlet private weak var speedLegendLabel: UILabel!
@IBOutlet private weak var speedWithLegendLabel: UILabel!
@IBOutlet private weak var timeLabel: UILabel!
@IBOutlet private weak var timePageControl: UIPageControl!
@IBOutlet private weak var extendButton: UIButton! {
didSet {
setExtendButtonImage()
}
}
@IBOutlet private weak var ttsButton: UIButton! {
didSet {
ttsButton.setImage(#imageLiteral(resourceName: "ic_voice_off"), for: .normal)
ttsButton.setImage(#imageLiteral(resourceName: "ic_voice_on"), for: .selected)
ttsButton.setImage(#imageLiteral(resourceName: "ic_voice_on"), for: [.selected, .highlighted])
onTTSStatusUpdated()
}
}
@IBOutlet private weak var trafficButton: UIButton! {
didSet {
trafficButton.setImage(#imageLiteral(resourceName: "ic_setting_traffic_off"), for: .normal)
trafficButton.setImage(#imageLiteral(resourceName: "ic_setting_traffic_on"), for: .selected)
trafficButton.setImage(#imageLiteral(resourceName: "ic_setting_traffic_on"), for: [.selected, .highlighted])
onTrafficStateUpdated()
}
}
private lazy var dimBackground: DimBackground = {
DimBackground(mainView: self)
}()
weak var ownerView: UIView!
private weak var navigationInfo: MWMNavigationDashboardEntity?
private var hiddenConstraint: NSLayoutConstraint!
private var extendedConstraint: NSLayoutConstraint!
var isVisible = false {
didSet {
guard isVisible != oldValue else { return }
if isVisible {
addView()
} else {
dimBackground.setVisible(false) {}
}
DispatchQueue.main.async {
self.superview?.setNeedsLayout()
self.hiddenConstraint.isActive = !self.isVisible
UIView.animate(withDuration: kDefaultAnimationDuration,
animations: { self.superview?.layoutIfNeeded() },
completion: { _ in
if (!self.isVisible) {
self.removeFromSuperview()
}
})
}
}
}
private var isExtended = false {
willSet {
guard isExtended != newValue else { return }
morphExtendButton()
}
didSet {
guard isVisible && superview != nil else { return }
guard isExtended != oldValue else { return }
superview?.setNeedsLayout()
extendedConstraint.isActive = isExtended
UIView.animate(withDuration: kDefaultAnimationDuration) { self.superview?.layoutIfNeeded() }
dimBackground.setVisible(isExtended) { [weak self] in
self?.diminish()
}
}
}
private func addView() {
guard superview != ownerView else { return }
ownerView.addSubview(self)
NSLayoutConstraint(item: self, attribute: .left, relatedBy: .equal, toItem: ownerView, attribute: .left, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: self, attribute: .right, relatedBy: .equal, toItem: ownerView, attribute: .right, multiplier: 1, constant: 0).isActive = true
hiddenConstraint = NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: ownerView, attribute: .bottom, multiplier: 1, constant: 0)
hiddenConstraint.priority = UILayoutPriorityDefaultHigh
hiddenConstraint.isActive = true
let visibleConstraint = NSLayoutConstraint(item: progressView, attribute: .bottom, relatedBy: .equal, toItem: ownerView, attribute: .bottom, multiplier: 1, constant: 0)
visibleConstraint.priority = UILayoutPriorityDefaultLow
visibleConstraint.isActive = true
extendedConstraint = NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: ownerView, attribute: .bottom, multiplier: 1, constant: 0)
extendedConstraint.priority = UILayoutPriorityDefaultHigh - 1
}
override func mwm_refreshUI() {
if isVisible {
super.mwm_refreshUI()
}
}
override func awakeFromNib() {
super.awakeFromNib()
translatesAutoresizingMaskIntoConstraints = false
MWMTextToSpeech.add(self)
MWMTrafficManager.add(self)
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
let isCompact = traitCollection.verticalSizeClass == .compact
distanceLabel.isHidden = isCompact
distanceLegendLabel.isHidden = isCompact
distanceWithLegendLabel.isHidden = !isCompact
speedLabel.isHidden = isCompact
speedLegendLabel.isHidden = isCompact
speedWithLegendLabel.isHidden = !isCompact
let pgScale: CGFloat = isCompact ? 0.7 : 1
timePageControl.transform = CGAffineTransform(scaleX: pgScale, y: pgScale)
}
func onNavigationInfoUpdated(_ info: MWMNavigationDashboardEntity) {
navigationInfo = info
guard !MWMRouter.isTaxi() else { return }
let routingNumberAttributes: [String : Any] =
[NSForegroundColorAttributeName : UIColor.blackPrimaryText(), NSFontAttributeName : UIFont.bold24()]
let routingLegendAttributes: [String : Any] =
[NSForegroundColorAttributeName : UIColor.blackSecondaryText(), NSFontAttributeName : UIFont.bold14()]
if timePageControl.currentPage == 0 {
timeLabel.text = info.eta
} else {
timeLabel.text = info.arrival
}
var distanceWithLegend: NSMutableAttributedString?
if let targetDistance = info.targetDistance {
distanceLabel.text = targetDistance
distanceWithLegend = NSMutableAttributedString(string: targetDistance, attributes: routingNumberAttributes)
}
if let targetUnits = info.targetUnits {
distanceLegendLabel.text = targetUnits
if let distanceWithLegend = distanceWithLegend {
distanceWithLegend.append(NSAttributedString(string: targetUnits, attributes: routingLegendAttributes))
distanceWithLegendLabel.attributedText = distanceWithLegend
}
}
let speed = info.speed ?? "0"
speedLabel.text = speed
speedLegendLabel.text = info.speedUnits
let speedWithLegend = NSMutableAttributedString(string: speed, attributes: routingNumberAttributes)
speedWithLegend.append(NSAttributedString(string: info.speedUnits, attributes: routingLegendAttributes))
speedWithLegendLabel.attributedText = speedWithLegend
progressView.setNeedsLayout()
routingProgress.constant = progressView.width * info.progress / 100
UIView.animate(withDuration: kDefaultAnimationDuration) { [progressView] in
progressView?.layoutIfNeeded()
}
}
@IBAction
private func toggleInfoAction() {
if let navigationInfo = navigationInfo {
timePageControl.currentPage = (timePageControl.currentPage + 1) % timePageControl.numberOfPages
onNavigationInfoUpdated(navigationInfo)
}
refreshDiminishTimer()
}
@IBAction
private func extendAction() {
isExtended = !isExtended
refreshDiminishTimer()
}
private func morphExtendButton() {
guard let imageView = extendButton.imageView else { return }
let morphImagesCount = 6
let startValue = isExtended ? morphImagesCount : 1
let endValue = isExtended ? 0 : morphImagesCount + 1
let stepValue = isExtended ? -1 : 1
var morphImages: [UIImage] = []
let nightMode = UIColor.isNightMode() ? "dark" : "light"
for i in stride(from: startValue, to: endValue, by: stepValue) {
let imageName = "ic_menu_\(i)_\(nightMode)"
morphImages.append(UIImage(named: imageName)!)
}
imageView.animationImages = morphImages
imageView.animationRepeatCount = 1
imageView.image = morphImages.last
imageView.startAnimating()
setExtendButtonImage()
}
private func setExtendButtonImage() {
DispatchQueue.main.async {
guard let imageView = self.extendButton.imageView else { return }
if imageView.isAnimating {
self.setExtendButtonImage()
} else {
self.extendButton.setImage(self.isExtended ? #imageLiteral(resourceName: "ic_menu_down") : #imageLiteral(resourceName: "ic_menu"), for: .normal)
}
}
}
private func refreshDiminishTimer() {
let sel = #selector(diminish)
NSObject.cancelPreviousPerformRequests(withTarget: self, selector: sel, object: self)
perform(sel, with: self, afterDelay: 5)
}
@objc
private func diminish() {
isExtended = false
}
func onTTSStatusUpdated() {
guard MWMRouter.isRoutingActive() else { return }
let isPedestrianRouting = MWMRouter.type() == .pedestrian
ttsButton.isHidden = isPedestrianRouting || !MWMTextToSpeech.isTTSEnabled()
if !ttsButton.isHidden {
ttsButton.isSelected = MWMTextToSpeech.tts().active
}
refreshDiminishTimer()
}
func onTrafficStateUpdated() {
trafficButton.isSelected = MWMTrafficManager.state() != .disabled
refreshDiminishTimer()
}
override var sideButtonsAreaAffectDirections: MWMAvailableAreaAffectDirections {
return .bottom
}
}

View file

@ -0,0 +1,349 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MWMNavigationDashboardManager">
<connections>
<outlet property="navigationControlView" destination="9fq-65-qd9" id="KXU-52-J0l"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="9fq-65-qd9" customClass="MWMNavigationControlView">
<rect key="frame" x="0.0" y="0.0" width="320" height="116"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="u7O-n6-ZXy">
<rect key="frame" x="0.0" y="0.0" width="320" height="52"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QLk-JN-wfO">
<rect key="frame" x="0.0" y="0.0" width="66" height="52"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LY7-dx-CtV">
<rect key="frame" x="33" y="4" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="b3M-75-5HW">
<rect key="frame" x="33" y="4" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
</userDefinedRuntimeAttributes>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wgS-eK-vfD">
<rect key="frame" x="33" y="11" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="12"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" priority="750" constant="72" id="6Dl-DP-LFT">
<variation key="heightClass=compact" constant="128"/>
<variation key="heightClass=regular" constant="88"/>
<variation key="heightClass=compact-widthClass=compact" constant="72"/>
</constraint>
<constraint firstItem="wgS-eK-vfD" firstAttribute="centerX" secondItem="QLk-JN-wfO" secondAttribute="centerX" id="9qv-fX-QKO"/>
<constraint firstItem="b3M-75-5HW" firstAttribute="top" secondItem="QLk-JN-wfO" secondAttribute="top" constant="4" id="FQd-Km-nUE"/>
<constraint firstItem="b3M-75-5HW" firstAttribute="centerX" secondItem="QLk-JN-wfO" secondAttribute="centerX" priority="750" id="guh-Tk-WSm"/>
<constraint firstItem="LY7-dx-CtV" firstAttribute="centerX" secondItem="QLk-JN-wfO" secondAttribute="centerX" priority="750" id="ngn-iE-YWb"/>
<constraint firstItem="b3M-75-5HW" firstAttribute="top" secondItem="LY7-dx-CtV" secondAttribute="top" id="oMq-Rn-clI"/>
<constraint firstItem="LY7-dx-CtV" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="QLk-JN-wfO" secondAttribute="leading" priority="800" id="oeQ-cx-SRl"/>
<constraint firstItem="b3M-75-5HW" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="QLk-JN-wfO" secondAttribute="leading" priority="800" id="yar-Nc-c7c"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HNY-h1-A95">
<rect key="frame" x="66" y="0.0" width="128" height="52"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wEc-R2-1Tv">
<rect key="frame" x="64.5" y="4" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
</userDefinedRuntimeAttributes>
</label>
<pageControl opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="100" contentHorizontalAlignment="center" contentVerticalAlignment="center" numberOfPages="2" translatesAutoresizingMaskIntoConstraints="NO" id="ppd-rW-dYo">
<rect key="frame" x="53" y="4" width="23" height="13"/>
<constraints>
<constraint firstAttribute="height" constant="13" id="BmO-Rd-DKp"/>
</constraints>
</pageControl>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="wEc-R2-1Tv" firstAttribute="top" secondItem="HNY-h1-A95" secondAttribute="top" constant="4" id="56P-TX-Y1M"/>
<constraint firstItem="ppd-rW-dYo" firstAttribute="top" secondItem="wEc-R2-1Tv" secondAttribute="bottom" id="PPK-he-lFX">
<variation key="heightClass=compact" constant="-6"/>
</constraint>
<constraint firstItem="wEc-R2-1Tv" firstAttribute="centerX" secondItem="HNY-h1-A95" secondAttribute="centerX" id="cQo-a6-jlH"/>
<constraint firstAttribute="width" constant="128" id="htd-vx-Rfi">
<variation key="heightClass=compact-widthClass=compact" constant="112"/>
</constraint>
<constraint firstItem="ppd-rW-dYo" firstAttribute="centerX" secondItem="HNY-h1-A95" secondAttribute="centerX" id="yab-6h-4LX"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sUB-KS-dnn">
<rect key="frame" x="194" y="0.0" width="66" height="52"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fxK-Ae-ebd">
<rect key="frame" x="33" y="4" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vbY-p5-3bX">
<rect key="frame" x="33" y="4" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
</userDefinedRuntimeAttributes>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7dx-1W-LWs">
<rect key="frame" x="33" y="11" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="12"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="fxK-Ae-ebd" firstAttribute="top" secondItem="vbY-p5-3bX" secondAttribute="top" id="0D2-Df-CBg"/>
<constraint firstItem="vbY-p5-3bX" firstAttribute="centerX" secondItem="sUB-KS-dnn" secondAttribute="centerX" priority="750" id="5d9-Lu-0Cm"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="vbY-p5-3bX" secondAttribute="trailing" priority="800" id="8nO-wt-deB"/>
<constraint firstItem="fxK-Ae-ebd" firstAttribute="centerX" secondItem="sUB-KS-dnn" secondAttribute="centerX" priority="750" id="O2N-5H-j6e"/>
<constraint firstItem="vbY-p5-3bX" firstAttribute="top" secondItem="sUB-KS-dnn" secondAttribute="top" constant="4" id="afW-J0-gsi"/>
<constraint firstItem="7dx-1W-LWs" firstAttribute="centerX" secondItem="sUB-KS-dnn" secondAttribute="centerX" id="loT-82-20Y"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="fxK-Ae-ebd" secondAttribute="trailing" priority="800" id="qlE-z0-Q0A"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Q0w-Me-x4p">
<rect key="frame" x="0.0" y="48" width="320" height="4"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="JiD-R1-DnS">
<rect key="frame" x="0.0" y="0.0" width="0.0" height="4"/>
<color key="backgroundColor" red="0.1176470588" green="0.58823529409999997" blue="0.94117647059999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" id="vxl-iA-p8N"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="linkBlue"/>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.12" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="JiD-R1-DnS" secondAttribute="bottom" id="91c-nx-vVB"/>
<constraint firstAttribute="height" constant="4" id="DSq-vZ-frm"/>
<constraint firstItem="JiD-R1-DnS" firstAttribute="top" secondItem="Q0w-Me-x4p" secondAttribute="top" id="Dwi-Ld-Q1A"/>
<constraint firstItem="JiD-R1-DnS" firstAttribute="leading" secondItem="Q0w-Me-x4p" secondAttribute="leading" id="eon-hA-hQn"/>
</constraints>
</view>
<button contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="UPO-sh-VhS" userLabel="ToggleInfo">
<rect key="frame" x="0.0" y="0.0" width="260" height="52"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<action selector="toggleInfoAction" destination="9fq-65-qd9" eventType="touchUpInside" id="h7P-d8-FJM"/>
</connections>
</button>
<button opaque="NO" contentMode="center" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="XwA-oz-M3Q" customClass="MWMButton">
<rect key="frame" x="260" y="0.0" width="60" height="52"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="menuButton"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="2B5-kg-8KQ"/>
</constraints>
<state key="normal" image="ic_menu"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="coloringName" value="MWMBlack"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="extendAction" destination="9fq-65-qd9" eventType="touchUpInside" id="uAL-Qn-4ne"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="QLk-JN-wfO" secondAttribute="bottom" id="0AT-pb-GFy"/>
<constraint firstItem="QLk-JN-wfO" firstAttribute="leading" secondItem="u7O-n6-ZXy" secondAttribute="leading" id="0hr-A3-h7F">
<variation key="heightClass=compact" constant="16"/>
<variation key="heightClass=regular-widthClass=regular" constant="16"/>
</constraint>
<constraint firstItem="UPO-sh-VhS" firstAttribute="top" secondItem="u7O-n6-ZXy" secondAttribute="top" id="2Y4-nO-oxo"/>
<constraint firstItem="XwA-oz-M3Q" firstAttribute="top" secondItem="u7O-n6-ZXy" secondAttribute="top" id="5lH-DU-U8t"/>
<constraint firstItem="QLk-JN-wfO" firstAttribute="top" secondItem="u7O-n6-ZXy" secondAttribute="top" id="68j-wb-JVW"/>
<constraint firstAttribute="bottom" secondItem="sUB-KS-dnn" secondAttribute="bottom" id="6n2-89-jZF"/>
<constraint firstItem="sUB-KS-dnn" firstAttribute="width" secondItem="QLk-JN-wfO" secondAttribute="width" id="7xg-vu-wVh"/>
<constraint firstAttribute="trailing" secondItem="Q0w-Me-x4p" secondAttribute="trailing" id="Ljf-W6-hhb"/>
<constraint firstItem="HNY-h1-A95" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="QLk-JN-wfO" secondAttribute="trailing" id="Mog-4d-Hi5"/>
<constraint firstAttribute="trailing" secondItem="XwA-oz-M3Q" secondAttribute="trailing" id="QZv-2x-d1t"/>
<constraint firstAttribute="bottom" secondItem="XwA-oz-M3Q" secondAttribute="bottom" id="UJh-uZ-ODO"/>
<constraint firstItem="sUB-KS-dnn" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="HNY-h1-A95" secondAttribute="trailing" id="Uh8-ST-KVx"/>
<constraint firstAttribute="bottom" secondItem="HNY-h1-A95" secondAttribute="bottom" id="XWQ-fY-sAs"/>
<constraint firstItem="XwA-oz-M3Q" firstAttribute="leading" secondItem="sUB-KS-dnn" secondAttribute="trailing" id="ZvS-46-HNH">
<variation key="heightClass=compact" constant="16"/>
<variation key="heightClass=regular-widthClass=regular" constant="16"/>
</constraint>
<constraint firstItem="HNY-h1-A95" firstAttribute="centerX" secondItem="u7O-n6-ZXy" secondAttribute="centerX" priority="700" id="dnJ-0H-Kj4"/>
<constraint firstItem="wgS-eK-vfD" firstAttribute="centerY" secondItem="ppd-rW-dYo" secondAttribute="centerY" priority="500" id="eEB-zX-D6C"/>
<constraint firstItem="7dx-1W-LWs" firstAttribute="centerY" secondItem="ppd-rW-dYo" secondAttribute="centerY" priority="500" id="eEw-8m-1R6"/>
<constraint firstAttribute="height" constant="52" id="gKx-sK-cYM">
<variation key="heightClass=compact" constant="40"/>
<variation key="heightClass=regular-widthClass=regular" constant="56"/>
</constraint>
<constraint firstAttribute="bottom" secondItem="UPO-sh-VhS" secondAttribute="bottom" id="gcG-aR-OyZ"/>
<constraint firstItem="Q0w-Me-x4p" firstAttribute="leading" secondItem="u7O-n6-ZXy" secondAttribute="leading" id="m3u-NJ-pQ3"/>
<constraint firstItem="sUB-KS-dnn" firstAttribute="top" secondItem="u7O-n6-ZXy" secondAttribute="top" id="sdn-AJ-ItP"/>
<constraint firstAttribute="bottom" secondItem="Q0w-Me-x4p" secondAttribute="bottom" id="sl4-ja-PfO"/>
<constraint firstItem="HNY-h1-A95" firstAttribute="top" secondItem="u7O-n6-ZXy" secondAttribute="top" id="t19-k5-MzQ"/>
<constraint firstItem="UPO-sh-VhS" firstAttribute="leading" secondItem="u7O-n6-ZXy" secondAttribute="leading" id="tlC-se-vPa"/>
<constraint firstItem="XwA-oz-M3Q" firstAttribute="leading" secondItem="UPO-sh-VhS" secondAttribute="trailing" id="viH-dq-rwd"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
</view>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="CMT-MI-d8X">
<rect key="frame" x="0.0" y="52" width="320" height="64"/>
<subviews>
<button opaque="NO" contentMode="center" horizontalHuggingPriority="249" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Bfb-5v-iWA" customClass="MWMButton">
<rect key="frame" x="8" y="0.0" width="57" height="64"/>
<state key="normal" image="ic_voice_on"/>
<state key="selected" image="ic_voice_off"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="coloringName" value="MWMBlack"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="ttsButtonAction" destination="-1" eventType="touchUpInside" id="2U8-vo-LOQ"/>
</connections>
</button>
<button opaque="NO" contentMode="center" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eaa-f0-INU" userLabel="Traffic" customClass="MWMButton">
<rect key="frame" x="73" y="0.0" width="58" height="64"/>
<state key="normal" image="ic_setting_traffic_on"/>
<state key="selected" image="ic_setting_traffic_off"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="coloringName" value="MWMBlack"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="trafficButtonAction" destination="-1" eventType="touchUpInside" id="ZI3-1D-OeH"/>
</connections>
</button>
<button opaque="NO" contentMode="center" horizontalHuggingPriority="249" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="skM-Xx-3En" userLabel="Settings" customClass="MWMButton">
<rect key="frame" x="139" y="0.0" width="57" height="64"/>
<state key="normal" image="ic_menu_settings"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="coloringName" value="MWMBlack"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="settingsButtonAction" destination="-1" eventType="touchUpInside" id="m7v-S7-aqm"/>
</connections>
</button>
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mtt-q0-SUx" customClass="MWMStopButton">
<rect key="frame" x="204" y="14" width="96" height="36"/>
<color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="96" id="N0o-f3-nuw"/>
<constraint firstAttribute="height" priority="750" constant="36" id="Pfs-0w-XX9"/>
</constraints>
<state key="normal" title="STOP">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="8"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="current_location_unknown_stop_button"/>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="whitePrimaryText"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="buttonRed"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="buttonRedHighlighted"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="stopRoutingButtonAction" destination="-1" eventType="touchUpInside" id="Xvf-fv-3GR"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="eaa-f0-INU" firstAttribute="top" secondItem="CMT-MI-d8X" secondAttribute="top" id="2ZI-jO-Rzb"/>
<constraint firstAttribute="bottom" secondItem="skM-Xx-3En" secondAttribute="bottom" id="3mJ-M7-QYs"/>
<constraint firstItem="eaa-f0-INU" firstAttribute="leading" secondItem="Bfb-5v-iWA" secondAttribute="trailing" constant="8" id="5ar-52-BSS"/>
<constraint firstItem="skM-Xx-3En" firstAttribute="top" secondItem="CMT-MI-d8X" secondAttribute="top" id="I7f-Pc-SUr"/>
<constraint firstItem="mtt-q0-SUx" firstAttribute="top" secondItem="CMT-MI-d8X" secondAttribute="top" priority="750" constant="14" id="L5z-8y-Duk"/>
<constraint firstAttribute="height" constant="64" id="LaX-SD-Kzr"/>
<constraint firstItem="Bfb-5v-iWA" firstAttribute="leading" secondItem="CMT-MI-d8X" secondAttribute="leading" constant="8" id="V74-6u-Ohx"/>
<constraint firstItem="eaa-f0-INU" firstAttribute="width" secondItem="Bfb-5v-iWA" secondAttribute="width" id="Wit-m1-Qhu"/>
<constraint firstItem="Bfb-5v-iWA" firstAttribute="top" secondItem="CMT-MI-d8X" secondAttribute="top" id="hZJ-Ek-eep"/>
<constraint firstAttribute="trailing" secondItem="mtt-q0-SUx" secondAttribute="trailing" constant="20" id="huM-XX-MM9"/>
<constraint firstAttribute="bottom" secondItem="Bfb-5v-iWA" secondAttribute="bottom" id="jWC-0W-pIV"/>
<constraint firstItem="eaa-f0-INU" firstAttribute="width" secondItem="skM-Xx-3En" secondAttribute="width" id="jg9-YP-GwC"/>
<constraint firstAttribute="bottom" secondItem="eaa-f0-INU" secondAttribute="bottom" id="mO5-Wj-UYu"/>
<constraint firstItem="skM-Xx-3En" firstAttribute="leading" secondItem="eaa-f0-INU" secondAttribute="trailing" constant="8" id="nCN-ow-4GR"/>
<constraint firstItem="mtt-q0-SUx" firstAttribute="leading" secondItem="skM-Xx-3En" secondAttribute="trailing" constant="8" id="rTu-89-tgS"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="u7O-n6-ZXy" secondAttribute="trailing" id="2zR-Xc-sbx"/>
<constraint firstItem="u7O-n6-ZXy" firstAttribute="top" secondItem="9fq-65-qd9" secondAttribute="top" id="Qaw-S4-hJf"/>
<constraint firstAttribute="bottom" secondItem="CMT-MI-d8X" secondAttribute="bottom" id="QmH-op-EWM"/>
<constraint firstItem="CMT-MI-d8X" firstAttribute="top" secondItem="u7O-n6-ZXy" secondAttribute="bottom" id="SaY-tH-rNS"/>
<constraint firstAttribute="trailing" secondItem="CMT-MI-d8X" secondAttribute="trailing" id="Y3v-mx-s41"/>
<constraint firstItem="u7O-n6-ZXy" firstAttribute="leading" secondItem="9fq-65-qd9" secondAttribute="leading" id="myS-vi-80i"/>
<constraint firstItem="CMT-MI-d8X" firstAttribute="leading" secondItem="9fq-65-qd9" secondAttribute="leading" id="rEB-5o-z8o"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<nil key="simulatedTopBarMetrics"/>
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="distanceLabel" destination="vbY-p5-3bX" id="uxW-PA-dra"/>
<outlet property="distanceLegendLabel" destination="7dx-1W-LWs" id="Kmh-8u-jgj"/>
<outlet property="distanceWithLegendLabel" destination="fxK-Ae-ebd" id="qhH-AB-nFm"/>
<outlet property="extendButton" destination="XwA-oz-M3Q" id="76Y-Qw-uPC"/>
<outlet property="progressView" destination="Q0w-Me-x4p" id="efq-ve-QAZ"/>
<outlet property="routingProgress" destination="vxl-iA-p8N" id="gw7-Pn-5m7"/>
<outlet property="speedLabel" destination="b3M-75-5HW" id="bLg-uX-05a"/>
<outlet property="speedLegendLabel" destination="wgS-eK-vfD" id="ZOP-Ro-KbD"/>
<outlet property="speedWithLegendLabel" destination="LY7-dx-CtV" id="tK9-Em-ztB"/>
<outlet property="timeLabel" destination="wEc-R2-1Tv" id="cfd-vS-d1G"/>
<outlet property="timePageControl" destination="ppd-rW-dYo" id="U1U-6U-JjR"/>
<outlet property="trafficButton" destination="eaa-f0-INU" id="nyl-Nf-A4Z"/>
<outlet property="ttsButton" destination="Bfb-5v-iWA" id="GMb-ft-G6X"/>
</connections>
<point key="canvasLocation" x="34" y="53.5"/>
</view>
</objects>
<resources>
<image name="ic_menu" width="48" height="48"/>
<image name="ic_menu_settings" width="28" height="28"/>
<image name="ic_setting_traffic_off" width="24" height="24"/>
<image name="ic_setting_traffic_on" width="24" height="24"/>
<image name="ic_voice_off" width="28" height="28"/>
<image name="ic_voice_on" width="28" height="28"/>
</resources>
</document>

View file

@ -1,21 +1,19 @@
#import "MWMCircularProgress.h"
#import "MWMNavigationDashboardInfoProtocol.h"
#import "MWMNavigationView.h"
#import "MWMCircularProgressState.h"
@class MWMNavigationDashboardEntity;
@class MWMNavigationDashboardManager;
@class MWMTaxiCollectionView;
@interface MWMRoutePreview : MWMNavigationView<MWMNavigationDashboardInfoProtocol>
@interface MWMRoutePreview : UIView
@property(weak, nonatomic, readonly) IBOutlet MWMTaxiCollectionView * taxiCollectionView;
@property(weak, nonatomic) MWMNavigationDashboardManager * dashboardManager;
- (void)addToView:(UIView *)superview;
- (void)remove;
- (void)statePrepare;
- (void)stateError;
- (void)stateReady;
- (void)selectRouter:(MWMRouterType)routerType;
- (void)router:(MWMRouterType)routerType setState:(MWMCircularProgressState)state;
- (void)router:(MWMRouterType)routerType setProgress:(CGFloat)progress;
- (CGRect)defaultFrame;
@end

View file

@ -2,6 +2,7 @@
#import "MWMCircularProgress.h"
#import "MWMCommon.h"
#import "MWMLocationManager.h"
#import "MWMNavigationDashboardEntity.h"
#import "MWMNavigationDashboardManager.h"
#import "MWMRouter.h"
#import "MWMTaxiPreviewDataSource.h"
@ -12,41 +13,15 @@
#include "platform/platform.hpp"
namespace
{
CGFloat constexpr kAdditionalHeight = 20.;
} // namespace
@interface MWMRoutePreview ()<MWMCircularProgressProtocol>
@property(nonatomic) BOOL isVisible;
@property(weak, nonatomic) IBOutlet UIButton * backButton;
@property(weak, nonatomic) IBOutlet UIView * pedestrian;
@property(weak, nonatomic) IBOutlet UIView * vehicle;
@property(weak, nonatomic) IBOutlet UIView * bicycle;
@property(weak, nonatomic) IBOutlet UIView * contentView;
@property(weak, nonatomic) IBOutlet UIView * pedestrian;
@property(weak, nonatomic) IBOutlet UIView * taxi;
@property(weak, nonatomic) IBOutlet UIButton * goButton;
@property(weak, nonatomic) IBOutlet UIView * statusBox;
@property(weak, nonatomic) IBOutlet UIView * planningBox;
@property(weak, nonatomic) IBOutlet UIView * resultsBox;
@property(weak, nonatomic) IBOutlet UIView * heightBox;
@property(weak, nonatomic) IBOutlet UIView * taxiBox;
@property(weak, nonatomic) IBOutlet UIView * errorBox;
@property(weak, nonatomic) IBOutlet UILabel * errorLabel;
@property(weak, nonatomic) IBOutlet UILabel * resultLabel;
@property(weak, nonatomic) IBOutlet UILabel * arriveLabel;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * statusBoxHeight;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * resultsBoxHeight;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * heightBoxHeight;
@property(weak, nonatomic) IBOutlet UIImageView * heightProfileImage;
@property(weak, nonatomic) IBOutlet UIView * heightProfileElevation;
@property(weak, nonatomic) IBOutlet UIImageView * elevationImage;
@property(weak, nonatomic) IBOutlet UILabel * elevationHeight;
@property(weak, nonatomic) IBOutlet MWMTaxiCollectionView * taxiCollectionView;
@property(nonatomic) UIImageView * movingCellImage;
@property(nonatomic) BOOL isNeedToMove;
@property(nonatomic) NSIndexPath * indexPathOfMovingCell;
@property(weak, nonatomic) IBOutlet UIView * vehicle;
@end
@ -58,14 +33,10 @@ CGFloat constexpr kAdditionalHeight = 20.;
- (void)awakeFromNib
{
[super awakeFromNib];
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = UIScreen.mainScreen.scale;
[self setupProgresses];
[self.backButton matchInterfaceOrientation];
self.elevationImage.mwm_coloring = MWMImageColoringBlue;
}
- (void)setupProgresses
@ -101,117 +72,15 @@ CGFloat constexpr kAdditionalHeight = 20.;
m_progresses[routerType] = progress;
}
- (void)didMoveToSuperview { [self setupActualHeight]; }
- (void)statePrepare
{
[[MWMNavigationDashboardManager manager] updateStartButtonTitle:self.goButton];
for (auto const & progress : m_progresses)
progress.second.state = MWMCircularProgressStateNormal;
self.goButton.hidden = NO;
self.goButton.enabled = NO;
[self setupActualHeight];
self.statusBox.hidden = YES;
self.resultsBox.hidden = YES;
self.heightBox.hidden = YES;
self.heightProfileElevation.hidden = YES;
self.planningBox.hidden = YES;
self.errorBox.hidden = YES;
self.taxiBox.hidden = YES;
if (!MWMLocationManager.lastLocation || !Platform::IsConnected())
[self.taxi removeFromSuperview];
}
- (void)stateError
{
[[MWMNavigationDashboardManager manager] updateStartButtonTitle:self.goButton];
self.goButton.hidden = NO;
self.goButton.enabled = NO;
self.statusBox.hidden = NO;
self.planningBox.hidden = YES;
self.resultsBox.hidden = YES;
self.heightBox.hidden = YES;
self.taxiBox.hidden = YES;
self.heightProfileElevation.hidden = YES;
self.errorBox.hidden = NO;
if (IPAD)
[self iPadNotReady];
}
- (void)stateReady
{
[[MWMNavigationDashboardManager manager] updateStartButtonTitle:self.goButton];
self.goButton.hidden = NO;
self.goButton.enabled = YES;
self.statusBox.hidden = NO;
self.planningBox.hidden = YES;
self.errorBox.hidden = YES;
self.resultsBox.hidden = NO;
BOOL const hasAltitude = [MWMRouter hasRouteAltitude];
self.heightBox.hidden = !hasAltitude;
self.heightProfileElevation.hidden = !hasAltitude;
if (IPAD)
[self iPadReady];
}
- (void)iPadReady
{
[self layoutIfNeeded];
if ([MWMRouter isTaxi])
{
self.statusBoxHeight.constant = self.taxiBox.height;
self.taxiBox.hidden = NO;
}
else
{
self.statusBoxHeight.constant =
self.resultsBoxHeight.constant +
([MWMRouter hasRouteAltitude] ? self.heightBoxHeight.constant : 0);
[UIView animateWithDuration:kDefaultAnimationDuration animations:^
{
[self layoutIfNeeded];
}
completion:^(BOOL finished)
{
[UIView animateWithDuration:kDefaultAnimationDuration animations:^
{
self.arriveLabel.alpha = 1.;
}
completion:^(BOOL finished)
{
[self updateHeightProfile];
}];
}];
}
}
- (void)updateHeightProfile
{
if (![MWMRouter hasRouteAltitude])
return;
dispatch_async(dispatch_get_main_queue(), ^{
[MWMRouter routeAltitudeImageForSize:self.heightProfileImage.frame.size
completion:^(UIImage * image, NSString * altitudeElevation) {
self.heightProfileImage.image = image;
self.elevationHeight.text = altitudeElevation;
}];
});
}
- (void)iPadNotReady
{
self.taxiBox.hidden = YES;
self.errorLabel.text = [MWMRouter isTaxi] ? L(@"taxi_not_found") : L(@"routing_planning_error");
self.arriveLabel.alpha = 0.;
[self layoutIfNeeded];
self.statusBoxHeight.constant = self.resultsBoxHeight.constant;
[UIView animateWithDuration:kDefaultAnimationDuration
animations:^{
[self layoutIfNeeded];
}];
}
- (void)selectRouter:(MWMRouterType)routerType
{
for (auto const & progress : m_progresses)
@ -219,13 +88,6 @@ CGFloat constexpr kAdditionalHeight = 20.;
m_progresses[routerType].state = MWMCircularProgressStateSelected;
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self setupActualHeight];
[self.delegate routePreviewDidChangeFrame:self.frame];
}
- (void)router:(MWMRouterType)routerType setState:(MWMCircularProgressState)state
{
m_progresses[routerType].state = state;
@ -254,96 +116,51 @@ CGFloat constexpr kAdditionalHeight = 20.;
[self selectRouter:routerType];
[MWMRouter setType:routerType];
[MWMRouter rebuildWithBestRouter:NO];
NSString * routerTypeString = nil;
switch (routerType)
{
case MWMRouterTypeVehicle:
[Statistics logEvent:kStatPointToPoint
withParameters:@{kStatAction : kStatChangeRoutingMode, kStatValue : kStatVehicle}];
break;
case MWMRouterTypePedestrian:
[Statistics logEvent:kStatPointToPoint
withParameters:@{kStatAction : kStatChangeRoutingMode, kStatValue : kStatPedestrian}];
break;
case MWMRouterTypeBicycle:
[Statistics logEvent:kStatPointToPoint
withParameters:@{kStatAction : kStatChangeRoutingMode, kStatValue : kStatBicycle}];
break;
case MWMRouterTypeTaxi:
[Statistics logEvent:kStatPointToPoint
withParameters:@{kStatAction : kStatChangeRoutingMode, kStatValue : kStatTaxi}];
break;
case MWMRouterTypeVehicle: routerTypeString = kStatVehicle; break;
case MWMRouterTypePedestrian: routerTypeString = kStatPedestrian; break;
case MWMRouterTypeBicycle: routerTypeString = kStatBicycle; break;
case MWMRouterTypeTaxi: routerTypeString = kStatTaxi; break;
}
[Statistics logEvent:kStatPointToPoint
withParameters:@{kStatAction : kStatChangeRoutingMode, kStatValue : routerTypeString}];
}
}
- (void)addToView:(UIView *)superview
{
NSAssert(superview != nil, @"Superview can't be nil");
if ([superview.subviews containsObject:self])
return;
[superview addSubview:self];
self.frame = self.defaultFrame;
self.isVisible = YES;
}
- (void)remove { self.isVisible = NO; }
- (void)layoutSubviews
{
[UIView animateWithDuration:kDefaultAnimationDuration
animations:^{
if (!CGRectEqualToRect(self.frame, self.defaultFrame))
self.frame = self.defaultFrame;
}
completion:^(BOOL finished) {
if (!self.isVisible)
[self removeFromSuperview];
}];
[super layoutSubviews];
}
#pragma mark - Properties
- (CGRect)defaultFrame
- (CGRect)defaultFrame { return CGRectNull; }
- (void)setIsVisible:(BOOL)isVisible
{
if (!IPAD)
return super.defaultFrame;
CGFloat const width = 320.;
CGFloat const origin = self.isVisible ? 0. : -width;
return {{origin, self.topBound}, {width, self.superview.height - kAdditionalHeight}};
}
- (void)setupActualHeight
{
if (!self.superview)
return;
CGFloat const selfHeight = IPAD ? self.superview.height - kAdditionalHeight : 44;
self.defaultHeight = selfHeight;
self.height = selfHeight;
}
#pragma mark - MWMNavigationDashboardInfoProtocol
- (void)updateNavigationInfo:(MWMNavigationDashboardEntity *)info
{
self.resultLabel.attributedText = info.estimate;
if (!IPAD)
return;
NSString * arriveStr = [NSDateFormatter
localizedStringFromDate:[[NSDate date] dateByAddingTimeInterval:info.timeToTarget]
dateStyle:NSDateFormatterNoStyle
timeStyle:NSDateFormatterShortStyle];
self.arriveLabel.text = [NSString stringWithFormat:L(@"routing_arrive"), arriveStr.UTF8String];
}
#pragma mark - AvailableArea / VisibleArea
- (MWMAvailableAreaAffectDirections)visibleAreaAffectDirections
{
return IPAD ? MWMAvailableAreaAffectDirectionsLeft : MWMAvailableAreaAffectDirectionsTop;
}
#pragma mark - AvailableArea / PlacePageArea
- (MWMAvailableAreaAffectDirections)placePageAreaAffectDirections
{
return IPAD ? MWMAvailableAreaAffectDirectionsLeft : MWMAvailableAreaAffectDirectionsNone;
}
#pragma mark - AvailableArea / WidgetsArea
- (MWMAvailableAreaAffectDirections)widgetsAreaAffectDirections
{
return IPAD ? MWMAvailableAreaAffectDirectionsLeft : MWMAvailableAreaAffectDirectionsNone;
}
#pragma mark - AvailableArea / SideButtonsArea
- (MWMAvailableAreaAffectDirections)sideButtonsAreaAffectDirections
{
return IPAD ? MWMAvailableAreaAffectDirectionsLeft : MWMAvailableAreaAffectDirectionsTop;
}
#pragma mark - AvailableArea / TrafficButtonArea
- (MWMAvailableAreaAffectDirections)trafficButtonAreaAffectDirections
{
return IPAD ? MWMAvailableAreaAffectDirectionsLeft : MWMAvailableAreaAffectDirectionsTop;
_isVisible = isVisible;
[self setNeedsLayout];
}
@end

View file

@ -1,128 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MWMNavigationDashboardManager">
<connections>
<outlet property="routePreview" destination="aNH-vh-DPz" id="ORz-pz-7sV"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="aNH-vh-DPz" customClass="MWMRoutePreview">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WqK-Yb-PmP" customClass="SolidTouchView">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wpf-tw-Coz" userLabel="Back">
<rect key="frame" x="0.0" y="0.0" width="44" height="44"/>
<accessibility key="accessibilityConfiguration" identifier="goBackButton"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="ELC-D6-uQM"/>
<constraint firstAttribute="width" constant="44" id="e40-iL-uvR"/>
</constraints>
<state key="normal" image="ic_nav_bar_back"/>
<connections>
<action selector="routingStopTouchUpInside" destination="-1" eventType="touchUpInside" id="Gvl-qB-zAN"/>
</connections>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oQc-l8-sZH" userLabel="Buttons Box">
<rect key="frame" x="54" y="0.0" width="212" height="44"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cZF-Ha-2tB">
<rect key="frame" x="6" y="3" width="38" height="38"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="routeAuto"/>
<constraints>
<constraint firstAttribute="width" constant="38" id="m6k-uU-yOl"/>
<constraint firstAttribute="height" constant="38" id="mp7-b4-xot"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FuO-c6-y9C" userLabel="Bicycle">
<rect key="frame" x="60" y="3" width="38" height="38"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="routeBicycle"/>
<constraints>
<constraint firstAttribute="width" constant="38" id="9fe-fw-05J"/>
<constraint firstAttribute="height" constant="38" id="gbm-NL-zgv"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6D3-QF-6wm">
<rect key="frame" x="114" y="3" width="38" height="38"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<accessibility key="accessibilityConfiguration" identifier="routePedestrian"/>
<constraints>
<constraint firstAttribute="width" constant="38" id="815-LJ-2tk"/>
<constraint firstAttribute="height" constant="38" id="hXi-E7-GUb"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="15Q-ZN-NzE" userLabel="Taxi">
<rect key="frame" x="168" y="3" width="38" height="38"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<accessibility key="accessibilityConfiguration" identifier="routeTaxi"/>
<constraints>
<constraint firstAttribute="width" constant="38" id="ibp-pJ-TuK"/>
<constraint firstAttribute="height" constant="38" id="zPC-M0-Jo1"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="FuO-c6-y9C" firstAttribute="centerY" secondItem="oQc-l8-sZH" secondAttribute="centerY" id="1De-4s-V8t"/>
<constraint firstItem="6D3-QF-6wm" firstAttribute="leading" secondItem="FuO-c6-y9C" secondAttribute="trailing" constant="16" id="91z-iC-oKp"/>
<constraint firstItem="cZF-Ha-2tB" firstAttribute="centerY" secondItem="oQc-l8-sZH" secondAttribute="centerY" id="MQh-op-cpN"/>
<constraint firstItem="cZF-Ha-2tB" firstAttribute="leading" secondItem="oQc-l8-sZH" secondAttribute="leading" constant="6" id="MjU-UA-Kax"/>
<constraint firstAttribute="height" constant="44" id="Mws-KZ-ghs"/>
<constraint firstItem="15Q-ZN-NzE" firstAttribute="leading" secondItem="6D3-QF-6wm" secondAttribute="trailing" constant="16" id="Td5-UQ-kzj"/>
<constraint firstAttribute="trailing" secondItem="15Q-ZN-NzE" secondAttribute="trailing" constant="6" id="WHK-N0-dCc"/>
<constraint firstItem="FuO-c6-y9C" firstAttribute="leading" secondItem="cZF-Ha-2tB" secondAttribute="trailing" constant="16" id="Z6M-UV-6x2"/>
<constraint firstItem="6D3-QF-6wm" firstAttribute="centerY" secondItem="oQc-l8-sZH" secondAttribute="centerY" id="vXO-6g-q4L"/>
<constraint firstAttribute="trailing" secondItem="6D3-QF-6wm" secondAttribute="trailing" priority="750" constant="6" id="zmG-EZ-8Wk"/>
<constraint firstItem="15Q-ZN-NzE" firstAttribute="centerY" secondItem="oQc-l8-sZH" secondAttribute="centerY" id="zvc-uG-Izm"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="0.12156862745098039" green="0.59999999999999998" blue="0.32156862745098036" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="2SX-TZ-tS3"/>
<constraint firstItem="oQc-l8-sZH" firstAttribute="centerY" secondItem="wpf-tw-Coz" secondAttribute="centerY" id="NwC-Dq-AAM"/>
<constraint firstItem="wpf-tw-Coz" firstAttribute="leading" secondItem="WqK-Yb-PmP" secondAttribute="leading" id="bK5-4Q-Rv9"/>
<constraint firstItem="wpf-tw-Coz" firstAttribute="top" secondItem="WqK-Yb-PmP" secondAttribute="top" id="cPc-fO-vAa"/>
<constraint firstItem="oQc-l8-sZH" firstAttribute="centerX" secondItem="WqK-Yb-PmP" secondAttribute="centerX" id="ltA-tm-z3P"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="primary"/>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="WqK-Yb-PmP" secondAttribute="trailing" id="hui-oa-rbV"/>
<constraint firstItem="WqK-Yb-PmP" firstAttribute="leading" secondItem="aNH-vh-DPz" secondAttribute="leading" id="rQB-KG-9Kg"/>
<constraint firstItem="WqK-Yb-PmP" firstAttribute="top" secondItem="aNH-vh-DPz" secondAttribute="top" id="u9l-Q9-28D"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="backButton" destination="wpf-tw-Coz" id="9nj-K5-pOR"/>
<outlet property="bicycle" destination="FuO-c6-y9C" id="UR2-pF-Amb"/>
<outlet property="contentView" destination="WqK-Yb-PmP" id="4ph-Dm-EFr"/>
<outlet property="pedestrian" destination="6D3-QF-6wm" id="bdh-zx-9LW"/>
<outlet property="taxi" destination="15Q-ZN-NzE" id="RaD-7N-ZE2"/>
<outlet property="vehicle" destination="cZF-Ha-2tB" id="QP3-tU-nfO"/>
</connections>
<point key="canvasLocation" x="448" y="341"/>
</view>
</objects>
<resources>
<image name="ic_nav_bar_back" width="14" height="22"/>
</resources>
</document>

View file

@ -0,0 +1,5 @@
typedef NS_ENUM(NSInteger, MWMRoutePreviewTaxiCellType) {
MWMRoutePreviewTaxiCellTypeTaxi,
MWMRoutePreviewTaxiCellTypeUber,
MWMRoutePreviewTaxiCellTypeYandex
};

View file

@ -1,4 +1,4 @@
#import "SwiftBridge.h"
#import "MWMRoutePreviewTaxiCellType.h"
@class MWMRoutePoint;

View file

@ -1,14 +1,16 @@
#import "MWMTaxiPreviewDataSource.h"
#import "MWMCommon.h"
#import "MWMNetworkPolicy.h"
#import "MWMRoutePoint.h"
#import "Statistics.h"
#import "SwiftBridge.h"
#include "Framework.h"
#include "geometry/mercator.hpp"
#include "partners_api/taxi_provider.hpp"
#include "geometry/mercator.hpp"
@interface MWMTaxiCollectionView ()
@property(nonatomic) UIPageControl * pageControl;

View file

@ -0,0 +1,5 @@
#import "MWMRoutePreview.h"
@interface MWMiPadRoutePreview : MWMRoutePreview
@end

View file

@ -0,0 +1,67 @@
#import "MWMiPadRoutePreview.h"
#import "MWMRouter.h"
#import "SwiftBridge.h"
@interface MWMRoutePreview ()
@property(nonatomic) BOOL isVisible;
@end
@implementation MWMiPadRoutePreview
- (CGRect)defaultFrame
{
CGFloat const width = 320;
return {{self.isVisible ? 0 : -width, 0}, {width, self.superview.height}};
}
#pragma mark - SolidTouchView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {}
#pragma mark - AvailableArea / VisibleArea
- (MWMAvailableAreaAffectDirections)visibleAreaAffectDirections
{
return MWMAvailableAreaAffectDirectionsLeft;
}
#pragma mark - AvailableArea / PlacePageArea
- (MWMAvailableAreaAffectDirections)placePageAreaAffectDirections
{
return MWMAvailableAreaAffectDirectionsLeft;
}
#pragma mark - AvailableArea / WidgetsArea
- (MWMAvailableAreaAffectDirections)widgetsAreaAffectDirections
{
return MWMAvailableAreaAffectDirectionsLeft;
}
#pragma mark - AvailableArea / SideButtonsArea
- (MWMAvailableAreaAffectDirections)sideButtonsAreaAffectDirections
{
return MWMAvailableAreaAffectDirectionsLeft;
}
#pragma mark - AvailableArea / TrafficButtonArea
- (MWMAvailableAreaAffectDirections)trafficButtonAreaAffectDirections
{
return MWMAvailableAreaAffectDirectionsLeft;
}
#pragma mark - AvailableArea / NavigationInfoArea
- (MWMAvailableAreaAffectDirections)navigationInfoAreaAffectDirections
{
return MWMAvailableAreaAffectDirectionsLeft;
}
@end

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
@ -17,16 +17,29 @@
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MWMNavigationDashboardManager">
<connections>
<outlet property="goButton" destination="4IJ-pR-Ztp" id="WdQ-Nn-rm4"/>
<outlet property="routePreview" destination="u2u-Vb-2eH" id="VZw-5q-2P6"/>
<outlet property="statusBox" destination="87p-Qg-8f3" id="dze-gL-fnK"/>
<outlet property="taxiCollectionView" destination="t6d-gI-JcN" id="b5y-vn-rwV"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="u2u-Vb-2eH" customClass="MWMRoutePreview">
<rect key="frame" x="0.0" y="0.0" width="320" height="655"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view contentMode="scaleToFill" id="u2u-Vb-2eH" customClass="MWMiPadRoutePreview">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3zr-me-gbI">
<rect key="frame" x="0.0" y="0.0" width="375" height="20"/>
<color key="backgroundColor" red="0.12156862745098039" green="0.59999999999999998" blue="0.32156862745098036" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="0AS-cy-xIW"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="primary"/>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3s2-BV-X5i" customClass="SolidTouchView">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="a4n-5I-PN3" userLabel="Back">
<rect key="frame" x="0.0" y="0.0" width="44" height="44"/>
@ -37,11 +50,11 @@
</constraints>
<state key="normal" image="ic_nav_bar_back"/>
<connections>
<action selector="routingStopTouchUpInside" destination="-1" eventType="touchUpInside" id="DWh-ls-fCL"/>
<action selector="stopRoutingButtonAction" destination="-1" eventType="touchUpInside" id="TRy-DB-zyD"/>
</connections>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sXu-tl-a0m" userLabel="Buttons Box">
<rect key="frame" x="48" y="0.0" width="224" height="44"/>
<rect key="frame" x="75.5" y="0.0" width="224" height="44"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jDl-pu-eov">
<rect key="frame" x="6" y="0.0" width="44" height="44"/>
@ -108,35 +121,14 @@
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="primary"/>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="87p-Qg-8f3" userLabel="Status Box">
<rect key="frame" x="0.0" y="80" width="320" height="64"/>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="87p-Qg-8f3" userLabel="Status Box" customClass="MWMRoutePreviewStatus">
<rect key="frame" x="0.0" y="100" width="375" height="132"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tdV-a8-fmG" userLabel="Planning Box">
<rect key="frame" x="0.0" y="0.0" width="320" height="64"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Planning..." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="14" translatesAutoresizingMaskIntoConstraints="NO" id="a7v-h1-j52">
<rect key="frame" x="120" y="22" width="80" height="20"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.26000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="p2p_planning"/>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackHintText"/>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="a7v-h1-j52" firstAttribute="centerX" secondItem="tdV-a8-fmG" secondAttribute="centerX" id="L9h-b7-iGd"/>
<constraint firstItem="a7v-h1-j52" firstAttribute="centerY" secondItem="tdV-a8-fmG" secondAttribute="centerY" id="PGc-Ph-A2k"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QEP-6s-YTM" userLabel="Error Box">
<rect key="frame" x="0.0" y="0.0" width="320" height="64"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="64"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Planning..." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="14" translatesAutoresizingMaskIntoConstraints="NO" id="VNi-4g-9gz" userLabel="Error">
<rect key="frame" x="120" y="22" width="80" height="20"/>
<rect key="frame" x="147.5" y="22" width="80" height="20"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
<color key="textColor" red="0.95686274510000002" green="0.26274509800000001" blue="0.21176470589999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
@ -149,15 +141,16 @@
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="64" id="DuS-FX-e47"/>
<constraint firstItem="VNi-4g-9gz" firstAttribute="centerY" secondItem="QEP-6s-YTM" secondAttribute="centerY" id="bfa-sc-ifi"/>
<constraint firstItem="VNi-4g-9gz" firstAttribute="centerX" secondItem="QEP-6s-YTM" secondAttribute="centerX" id="iKJ-3u-Al9"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Rqr-bu-crx" userLabel="Results Box">
<rect key="frame" x="0.0" y="0.0" width="320" height="64"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="64"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="results" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zml-eW-DsI">
<rect key="frame" x="16" y="14" width="234" height="20"/>
<rect key="frame" x="16" y="14" width="289" height="20"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.54000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
@ -167,7 +160,7 @@
</userDefinedRuntimeAttributes>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Arrive at 12:24" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="oec-Ee-6ha">
<rect key="frame" x="16" y="38" width="234" height="17"/>
<rect key="frame" x="16" y="38" width="289" height="17"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Medium" family="Helvetica Neue" pointSize="14"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.54000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
@ -176,8 +169,22 @@
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium14"/>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="oec-Ee-6ha" firstAttribute="leading" secondItem="zml-eW-DsI" secondAttribute="leading" id="Am2-25-Zn9"/>
<constraint firstItem="zml-eW-DsI" firstAttribute="leading" secondItem="Rqr-bu-crx" secondAttribute="leading" constant="16" id="QNo-az-LlD"/>
<constraint firstAttribute="height" constant="64" id="bHW-iR-rAA"/>
<constraint firstItem="zml-eW-DsI" firstAttribute="top" secondItem="Rqr-bu-crx" secondAttribute="top" constant="14" id="c1k-EY-nwQ"/>
<constraint firstItem="oec-Ee-6ha" firstAttribute="top" secondItem="zml-eW-DsI" secondAttribute="bottom" constant="4" id="lV9-S0-yy4"/>
<constraint firstItem="oec-Ee-6ha" firstAttribute="trailing" secondItem="zml-eW-DsI" secondAttribute="trailing" id="rfO-2Z-g12"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6iM-A6-4JK" userLabel="Height Box">
<rect key="frame" x="0.0" y="64" width="375" height="68"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rXP-rM-9cx">
<rect key="frame" x="254" y="18" width="50" height="12"/>
<rect key="frame" x="309" y="-46" width="50" height="12"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ic_elevation" translatesAutoresizingMaskIntoConstraints="NO" id="Ac5-gf-3tf">
<rect key="frame" x="0.0" y="0.0" width="10" height="12"/>
@ -185,6 +192,9 @@
<constraint firstAttribute="width" constant="10" id="R4J-Uu-52U"/>
<constraint firstAttribute="height" constant="12" id="v5V-2M-Fnx"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="coloring" value="MWMBlue"/>
</userDefinedRuntimeAttributes>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="260" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JtS-om-arD">
<rect key="frame" x="14" y="-2.5" width="36" height="17"/>
@ -207,28 +217,11 @@
<constraint firstItem="JtS-om-arD" firstAttribute="leading" secondItem="Ac5-gf-3tf" secondAttribute="trailing" constant="4" id="qQ6-yw-n2d"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="oec-Ee-6ha" firstAttribute="leading" secondItem="zml-eW-DsI" secondAttribute="leading" id="Am2-25-Zn9"/>
<constraint firstItem="rXP-rM-9cx" firstAttribute="leading" secondItem="zml-eW-DsI" secondAttribute="trailing" constant="4" id="BCS-il-tys"/>
<constraint firstItem="rXP-rM-9cx" firstAttribute="centerY" secondItem="zml-eW-DsI" secondAttribute="centerY" id="PEx-MA-POC"/>
<constraint firstItem="zml-eW-DsI" firstAttribute="leading" secondItem="Rqr-bu-crx" secondAttribute="leading" constant="16" id="QNo-az-LlD"/>
<constraint firstAttribute="height" constant="64" id="bHW-iR-rAA"/>
<constraint firstItem="zml-eW-DsI" firstAttribute="top" secondItem="Rqr-bu-crx" secondAttribute="top" constant="14" id="c1k-EY-nwQ"/>
<constraint firstItem="oec-Ee-6ha" firstAttribute="top" secondItem="zml-eW-DsI" secondAttribute="bottom" constant="4" id="lV9-S0-yy4"/>
<constraint firstItem="oec-Ee-6ha" firstAttribute="trailing" secondItem="zml-eW-DsI" secondAttribute="trailing" id="rfO-2Z-g12"/>
<constraint firstAttribute="trailing" secondItem="rXP-rM-9cx" secondAttribute="trailing" constant="16" id="xUV-qS-bQc"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6iM-A6-4JK" userLabel="Height Box">
<rect key="frame" x="0.0" y="64" width="320" height="68"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Apa-nH-KWJ">
<rect key="frame" x="16" y="14" width="288" height="40"/>
<rect key="frame" x="16" y="14" width="343" height="40"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="zhI-92-6JG">
<rect key="frame" x="0.0" y="0.0" width="288" height="40"/>
<rect key="frame" x="0.0" y="0.0" width="343" height="40"/>
</imageView>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
@ -250,14 +243,11 @@
</constraints>
</view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xAP-RW-zvp" userLabel="Taxi Box">
<rect key="frame" x="0.0" y="0.0" width="320" height="84"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="84"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" pagingEnabled="YES" dataMode="none" prefetchingEnabled="NO" translatesAutoresizingMaskIntoConstraints="NO" id="t6d-gI-JcN" customClass="MWMTaxiCollectionView">
<rect key="frame" x="0.0" y="0.0" width="320" height="84"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="84"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" constant="84" id="TGC-wp-JtU"/>
</constraints>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="9nw-pA-D89" customClass="MWMTaxiCollectionLayout">
<size key="itemSize" width="320" height="100"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
@ -281,24 +271,26 @@
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="tdV-a8-fmG" firstAttribute="leading" secondItem="Rqr-bu-crx" secondAttribute="leading" id="1s7-bh-347"/>
<constraint firstItem="xAP-RW-zvp" firstAttribute="top" secondItem="87p-Qg-8f3" secondAttribute="top" id="4Zu-Ow-GQe"/>
<constraint firstAttribute="height" constant="64" id="4qT-ha-p75"/>
<constraint firstItem="QEP-6s-YTM" firstAttribute="top" secondItem="Rqr-bu-crx" secondAttribute="top" id="7qG-zS-yqf"/>
<constraint firstItem="xAP-RW-zvp" firstAttribute="centerX" secondItem="87p-Qg-8f3" secondAttribute="centerX" id="BGb-OV-lAF"/>
<constraint firstItem="6iM-A6-4JK" firstAttribute="trailing" secondItem="Rqr-bu-crx" secondAttribute="trailing" id="BdC-p6-tnB"/>
<constraint firstAttribute="height" priority="100" constant="64" id="4qT-ha-p75"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="Rqr-bu-crx" secondAttribute="bottom" id="82W-n1-9wJ"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="xAP-RW-zvp" secondAttribute="bottom" id="CCT-23-3wk"/>
<constraint firstItem="Rqr-bu-crx" firstAttribute="leading" secondItem="87p-Qg-8f3" secondAttribute="leading" id="Fkj-U2-xyQ"/>
<constraint firstItem="xAP-RW-zvp" firstAttribute="width" secondItem="87p-Qg-8f3" secondAttribute="width" id="GaY-U1-jNg"/>
<constraint firstItem="6iM-A6-4JK" firstAttribute="leading" secondItem="Rqr-bu-crx" secondAttribute="leading" id="K40-dq-JmP"/>
<constraint firstItem="6iM-A6-4JK" firstAttribute="top" secondItem="Rqr-bu-crx" secondAttribute="bottom" id="HfZ-Ca-Mmj"/>
<constraint firstItem="QEP-6s-YTM" firstAttribute="top" secondItem="87p-Qg-8f3" secondAttribute="top" id="LrP-YM-0DL"/>
<constraint firstItem="xAP-RW-zvp" firstAttribute="leading" secondItem="87p-Qg-8f3" secondAttribute="leading" id="Lyf-8P-Jd6"/>
<constraint firstItem="Rqr-bu-crx" firstAttribute="top" secondItem="87p-Qg-8f3" secondAttribute="top" id="N7H-ZL-K7y"/>
<constraint firstAttribute="trailing" secondItem="Rqr-bu-crx" secondAttribute="trailing" id="QH4-pv-oKn"/>
<constraint firstItem="QEP-6s-YTM" firstAttribute="bottom" secondItem="Rqr-bu-crx" secondAttribute="bottom" id="SmI-QQ-bUn"/>
<constraint firstItem="QEP-6s-YTM" firstAttribute="trailing" secondItem="Rqr-bu-crx" secondAttribute="trailing" id="Ttu-kY-vjH"/>
<constraint firstItem="tdV-a8-fmG" firstAttribute="top" secondItem="Rqr-bu-crx" secondAttribute="top" id="axQ-FJ-jAM"/>
<constraint firstItem="tdV-a8-fmG" firstAttribute="bottom" secondItem="Rqr-bu-crx" secondAttribute="bottom" id="d05-rK-0iZ"/>
<constraint firstItem="tdV-a8-fmG" firstAttribute="trailing" secondItem="Rqr-bu-crx" secondAttribute="trailing" id="fP8-Fd-bYt"/>
<constraint firstItem="6iM-A6-4JK" firstAttribute="top" secondItem="Rqr-bu-crx" secondAttribute="bottom" id="gCd-UZ-my5"/>
<constraint firstItem="QEP-6s-YTM" firstAttribute="leading" secondItem="Rqr-bu-crx" secondAttribute="leading" id="tfA-kG-wTD"/>
<constraint firstAttribute="trailing" secondItem="QEP-6s-YTM" secondAttribute="trailing" id="QOg-C7-dgi"/>
<constraint firstItem="rXP-rM-9cx" firstAttribute="centerY" secondItem="zml-eW-DsI" secondAttribute="centerY" id="SAf-Qy-9uj"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="6iM-A6-4JK" secondAttribute="bottom" id="a6M-h3-DzB"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="QEP-6s-YTM" secondAttribute="bottom" id="c3U-eM-8ig"/>
<constraint firstItem="rXP-rM-9cx" firstAttribute="leading" secondItem="zml-eW-DsI" secondAttribute="trailing" constant="4" id="fqI-7g-oBJ"/>
<constraint firstAttribute="trailing" secondItem="xAP-RW-zvp" secondAttribute="trailing" id="hFn-i8-Do8"/>
<constraint firstAttribute="trailing" secondItem="6iM-A6-4JK" secondAttribute="trailing" id="kek-Gu-EN2"/>
<constraint firstItem="Rqr-bu-crx" firstAttribute="trailing" secondItem="rXP-rM-9cx" secondAttribute="trailing" constant="16" id="mHh-IV-b00"/>
<constraint firstItem="6iM-A6-4JK" firstAttribute="leading" secondItem="87p-Qg-8f3" secondAttribute="leading" id="oeU-OH-ezY"/>
<constraint firstItem="QEP-6s-YTM" firstAttribute="leading" secondItem="87p-Qg-8f3" secondAttribute="leading" id="x6v-27-R7O"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="layer.borderUIColor">
@ -309,12 +301,27 @@
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="arriveLabel" destination="oec-Ee-6ha" id="FLF-8X-PAf"/>
<outlet property="errorBox" destination="QEP-6s-YTM" id="cV6-hZ-IMv"/>
<outlet property="errorBoxBottom" destination="c3U-eM-8ig" id="oyN-uq-qC5"/>
<outlet property="errorLabel" destination="VNi-4g-9gz" id="BPc-Ib-vTt"/>
<outlet property="heightBox" destination="6iM-A6-4JK" id="pYC-Jp-UQT"/>
<outlet property="heightBoxBottom" destination="a6M-h3-DzB" id="qEw-fx-cle"/>
<outlet property="heightProfileElevationHeight" destination="JtS-om-arD" id="a8J-z7-RsP"/>
<outlet property="heightProfileImage" destination="zhI-92-6JG" id="MKv-4F-F9A"/>
<outlet property="resultLabel" destination="zml-eW-DsI" id="lP5-pC-IIe"/>
<outlet property="resultsBox" destination="Rqr-bu-crx" id="iaF-Im-C5p"/>
<outlet property="resultsBoxBottom" destination="82W-n1-9wJ" id="RLp-VX-RD7"/>
<outlet property="taxiBox" destination="xAP-RW-zvp" id="SOO-SU-fDu"/>
<outlet property="taxiBoxBottom" destination="CCT-23-3wk" id="e2w-eO-HqA"/>
</connections>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gcR-zj-b7P">
<rect key="frame" x="0.0" y="607" width="320" height="48"/>
<rect key="frame" x="0.0" y="619" width="375" height="48"/>
<subviews>
<button hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4IJ-pR-Ztp" userLabel="Go" customClass="MWMStartButton">
<rect key="frame" x="0.0" y="0.0" width="320" height="48"/>
<button hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4IJ-pR-Ztp" userLabel="Go" customClass="MWMRouteStartButton">
<rect key="frame" x="0.0" y="0.0" width="375" height="48"/>
<accessibility key="accessibilityConfiguration" identifier="goButton"/>
<inset key="contentEdgeInsets" minX="8" minY="0.0" maxX="8" maxY="0.0"/>
<state key="normal" title="Start"/>
@ -356,16 +363,17 @@
<constraints>
<constraint firstItem="gcR-zj-b7P" firstAttribute="leading" secondItem="u2u-Vb-2eH" secondAttribute="leading" id="1RD-kG-W2O"/>
<constraint firstAttribute="trailing" secondItem="87p-Qg-8f3" secondAttribute="trailing" id="5wh-lx-rUz"/>
<constraint firstItem="3s2-BV-X5i" firstAttribute="top" secondItem="u2u-Vb-2eH" secondAttribute="top" id="8Qb-GY-2hU"/>
<constraint firstItem="3s2-BV-X5i" firstAttribute="top" secondItem="3zr-me-gbI" secondAttribute="bottom" id="6c0-tH-qlJ"/>
<constraint firstItem="87p-Qg-8f3" firstAttribute="top" secondItem="3s2-BV-X5i" secondAttribute="bottom" constant="36" id="8nt-tf-wyq"/>
<constraint firstItem="87p-Qg-8f3" firstAttribute="leading" secondItem="u2u-Vb-2eH" secondAttribute="leading" id="9bA-9R-pwq"/>
<constraint firstAttribute="trailing" secondItem="3zr-me-gbI" secondAttribute="trailing" id="OZ2-dP-mna"/>
<constraint firstAttribute="bottom" secondItem="gcR-zj-b7P" secondAttribute="bottom" id="QYs-r4-Jyl"/>
<constraint firstItem="3s2-BV-X5i" firstAttribute="leading" secondItem="u2u-Vb-2eH" secondAttribute="leading" id="e90-R4-YQR"/>
<constraint firstItem="3zr-me-gbI" firstAttribute="top" secondItem="u2u-Vb-2eH" secondAttribute="top" id="hE5-50-mMA"/>
<constraint firstAttribute="trailing" secondItem="3s2-BV-X5i" secondAttribute="trailing" id="lnu-7l-aPG"/>
<constraint firstAttribute="trailing" secondItem="gcR-zj-b7P" secondAttribute="trailing" id="n9j-dG-kOB"/>
<constraint firstItem="3zr-me-gbI" firstAttribute="leading" secondItem="u2u-Vb-2eH" secondAttribute="leading" id="xgY-7G-jgv"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="layer.shadowRadius">
<integer key="value" value="2"/>
@ -382,29 +390,11 @@
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="pressBackground"/>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="arriveLabel" destination="oec-Ee-6ha" id="7Ep-ck-NSQ"/>
<outlet property="backButton" destination="a4n-5I-PN3" id="42W-5B-Z8i"/>
<outlet property="bicycle" destination="yiM-fM-sSS" id="pMf-6J-9Gd"/>
<outlet property="contentView" destination="3s2-BV-X5i" id="mp7-Qq-drU"/>
<outlet property="elevationHeight" destination="JtS-om-arD" id="Dah-Ui-zNW"/>
<outlet property="elevationImage" destination="Ac5-gf-3tf" id="Gka-BR-4ZM"/>
<outlet property="errorBox" destination="QEP-6s-YTM" id="kH0-yP-1Gk"/>
<outlet property="errorLabel" destination="VNi-4g-9gz" id="L8Q-MT-bnO"/>
<outlet property="goButton" destination="4IJ-pR-Ztp" id="48a-At-Nqq"/>
<outlet property="heightBox" destination="6iM-A6-4JK" id="cav-Cj-Aqr"/>
<outlet property="heightBoxHeight" destination="Fl4-Tb-OER" id="MEr-ms-WF4"/>
<outlet property="heightProfileElevation" destination="rXP-rM-9cx" id="9ME-YW-7qO"/>
<outlet property="heightProfileImage" destination="zhI-92-6JG" id="BAQ-2W-WFu"/>
<outlet property="pedestrian" destination="VhE-hA-Leo" id="R3O-th-Jw0"/>
<outlet property="planningBox" destination="tdV-a8-fmG" id="dR4-f7-H2J"/>
<outlet property="resultLabel" destination="zml-eW-DsI" id="GaF-AU-thr"/>
<outlet property="resultsBox" destination="Rqr-bu-crx" id="MgA-Aj-m5e"/>
<outlet property="resultsBoxHeight" destination="bHW-iR-rAA" id="gtD-94-xk7"/>
<outlet property="statusBox" destination="87p-Qg-8f3" id="mSF-4e-CPU"/>
<outlet property="statusBoxHeight" destination="4qT-ha-p75" id="e6i-4p-0cu"/>
<outlet property="taxi" destination="f6i-lw-K3R" id="s0G-le-Kbz"/>
<outlet property="taxiBox" destination="xAP-RW-zvp" id="ikQ-lE-jLs"/>
<outlet property="taxiCollectionView" destination="t6d-gI-JcN" id="vyv-dZ-Sv3"/>
<outlet property="vehicle" destination="jDl-pu-eov" id="awM-KI-2xO"/>
</connections>
<point key="canvasLocation" x="448" y="574"/>

View file

@ -0,0 +1,5 @@
#import "MWMRoutePreview.h"
@interface MWMiPhoneRoutePreview : MWMRoutePreview
@end

View file

@ -0,0 +1,39 @@
#import "MWMiPhoneRoutePreview.h"
#import "SwiftBridge.h"
@interface MWMRoutePreview ()
@property(nonatomic) BOOL isVisible;
@end
@implementation MWMiPhoneRoutePreview
- (CGRect)defaultFrame
{
CGFloat const height = 64;
return {{0, self.isVisible ? 0 : -height}, {self.superview.width, height}};
}
#pragma mark - AvailableArea / VisibleArea
- (MWMAvailableAreaAffectDirections)visibleAreaAffectDirections
{
return MWMAvailableAreaAffectDirectionsTop;
}
#pragma mark - AvailableArea / SideButtonsArea
- (MWMAvailableAreaAffectDirections)sideButtonsAreaAffectDirections
{
return MWMAvailableAreaAffectDirectionsTop;
}
#pragma mark - AvailableArea / TrafficButtonArea
- (MWMAvailableAreaAffectDirections)trafficButtonAreaAffectDirections
{
return MWMAvailableAreaAffectDirectionsTop;
}
@end

View file

@ -0,0 +1,320 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MWMNavigationDashboardManager">
<connections>
<outlet property="goButton" destination="CQB-xn-DSM" id="Vb1-tV-AR9"/>
<outlet property="routePreview" destination="aNH-vh-DPz" id="ORz-pz-7sV"/>
<outlet property="statusBox" destination="hIE-BJ-nFm" id="j6g-xk-RgK"/>
<outlet property="taxiCollectionView" destination="Dm8-yS-U68" id="crw-jv-vGq"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="aNH-vh-DPz" customClass="MWMiPhoneRoutePreview">
<rect key="frame" x="0.0" y="0.0" width="320" height="64"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tRj-9k-ciR">
<rect key="frame" x="0.0" y="0.0" width="320" height="20"/>
<color key="backgroundColor" red="0.1215686275" green="0.59999999999999998" blue="0.32156862749999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="QYY-96-CiC"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="primary"/>
</userDefinedRuntimeAttributes>
</view>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WqK-Yb-PmP" customClass="SolidTouchView">
<rect key="frame" x="0.0" y="20" width="320" height="44"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wpf-tw-Coz" userLabel="Back">
<rect key="frame" x="0.0" y="0.0" width="44" height="44"/>
<accessibility key="accessibilityConfiguration" identifier="goBackButton"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="ELC-D6-uQM"/>
<constraint firstAttribute="width" constant="44" id="e40-iL-uvR"/>
</constraints>
<state key="normal" image="ic_nav_bar_back"/>
<connections>
<action selector="stopRoutingButtonAction" destination="-1" eventType="touchUpInside" id="64T-4A-qPD"/>
</connections>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oQc-l8-sZH" userLabel="Buttons Box">
<rect key="frame" x="54" y="0.0" width="212" height="44"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cZF-Ha-2tB">
<rect key="frame" x="6" y="3" width="38" height="38"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="routeAuto"/>
<constraints>
<constraint firstAttribute="width" constant="38" id="m6k-uU-yOl"/>
<constraint firstAttribute="height" constant="38" id="mp7-b4-xot"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FuO-c6-y9C" userLabel="Bicycle">
<rect key="frame" x="60" y="3" width="38" height="38"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="routeBicycle"/>
<constraints>
<constraint firstAttribute="width" constant="38" id="9fe-fw-05J"/>
<constraint firstAttribute="height" constant="38" id="gbm-NL-zgv"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6D3-QF-6wm">
<rect key="frame" x="114" y="3" width="38" height="38"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<accessibility key="accessibilityConfiguration" identifier="routePedestrian"/>
<constraints>
<constraint firstAttribute="width" constant="38" id="815-LJ-2tk"/>
<constraint firstAttribute="height" constant="38" id="hXi-E7-GUb"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="15Q-ZN-NzE" userLabel="Taxi">
<rect key="frame" x="168" y="3" width="38" height="38"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<accessibility key="accessibilityConfiguration" identifier="routeTaxi"/>
<constraints>
<constraint firstAttribute="width" constant="38" id="ibp-pJ-TuK"/>
<constraint firstAttribute="height" constant="38" id="zPC-M0-Jo1"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="FuO-c6-y9C" firstAttribute="centerY" secondItem="oQc-l8-sZH" secondAttribute="centerY" id="1De-4s-V8t"/>
<constraint firstItem="6D3-QF-6wm" firstAttribute="leading" secondItem="FuO-c6-y9C" secondAttribute="trailing" constant="16" id="91z-iC-oKp"/>
<constraint firstItem="cZF-Ha-2tB" firstAttribute="centerY" secondItem="oQc-l8-sZH" secondAttribute="centerY" id="MQh-op-cpN"/>
<constraint firstItem="cZF-Ha-2tB" firstAttribute="leading" secondItem="oQc-l8-sZH" secondAttribute="leading" constant="6" id="MjU-UA-Kax"/>
<constraint firstAttribute="height" constant="44" id="Mws-KZ-ghs"/>
<constraint firstItem="15Q-ZN-NzE" firstAttribute="leading" secondItem="6D3-QF-6wm" secondAttribute="trailing" constant="16" id="Td5-UQ-kzj"/>
<constraint firstAttribute="trailing" secondItem="15Q-ZN-NzE" secondAttribute="trailing" constant="6" id="WHK-N0-dCc"/>
<constraint firstItem="FuO-c6-y9C" firstAttribute="leading" secondItem="cZF-Ha-2tB" secondAttribute="trailing" constant="16" id="Z6M-UV-6x2"/>
<constraint firstItem="6D3-QF-6wm" firstAttribute="centerY" secondItem="oQc-l8-sZH" secondAttribute="centerY" id="vXO-6g-q4L"/>
<constraint firstAttribute="trailing" secondItem="6D3-QF-6wm" secondAttribute="trailing" priority="750" constant="6" id="zmG-EZ-8Wk"/>
<constraint firstItem="15Q-ZN-NzE" firstAttribute="centerY" secondItem="oQc-l8-sZH" secondAttribute="centerY" id="zvc-uG-Izm"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="0.12156862745098039" green="0.59999999999999998" blue="0.32156862745098036" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="2SX-TZ-tS3"/>
<constraint firstItem="oQc-l8-sZH" firstAttribute="centerY" secondItem="wpf-tw-Coz" secondAttribute="centerY" id="NwC-Dq-AAM"/>
<constraint firstItem="wpf-tw-Coz" firstAttribute="leading" secondItem="WqK-Yb-PmP" secondAttribute="leading" id="bK5-4Q-Rv9"/>
<constraint firstItem="wpf-tw-Coz" firstAttribute="top" secondItem="WqK-Yb-PmP" secondAttribute="top" id="cPc-fO-vAa"/>
<constraint firstItem="oQc-l8-sZH" firstAttribute="centerX" secondItem="WqK-Yb-PmP" secondAttribute="centerX" id="ltA-tm-z3P"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="primary"/>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="tRj-9k-ciR" secondAttribute="trailing" id="7jY-DP-PkA"/>
<constraint firstItem="tRj-9k-ciR" firstAttribute="top" secondItem="aNH-vh-DPz" secondAttribute="top" id="THE-lZ-g3P"/>
<constraint firstItem="tRj-9k-ciR" firstAttribute="leading" secondItem="aNH-vh-DPz" secondAttribute="leading" id="gxu-Mc-DSI"/>
<constraint firstAttribute="trailing" secondItem="WqK-Yb-PmP" secondAttribute="trailing" id="hui-oa-rbV"/>
<constraint firstItem="WqK-Yb-PmP" firstAttribute="leading" secondItem="aNH-vh-DPz" secondAttribute="leading" id="rQB-KG-9Kg"/>
<constraint firstItem="WqK-Yb-PmP" firstAttribute="top" secondItem="tRj-9k-ciR" secondAttribute="bottom" id="zoU-RG-pIh"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="backButton" destination="wpf-tw-Coz" id="49c-Xq-QOk"/>
<outlet property="bicycle" destination="FuO-c6-y9C" id="UR2-pF-Amb"/>
<outlet property="contentView" destination="WqK-Yb-PmP" id="4ph-Dm-EFr"/>
<outlet property="pedestrian" destination="6D3-QF-6wm" id="bdh-zx-9LW"/>
<outlet property="taxi" destination="15Q-ZN-NzE" id="RaD-7N-ZE2"/>
<outlet property="vehicle" destination="cZF-Ha-2tB" id="QP3-tU-nfO"/>
</connections>
<point key="canvasLocation" x="448" y="341"/>
</view>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hIE-BJ-nFm" userLabel="Status Box" customClass="MWMRoutePreviewStatus">
<rect key="frame" x="0.0" y="0.0" width="320" height="108"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fD2-1N-x27" userLabel="Error Box">
<rect key="frame" x="0.0" y="0.0" width="320" height="48"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Planning..." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="14" translatesAutoresizingMaskIntoConstraints="NO" id="vGz-fB-9Oi" userLabel="Error">
<rect key="frame" x="120" y="14" width="80" height="20"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
<color key="textColor" red="0.95686274510000002" green="0.26274509800000001" blue="0.21176470589999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="routing_planning_error"/>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="red"/>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="vGz-fB-9Oi" firstAttribute="centerX" secondItem="fD2-1N-x27" secondAttribute="centerX" id="GDN-cJ-f4O"/>
<constraint firstItem="vGz-fB-9Oi" firstAttribute="centerY" secondItem="fD2-1N-x27" secondAttribute="centerY" id="i8z-Bu-10Z"/>
<constraint firstAttribute="height" constant="48" id="uRP-aY-61z"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Tai-sE-6DC" userLabel="Results Box">
<rect key="frame" x="0.0" y="0.0" width="320" height="48"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="results" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sjQ-Sc-mtN">
<rect key="frame" x="16" y="14" width="50.5" height="20"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.54000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
</userDefinedRuntimeAttributes>
</label>
<button hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CQB-xn-DSM" userLabel="Go" customClass="MWMRouteStartButton">
<rect key="frame" x="228" y="8" width="80" height="32"/>
<accessibility key="accessibilityConfiguration" identifier="goButton"/>
<constraints>
<constraint firstAttribute="width" constant="80" id="5fJ-hA-Bme"/>
<constraint firstAttribute="height" constant="32" id="b2e-N4-xY6"/>
</constraints>
<inset key="contentEdgeInsets" minX="8" minY="0.0" maxX="8" maxY="0.0"/>
<state key="normal" title="Start"/>
<state key="selected">
<color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="0.26000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="p2p_start"/>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="white"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="linkBlue"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="linkBlueHighlighted"/>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="6"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="routingStartTouchUpInside" destination="-1" eventType="touchUpInside" id="IWD-gV-wDp"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="sjQ-Sc-mtN" firstAttribute="centerY" secondItem="Tai-sE-6DC" secondAttribute="centerY" id="Aer-5j-lt1"/>
<constraint firstAttribute="trailing" secondItem="CQB-xn-DSM" secondAttribute="trailing" constant="12" id="Any-Qx-9mT"/>
<constraint firstItem="CQB-xn-DSM" firstAttribute="centerY" secondItem="Tai-sE-6DC" secondAttribute="centerY" id="XI7-0e-bgf"/>
<constraint firstItem="CQB-xn-DSM" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="sjQ-Sc-mtN" secondAttribute="trailing" constant="16" id="Xqn-Rd-gR3"/>
<constraint firstItem="sjQ-Sc-mtN" firstAttribute="leading" secondItem="Tai-sE-6DC" secondAttribute="leading" constant="16" id="gdz-UZ-QkO"/>
<constraint firstAttribute="height" constant="48" id="tqy-f7-E4I"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FBs-iT-nWY" userLabel="Height Box">
<rect key="frame" x="0.0" y="48" width="320" height="60"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Z94-gs-dwB">
<rect key="frame" x="16" y="14" width="288" height="32"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="OqA-sS-wmI">
<rect key="frame" x="0.0" y="0.0" width="288" height="32"/>
</imageView>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="OqA-sS-wmI" firstAttribute="leading" secondItem="Z94-gs-dwB" secondAttribute="leading" id="53L-rq-Bau"/>
<constraint firstItem="OqA-sS-wmI" firstAttribute="top" secondItem="Z94-gs-dwB" secondAttribute="top" id="at0-E7-wDb"/>
<constraint firstAttribute="trailing" secondItem="OqA-sS-wmI" secondAttribute="trailing" id="ooX-y2-4kT"/>
<constraint firstAttribute="bottom" secondItem="OqA-sS-wmI" secondAttribute="bottom" id="wy6-zt-Lfz"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="Z94-gs-dwB" secondAttribute="bottom" constant="14" id="GiP-PC-EQA"/>
<constraint firstAttribute="height" constant="60" id="Isf-h4-Hen"/>
<constraint firstItem="Z94-gs-dwB" firstAttribute="leading" secondItem="FBs-iT-nWY" secondAttribute="leading" constant="16" id="h5e-gY-AhN"/>
<constraint firstAttribute="trailing" secondItem="Z94-gs-dwB" secondAttribute="trailing" constant="16" id="xNl-p8-3J5"/>
<constraint firstItem="Z94-gs-dwB" firstAttribute="top" secondItem="FBs-iT-nWY" secondAttribute="top" constant="14" id="zAG-Jd-mUl"/>
</constraints>
</view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5a5-vb-p6T" userLabel="Taxi Box">
<rect key="frame" x="0.0" y="0.0" width="320" height="60"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" pagingEnabled="YES" dataMode="none" prefetchingEnabled="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Dm8-yS-U68" customClass="MWMTaxiCollectionView">
<rect key="frame" x="0.0" y="0.0" width="320" height="60"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="yr1-ni-nMn" customClass="MWMTaxiCollectionLayout">
<size key="itemSize" width="320" height="100"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
</collectionView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="Dm8-yS-U68" firstAttribute="top" secondItem="5a5-vb-p6T" secondAttribute="top" id="1BT-nc-NyC"/>
<constraint firstAttribute="trailing" secondItem="Dm8-yS-U68" secondAttribute="trailing" id="9jL-oy-VfM"/>
<constraint firstItem="Dm8-yS-U68" firstAttribute="leading" secondItem="5a5-vb-p6T" secondAttribute="leading" id="GAn-kd-ghT"/>
<constraint firstAttribute="height" constant="60" id="NNM-cn-dVc"/>
<constraint firstAttribute="bottom" secondItem="Dm8-yS-U68" secondAttribute="bottom" id="bnt-sj-3pO"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="FBs-iT-nWY" secondAttribute="bottom" id="0pP-L9-PjJ"/>
<constraint firstItem="5a5-vb-p6T" firstAttribute="leading" secondItem="hIE-BJ-nFm" secondAttribute="leading" id="378-vg-65G"/>
<constraint firstAttribute="trailing" secondItem="fD2-1N-x27" secondAttribute="trailing" id="Alb-Vc-3pV"/>
<constraint firstItem="5a5-vb-p6T" firstAttribute="top" secondItem="hIE-BJ-nFm" secondAttribute="top" id="C3e-aL-kQq"/>
<constraint firstItem="Tai-sE-6DC" firstAttribute="top" secondItem="hIE-BJ-nFm" secondAttribute="top" id="D1o-4y-GV6"/>
<constraint firstAttribute="height" priority="100" constant="48" id="HTC-IH-1gA"/>
<constraint firstAttribute="trailing" secondItem="5a5-vb-p6T" secondAttribute="trailing" id="I7D-Xr-4Bd"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="5a5-vb-p6T" secondAttribute="bottom" id="LNP-ys-o3e"/>
<constraint firstItem="fD2-1N-x27" firstAttribute="leading" secondItem="hIE-BJ-nFm" secondAttribute="leading" id="OkZ-n1-6M1"/>
<constraint firstItem="FBs-iT-nWY" firstAttribute="top" secondItem="Tai-sE-6DC" secondAttribute="bottom" id="UK2-a3-v7h"/>
<constraint firstAttribute="trailing" secondItem="Tai-sE-6DC" secondAttribute="trailing" id="a1W-Je-BvX"/>
<constraint firstAttribute="trailing" secondItem="FBs-iT-nWY" secondAttribute="trailing" id="aFh-Oh-dMW"/>
<constraint firstItem="Tai-sE-6DC" firstAttribute="leading" secondItem="hIE-BJ-nFm" secondAttribute="leading" id="k8m-8C-aK9"/>
<constraint firstItem="fD2-1N-x27" firstAttribute="top" secondItem="hIE-BJ-nFm" secondAttribute="top" id="rcc-1j-0Af"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="Tai-sE-6DC" secondAttribute="bottom" id="trf-mi-xeb"/>
<constraint firstItem="FBs-iT-nWY" firstAttribute="leading" secondItem="hIE-BJ-nFm" secondAttribute="leading" id="vEM-Q6-T7g"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="fD2-1N-x27" secondAttribute="bottom" id="x7F-TL-lJx"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="layer.borderUIColor">
<color key="value" red="0.0" green="0.0" blue="0.0" alpha="0.12" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="layer.borderWidth">
<integer key="value" value="1"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="errorBox" destination="fD2-1N-x27" id="IV5-eS-JLl"/>
<outlet property="errorBoxBottom" destination="x7F-TL-lJx" id="W6w-05-Dll"/>
<outlet property="errorLabel" destination="vGz-fB-9Oi" id="Ojx-cU-Jpc"/>
<outlet property="heightBox" destination="FBs-iT-nWY" id="1Vi-nB-gGz"/>
<outlet property="heightBoxBottom" destination="0pP-L9-PjJ" id="BP0-zq-7kV"/>
<outlet property="heightProfileImage" destination="OqA-sS-wmI" id="NdN-LR-j7e"/>
<outlet property="resultLabel" destination="sjQ-Sc-mtN" id="XIY-sS-M2V"/>
<outlet property="resultsBox" destination="Tai-sE-6DC" id="l4p-m2-z4z"/>
<outlet property="resultsBoxBottom" destination="trf-mi-xeb" id="tdb-sa-2ak"/>
<outlet property="taxiBox" destination="5a5-vb-p6T" id="MLv-mh-dK2"/>
<outlet property="taxiBoxBottom" destination="LNP-ys-o3e" id="B9A-Lx-cDJ"/>
</connections>
<point key="canvasLocation" x="448" y="521"/>
</view>
</objects>
<resources>
<image name="ic_nav_bar_back" width="14" height="22"/>
</resources>
</document>

View file

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="Xaa-X0-mDi">
<rect key="frame" x="0.0" y="0.0" width="320" height="88"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="600" text="33 мин • 7.0 км" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="K4b-2l-XNs">
<rect key="frame" x="16" y="33.5" width="122" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wjg-5S-gNt">
<rect key="frame" x="154" y="12" width="62" height="64"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="150" verticalHuggingPriority="150" horizontalCompressionResistancePriority="240" verticalCompressionResistancePriority="240" translatesAutoresizingMaskIntoConstraints="NO" id="Oo6-5d-9eZ">
<rect key="frame" x="0.0" y="0.0" width="62" height="64"/>
</imageView>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="Oo6-5d-9eZ" firstAttribute="leading" secondItem="wjg-5S-gNt" secondAttribute="leading" id="89z-RC-KuC"/>
<constraint firstAttribute="trailing" secondItem="Oo6-5d-9eZ" secondAttribute="trailing" id="MmD-qc-SEp"/>
<constraint firstItem="Oo6-5d-9eZ" firstAttribute="top" secondItem="wjg-5S-gNt" secondAttribute="top" id="kNu-uB-gG1"/>
<constraint firstAttribute="bottom" secondItem="Oo6-5d-9eZ" secondAttribute="bottom" id="svL-UF-Z5y"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="18D-V2-rlE">
<rect key="frame" x="16" y="64" width="50" height="12"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ic_elevation" translatesAutoresizingMaskIntoConstraints="NO" id="Bgk-nl-CPG">
<rect key="frame" x="0.0" y="0.0" width="10" height="12"/>
<constraints>
<constraint firstAttribute="width" constant="10" id="XUL-6h-s9q"/>
<constraint firstAttribute="height" constant="12" id="hFD-A2-CVc"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="270" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eXd-jF-8tK">
<rect key="frame" x="14" y="-2" width="36" height="17"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="linkBlue"/>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium14"/>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="eXd-jF-8tK" firstAttribute="leading" secondItem="Bgk-nl-CPG" secondAttribute="trailing" constant="4" id="DhC-By-5KJ"/>
<constraint firstAttribute="bottom" secondItem="Bgk-nl-CPG" secondAttribute="bottom" id="SCl-B1-VGS"/>
<constraint firstAttribute="trailing" secondItem="eXd-jF-8tK" secondAttribute="trailing" id="YK2-3q-PdX"/>
<constraint firstItem="Bgk-nl-CPG" firstAttribute="top" secondItem="18D-V2-rlE" secondAttribute="top" id="bsg-Yr-c8G"/>
<constraint firstItem="Bgk-nl-CPG" firstAttribute="leading" secondItem="18D-V2-rlE" secondAttribute="leading" id="iBZ-WQ-4UJ"/>
<constraint firstItem="eXd-jF-8tK" firstAttribute="centerY" secondItem="Bgk-nl-CPG" secondAttribute="centerY" id="swr-tV-EEJ"/>
</constraints>
</view>
<button hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" horizontalHuggingPriority="501" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yQh-cZ-1P4" userLabel="Go" customClass="MWMRouteStartButton">
<rect key="frame" x="228" y="28" width="80" height="32"/>
<accessibility key="accessibilityConfiguration" identifier="routeStartButton"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="80" id="1p5-ha-b88"/>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="32" id="RFF-8b-nk7"/>
</constraints>
<inset key="contentEdgeInsets" minX="8" minY="0.0" maxX="8" maxY="0.0"/>
<state key="normal" title="Start"/>
<state key="selected">
<color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="0.26000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="bold14"/>
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="p2p_start"/>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="white"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="linkBlue"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="linkBlueHighlighted"/>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="6"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</button>
<view hidden="YES" contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hHk-Cl-By7" userLabel="Taxi View">
<rect key="frame" x="0.0" y="0.0" width="216" height="48"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" pagingEnabled="YES" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="O8C-9w-LXS" customClass="MWMTaxiCollectionView">
<rect key="frame" x="0.0" y="0.0" width="216" height="48"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="0yy-TG-JGK" customClass="MWMTaxiCollectionLayout">
<size key="itemSize" width="50" height="50"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
</collectionView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="O8C-9w-LXS" secondAttribute="bottom" id="Pzn-mo-fcc"/>
<constraint firstAttribute="trailing" secondItem="O8C-9w-LXS" secondAttribute="trailing" id="ahz-lQ-8YV"/>
<constraint firstItem="O8C-9w-LXS" firstAttribute="top" secondItem="hHk-Cl-By7" secondAttribute="top" id="fwA-xR-OXZ"/>
<constraint firstItem="O8C-9w-LXS" firstAttribute="leading" secondItem="hHk-Cl-By7" secondAttribute="leading" id="j6p-Ad-ugo"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="wjg-5S-gNt" firstAttribute="leading" secondItem="K4b-2l-XNs" secondAttribute="trailing" priority="500" constant="16" id="2Eb-Hz-oub"/>
<constraint firstAttribute="trailing" secondItem="yQh-cZ-1P4" secondAttribute="trailing" constant="12" id="2QT-iF-LCh"/>
<constraint firstItem="yQh-cZ-1P4" firstAttribute="leading" secondItem="wjg-5S-gNt" secondAttribute="trailing" constant="12" id="5xN-BN-mLj"/>
<constraint firstAttribute="bottom" secondItem="wjg-5S-gNt" secondAttribute="bottom" constant="12" id="8T9-n2-ikR"/>
<constraint firstItem="yQh-cZ-1P4" firstAttribute="leading" secondItem="hHk-Cl-By7" secondAttribute="trailing" constant="12" id="DOT-rM-wmf"/>
<constraint firstItem="18D-V2-rlE" firstAttribute="centerY" secondItem="K4b-2l-XNs" secondAttribute="centerY" priority="250" id="GMi-pw-NKE"/>
<constraint firstItem="wjg-5S-gNt" firstAttribute="top" secondItem="K4b-2l-XNs" secondAttribute="bottom" priority="250" constant="8" id="H8e-As-Oyz"/>
<constraint firstItem="18D-V2-rlE" firstAttribute="bottom" secondItem="wjg-5S-gNt" secondAttribute="bottom" priority="500" id="JkX-WU-gQJ"/>
<constraint firstItem="18D-V2-rlE" firstAttribute="leading" secondItem="K4b-2l-XNs" secondAttribute="leading" priority="260" id="Jpn-Wg-YEN"/>
<constraint firstItem="wjg-5S-gNt" firstAttribute="top" secondItem="Xaa-X0-mDi" secondAttribute="top" priority="500" constant="12" id="MyD-zr-zH4"/>
<constraint firstItem="wjg-5S-gNt" firstAttribute="leading" secondItem="Xaa-X0-mDi" secondAttribute="leading" priority="250" constant="12" id="OJa-9b-FHr"/>
<constraint firstItem="K4b-2l-XNs" firstAttribute="leading" secondItem="Xaa-X0-mDi" secondAttribute="leading" constant="16" id="bqJ-9L-w7R"/>
<constraint firstItem="yQh-cZ-1P4" firstAttribute="centerY" secondItem="Xaa-X0-mDi" secondAttribute="centerY" id="d3y-ms-1oT"/>
<constraint firstItem="hHk-Cl-By7" firstAttribute="top" secondItem="Xaa-X0-mDi" secondAttribute="top" id="eAy-oK-FaM"/>
<constraint firstItem="18D-V2-rlE" firstAttribute="trailing" secondItem="wjg-5S-gNt" secondAttribute="trailing" priority="250" id="eBu-KG-YeI"/>
<constraint firstItem="K4b-2l-XNs" firstAttribute="centerY" secondItem="Xaa-X0-mDi" secondAttribute="centerY" priority="500" id="ucC-IH-9zH"/>
<constraint firstItem="K4b-2l-XNs" firstAttribute="top" secondItem="Xaa-X0-mDi" secondAttribute="top" priority="250" constant="12" id="wCM-qF-y96"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
</view>
</objects>
<resources>
<image name="ic_elevation" width="10" height="12"/>
</resources>
</document>

View file

@ -0,0 +1,130 @@
@objc(MWMRoutePreviewStatus)
final class RoutePreviewStatus: SolidTouchView {
@IBOutlet private weak var errorBox: UIView!
@IBOutlet private weak var resultsBox: UIView!
@IBOutlet private weak var heightBox: UIView!
@IBOutlet private weak var taxiBox: UIView!
@IBOutlet private weak var errorLabel: UILabel!
@IBOutlet private weak var resultLabel: UILabel!
@IBOutlet private weak var arriveLabel: UILabel?
@IBOutlet private weak var heightProfileImage: UIImageView!
@IBOutlet private weak var heightProfileElevationHeight: UILabel?
@IBOutlet private var errorBoxBottom: NSLayoutConstraint!
@IBOutlet private var resultsBoxBottom: NSLayoutConstraint!
@IBOutlet private var heightBoxBottom: NSLayoutConstraint!
@IBOutlet private var taxiBoxBottom: NSLayoutConstraint!
private var hiddenConstraint: NSLayoutConstraint!
weak var ownerView: UIView!
var isVisible = false {
didSet {
alternative(iPhone: {
guard self.isVisible != oldValue else { return }
if self.isVisible {
self.addView()
}
DispatchQueue.main.async {
guard let sv = self.superview else { return }
sv.setNeedsLayout()
self.hiddenConstraint.isActive = !self.isVisible
UIView.animate(withDuration: kDefaultAnimationDuration,
animations: { sv.layoutIfNeeded() },
completion: { _ in
if (!self.isVisible) {
self.removeFromSuperview()
}
})
}
},
iPad: { self.isHidden = !self.isVisible })()
}
}
private func addView() {
guard superview != ownerView else { return }
ownerView.addSubview(self)
NSLayoutConstraint(item: self, attribute: .left, relatedBy: .equal, toItem: ownerView, attribute: .left, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: self, attribute: .right, relatedBy: .equal, toItem: ownerView, attribute: .right, multiplier: 1, constant: 0).isActive = true
hiddenConstraint = NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: ownerView, attribute: .bottom, multiplier: 1, constant: 0)
hiddenConstraint.priority = UILayoutPriorityDefaultHigh
hiddenConstraint.isActive = true
let visibleConstraint = NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: ownerView, attribute: .bottom, multiplier: 1, constant: 0)
visibleConstraint.priority = UILayoutPriorityDefaultLow
visibleConstraint.isActive = true
}
private func updateHeight() {
DispatchQueue.main.async {
self.setNeedsLayout()
self.errorBoxBottom.isActive = !self.errorBox.isHidden
self.resultsBoxBottom.isActive = !self.resultsBox.isHidden
self.heightBoxBottom.isActive = !self.heightBox.isHidden
self.taxiBoxBottom.isActive = !self.taxiBox.isHidden
UIView.animate(withDuration: kDefaultAnimationDuration) { self.layoutIfNeeded() }
}
}
func stateHidden() {
isVisible = false
}
func statePrepare() {
isVisible = false
}
func stateError(message: String) {
isVisible = true
errorBox.isHidden = false
resultsBox.isHidden = true
heightBox.isHidden = true
taxiBox.isHidden = true
errorLabel.text = message
updateHeight()
}
func stateReady() {
isVisible = true
errorBox.isHidden = true
if MWMRouter.isTaxi() {
taxiBox.isHidden = false
resultsBox.isHidden = true
heightBox.isHidden = true
} else {
taxiBox.isHidden = true
resultsBox.isHidden = false
if MWMRouter.hasRouteAltitude() {
heightBox.isHidden = false
MWMRouter.routeAltitudeImage(for: heightProfileImage.frame.size,
completion: { (image, elevation) in
self.heightProfileImage.image = image
self.heightProfileElevationHeight?.text = elevation
})
} else {
heightBox.isHidden = true
}
}
updateHeight()
}
func stateNavigation() {
isVisible = false
}
func onNavigationInfoUpdated(_ info: MWMNavigationDashboardEntity) {
resultLabel.attributedText = info.estimate
arriveLabel?.text = String(coreFormat: L("routing_arrive"), arguments: [info.arrival])
}
override var sideButtonsAreaAffectDirections: MWMAvailableAreaAffectDirections {
return alternative(iPhone: .bottom, iPad: [])
}
}

View file

@ -1,10 +1,3 @@
@objc(MWMRoutePreviewTaxiCellType)
enum RoutePreviewTaxiCellType: Int {
case taxi
case uber
case yandex
}
@objc(MWMRoutePreviewTaxiCell)
final class RoutePreviewTaxiCell: UICollectionViewCell {
@ -22,7 +15,7 @@ final class RoutePreviewTaxiCell: UICollectionViewCell {
}
}
func config(type: RoutePreviewTaxiCellType, title: String, eta: String, price: String, currency: String) {
func config(type: MWMRoutePreviewTaxiCellType, title: String, eta: String, price: String, currency: String) {
let iconImage = { () -> UIImage in
switch type {
case .taxi: return #imageLiteral(resourceName: "icTaxiTaxi")

View file

@ -0,0 +1,23 @@
@objc(MWMRouteStartButton)
final class RouteStartButton: UIButton {
func statePrepare() {
isHidden = false
isEnabled = false
}
func stateError() {
isHidden = alternative(iPhone: true, iPad: false)
isEnabled = false
}
func stateReady() {
isHidden = false
isEnabled = true
}
override func mwm_refreshUI() {
super.mwm_refreshUI()
setBackgroundColor(UIColor.linkBlue(), for: .normal)
setBackgroundColor(UIColor.linkBlueHighlighted(), for: .highlighted)
}
}

View file

@ -134,8 +134,10 @@ BOOL gIsFirstMyPositionMode = YES;
if ([MapsAppDelegate theApp].hasApiURL)
return;
MWMMapViewControlsManager * cm = self.controlsManager;
if (cm.searchHidden && cm.navigationState == MWMNavigationDashboardStateHidden)
BOOL const isSearchHidden = ([MWMSearchManager manager].state == MWMSearchManagerStateHidden);
BOOL const isNavigationDashboardHidden =
([MWMNavigationDashboardManager manager].state == MWMNavigationDashboardStateHidden);
if (isSearchHidden && isNavigationDashboardHidden)
self.controlsManager.hidden = !self.controlsManager.hidden;
}
@ -262,7 +264,8 @@ BOOL gIsFirstMyPositionMode = YES;
name:UIDeviceOrientationDidChangeNotification
object:nil];
self.controlsManager.menuState = self.controlsManager.menuRestoreState;
if (![MWMRouter isRoutingActive])
self.controlsManager.menuState = self.controlsManager.menuRestoreState;
[self updateStatusBarStyle];
GetFramework().InvalidateRendering();
@ -516,15 +519,15 @@ BOOL gIsFirstMyPositionMode = YES;
[self.navigationController popToRootViewControllerAnimated:NO];
if (self.isViewLoaded)
{
BOOL isSearchHidden = YES;
auto searchState = MWMSearchManagerStateHidden;
[MWMRouter stopRouting];
if ([action isEqualToString:@"me.maps.3daction.bookmarks"])
[self openBookmarks];
else if ([action isEqualToString:@"me.maps.3daction.search"])
isSearchHidden = NO;
searchState = MWMSearchManagerStateDefault;
else if ([action isEqualToString:@"me.maps.3daction.route"])
[self.controlsManager onRoutePrepare];
self.controlsManager.searchHidden = isSearchHidden;
[MWMSearchManager manager].state = MWMSearchManagerStateHidden;
}
else
{

View file

@ -10,7 +10,7 @@
#import "MWMLocationManager.h"
#import "MWMLocationObserver.h"
#import "MWMMapViewControlsManager.h"
#import "MWMNavigationDashboardManager.h"
#import "MWMNavigationDashboardManager+Entity.h"
#import "MWMRoutePoint+CPP.h"
#import "MWMSearch.h"
#import "MWMSettings.h"
@ -115,7 +115,6 @@ char const * kRenderAltitudeImagesQueueLabel = "mapsme.mwmrouter.renderAltitudeI
+ (void)stopRouting
{
[self stop];
[MWMNavigationDashboardManager manager].taxiDataSource = nil;
}
+ (BOOL)isRoutingActive { return GetFramework().GetRoutingManager().IsRoutingActive(); }
@ -440,23 +439,23 @@ char const * kRenderAltitudeImagesQueueLabel = "mapsme.mwmrouter.renderAltitudeI
+ (void)doStop:(BOOL)removeRoutePoints
{
auto & rm = GetFramework().GetRoutingManager();
// Don't save taxi routing type as default.
if ([[self class] isTaxi])
GetFramework().GetRoutingManager().SetRouter(routing::RouterType::Vehicle);
if ([MWMRouter isTaxi])
rm.SetRouter(routing::RouterType::Vehicle);
[self clearAltitudeImagesData];
GetFramework().GetRoutingManager().CloseRouting(removeRoutePoints);
rm.CloseRouting(removeRoutePoints);
[MWMThemeManager setAutoUpdates:NO];
[MapsAppDelegate.theApp showAlertIfRequired];
}
- (void)updateFollowingInfo
{
auto const & f = GetFramework();
if (!f.GetRoutingManager().IsRoutingActive())
if (![MWMRouter isRoutingActive])
return;
location::FollowingInfo info;
f.GetRoutingManager().GetRouteFollowingInfo(info);
GetFramework().GetRoutingManager().GetRouteFollowingInfo(info);
if (info.IsValid())
[[MWMNavigationDashboardManager manager] updateFollowingInfo:info];
}
@ -544,10 +543,6 @@ char const * kRenderAltitudeImagesQueueLabel = "mapsme.mwmrouter.renderAltitudeI
f.DeactivateMapSelection(true);
[mapViewControlsManager onRouteReady];
[self updateFollowingInfo];
if (![MWMRouter isTaxi])
[[MWMNavigationDashboardManager manager] setRouteBuilderProgress:100];
mapViewControlsManager.searchHidden = YES;
break;
}
case routing::IRouter::RouteFileNotExist:

View file

@ -0,0 +1,18 @@
#import "MWMTextToSpeech.h"
#include "std/string.hpp"
#include "std/vector.hpp"
@interface MWMTextToSpeech (CPP)
// Returns a list of available languages in the following format:
// * name in bcp47;
// * localized name;
- (vector<std::pair<string, string>>)availableLanguages;
@end
namespace tts
{
string translatedTwine(string const & twine);
} // namespace tts

View file

@ -1,5 +1,4 @@
#include "std/string.hpp"
#include "std/vector.hpp"
#import "MWMTextToSpeechObserver.h"
@interface MWMTextToSpeech : NSObject
@ -8,13 +7,10 @@
+ (void)setTTSEnabled:(BOOL)enabled;
+ (NSString *)savedLanguage;
+ (NSString *)ttsStatusNotificationKey;
+ (void)addObserver:(id<MWMTextToSpeechObserver>)observer;
+ (void)removeObserver:(id<MWMTextToSpeechObserver>)observer;
@property(nonatomic) BOOL active;
// Returns a list of available languages in the following format:
// * name in bcp47;
// * localized name;
- (vector<std::pair<string, string>>)availableLanguages;
- (void)setNotificationsLocale:(NSString *)locale;
- (void)playTurnNotifications;
@ -27,9 +23,3 @@
+ (instancetype) new __attribute__((unavailable("call tts instead")));
@end
namespace tts
{
string translatedTwine(string const & twine);
} // namespace tts

View file

@ -1,7 +1,7 @@
#import "MWMTextToSpeech.h"
#import <AVFoundation/AVFoundation.h>
#import "MWMCommon.h"
#import "MWMRouter.h"
#import "MWMTextToSpeech+CPP.h"
#import "Statistics.h"
#include "LocaleTranslator.h"
@ -40,6 +40,9 @@ vector<pair<string, string>> availableLanguages()
}
return result;
}
using TObserver = id<MWMTextToSpeechObserver>;
using TObservers = NSHashTable<__kindof TObserver>;
} // namespace
@interface MWMTextToSpeech ()<AVSpeechSynthesizerDelegate>
@ -52,6 +55,8 @@ vector<pair<string, string>> availableLanguages()
@property(nonatomic) float speechRate;
@property(nonatomic) AVAudioSession * audioSession;
@property(nonatomic) TObservers * observers;
@end
@implementation MWMTextToSpeech
@ -72,6 +77,7 @@ vector<pair<string, string>> availableLanguages()
if (self)
{
_availableLanguages = availableLanguages();
_observers = [TObservers weakObjectsHashTable];
NSString * saved = [[self class] savedLanguage];
NSString * preferedLanguageBcp47;
@ -112,12 +118,7 @@ vector<pair<string, string>> availableLanguages()
return self;
}
- (void)dealloc
{
self.speechSynthesizer.delegate = nil;
}
+ (NSString *)ttsStatusNotificationKey { return @"TTFStatusWasChangedFromSettingsNotification"; }
- (void)dealloc { self.speechSynthesizer.delegate = nil; }
- (vector<pair<string, string>>)availableLanguages { return _availableLanguages; }
- (void)setNotificationsLocale:(NSString *)locale
{
@ -140,11 +141,11 @@ vector<pair<string, string>> availableLanguages()
NSUserDefaults * ud = [NSUserDefaults standardUserDefaults];
[ud setBool:enabled forKey:kIsTTSEnabled];
[ud synchronize];
[[NSNotificationCenter defaultCenter] postNotificationName:[self ttsStatusNotificationKey]
object:nil
userInfo:nil];
auto tts = [MWMTextToSpeech tts];
[tts onTTSStatusUpdated];
if (enabled)
[[self tts] setActive:YES];
[tts setActive:YES];
}
- (void)setActive:(BOOL)active
@ -156,18 +157,11 @@ vector<pair<string, string>> availableLanguages()
[self setAudioSessionActive:active];
[MWMRouter enableTurnNotifications:active];
runAsyncOnMainQueue(^{
[[NSNotificationCenter defaultCenter]
postNotificationName:[[self class] ttsStatusNotificationKey]
object:nil
userInfo:nil];
[self onTTSStatusUpdated];
});
}
- (BOOL)active
{
return [[self class] isTTSEnabled] && [MWMRouter areTurnNotificationsEnabled];
}
- (BOOL)active { return [[self class] isTTSEnabled] && [MWMRouter areTurnNotificationsEnabled]; }
+ (NSString *)savedLanguage
{
return [[NSUserDefaults standardUserDefaults] stringForKey:kUserDefaultsTTSLanguageBcp47];
@ -265,6 +259,26 @@ vector<pair<string, string>> availableLanguages()
return YES;
}
#pragma mark - MWMNavigationDashboardObserver
- (void)onTTSStatusUpdated
{
for (TObserver observer in self.observers)
[observer onTTSStatusUpdated];
}
#pragma mark - Add/Remove Observers
+ (void)addObserver:(id<MWMTextToSpeechObserver>)observer
{
[[MWMTextToSpeech tts].observers addObject:observer];
}
+ (void)removeObserver:(id<MWMTextToSpeechObserver>)observer
{
[[MWMTextToSpeech tts].observers removeObject:observer];
}
@end
namespace tts

View file

@ -0,0 +1,5 @@
@protocol MWMTextToSpeechObserver<NSObject>
- (void)onTTSStatusUpdated;
@end

View file

@ -1,13 +1,12 @@
#import "MWMTrafficManagerObserver.h"
#include "map/traffic_manager.hpp"
#import "MWMTrafficManagerState.h"
@interface MWMTrafficManager : NSObject
+ (void)addObserver:(id<MWMTrafficManagerObserver>)observer;
+ (void)removeObserver:(id<MWMTrafficManagerObserver>)observer;
+ (TrafficManager::TrafficState)state;
+ (MWMTrafficManagerState)state;
+ (void)enableTraffic:(BOOL)enable;

View file

@ -3,6 +3,8 @@
#include "Framework.h"
#include "map/traffic_manager.hpp"
namespace
{
using TObserver = id<MWMTrafficManagerObserver>;
@ -39,11 +41,9 @@ using TObservers = NSHashTable<__kindof TObserver>;
_observers = [TObservers weakObjectsHashTable];
auto & m = GetFramework().GetTrafficManager();
m.SetStateListener([self](TrafficManager::TrafficState state) {
runAsyncOnMainQueue(^{
self.state = state;
for (TObserver observer in self.observers)
[observer onTrafficStateUpdated];
});
self.state = state;
for (TObserver observer in self.observers)
[observer onTrafficStateUpdated];
});
}
return self;
@ -61,7 +61,21 @@ using TObservers = NSHashTable<__kindof TObserver>;
[[MWMTrafficManager manager].observers removeObject:observer];
}
+ (TrafficManager::TrafficState)state { return [MWMTrafficManager manager].state; }
+ (MWMTrafficManagerState)state
{
switch ([MWMTrafficManager manager].state)
{
case TrafficManager::TrafficState::Disabled: return MWMTrafficManagerStateDisabled;
case TrafficManager::TrafficState::Enabled: return MWMTrafficManagerStateEnabled;
case TrafficManager::TrafficState::WaitingData: return MWMTrafficManagerStateWaitingData;
case TrafficManager::TrafficState::Outdated: return MWMTrafficManagerStateOutdated;
case TrafficManager::TrafficState::NoData: return MWMTrafficManagerStateNoData;
case TrafficManager::TrafficState::NetworkError: return MWMTrafficManagerStateNetworkError;
case TrafficManager::TrafficState::ExpiredData: return MWMTrafficManagerStateExpiredData;
case TrafficManager::TrafficState::ExpiredApp: return MWMTrafficManagerStateExpiredApp;
}
}
+ (void)enableTraffic:(BOOL)enable
{
auto & f = GetFramework();

View file

@ -0,0 +1,10 @@
typedef NS_ENUM(NSUInteger, MWMTrafficManagerState) {
MWMTrafficManagerStateDisabled,
MWMTrafficManagerStateEnabled,
MWMTrafficManagerStateWaitingData,
MWMTrafficManagerStateOutdated,
MWMTrafficManagerStateNoData,
MWMTrafficManagerStateNetworkError,
MWMTrafficManagerStateExpiredData,
MWMTrafficManagerStateExpiredApp
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,21 @@
final class MenuArea: AvailableArea {
override func isAreaAffectingView(_ other: UIView) -> Bool {
return !other.menuAreaAffectDirections.isEmpty
}
override func addAffectingView(_ other: UIView) {
let ov = other.menuAreaAffectView
let directions = ov.menuAreaAffectDirections
addConstraints(otherView: ov, directions: directions)
}
override func notifyObserver() {
MWMBottomMenuViewController.updateAvailableArea(frame)
}
}
extension UIView {
var menuAreaAffectDirections: MWMAvailableAreaAffectDirections { return [] }
var menuAreaAffectView: UIView { return self }
}

View file

@ -0,0 +1,21 @@
final class NavigationInfoArea: AvailableArea {
override func isAreaAffectingView(_ other: UIView) -> Bool {
return !other.navigationInfoAreaAffectDirections.isEmpty
}
override func addAffectingView(_ other: UIView) {
let ov = other.navigationInfoAreaAffectView
let directions = ov.navigationInfoAreaAffectDirections
addConstraints(otherView: ov, directions: directions)
}
override func notifyObserver() {
MWMNavigationDashboardManager.updateNavigationInfoAvailableArea(frame)
}
}
extension UIView {
var navigationInfoAreaAffectDirections: MWMAvailableAreaAffectDirections { return [] }
var navigationInfoAreaAffectView: UIView { return self }
}

View file

@ -0,0 +1,11 @@
#import "MWMMapDownloaderTypes.h"
#include "platform/location.hpp"
@protocol MWMBottomMenuControllerProtocol<NSObject>
- (void)actionDownloadMaps:(mwm::DownloaderMode)mode;
- (void)addPlace:(BOOL)isBusiness hasPoint:(BOOL)hasPoint point:(m2::PointD const &)point;
- (void)didFinishAddingPlace;
@end

View file

@ -1,28 +1,18 @@
typedef NS_ENUM(NSUInteger, MWMBottomMenuState) {
MWMBottomMenuStateHidden,
MWMBottomMenuStateInactive,
MWMBottomMenuStateActive,
MWMBottomMenuStateCompact,
MWMBottomMenuStateGo,
MWMBottomMenuStateRoutingError,
MWMBottomMenuStateRouting,
MWMBottomMenuStateRoutingExpanded
MWMBottomMenuStateActive
};
@class MWMTaxiCollectionView;
@interface MWMBottomMenuView : SolidTouchView
@property(nonatomic) MWMBottomMenuState state;
@property(nonatomic) MWMBottomMenuState restoreState;
@property(nonatomic) CGFloat leftBound;
@property(nonatomic) CGFloat layoutThreshold;
@property(weak, nonatomic, readonly) IBOutlet MWMTaxiCollectionView * taxiCollectionView;
@property(nonatomic) BOOL searchIsActive;
- (void)refreshLayout;
- (void)updateAvailableArea:(CGRect)frame;
- (BOOL)isCompact;
@end

View file

@ -1,5 +1,6 @@
#import "MWMBottomMenuView.h"
#import "EAGLView.h"
#import "MWMAvailableAreaAffectDirection.h"
#import "MWMBottomMenuViewController.h"
#import "MWMButton.h"
#import "MWMCommon.h"
@ -18,39 +19,12 @@ namespace
{
CGFloat constexpr kAdditionalHeight = 64;
CGFloat constexpr kDefaultMainButtonsHeight = 48;
CGFloat constexpr kBicyclePlanningMainButtonsHeightLandscape = 62;
CGFloat constexpr kBicyclePlanningMainButtonsHeightRegular = 94;
CGFloat constexpr kTaxiPreviewMainButtonHeight = 68.;
CGFloat constexpr kDefaultMenuButtonWidth = 60;
CGFloat constexpr kRoutingAdditionalButtonsOffsetCompact = 0;
CGFloat constexpr kRoutingAdditionalButtonsOffsetRegular = 48;
CGFloat constexpr kRoutingMainButtonsHeightCompact = 52;
CGFloat constexpr kRoutingMainButtonsHeightRegular = 56;
CGFloat constexpr kRoutingMainButtonsHeightLandscape = 40;
CGFloat constexpr kRoutingMenuButtonWidthCompact = 40;
CGFloat constexpr kRoutingMenuButtonWidthRegular = 56;
CGFloat constexpr kSpeedDistanceOffsetCompact = 0;
CGFloat constexpr kSpeedDistanceOffsetRegular = 16;
CGFloat constexpr kSpeedDistanceWidthCompact = 72;
CGFloat constexpr kSpeedDistanceWidthLandscape = 128;
CGFloat constexpr kSpeedDistanceWidthRegular = 88;
CGFloat constexpr kGoButtonWidthLandscape = 128;
CGFloat constexpr kGoButtonWidthRegular = 80;
CGFloat constexpr kPageControlTopOffsetRegular = 0;
CGFloat constexpr kPageControlTopOffsetLandscape = -8;
CGFloat constexpr kPageControlScaleLandscape = 0.7;
CGFloat constexpr kThresholdCompact = 321;
CGFloat constexpr kThresholdRegular = 415;
CGFloat constexpr kTimeWidthCompact = 112;
CGFloat constexpr kTimeWidthRegular = 128;
} // namespace
@interface MWMBottomMenuView ()
@property(weak, nonatomic) IBOutlet UIView * mainButtons;
@property(weak, nonatomic) IBOutlet UIView * separator;
@property(weak, nonatomic) IBOutlet UICollectionView * additionalButtons;
@property(weak, nonatomic) IBOutlet MWMTaxiCollectionView * taxiCollectionView;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * mainButtonsHeight;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * additionalButtonsHeight;
@ -58,55 +32,17 @@ CGFloat constexpr kTimeWidthRegular = 128;
@property(weak, nonatomic) IBOutlet UIView * downloadBadge;
@property(weak, nonatomic) IBOutlet MWMButton * p2pButton;
@property(weak, nonatomic) IBOutlet MWMButton * searchButton;
@property(weak, nonatomic) IBOutlet MWMButton * bookmarksButton;
@property(weak, nonatomic) IBOutlet MWMButton * menuButton;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * menuButtonWidth;
@property(weak, nonatomic) IBOutlet UIView * routingView;
@property(weak, nonatomic) IBOutlet UIButton * goButton;
@property(weak, nonatomic) IBOutlet UIButton * toggleInfoButton;
@property(weak, nonatomic) IBOutlet UIView * speedView;
@property(weak, nonatomic) IBOutlet UIView * timeView;
@property(weak, nonatomic) IBOutlet UIView * distanceView;
@property(weak, nonatomic) IBOutlet UIView * progressView;
@property(weak, nonatomic) IBOutlet UIView * routingAdditionalView;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * routingAdditionalViewHeight;
@property(nonatomic) IBOutletCollection(NSLayoutConstraint)
NSArray * routingAdditionalButtonsOffset;
@property(nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray * speedDistanceOffset;
@property(weak, nonatomic) IBOutlet UILabel * speedLabel;
@property(weak, nonatomic) IBOutlet UILabel * timeLabel;
@property(weak, nonatomic) IBOutlet UILabel * distanceLabel;
@property(weak, nonatomic) IBOutlet UILabel * speedLegendLabel;
@property(weak, nonatomic) IBOutlet UILabel * distanceLegendLabel;
@property(weak, nonatomic) IBOutlet UILabel * speedWithLegendLabel;
@property(weak, nonatomic) IBOutlet UILabel * distanceWithLegendLabel;
@property(weak, nonatomic) IBOutlet UILabel * estimateLabel;
@property(weak, nonatomic) IBOutlet UIView * heightProfileContainer;
@property(weak, nonatomic) IBOutlet UIView * taxiContainer;
@property(weak, nonatomic) IBOutlet UIImageView * heightProfileImage;
@property(weak, nonatomic) IBOutlet UIView * heightProfileElevation;
@property(weak, nonatomic) IBOutlet UIImageView * elevationImage;
@property(weak, nonatomic) IBOutlet UILabel * elevationHeight;
@property(weak, nonatomic) IBOutlet UIPageControl * pageControl;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * pageControlTopOffset;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * speedDistanceWidth;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * timeWidth;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * goButtonWidth;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * estimateLabelTopOffset;
@property(nonatomic) IBOutletCollection(NSLayoutConstraint)
NSArray * heightProfileContainerVerticalOrientation;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * routingViewManuButtonPffset;
@property(nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray * mainButtonConstraintsLeftToRight;
@property(nonatomic) CGFloat layoutDuration;
@property(weak, nonatomic) IBOutlet MWMBottomMenuViewController * owner;
@property(nonatomic) CGFloat layoutDuration;
@property(nonatomic) CGRect availableArea;
@end
@implementation MWMBottomMenuView
@ -116,22 +52,6 @@ CGFloat constexpr kTimeWidthRegular = 128;
[super awakeFromNib];
self.additionalButtons.hidden = YES;
self.downloadBadge.hidden = YES;
self.goButton.hidden = YES;
self.estimateLabel.hidden = YES;
self.heightProfileContainer.hidden = YES;
self.heightProfileElevation.hidden = YES;
self.toggleInfoButton.hidden = YES;
self.speedView.hidden = YES;
self.timeView.hidden = YES;
self.distanceView.hidden = YES;
self.progressView.hidden = YES;
self.routingView.hidden = YES;
self.routingAdditionalView.hidden = YES;
self.restoreState = MWMBottomMenuStateInactive;
[self.goButton setBackgroundColor:[UIColor linkBlue] forState:UIControlStateNormal];
[self.goButton setBackgroundColor:[UIColor linkBlueHighlighted]
forState:UIControlStateHighlighted];
self.elevationImage.mwm_coloring = MWMImageColoringBlue;
if (isInterfaceRightToLeft())
{
@ -140,36 +60,41 @@ CGFloat constexpr kTimeWidthRegular = 128;
}
}
- (void)didMoveToSuperview
{
[super didMoveToSuperview];
self.minY = self.superview.height;
self.width = self.superview.width;
}
- (void)layoutSubviews
{
[self refreshOnOrientationChange];
if (self.layoutDuration > 0.0)
{
CGFloat const duration = self.layoutDuration;
self.layoutDuration = 0.0;
[self layoutIfNeeded];
if (self.state != MWMBottomMenuStateHidden)
self.hidden = NO;
[self setNeedsLayout];
[UIView animateWithDuration:duration
animations:^{
[self layoutGeometry];
[self layoutIfNeeded];
}];
animations:^{
[self updateAppearance];
[self layoutIfNeeded];
}
completion:^(BOOL finished) {
if (self.state == MWMBottomMenuStateHidden)
self.hidden = YES;
}];
}
else
{
[self layoutGeometry];
}
[UIView animateWithDuration:kDefaultAnimationDuration
animations:^{
[self updateAlphaAndColor];
}
completion:^(BOOL finished) {
[self updateVisibility];
}];
[self updateFonts];
[self updateHeightProfile];
[super layoutSubviews];
}
- (void)updateAppearance
{
[self updateAlphaAndColor];
[self updateGeometry];
}
- (void)updateAlphaAndColor
{
switch (self.state)
@ -177,233 +102,30 @@ CGFloat constexpr kTimeWidthRegular = 128;
case MWMBottomMenuStateHidden: break;
case MWMBottomMenuStateInactive:
self.backgroundColor = [UIColor menuBackground];
self.menuButton.alpha = 1.0;
self.bookmarksButton.alpha = 1.0;
self.downloadBadge.alpha = 1.0;
self.routingView.alpha = 0.0;
self.routingAdditionalView.alpha = 0.0;
self.p2pButton.alpha = 1.0;
self.searchButton.alpha = 1.0;
self.downloadBadge.alpha = [self isCompact] ? 0.0 : 1.0;
self.additionalButtons.alpha = 0.0;
break;
case MWMBottomMenuStateActive:
self.backgroundColor = [UIColor white];
self.menuButton.alpha = 1.0;
self.bookmarksButton.alpha = 1.0;
self.downloadBadge.alpha = 0.0;
self.routingView.alpha = 0.0;
self.routingAdditionalView.alpha = 0.0;
self.p2pButton.alpha = 1.0;
self.searchButton.alpha = 1.0;
break;
case MWMBottomMenuStateCompact:
self.backgroundColor = [UIColor menuBackground];
if (!IPAD)
{
self.bookmarksButton.alpha = 0.0;
self.p2pButton.alpha = 0.0;
self.searchButton.alpha = 0.0;
}
self.menuButton.alpha = 1.0;
self.downloadBadge.alpha = 0.0;
self.routingView.alpha = 0.0;
self.routingAdditionalView.alpha = 0.0;
break;
case MWMBottomMenuStateGo:
self.backgroundColor = [UIColor white];
self.menuButton.alpha = 0.0;
self.downloadBadge.alpha = 1.0;
self.bookmarksButton.alpha = 0.0;
self.routingView.alpha = 1.0;
self.goButton.alpha = 1.0;
self.estimateLabel.alpha = 1.0;
self.heightProfileContainer.alpha = 1.0;
self.speedView.alpha = 0.0;
self.timeView.alpha = 0.0;
self.distanceView.alpha = 0.0;
self.progressView.alpha = 0.0;
self.routingAdditionalView.alpha = 0.0;
self.p2pButton.alpha = 0.0;
self.searchButton.alpha = 0.0;
break;
case MWMBottomMenuStateRoutingError:
self.backgroundColor = [UIColor white];
self.menuButton.alpha = 0.0;
self.downloadBadge.alpha = 1.0;
self.bookmarksButton.alpha = 0.0;
self.routingView.alpha = 1.0;
self.goButton.alpha = 0.0;
self.estimateLabel.alpha = 1.0;
self.heightProfileContainer.alpha = 0.0;
self.speedView.alpha = 0.0;
self.timeView.alpha = 0.0;
self.distanceView.alpha = 0.0;
self.progressView.alpha = 0.0;
self.routingAdditionalView.alpha = 0.0;
self.p2pButton.alpha = 0.0;
self.searchButton.alpha = 0.0;
break;
case MWMBottomMenuStateRouting:
case MWMBottomMenuStateRoutingExpanded:
self.backgroundColor = [UIColor white];
self.menuButton.alpha = 1.0;
self.downloadBadge.alpha = 0.0;
self.bookmarksButton.alpha = 0.0;
self.routingView.alpha = 1.0;
self.goButton.alpha = 0.0;
self.estimateLabel.alpha = 0.0;
self.heightProfileContainer.alpha = 0.0;
self.speedView.alpha = 1.0;
self.timeView.alpha = 1.0;
self.distanceView.alpha = 1.0;
self.progressView.alpha = 1.0;
self.routingAdditionalView.alpha = 1.0;
self.p2pButton.alpha = 0.0;
self.searchButton.alpha = 0.0;
self.additionalButtons.alpha = 1.0;
break;
}
}
- (void)updateFonts
- (void)updateGeometry
{
if (self.state != MWMBottomMenuStateRouting && self.state != MWMBottomMenuStateRoutingExpanded)
auto const availableArea = self.availableArea;
if (CGRectEqualToRect(availableArea, CGRectZero))
return;
UIFont * numberFont =
(IPAD || self.width > kThresholdRegular) ? [UIFont bold24] : [UIFont bold22];
UIFont * legendFont = [UIFont bold12];
self.speedLabel.font = numberFont;
self.timeLabel.font = numberFont;
self.distanceLabel.font = numberFont;
self.speedLegendLabel.font = legendFont;
self.distanceLegendLabel.font = legendFont;
}
- (void)updateHeightProfile
{
if (self.heightProfileContainer.hidden || ![MWMRouter hasRouteAltitude])
return;
dispatch_async(dispatch_get_main_queue(), ^{
[MWMRouter routeAltitudeImageForSize:self.heightProfileImage.frame.size
completion:^(UIImage * image, NSString * altitudeElevation) {
self.heightProfileImage.image = image;
self.elevationHeight.text = altitudeElevation;
}];
});
}
- (void)updateVisibility
{
switch (self.state)
{
case MWMBottomMenuStateHidden: break;
case MWMBottomMenuStateInactive:
self.additionalButtons.hidden = YES;
self.routingView.hidden = YES;
self.routingAdditionalView.hidden = YES;
self.taxiContainer.hidden = YES;
self.estimateLabel.hidden = YES;
break;
case MWMBottomMenuStateActive:
self.downloadBadge.hidden = YES;
self.routingView.hidden = YES;
self.routingAdditionalView.hidden = YES;
self.taxiContainer.hidden = YES;
self.estimateLabel.hidden = YES;
break;
case MWMBottomMenuStateCompact:
if (!IPAD)
{
self.bookmarksButton.hidden = YES;
self.p2pButton.hidden = YES;
self.searchButton.hidden = YES;
}
self.downloadBadge.hidden = YES;
self.routingView.hidden = YES;
self.routingAdditionalView.hidden = YES;
self.taxiContainer.hidden = YES;
self.estimateLabel.hidden = YES;
break;
case MWMBottomMenuStateGo:
{
self.downloadBadge.hidden = YES;
self.menuButton.hidden = YES;
self.bookmarksButton.hidden = YES;
self.p2pButton.hidden = YES;
self.searchButton.hidden = YES;
self.routingAdditionalView.hidden = YES;
BOOL const isNeedToShowTaxi = [MWMRouter isTaxi] || IPAD;
self.estimateLabel.hidden = isNeedToShowTaxi;
self.taxiContainer.hidden = !isNeedToShowTaxi;
break;
}
case MWMBottomMenuStateRoutingError:
self.downloadBadge.hidden = YES;
self.menuButton.hidden = YES;
self.bookmarksButton.hidden = YES;
self.p2pButton.hidden = YES;
self.searchButton.hidden = YES;
self.routingAdditionalView.hidden = YES;
self.estimateLabel.hidden = NO;
self.taxiContainer.hidden = YES;
break;
case MWMBottomMenuStateRouting:
case MWMBottomMenuStateRoutingExpanded:
self.downloadBadge.hidden = YES;
self.bookmarksButton.hidden = YES;
self.routingView.hidden = NO;
self.routingAdditionalView.hidden = NO;
self.p2pButton.hidden = YES;
self.searchButton.hidden = YES;
self.taxiContainer.hidden = YES;
break;
}
}
- (void)layoutGeometry
{
self.separatorHeight.constant = 0.0;
self.additionalButtonsHeight.constant = 0.0;
self.menuButtonWidth.constant = kDefaultMenuButtonWidth;
self.mainButtonsHeight.constant = kDefaultMainButtonsHeight;
self.routingViewManuButtonPffset.priority = UILayoutPriorityDefaultHigh;
self.routingAdditionalViewHeight.constant = 0.0;
switch (self.state)
{
case MWMBottomMenuStateHidden: self.minY = self.superview.height; return;
case MWMBottomMenuStateInactive: break;
case MWMBottomMenuStateGo:
{
[[MWMNavigationDashboardManager manager] updateStartButtonTitle:self.goButton];
[self layoutGoGeometry];
if ([MWMRouter hasRouteAltitude])
{
BOOL const isLandscape = self.width > self.layoutThreshold;
if (isLandscape)
{
self.mainButtonsHeight.constant = kBicyclePlanningMainButtonsHeightLandscape;
self.estimateLabelTopOffset.priority = UILayoutPriorityDefaultHigh;
}
else
{
self.estimateLabelTopOffset.priority = UILayoutPriorityDefaultHigh;
for (NSLayoutConstraint * constraint in self.heightProfileContainerVerticalOrientation)
constraint.priority = UILayoutPriorityDefaultHigh;
self.mainButtonsHeight.constant = kBicyclePlanningMainButtonsHeightRegular;
}
}
else if ([MWMRouter isTaxi])
{
self.mainButtonsHeight.constant = kTaxiPreviewMainButtonHeight;
}
break;
}
case MWMBottomMenuStateRoutingError:
self.mainButtonsHeight.constant = kDefaultMainButtonsHeight;
break;
case MWMBottomMenuStateCompact:
if (self.restoreState == MWMBottomMenuStateRouting && !IPAD &&
UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
self.mainButtonsHeight.constant = kRoutingMainButtonsHeightLandscape;
break;
case MWMBottomMenuStateActive:
{
self.separatorHeight.constant = 1.0;
@ -420,104 +142,16 @@ CGFloat constexpr kTimeWidthRegular = 128;
}
}
break;
case MWMBottomMenuStateRouting: [self layoutRoutingGeometry]; break;
case MWMBottomMenuStateRoutingExpanded:
self.routingAdditionalViewHeight.constant = kAdditionalHeight;
[self layoutRoutingGeometry];
break;
}
CGFloat const width = MIN(self.superview.width - self.leftBound, self.superview.width);
CGFloat const additionalHeight =
MAX(self.additionalButtonsHeight.constant, self.routingAdditionalViewHeight.constant);
CGFloat const height =
auto const additionalHeight = self.additionalButtonsHeight.constant;
auto const height =
self.mainButtonsHeight.constant + self.separatorHeight.constant + additionalHeight;
self.frame = {{self.superview.width - width, self.superview.height - height}, {width, height}};
self.frame = {{availableArea.origin.x, availableArea.size.height - height},
{availableArea.size.width, height}};
}
- (void)layoutGoGeometry
- (void)morphMenuButtonTemplate:(NSString *)morphTemplate direct:(BOOL)direct
{
BOOL const isLandscape = self.width > self.layoutThreshold;
self.estimateLabelTopOffset.priority = UILayoutPriorityDefaultLow;
self.routingViewManuButtonPffset.priority = UILayoutPriorityDefaultLow;
for (NSLayoutConstraint * constraint in self.heightProfileContainerVerticalOrientation)
constraint.priority = UILayoutPriorityDefaultLow;
self.goButtonWidth.constant = isLandscape ? kGoButtonWidthLandscape : kGoButtonWidthRegular;
}
- (void)layoutRoutingGeometry
{
auto layoutAdditionalButtonsOffset = ^(CGFloat offset) {
for (NSLayoutConstraint * constraint in self.routingAdditionalButtonsOffset)
constraint.constant = offset;
};
auto layoutSpeedDistanceOffset = ^(CGFloat offset) {
for (NSLayoutConstraint * constraint in self.speedDistanceOffset)
constraint.constant = offset;
};
self.pageControlTopOffset.constant = kPageControlTopOffsetRegular;
self.pageControl.transform = CGAffineTransformIdentity;
self.speedLabel.hidden = NO;
self.distanceLabel.hidden = NO;
self.speedLegendLabel.hidden = NO;
self.distanceLegendLabel.hidden = NO;
self.speedWithLegendLabel.hidden = YES;
self.distanceWithLegendLabel.hidden = YES;
if (IPAD)
{
self.speedDistanceWidth.constant = kSpeedDistanceWidthRegular;
self.timeWidth.constant = kTimeWidthRegular;
self.mainButtonsHeight.constant = kRoutingMainButtonsHeightRegular;
self.menuButtonWidth.constant = kDefaultMenuButtonWidth;
layoutAdditionalButtonsOffset(kRoutingAdditionalButtonsOffsetRegular);
layoutSpeedDistanceOffset(kSpeedDistanceOffsetRegular);
}
else
{
self.timeWidth.constant = kTimeWidthRegular;
self.mainButtonsHeight.constant = kRoutingMainButtonsHeightCompact;
self.menuButtonWidth.constant = kRoutingMenuButtonWidthCompact;
layoutAdditionalButtonsOffset(kRoutingAdditionalButtonsOffsetCompact);
layoutSpeedDistanceOffset(kSpeedDistanceOffsetCompact);
if (self.width <= kThresholdCompact)
{
self.speedDistanceWidth.constant = kSpeedDistanceWidthCompact;
self.timeWidth.constant = kTimeWidthCompact;
}
else if (self.width <= kThresholdRegular)
{
self.speedDistanceWidth.constant = kSpeedDistanceWidthRegular;
}
else
{
self.pageControlTopOffset.constant = kPageControlTopOffsetLandscape;
self.pageControl.transform =
CGAffineTransformMakeScale(kPageControlScaleLandscape, kPageControlScaleLandscape);
self.speedDistanceWidth.constant = kSpeedDistanceWidthLandscape;
self.mainButtonsHeight.constant = kRoutingMainButtonsHeightLandscape;
self.menuButtonWidth.constant = kRoutingMenuButtonWidthRegular;
layoutAdditionalButtonsOffset(kRoutingAdditionalButtonsOffsetRegular);
self.speedLabel.hidden = YES;
self.distanceLabel.hidden = YES;
self.speedLegendLabel.hidden = YES;
self.distanceLegendLabel.hidden = YES;
self.speedWithLegendLabel.hidden = NO;
self.distanceWithLegendLabel.hidden = NO;
}
}
}
- (void)updateMenuButtonFromState:(MWMBottomMenuState)fromState toState:(MWMBottomMenuState)toState
{
if (fromState == MWMBottomMenuStateActive || toState == MWMBottomMenuStateActive)
[self morphMenuButtonTemplate:@"ic_menu_" toState:toState];
else if (fromState == MWMBottomMenuStateCompact || toState == MWMBottomMenuStateCompact)
[self morphMenuButtonTemplate:@"ic_menu_rotate_" toState:toState];
[self refreshMenuButtonState];
}
- (void)morphMenuButtonTemplate:(NSString *)morphTemplate toState:(MWMBottomMenuState)toState
{
BOOL const direct = toState == MWMBottomMenuStateActive || toState == MWMBottomMenuStateCompact;
UIButton * btn = self.menuButton;
NSUInteger const morphImagesCount = 6;
NSUInteger const startValue = direct ? 1 : morphImagesCount;
@ -535,6 +169,7 @@ CGFloat constexpr kTimeWidthRegular = 128;
btn.imageView.animationRepeatCount = 1;
btn.imageView.image = morphImages.lastObject;
[btn.imageView startAnimating];
[self refreshMenuButtonState];
}
- (void)refreshMenuButtonState
@ -546,64 +181,28 @@ CGFloat constexpr kTimeWidthRegular = 128;
}
else
{
UIButton * btn = self.menuButton;
NSString * name = nil;
switch (self.state)
{
case MWMBottomMenuStateHidden:
case MWMBottomMenuStateHidden: name = @"ic_menu"; break;
case MWMBottomMenuStateInactive:
case MWMBottomMenuStateRoutingError:
case MWMBottomMenuStateGo: name = @"ic_menu"; break;
case MWMBottomMenuStateActive:
case MWMBottomMenuStateRouting:
case MWMBottomMenuStateRoutingExpanded: name = @"ic_menu_down"; break;
case MWMBottomMenuStateCompact: name = @"ic_menu_left"; break;
}
UIImage * image = [UIImage imageNamed:name];
[btn setImage:image forState:UIControlStateNormal];
if (self.state == MWMBottomMenuStateInactive)
{
btn.transform = CGAffineTransformIdentity;
}
else
{
BOOL const rotate = (self.state == MWMBottomMenuStateRouting);
[UIView animateWithDuration:kDefaultAnimationDuration
animations:^{
btn.transform = rotate ? CGAffineTransformMakeRotation(M_PI)
: CGAffineTransformIdentity;
}];
name = [self isCompact] ? @"ic_menu_left" : @"ic_menu";
break;
case MWMBottomMenuStateActive: name = @"ic_menu_down"; break;
}
[self.menuButton setImage:[UIImage imageNamed:name] forState:UIControlStateNormal];
}
});
}
- (void)refreshOnOrientationChange
{
if (IPAD || self.state != MWMBottomMenuStateCompact)
return;
BOOL const isPortrait = self.superview.width < self.superview.height;
if (isPortrait)
self.owner.leftBound = 0.0;
}
- (void)refreshLayout
{
self.layoutDuration = kDefaultAnimationDuration;
[self setNeedsLayout];
if (self.state == MWMBottomMenuStateInactive)
[self updateBadge];
}
- (void)updateBadge
{
auto state = self.state;
if (state == MWMBottomMenuStateRouting || state == MWMBottomMenuStateRoutingExpanded ||
state == MWMBottomMenuStateGo)
{
self.downloadBadge.hidden = YES;
return;
}
auto & s = GetFramework().GetStorage();
storage::Storage::UpdateInfo updateInfo{};
s.GetUpdateInfo(s.GetRootId(), updateInfo);
@ -613,124 +212,32 @@ CGFloat constexpr kTimeWidthRegular = 128;
#pragma mark - Properties
- (void)setFrame:(CGRect)frame
{
frame.size.width = MAX(self.menuButtonWidth.constant, frame.size.width);
super.frame = frame;
}
- (void)setState:(MWMBottomMenuState)state
{
if (_state == state)
return;
[self refreshLayout];
BOOL updateMenuButton = YES;
switch (state)
{
case MWMBottomMenuStateHidden: updateMenuButton = NO; break;
case MWMBottomMenuStateInactive:
{
if (![MWMRouter isRoutingActive])
_leftBound = 0.0;
self.p2pButton.hidden = self.searchButton.hidden = self.bookmarksButton.hidden = NO;
self.menuButton.hidden = NO;
self.layoutDuration =
(_state == MWMBottomMenuStateCompact && !IPAD) ? 0.0 : kDefaultAnimationDuration;
break;
}
case MWMBottomMenuStateActive:
self.restoreState = _state;
[self updateMenuButtonFromState:_state toState:state];
self.menuButton.hidden = NO;
self.additionalButtons.hidden = NO;
self.bookmarksButton.hidden = NO;
self.p2pButton.hidden = NO;
self.searchButton.hidden = NO;
break;
case MWMBottomMenuStateCompact:
if (_state == MWMBottomMenuStateGo)
self.restoreState = _state;
self.layoutDuration = IPAD ? kDefaultAnimationDuration : 0.0;
self.menuButton.hidden = NO;
break;
case MWMBottomMenuStateGo:
{
self.goButton.enabled = YES;
self.goButton.hidden = NO;
self.estimateLabel.hidden = NO;
BOOL const hasAltitude = [MWMRouter hasRouteAltitude];
self.heightProfileContainer.hidden = !hasAltitude;
self.heightProfileElevation.hidden = !hasAltitude;
self.toggleInfoButton.hidden = YES;
self.speedView.hidden = YES;
self.timeView.hidden = YES;
self.distanceView.hidden = YES;
self.progressView.hidden = YES;
self.routingView.hidden = NO;
self.routingAdditionalView.hidden = YES;
break;
}
case MWMBottomMenuStateRoutingError:
self.goButton.hidden = YES;
self.estimateLabel.hidden = NO;
self.heightProfileContainer.hidden = YES;
self.heightProfileElevation.hidden = YES;
self.toggleInfoButton.hidden = YES;
self.speedView.hidden = YES;
self.timeView.hidden = YES;
self.distanceView.hidden = YES;
self.progressView.hidden = YES;
self.routingView.hidden = NO;
self.routingAdditionalView.hidden = YES;
break;
case MWMBottomMenuStateRouting:
self.menuButton.hidden = NO;
self.goButton.hidden = YES;
self.estimateLabel.hidden = YES;
self.heightProfileContainer.hidden = YES;
self.heightProfileElevation.hidden = YES;
self.toggleInfoButton.hidden = NO;
self.speedView.hidden = NO;
self.timeView.hidden = NO;
self.distanceView.hidden = NO;
self.progressView.hidden = NO;
self.routingView.hidden = NO;
self.routingAdditionalView.hidden = YES;
break;
case MWMBottomMenuStateRoutingExpanded:
self.menuButton.hidden = NO;
self.goButton.hidden = YES;
self.estimateLabel.hidden = YES;
self.heightProfileContainer.hidden = YES;
self.heightProfileElevation.hidden = YES;
self.toggleInfoButton.hidden = NO;
self.speedView.hidden = NO;
self.timeView.hidden = NO;
self.distanceView.hidden = NO;
self.progressView.hidden = NO;
self.routingView.hidden = NO;
self.routingAdditionalView.hidden = NO;
break;
}
if (updateMenuButton)
[self updateMenuButtonFromState:_state toState:state];
BOOL const isActive = (state == MWMBottomMenuStateActive);
self.additionalButtons.hidden = !isActive;
if (_state == MWMBottomMenuStateActive || isActive)
[self morphMenuButtonTemplate:@"ic_menu_" direct:isActive];
_state = state;
[self refreshLayout];
[self updateBadge];
}
- (void)setLeftBound:(CGFloat)leftBound
- (void)updateAvailableArea:(CGRect)frame
{
_leftBound = MAX(leftBound, 0.0);
if ([MWMNavigationDashboardManager manager].state != MWMNavigationDashboardStatePrepare)
self.state = _leftBound > 1.0 ? MWMBottomMenuStateCompact : self.restoreState;
[self setNeedsLayout];
}
- (void)setSearchIsActive:(BOOL)searchIsActive
{
_searchIsActive = self.searchButton.selected = searchIsActive;
if (CGRectEqualToRect(self.availableArea, frame))
return;
BOOL const wasCompact = [self isCompact];
self.availableArea = frame;
BOOL const isCompact = [self isCompact];
if (wasCompact || isCompact)
[self morphMenuButtonTemplate:@"ic_menu_rotate_" direct:isCompact];
[self refreshLayout];
}
- (BOOL)isCompact { return self.availableArea.origin.x > 0; }
#pragma mark - AvailableArea / PlacePageArea
- (MWMAvailableAreaAffectDirections)placePageAreaAffectDirections

View file

@ -1,33 +1,19 @@
#import "MWMBottomMenuView.h"
#import "MWMMapDownloaderTypes.h"
#import "MWMNavigationDashboardManager.h"
#include "platform/location.hpp"
@class MapViewController, MWMButton;
@protocol MWMBottomMenuControllerProtocol;
@class MapViewController, MWMButton, MWMTaxiCollectionView;
@protocol MWMBottomMenuControllerProtocol<NSObject>
- (void)actionDownloadMaps:(mwm::DownloaderMode)mode;
- (void)closeInfoScreens;
- (void)addPlace:(BOOL)isBusiness hasPoint:(BOOL)hasPoint point:(m2::PointD const &)point;
- (void)didFinishAddingPlace;
@end
@interface MWMBottomMenuViewController : UIViewController<MWMNavigationDashboardInfoProtocol>
@interface MWMBottomMenuViewController : UIViewController
+ (MWMBottomMenuViewController *)controller;
@property(nonatomic) MWMBottomMenuState state;
@property(weak, nonatomic) IBOutlet MWMButton * p2pButton;
@property(nonatomic) CGFloat leftBound;
- (instancetype)initWithParentController:(MapViewController *)controller
delegate:(id<MWMBottomMenuControllerProtocol>)delegate;
- (void)mwm_refreshUI;
- (MWMTaxiCollectionView *)taxiCollectionView;
- (void)setRoutingErrorMessage:(NSString *)routingErrorMessage;
+ (void)updateAvailableArea:(CGRect)frame;
@end

View file

@ -3,6 +3,7 @@
#import "EAGLView.h"
#import "MWMActivityViewController.h"
#import "MWMBottomMenuCollectionViewCell.h"
#import "MWMBottomMenuControllerProtocol.h"
#import "MWMBottomMenuLayout.h"
#import "MWMBottomMenuView.h"
#import "MWMButton.h"
@ -15,7 +16,6 @@
#import "MWMSearchManager.h"
#import "MWMSettingsViewController.h"
#import "MWMTextToSpeech.h"
#import "MWMTrafficManager.h"
#import "MapViewController.h"
#import "MapsAppDelegate.h"
#import "Statistics.h"
@ -30,13 +30,11 @@
#include "platform/mwm_version.hpp"
extern NSString * const kAlohalyticsTapEventKey;
extern NSString * const kSearchStateWillChangeNotification;
extern NSString * const kSearchStateKey;
namespace
{
CGFloat constexpr kLayoutThreshold = 420.0;
NSTimeInterval constexpr kRoutingDiminishInterval = 5.0;
} // namespace
typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
@ -54,43 +52,16 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
@end
@interface MWMBottomMenuViewController ()<UICollectionViewDataSource, UICollectionViewDelegate,
MWMTrafficManagerObserver>
@property(weak, nonatomic) MapViewController * controller;
@property(weak, nonatomic) IBOutlet UICollectionView * buttonsCollectionView;
@property(weak, nonatomic) IBOutlet UICollectionView * additionalButtons;
@property(weak, nonatomic) id<MWMBottomMenuControllerProtocol> delegate;
@property(nonatomic) BOOL searchIsActive;
@property(nonatomic) SolidTouchView * dimBackground;
MWMNavigationDashboardObserver, MWMSearchManagerObserver>
@property(nonatomic) MWMBottomMenuState restoreState;
@property(nonatomic) MWMDimBackground * dimBackground;
@property(nonatomic, readonly) NSUInteger additionalButtonsCount;
@property(weak, nonatomic) MWMNavigationDashboardEntity * navigationInfo;
@property(copy, nonatomic) NSString * routingErrorMessage;
@property(weak, nonatomic) IBOutlet UILabel * speedLabel;
@property(weak, nonatomic) IBOutlet UILabel * timeLabel;
@property(weak, nonatomic) IBOutlet UILabel * distanceLabel;
@property(weak, nonatomic) IBOutlet UILabel * speedLegendLabel;
@property(weak, nonatomic) IBOutlet UILabel * distanceLegendLabel;
@property(weak, nonatomic) IBOutlet UILabel * speedWithLegendLabel;
@property(weak, nonatomic) IBOutlet UILabel * distanceWithLegendLabel;
@property(weak, nonatomic) IBOutlet UIPageControl * routingInfoPageControl;
@property(weak, nonatomic) IBOutlet UILabel * estimateLabel;
@property(weak, nonatomic) IBOutlet UIView * progressView;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * routingProgress;
@property(weak, nonatomic) IBOutlet MWMButton * ttsSoundButton;
@property(weak, nonatomic) IBOutlet MWMButton * trafficButton;
@property(weak, nonatomic) IBOutlet MWMButton * searchButton;
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * mainButtonsHeight;
@property(weak, nonatomic) IBOutlet UICollectionView * additionalButtons;
@property(weak, nonatomic) MapViewController * controller;
@property(weak, nonatomic) id<MWMBottomMenuControllerProtocol> delegate;
@end
@ -101,6 +72,12 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
return [MWMMapViewControlsManager manager].menuController;
}
+ (void)updateAvailableArea:(CGRect)frame
{
auto view = static_cast<MWMBottomMenuView *>([self controller].view);
[view updateAvailableArea:frame];
}
- (instancetype)initWithParentController:(MapViewController *)controller
delegate:(id<MWMBottomMenuControllerProtocol>)delegate
{
@ -110,9 +87,7 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
_controller = controller;
_delegate = delegate;
[controller addChildViewController:self];
MWMBottomMenuView * view = (MWMBottomMenuView *)self.view;
[controller.view addSubview:view];
view.maxY = controller.view.height;
[controller.view addSubview:self.view];
}
return self;
}
@ -121,24 +96,16 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
- (void)viewDidLoad
{
[super viewDidLoad];
UICollectionView * bcv = self.buttonsCollectionView;
UICollectionView * bcv = self.additionalButtons;
[bcv registerWithCellClass:[MWMBottomMenuCollectionViewPortraitCell class]];
[bcv registerWithCellClass:[MWMBottomMenuCollectionViewLandscapeCell class]];
MWMBottomMenuLayout * cvLayout =
(MWMBottomMenuLayout *)self.buttonsCollectionView.collectionViewLayout;
(MWMBottomMenuLayout *)self.additionalButtons.collectionViewLayout;
cvLayout.layoutThreshold = kLayoutThreshold;
((MWMBottomMenuView *)self.view).layoutThreshold = kLayoutThreshold;
self.menuView.layoutThreshold = kLayoutThreshold;
NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(searchStateWillChange:)
name:kSearchStateWillChangeNotification
object:nil];
[nc addObserver:self
selector:@selector(ttsButtonStatusChanged:)
name:[MWMTextToSpeech ttsStatusNotificationKey]
object:nil];
[MWMTrafficManager addObserver:self];
[MWMSearchManager addObserver:self];
[MWMNavigationDashboardManager addObserver:self];
}
- (void)viewWillAppear:(BOOL)animated
@ -148,124 +115,16 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
}
- (void)mwm_refreshUI { [self.view mwm_refreshUI]; }
#pragma mark - MWMNavigationDashboardInfoProtocol
- (void)updateNavigationInfo:(MWMNavigationDashboardEntity *)info
{
if ([MWMRouter isTaxi])
return;
self.navigationInfo = info;
if (!info)
return;
NSDictionary * routingNumberAttributes = @{
NSForegroundColorAttributeName : [UIColor blackPrimaryText],
NSFontAttributeName : [UIFont bold24]
};
NSDictionary * routingLegendAttributes = @{
NSForegroundColorAttributeName : [UIColor blackSecondaryText],
NSFontAttributeName : [UIFont bold14]
};
self.estimateLabel.attributedText = info.estimate;
if (self.routingInfoPageControl.currentPage == 0)
{
self.timeLabel.text = [NSDateComponentsFormatter etaStringFrom:info.timeToTarget];
}
else
{
NSDate * arrivalDate = [[NSDate date] dateByAddingTimeInterval:info.timeToTarget];
self.timeLabel.text = [NSDateFormatter localizedStringFromDate:arrivalDate
dateStyle:NSDateFormatterNoStyle
timeStyle:NSDateFormatterShortStyle];
}
NSString * targetDistance = info.targetDistance;
NSMutableAttributedString * distance;
if (targetDistance)
{
self.distanceLabel.text = targetDistance;
distance = [[NSMutableAttributedString alloc] initWithString:targetDistance
attributes:routingNumberAttributes];
}
NSString * targetUnits = info.targetUnits;
if (targetUnits)
{
self.distanceLegendLabel.text = targetUnits;
if (distance)
{
[distance appendAttributedString:[[NSAttributedString alloc] initWithString:targetUnits
attributes:routingLegendAttributes]];
self.distanceWithLegendLabel.attributedText = distance;
}
}
NSString * currentSpeed = info.speed ?: @"0";
self.speedLabel.text = currentSpeed;
self.speedLegendLabel.text = info.speedUnits;
NSMutableAttributedString * speed =
[[NSMutableAttributedString alloc] initWithString:currentSpeed
attributes:routingNumberAttributes];
[speed
appendAttributedString:[[NSAttributedString alloc] initWithString:info.speedUnits
attributes:routingLegendAttributes]];
self.speedWithLegendLabel.attributedText = speed;
[self.progressView layoutIfNeeded];
[UIView animateWithDuration:kDefaultAnimationDuration
animations:^{
self.routingProgress.constant = self.progressView.width * info.progress / 100.;
[self.progressView layoutIfNeeded];
}];
}
#pragma mark - Routing
- (IBAction)toggleInfoTouchUpInside
{
self.routingInfoPageControl.currentPage =
(self.routingInfoPageControl.currentPage + 1) % self.routingInfoPageControl.numberOfPages;
[self updateNavigationInfo:self.navigationInfo];
[self refreshRoutingDiminishTimer];
}
- (IBAction)routingStartTouchUpInside { [MWMRouter startRouting]; }
- (IBAction)routingStopTouchUpInside { [MWMRouter stopRouting]; }
- (IBAction)soundTouchUpInside:(MWMButton *)sender
{
BOOL const isEnabled = sender.selected;
[Statistics logEvent:kStatMenu withParameters:@{kStatTTS : isEnabled ? kStatOn : kStatOff}];
[MWMTextToSpeech tts].active = !isEnabled;
[self refreshRoutingDiminishTimer];
}
#pragma mark - MWMTrafficManagerObserver
- (void)onTrafficStateUpdated
{
MWMButton * tb = self.trafficButton;
BOOL const enabled = ([MWMTrafficManager state] != TrafficManager::TrafficState::Disabled);
tb.selected = enabled;
}
- (IBAction)trafficTouchUpInside:(MWMButton *)sender
{
BOOL const switchOn = ([MWMTrafficManager state] == TrafficManager::TrafficState::Disabled);
[Statistics logEvent:kStatMenu withParameters:@{kStatTraffic : switchOn ? kStatOn : kStatOff}];
[MWMTrafficManager enableTraffic:switchOn];
[self refreshRoutingDiminishTimer];
}
#pragma mark - Refresh Collection View layout
- (void)refreshLayout
{
MWMBottomMenuLayout * cvLayout =
(MWMBottomMenuLayout *)self.buttonsCollectionView.collectionViewLayout;
(MWMBottomMenuLayout *)self.additionalButtons.collectionViewLayout;
cvLayout.buttonsCount = [self collectionView:self.additionalButtons numberOfItemsInSection:0];
[self.additionalButtons reloadData];
[(MWMBottomMenuView *)self.view refreshLayout];
[self.menuView refreshLayout];
}
#pragma mark - Layout
@ -276,24 +135,23 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
[self.additionalButtons reloadData];
}
#pragma mark - Notifications
#pragma mark - MWMNavigationDashboardObserver
- (void)searchStateWillChange:(NSNotification *)notification
- (void)onNavigationDashboardStateChanged
{
MWMSearchManagerState state =
MWMSearchManagerState([[notification userInfo][kSearchStateKey] unsignedIntegerValue]);
self.searchIsActive = state != MWMSearchManagerStateHidden;
auto const navigationState = [MWMNavigationDashboardManager manager].state;
if (navigationState == MWMNavigationDashboardStateHidden)
self.state = MWMBottomMenuStateInactive;
else
self.state = MWMBottomMenuStateHidden;
}
- (void)ttsButtonStatusChanged:(NSNotification *)notification
#pragma mark - MWMSearchManagerObserver
- (void)onSearchManagerStateChanged
{
if (![MWMRouter isRoutingActive])
return;
BOOL const isPedestrianRouting = [MWMRouter type] == MWMRouterTypePedestrian;
MWMButton * ttsButton = self.ttsSoundButton;
ttsButton.hidden = isPedestrianRouting || ![MWMTextToSpeech isTTSEnabled];
if (!ttsButton.hidden)
ttsButton.selected = [MWMTextToSpeech tts].active;
auto state = [MWMSearchManager manager].state;
self.searchButton.selected = (state != MWMSearchManagerStateHidden);
}
#pragma mark - UICollectionViewDataSource
@ -320,7 +178,7 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
case MWMBottomMenuViewCellAddPlace:
{
BOOL const isEnabled =
self.controller.controlsManager.navigationState == MWMNavigationDashboardStateHidden &&
[MWMNavigationDashboardManager manager].state == MWMNavigationDashboardStateHidden &&
GetFramework().CanEditMap();
[cell configureWithImageName:@"ic_add_place"
label:L(@"placepage_add_place_button")
@ -386,7 +244,7 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
- (void)menuActionDownloadMaps
{
[Statistics logEvent:kStatMenu withParameters:@{kStatButton : kStatDownloadMaps}];
self.state = self.restoreState;
self.state = MWMBottomMenuStateInactive;
[self.delegate actionDownloadMaps:mwm::DownloaderMode::Downloaded];
}
@ -424,9 +282,7 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
- (IBAction)point2PointButtonTouchUpInside:(UIButton *)sender
{
[Statistics logEvent:kStatMenu withParameters:@{kStatButton : kStatPointToPoint}];
self.state = self.restoreState;
BOOL const isSelected = !sender.isSelected;
sender.selected = isSelected;
if (isSelected)
[[MWMMapViewControlsManager manager] onRoutePrepare];
else
@ -437,16 +293,19 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
{
[Statistics logEvent:kStatMenu withParameters:@{kStatButton : kStatSearch}];
[Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"search"];
self.state = self.restoreState;
self.controller.controlsManager.searchHidden = self.searchIsActive;
self.state = MWMBottomMenuStateInactive;
auto searchManager = [MWMSearchManager manager];
if (searchManager.state == MWMSearchManagerStateHidden)
searchManager.state = MWMSearchManagerStateDefault;
else
searchManager.state = MWMSearchManagerStateHidden;
}
- (IBAction)bookmarksButtonTouchUpInside
{
[Statistics logEvent:kStatMenu withParameters:@{kStatButton : kStatBookmarks}];
[Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"bookmarks"];
self.state = self.restoreState;
[self.delegate closeInfoScreens];
self.state = MWMBottomMenuStateInactive;
[self.controller openBookmarks];
}
@ -456,161 +315,64 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) {
{
case MWMBottomMenuStateHidden: NSAssert(false, @"Incorrect state"); break;
case MWMBottomMenuStateInactive:
case MWMBottomMenuStateGo:
case MWMBottomMenuStateRoutingError:
[Statistics logEvent:kStatMenu withParameters:@{kStatButton : kStatExpand}];
self.state = MWMBottomMenuStateActive;
if ([self.menuView isCompact])
{
[Statistics logEvent:kStatMenu withParameters:@{kStatButton : kStatRegular}];
if (IPAD)
{
[MWMSearchManager manager].state = MWMSearchManagerStateHidden;
[MWMRouter stopRouting];
}
}
else
{
[Statistics logEvent:kStatMenu withParameters:@{kStatButton : kStatExpand}];
self.state = MWMBottomMenuStateActive;
}
break;
case MWMBottomMenuStateActive:
case MWMBottomMenuStateRoutingExpanded:
[Statistics logEvent:kStatMenu withParameters:@{kStatButton : kStatCollapse}];
self.state = self.restoreState;
self.state = MWMBottomMenuStateInactive;
break;
case MWMBottomMenuStateCompact:
[Statistics logEvent:kStatMenu withParameters:@{kStatButton : kStatRegular}];
[self.delegate closeInfoScreens];
break;
case MWMBottomMenuStateRouting: self.state = MWMBottomMenuStateRoutingExpanded; break;
}
}
- (void)dimBackgroundTap
{
// In case when there are 2 touch events (dimBackgroundTap & menuButtonTouchUpInside)
// if dimBackgroundTap is processed first then menuButtonTouchUpInside behaves as if menu is
// inactive this is wrong case, so we postpone dimBackgroundTap to make sure
// menuButtonTouchUpInside processed first
dispatch_async(dispatch_get_main_queue(), ^{
self.state = self.restoreState;
});
}
- (void)toggleDimBackgroundVisible:(BOOL)visible
{
if (visible)
[self.controller.view insertSubview:self.dimBackground belowSubview:self.view];
self.dimBackground.alpha = visible ? 0.0 : 0.8;
[UIView animateWithDuration:kDefaultAnimationDuration
animations:^{
self.dimBackground.alpha = visible ? 0.8 : 0.0;
}
completion:^(BOOL finished) {
if (!visible)
{
[self.dimBackground removeFromSuperview];
self.dimBackground = nil;
}
}];
}
- (void)refreshRoutingDiminishTimer
{
SEL const diminishFunction = @selector(diminishRoutingState);
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:diminishFunction object:self];
runAsyncOnMainQueue(^{
if (self.state == MWMBottomMenuStateRoutingExpanded)
[self performSelector:diminishFunction withObject:self afterDelay:kRoutingDiminishInterval];
});
}
- (void)diminishRoutingState { self.state = MWMBottomMenuStateRouting; }
#pragma mark - Properties
- (SolidTouchView *)dimBackground
- (MWMBottomMenuView *)menuView { return (MWMBottomMenuView *)self.view; }
- (MWMDimBackground *)dimBackground
{
if (!_dimBackground)
{
_dimBackground = [[SolidTouchView alloc] initWithFrame:self.controller.view.bounds];
_dimBackground.backgroundColor = [UIColor fadeBackground];
_dimBackground.autoresizingMask =
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
UITapGestureRecognizer * tap =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dimBackgroundTap)];
[_dimBackground addGestureRecognizer:tap];
}
_dimBackground = [[MWMDimBackground alloc] initWithMainView:self.view];
return _dimBackground;
}
- (MWMTaxiCollectionView *)taxiCollectionView
{
return static_cast<MWMBottomMenuView *>(self.view).taxiCollectionView;
}
- (void)setState:(MWMBottomMenuState)state
{
runAsyncOnMainQueue(^{
[self.controller setNeedsStatusBarAppearanceUpdate];
});
[self refreshRoutingDiminishTimer];
MWMBottomMenuView * view = (MWMBottomMenuView *)self.view;
BOOL const menuActive =
(state == MWMBottomMenuStateActive || state == MWMBottomMenuStateRoutingExpanded);
MWMBottomMenuView * view = self.menuView;
BOOL const menuActive = (state == MWMBottomMenuStateActive);
if (menuActive)
[self.controller.view bringSubviewToFront:view];
[self toggleDimBackgroundVisible:menuActive];
if (state == MWMBottomMenuStateRoutingExpanded)
[self ttsButtonStatusChanged:nil];
if (state == MWMBottomMenuStateInactive || state == MWMBottomMenuStateRouting)
{
dispatch_async(dispatch_get_main_queue(), ^{
self.p2pButton.selected =
([MWMNavigationDashboardManager manager].state == MWMNavigationDashboardStatePrepare);
});
view.state = self.restoreState = state;
return;
}
if (IPAD && state == MWMBottomMenuStateGo)
return;
if (view.state == MWMBottomMenuStateCompact &&
(state == MWMBottomMenuStateGo || state == MWMBottomMenuStateRouting))
self.restoreState = state;
else
view.state = state;
if (state == MWMBottomMenuStateRoutingError)
self.estimateLabel.text = self.routingErrorMessage;
}
- (MWMBottomMenuState)state { return ((MWMBottomMenuView *)self.view).state; }
- (void)setRestoreState:(MWMBottomMenuState)restoreState
{
((MWMBottomMenuView *)self.view).restoreState = restoreState;
}
- (MWMBottomMenuState)restoreState { return ((MWMBottomMenuView *)self.view).restoreState; }
- (void)setLeftBound:(CGFloat)leftBound
{
((MWMBottomMenuView *)self.view).leftBound = leftBound;
}
- (CGFloat)leftBound { return ((MWMBottomMenuView *)self.view).leftBound; }
- (void)setSearchIsActive:(BOOL)searchIsActive
{
((MWMBottomMenuView *)self.view).searchIsActive = searchIsActive;
}
- (BOOL)searchIsActive { return ((MWMBottomMenuView *)self.view).searchIsActive; }
- (void)setTtsSoundButton:(MWMButton *)ttsSoundButton
{
_ttsSoundButton = ttsSoundButton;
[ttsSoundButton setImage:[UIImage imageNamed:@"ic_voice_off"] forState:UIControlStateNormal];
[ttsSoundButton setImage:[UIImage imageNamed:@"ic_voice_on"] forState:UIControlStateSelected];
[ttsSoundButton setImage:[UIImage imageNamed:@"ic_voice_on"]
forState:UIControlStateSelected | UIControlStateHighlighted];
[self ttsButtonStatusChanged:nil];
}
- (void)setTrafficButton:(MWMButton *)trafficButton
{
_trafficButton = trafficButton;
[trafficButton setImage:[UIImage imageNamed:@"ic_setting_traffic_off"]
forState:UIControlStateNormal];
[trafficButton setImage:[UIImage imageNamed:@"ic_setting_traffic_on"]
forState:UIControlStateSelected];
[trafficButton setImage:[UIImage imageNamed:@"ic_setting_traffic_on"]
forState:UIControlStateSelected | UIControlStateHighlighted];
__weak auto wSelf = self;
[self.dimBackground setVisible:menuActive
tapAction:^{
// In case when there are 2 touch events (dimBackgroundTap &
// menuButtonTouchUpInside)
// if dimBackgroundTap is processed first then menuButtonTouchUpInside
// behaves as if menu is
// inactive this is wrong case, so we postpone dimBackgroundTap to make
// sure
// menuButtonTouchUpInside processed first
dispatch_async(dispatch_get_main_queue(), ^{
wSelf.state = MWMBottomMenuStateInactive;
});
}];
view.state = state;
}
- (MWMBottomMenuState)state { return self.menuView.state; }
@end

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
@ -13,22 +13,8 @@
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MWMBottomMenuViewController">
<connections>
<outlet property="additionalButtons" destination="hSd-fM-qKd" id="tT1-ml-chk"/>
<outlet property="buttonsCollectionView" destination="hSd-fM-qKd" id="Qrb-GJ-Buz"/>
<outlet property="distanceLabel" destination="LBZ-kD-25J" id="mBJ-kK-1Af"/>
<outlet property="distanceLegendLabel" destination="5ad-tg-al9" id="KFC-sq-rNA"/>
<outlet property="distanceWithLegendLabel" destination="LOZ-cm-r9V" id="H0T-Dh-0Q0"/>
<outlet property="estimateLabel" destination="EQy-vz-gyi" id="gJq-I7-TaC"/>
<outlet property="mainButtonsHeight" destination="HtR-j8-Qpc" id="uZ3-Im-taa"/>
<outlet property="p2pButton" destination="xQ0-ZK-UXk" id="LdY-Rt-Dh4"/>
<outlet property="progressView" destination="qvF-jY-5Gi" id="vS9-Cr-K1S"/>
<outlet property="routingInfoPageControl" destination="7hO-Gk-BGJ" id="gDI-Bk-PCb"/>
<outlet property="routingProgress" destination="pSf-au-FVR" id="FUM-bZ-3NE"/>
<outlet property="speedLabel" destination="Y2P-la-daO" id="xSa-kB-wlP"/>
<outlet property="speedLegendLabel" destination="P9v-a6-EaA" id="Bsq-v2-iGX"/>
<outlet property="speedWithLegendLabel" destination="azs-RS-4KE" id="v35-2h-E3B"/>
<outlet property="timeLabel" destination="jSU-Ns-SpQ" id="iJI-uD-Nz2"/>
<outlet property="trafficButton" destination="yHt-kJ-gHg" id="74n-Pu-wHS"/>
<outlet property="ttsSoundButton" destination="q6M-3k-tKX" id="rQp-HS-cub"/>
<outlet property="searchButton" destination="IzQ-aQ-aPH" id="XWA-9H-Hvg"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
@ -85,293 +71,6 @@
<action selector="bookmarksButtonTouchUpInside" destination="-1" eventType="touchUpInside" id="c14-Dx-sRy"/>
</connections>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="c75-ZF-hKn">
<rect key="frame" x="0.0" y="0.0" width="320" height="48"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="600" text="33 мин • 7.0 км" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EQy-vz-gyi">
<rect key="frame" x="16" y="14" width="122" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4Xc-Kl-hAm">
<rect key="frame" x="154" y="12" width="62" height="24"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="150" verticalHuggingPriority="150" horizontalCompressionResistancePriority="240" verticalCompressionResistancePriority="240" translatesAutoresizingMaskIntoConstraints="NO" id="ViI-p6-hUf">
<rect key="frame" x="0.0" y="0.0" width="62" height="24"/>
</imageView>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="ViI-p6-hUf" firstAttribute="leading" secondItem="4Xc-Kl-hAm" secondAttribute="leading" id="4Rl-3k-ej1"/>
<constraint firstAttribute="bottom" secondItem="ViI-p6-hUf" secondAttribute="bottom" id="YtA-RO-fmc"/>
<constraint firstItem="ViI-p6-hUf" firstAttribute="top" secondItem="4Xc-Kl-hAm" secondAttribute="top" id="gHG-Ij-huG"/>
<constraint firstAttribute="trailing" secondItem="ViI-p6-hUf" secondAttribute="trailing" id="tnv-Fq-At9"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nD5-wx-7Ui">
<rect key="frame" x="16" y="24" width="50" height="12"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ic_elevation" translatesAutoresizingMaskIntoConstraints="NO" id="FpX-u9-FuR">
<rect key="frame" x="0.0" y="0.0" width="10" height="12"/>
<constraints>
<constraint firstAttribute="height" constant="12" id="Wup-Xg-5Ce"/>
<constraint firstAttribute="width" constant="10" id="rVv-JG-SyM"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="270" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dVz-cc-LUM">
<rect key="frame" x="14" y="-2" width="36" height="17"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="linkBlue"/>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium14"/>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="FpX-u9-FuR" firstAttribute="leading" secondItem="nD5-wx-7Ui" secondAttribute="leading" id="2as-BP-0az"/>
<constraint firstItem="dVz-cc-LUM" firstAttribute="leading" secondItem="FpX-u9-FuR" secondAttribute="trailing" constant="4" id="Nhd-Y8-dTQ"/>
<constraint firstAttribute="trailing" secondItem="dVz-cc-LUM" secondAttribute="trailing" id="QIw-po-XUM"/>
<constraint firstAttribute="bottom" secondItem="FpX-u9-FuR" secondAttribute="bottom" id="a6A-3c-6yL"/>
<constraint firstItem="FpX-u9-FuR" firstAttribute="top" secondItem="nD5-wx-7Ui" secondAttribute="top" id="lus-SX-O0h"/>
<constraint firstItem="dVz-cc-LUM" firstAttribute="centerY" secondItem="FpX-u9-FuR" secondAttribute="centerY" id="yEP-oH-4ti"/>
</constraints>
</view>
<button hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" horizontalHuggingPriority="501" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pLD-sZ-ejH" userLabel="Go" customClass="MWMStartButton">
<rect key="frame" x="228" y="8" width="80" height="32"/>
<accessibility key="accessibilityConfiguration" identifier="routeStartButton"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="32" id="9LQ-Sj-W8f"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="80" id="ZHw-Ha-INX"/>
</constraints>
<inset key="contentEdgeInsets" minX="8" minY="0.0" maxX="8" maxY="0.0"/>
<state key="normal" title="Start"/>
<state key="selected">
<color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="0.26000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="bold14"/>
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="p2p_start"/>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="white"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="linkBlue"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="linkBlueHighlighted"/>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="6"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="routingStartTouchUpInside" destination="-1" eventType="touchUpInside" id="MfT-Tr-kyw"/>
</connections>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UhW-en-7qq">
<rect key="frame" x="0.0" y="0.0" width="72" height="48"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="azs-RS-4KE">
<rect key="frame" x="36" y="4" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Y2P-la-daO">
<rect key="frame" x="36" y="4" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
</userDefinedRuntimeAttributes>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="P9v-a6-EaA">
<rect key="frame" x="36" y="11" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="12"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="Y2P-la-daO" firstAttribute="centerX" secondItem="UhW-en-7qq" secondAttribute="centerX" priority="750" id="88p-qa-uC4"/>
<constraint firstItem="Y2P-la-daO" firstAttribute="top" secondItem="UhW-en-7qq" secondAttribute="top" constant="4" id="MZ8-us-Rv7"/>
<constraint firstItem="Y2P-la-daO" firstAttribute="top" secondItem="azs-RS-4KE" secondAttribute="top" id="QT8-xT-Ejv"/>
<constraint firstAttribute="width" constant="72" id="gTV-It-Bw2"/>
<constraint firstItem="P9v-a6-EaA" firstAttribute="centerX" secondItem="UhW-en-7qq" secondAttribute="centerX" id="iBn-F5-ghi"/>
<constraint firstItem="azs-RS-4KE" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="UhW-en-7qq" secondAttribute="leading" priority="800" id="n25-of-BgP"/>
<constraint firstItem="Y2P-la-daO" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="UhW-en-7qq" secondAttribute="leading" priority="800" id="ngt-x0-ZxF"/>
<constraint firstItem="azs-RS-4KE" firstAttribute="centerX" secondItem="UhW-en-7qq" secondAttribute="centerX" priority="750" id="w6y-IV-gBx"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Z68-6z-5Ph">
<rect key="frame" x="104" y="0.0" width="112" height="48"/>
<subviews>
<pageControl opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="100" contentHorizontalAlignment="center" contentVerticalAlignment="center" numberOfPages="2" translatesAutoresizingMaskIntoConstraints="NO" id="7hO-Gk-BGJ">
<rect key="frame" x="45" y="4" width="23" height="13"/>
<constraints>
<constraint firstAttribute="height" constant="13" id="a7i-03-Hg1"/>
</constraints>
</pageControl>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jSU-Ns-SpQ">
<rect key="frame" x="56" y="4" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="jSU-Ns-SpQ" firstAttribute="centerX" secondItem="Z68-6z-5Ph" secondAttribute="centerX" id="DKb-2f-om1"/>
<constraint firstAttribute="width" constant="112" id="GYP-RF-12U"/>
<constraint firstItem="7hO-Gk-BGJ" firstAttribute="top" secondItem="jSU-Ns-SpQ" secondAttribute="bottom" id="QPZ-lb-msg"/>
<constraint firstItem="jSU-Ns-SpQ" firstAttribute="top" secondItem="Z68-6z-5Ph" secondAttribute="top" constant="4" id="Rhh-4M-TJc"/>
<constraint firstItem="7hO-Gk-BGJ" firstAttribute="centerX" secondItem="Z68-6z-5Ph" secondAttribute="centerX" id="eUo-54-PMU"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="mab-rl-ueg">
<rect key="frame" x="248" y="0.0" width="72" height="48"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LOZ-cm-r9V">
<rect key="frame" x="36" y="4" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LBZ-kD-25J">
<rect key="frame" x="36" y="4" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
</userDefinedRuntimeAttributes>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5ad-tg-al9">
<rect key="frame" x="36" y="11" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="12"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="LBZ-kD-25J" firstAttribute="top" secondItem="mab-rl-ueg" secondAttribute="top" constant="4" id="LHZ-Zi-oiI"/>
<constraint firstItem="5ad-tg-al9" firstAttribute="centerX" secondItem="mab-rl-ueg" secondAttribute="centerX" id="Np5-b9-h9o"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="LBZ-kD-25J" secondAttribute="trailing" priority="800" id="cNE-r0-4Yr"/>
<constraint firstItem="LOZ-cm-r9V" firstAttribute="centerX" secondItem="mab-rl-ueg" secondAttribute="centerX" priority="750" id="eGb-8g-Xqu"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="LOZ-cm-r9V" secondAttribute="trailing" priority="800" id="f0u-ZK-Wth"/>
<constraint firstItem="LBZ-kD-25J" firstAttribute="centerX" secondItem="mab-rl-ueg" secondAttribute="centerX" priority="750" id="inD-aE-NAs"/>
<constraint firstItem="LOZ-cm-r9V" firstAttribute="top" secondItem="LBZ-kD-25J" secondAttribute="top" id="wrB-2E-Qo4"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qvF-jY-5Gi">
<rect key="frame" x="0.0" y="44" width="320" height="4"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xqD-Zl-BRc">
<rect key="frame" x="0.0" y="0.0" width="0.0" height="4"/>
<color key="backgroundColor" red="0.11764705882352941" green="0.58823529411764708" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" id="pSf-au-FVR"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="linkBlue"/>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.12" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="xqD-Zl-BRc" secondAttribute="bottom" id="4PZ-NH-ZvR"/>
<constraint firstItem="xqD-Zl-BRc" firstAttribute="leading" secondItem="qvF-jY-5Gi" secondAttribute="leading" id="Mfi-1F-Szz"/>
<constraint firstItem="xqD-Zl-BRc" firstAttribute="top" secondItem="qvF-jY-5Gi" secondAttribute="top" id="OJX-nO-nv6"/>
<constraint firstAttribute="height" constant="4" id="Ykh-lY-vbx"/>
</constraints>
</view>
<button contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3oJ-Rv-JS7" userLabel="ToggleInfo">
<rect key="frame" x="0.0" y="0.0" width="320" height="48"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<action selector="toggleInfoTouchUpInside" destination="-1" eventType="touchUpInside" id="kuP-Ue-Syq"/>
</connections>
</button>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iYj-za-A2N" userLabel="Taxi View">
<rect key="frame" x="0.0" y="0.0" width="216" height="48"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" pagingEnabled="YES" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="pUj-hX-AzZ" customClass="MWMTaxiCollectionView">
<rect key="frame" x="0.0" y="0.0" width="216" height="48"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="7nN-GY-zbW" customClass="MWMTaxiCollectionLayout">
<size key="itemSize" width="50" height="50"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
</collectionView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="pUj-hX-AzZ" firstAttribute="top" secondItem="iYj-za-A2N" secondAttribute="top" id="BBS-8B-zgK"/>
<constraint firstItem="pUj-hX-AzZ" firstAttribute="leading" secondItem="iYj-za-A2N" secondAttribute="leading" id="jpM-ZK-R3N"/>
<constraint firstAttribute="trailing" secondItem="pUj-hX-AzZ" secondAttribute="trailing" id="pgB-jZ-CDF"/>
<constraint firstAttribute="bottom" secondItem="pUj-hX-AzZ" secondAttribute="bottom" id="pt8-Js-FpC"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="3oJ-Rv-JS7" secondAttribute="trailing" id="3R5-Ud-LdZ"/>
<constraint firstItem="mab-rl-ueg" firstAttribute="top" secondItem="c75-ZF-hKn" secondAttribute="top" id="3xv-Y2-YLW"/>
<constraint firstAttribute="bottom" secondItem="qvF-jY-5Gi" secondAttribute="bottom" id="67I-jw-w1H"/>
<constraint firstItem="5ad-tg-al9" firstAttribute="centerY" secondItem="7hO-Gk-BGJ" secondAttribute="centerY" priority="500" id="6Q9-vO-V4W"/>
<constraint firstItem="Z68-6z-5Ph" firstAttribute="centerX" secondItem="c75-ZF-hKn" secondAttribute="centerX" id="AcE-Sk-hhd"/>
<constraint firstAttribute="bottom" secondItem="Z68-6z-5Ph" secondAttribute="bottom" id="BlR-TS-xJa"/>
<constraint firstItem="nD5-wx-7Ui" firstAttribute="trailing" secondItem="4Xc-Kl-hAm" secondAttribute="trailing" priority="250" id="CRC-g9-WLM"/>
<constraint firstAttribute="trailing" secondItem="pLD-sZ-ejH" secondAttribute="trailing" constant="12" id="E7k-Dh-qE5"/>
<constraint firstAttribute="bottom" secondItem="4Xc-Kl-hAm" secondAttribute="bottom" constant="12" id="IBg-Su-7fT"/>
<constraint firstAttribute="bottom" secondItem="3oJ-Rv-JS7" secondAttribute="bottom" id="QSK-8y-lMm"/>
<constraint firstAttribute="bottom" secondItem="mab-rl-ueg" secondAttribute="bottom" id="RM8-hF-4fE"/>
<constraint firstItem="mab-rl-ueg" firstAttribute="width" secondItem="UhW-en-7qq" secondAttribute="width" id="RsJ-Zl-Sbw"/>
<constraint firstItem="4Xc-Kl-hAm" firstAttribute="leading" secondItem="EQy-vz-gyi" secondAttribute="trailing" priority="500" constant="16" id="S6n-p8-BQM"/>
<constraint firstItem="UhW-en-7qq" firstAttribute="top" secondItem="c75-ZF-hKn" secondAttribute="top" id="SX8-Al-kd6"/>
<constraint firstItem="pLD-sZ-ejH" firstAttribute="centerY" secondItem="c75-ZF-hKn" secondAttribute="centerY" id="WrY-b3-G79"/>
<constraint firstItem="3oJ-Rv-JS7" firstAttribute="leading" secondItem="c75-ZF-hKn" secondAttribute="leading" id="Y2N-5d-l3x"/>
<constraint firstItem="UhW-en-7qq" firstAttribute="leading" secondItem="c75-ZF-hKn" secondAttribute="leading" id="ZCC-xJ-5Vg"/>
<constraint firstItem="4Xc-Kl-hAm" firstAttribute="top" secondItem="EQy-vz-gyi" secondAttribute="bottom" priority="250" constant="8" id="ZCb-We-WNy"/>
<constraint firstItem="EQy-vz-gyi" firstAttribute="centerY" secondItem="c75-ZF-hKn" secondAttribute="centerY" priority="500" id="ZKG-5z-sra"/>
<constraint firstItem="nD5-wx-7Ui" firstAttribute="leading" secondItem="EQy-vz-gyi" secondAttribute="leading" priority="260" id="b4o-Ke-eqq"/>
<constraint firstItem="Z68-6z-5Ph" firstAttribute="top" secondItem="c75-ZF-hKn" secondAttribute="top" id="cpY-Wy-lyr"/>
<constraint firstItem="EQy-vz-gyi" firstAttribute="leading" secondItem="c75-ZF-hKn" secondAttribute="leading" constant="16" id="fIE-wa-hE8"/>
<constraint firstItem="EQy-vz-gyi" firstAttribute="top" secondItem="c75-ZF-hKn" secondAttribute="top" priority="250" constant="12" id="fOa-qL-A5d"/>
<constraint firstItem="pLD-sZ-ejH" firstAttribute="leading" secondItem="4Xc-Kl-hAm" secondAttribute="trailing" constant="12" id="h3c-E6-aX6"/>
<constraint firstItem="nD5-wx-7Ui" firstAttribute="centerY" secondItem="EQy-vz-gyi" secondAttribute="centerY" priority="250" id="h5a-LJ-T8H"/>
<constraint firstItem="P9v-a6-EaA" firstAttribute="centerY" secondItem="7hO-Gk-BGJ" secondAttribute="centerY" priority="500" id="hEB-H2-4WJ"/>
<constraint firstItem="pLD-sZ-ejH" firstAttribute="leading" secondItem="iYj-za-A2N" secondAttribute="trailing" constant="12" id="i2q-jR-ekX"/>
<constraint firstItem="4Xc-Kl-hAm" firstAttribute="leading" secondItem="c75-ZF-hKn" secondAttribute="leading" priority="250" constant="12" id="mac-YL-Cyx"/>
<constraint firstItem="3oJ-Rv-JS7" firstAttribute="top" secondItem="c75-ZF-hKn" secondAttribute="top" id="plc-KQ-Bxg"/>
<constraint firstItem="iYj-za-A2N" firstAttribute="top" secondItem="c75-ZF-hKn" secondAttribute="top" id="sel-y0-6g8"/>
<constraint firstAttribute="bottom" secondItem="UhW-en-7qq" secondAttribute="bottom" id="tF2-H2-VBe"/>
<constraint firstItem="4Xc-Kl-hAm" firstAttribute="top" secondItem="c75-ZF-hKn" secondAttribute="top" priority="500" constant="12" id="vt3-dc-Ngf"/>
<constraint firstAttribute="trailing" secondItem="mab-rl-ueg" secondAttribute="trailing" id="w4c-fR-znA"/>
<constraint firstItem="nD5-wx-7Ui" firstAttribute="bottom" secondItem="4Xc-Kl-hAm" secondAttribute="bottom" priority="500" id="wq2-oV-MOH"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
</view>
<button opaque="NO" contentMode="center" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="YLY-C4-SBu" userLabel="Menu" customClass="MWMButton">
<rect key="frame" x="260" y="0.0" width="60" height="48"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
@ -404,30 +103,21 @@
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="qvF-jY-5Gi" firstAttribute="leading" secondItem="kbJ-If-gUR" secondAttribute="leading" id="4FM-cc-hga"/>
<constraint firstItem="YLY-C4-SBu" firstAttribute="leading" secondItem="c75-ZF-hKn" secondAttribute="trailing" priority="250" id="4e2-YH-he6"/>
<constraint firstAttribute="trailing" secondItem="YLY-C4-SBu" secondAttribute="trailing" identifier="menuTrailing" id="Ade-MQ-41P"/>
<constraint firstItem="c75-ZF-hKn" firstAttribute="leading" secondItem="kbJ-If-gUR" secondAttribute="leading" id="B1y-C3-Q6g"/>
<constraint firstItem="WLn-2O-Ivv" firstAttribute="centerY" secondItem="YLY-C4-SBu" secondAttribute="centerY" constant="-8" id="CjF-ja-g56"/>
<constraint firstItem="YLY-C4-SBu" firstAttribute="centerY" secondItem="kbJ-If-gUR" secondAttribute="centerY" id="Hly-tK-GHj"/>
<constraint firstAttribute="height" constant="48" id="HtR-j8-Qpc"/>
<constraint firstItem="iYj-za-A2N" firstAttribute="leading" secondItem="kbJ-If-gUR" secondAttribute="leading" id="JCb-W7-rfR"/>
<constraint firstItem="IzQ-aQ-aPH" firstAttribute="height" secondItem="kbJ-If-gUR" secondAttribute="height" id="JFI-3b-72w"/>
<constraint firstAttribute="trailing" secondItem="c75-ZF-hKn" secondAttribute="trailing" priority="500" id="L0y-Zo-LJu"/>
<constraint firstItem="c75-ZF-hKn" firstAttribute="top" secondItem="kbJ-If-gUR" secondAttribute="top" id="OyE-mG-Zi1"/>
<constraint firstItem="xQ0-ZK-UXk" firstAttribute="centerX" secondItem="kbJ-If-gUR" secondAttribute="centerX" multiplier="22:30" priority="999" id="RMv-Kx-9s6"/>
<constraint firstItem="qVh-dm-DDH" firstAttribute="centerY" secondItem="kbJ-If-gUR" secondAttribute="centerY" id="Rgu-Ok-h30"/>
<constraint firstItem="qVh-dm-DDH" firstAttribute="centerX" secondItem="kbJ-If-gUR" secondAttribute="centerX" multiplier="22:30" priority="998" id="SJM-MP-uAt"/>
<constraint firstItem="xQ0-ZK-UXk" firstAttribute="height" secondItem="kbJ-If-gUR" secondAttribute="height" id="WRQ-HY-d1P"/>
<constraint firstItem="qVh-dm-DDH" firstAttribute="centerX" secondItem="kbJ-If-gUR" secondAttribute="centerX" multiplier="385:300" priority="999" id="Wda-vl-hB4"/>
<constraint firstItem="qVh-dm-DDH" firstAttribute="height" secondItem="kbJ-If-gUR" secondAttribute="height" id="d2K-hv-PmH"/>
<constraint firstItem="iYj-za-A2N" firstAttribute="height" secondItem="kbJ-If-gUR" secondAttribute="height" id="erS-UF-ESy"/>
<constraint firstAttribute="bottom" secondItem="c75-ZF-hKn" secondAttribute="bottom" id="f6U-e7-mij"/>
<constraint firstItem="WLn-2O-Ivv" firstAttribute="centerX" secondItem="YLY-C4-SBu" secondAttribute="centerX" constant="8" id="lUQ-gw-psA"/>
<constraint firstItem="IzQ-aQ-aPH" firstAttribute="centerY" secondItem="kbJ-If-gUR" secondAttribute="centerY" id="nbW-x7-1M5"/>
<constraint firstItem="IzQ-aQ-aPH" firstAttribute="leading" secondItem="kbJ-If-gUR" secondAttribute="leading" id="qEI-fz-zc8"/>
<constraint firstItem="xQ0-ZK-UXk" firstAttribute="centerX" secondItem="kbJ-If-gUR" secondAttribute="centerX" multiplier="385:300" priority="998" id="r8v-8m-Uxx"/>
<constraint firstAttribute="trailing" secondItem="qvF-jY-5Gi" secondAttribute="trailing" id="tRN-si-eTf"/>
<constraint firstItem="YLY-C4-SBu" firstAttribute="height" secondItem="kbJ-If-gUR" secondAttribute="height" id="wGb-xV-jeL"/>
<constraint firstItem="xQ0-ZK-UXk" firstAttribute="centerY" secondItem="kbJ-If-gUR" secondAttribute="centerY" id="xfg-wf-76Q"/>
</constraints>
@ -454,109 +144,18 @@
<outlet property="delegate" destination="-1" id="vCZ-oz-Dam"/>
</connections>
</collectionView>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Z8y-bh-6dN">
<rect key="frame" x="0.0" y="48" width="320" height="64"/>
<subviews>
<button opaque="NO" contentMode="center" horizontalHuggingPriority="249" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="q6M-3k-tKX" customClass="MWMButton">
<rect key="frame" x="8" y="0.0" width="64" height="64"/>
<constraints>
<constraint firstAttribute="height" constant="64" id="10m-d2-9gu"/>
<constraint firstAttribute="width" priority="750" constant="64" id="7Ac-c5-WC7"/>
</constraints>
<state key="normal" image="ic_voice_on"/>
<state key="selected" image="ic_voice_off"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="coloringName" value="MWMBlack"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="soundTouchUpInside:" destination="-1" eventType="touchUpInside" id="CEW-OG-NlS"/>
</connections>
</button>
<button opaque="NO" contentMode="center" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yHt-kJ-gHg" userLabel="Traffic" customClass="MWMButton">
<rect key="frame" x="72" y="0.0" width="60" height="64"/>
<constraints>
<constraint firstAttribute="width" priority="750" constant="64" id="K7h-UL-AI3"/>
<constraint firstAttribute="height" constant="64" id="xes-CM-P6R"/>
</constraints>
<state key="normal" image="ic_setting_traffic_on"/>
<state key="selected" image="ic_setting_traffic_off"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="coloringName" value="MWMBlack"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="trafficTouchUpInside:" destination="-1" eventType="touchUpInside" id="4Fg-pP-9MU"/>
</connections>
</button>
<button opaque="NO" contentMode="center" horizontalHuggingPriority="249" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="o9v-sB-QHp" userLabel="Settings" customClass="MWMButton">
<rect key="frame" x="132" y="0.0" width="64" height="64"/>
<constraints>
<constraint firstAttribute="width" priority="750" constant="64" id="Jnf-Lp-dkq"/>
<constraint firstAttribute="height" constant="64" id="sw9-N1-meA"/>
</constraints>
<state key="normal" image="ic_menu_settings"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="coloringName" value="MWMBlack"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="menuActionOpenSettings" destination="-1" eventType="touchUpInside" id="CTJ-mX-3im"/>
</connections>
</button>
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Kyc-p0-3HI" customClass="MWMStopButton">
<rect key="frame" x="204" y="14" width="96" height="36"/>
<color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="96" id="aRk-9J-VLI"/>
<constraint firstAttribute="height" priority="750" constant="36" id="vAX-VM-89C"/>
</constraints>
<state key="normal" title="STOP">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="8"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="current_location_unknown_stop_button"/>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="whitePrimaryText"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="buttonRed"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="buttonRedHighlighted"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="routingStopTouchUpInside" destination="-1" eventType="touchUpInside" id="BSa-BK-A89"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="64" id="7YS-h4-f40"/>
<constraint firstItem="q6M-3k-tKX" firstAttribute="top" secondItem="Z8y-bh-6dN" secondAttribute="top" id="7fw-Gt-Pc2"/>
<constraint firstItem="yHt-kJ-gHg" firstAttribute="top" secondItem="Z8y-bh-6dN" secondAttribute="top" id="Gps-YB-s6h"/>
<constraint firstItem="o9v-sB-QHp" firstAttribute="leading" secondItem="yHt-kJ-gHg" secondAttribute="trailing" priority="250" constant="28" id="LLg-EQ-Wfh"/>
<constraint firstItem="yHt-kJ-gHg" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="q6M-3k-tKX" secondAttribute="trailing" id="QB4-T9-JP4"/>
<constraint firstItem="Kyc-p0-3HI" firstAttribute="top" secondItem="Z8y-bh-6dN" secondAttribute="top" priority="750" constant="14" id="YXv-ir-H20"/>
<constraint firstItem="q6M-3k-tKX" firstAttribute="leading" secondItem="Z8y-bh-6dN" secondAttribute="leading" constant="8" id="YYg-F1-zgo"/>
<constraint firstItem="yHt-kJ-gHg" firstAttribute="leading" secondItem="q6M-3k-tKX" secondAttribute="trailing" priority="250" constant="28" id="eRQ-gN-oVh"/>
<constraint firstItem="Kyc-p0-3HI" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="o9v-sB-QHp" secondAttribute="trailing" constant="8" id="qOR-b7-Cd3"/>
<constraint firstAttribute="trailing" secondItem="Kyc-p0-3HI" secondAttribute="trailing" constant="20" id="tcG-sa-4ho"/>
<constraint firstItem="o9v-sB-QHp" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="yHt-kJ-gHg" secondAttribute="trailing" id="tnG-Yt-PSq"/>
<constraint firstItem="o9v-sB-QHp" firstAttribute="top" secondItem="Z8y-bh-6dN" secondAttribute="top" id="tuu-Qe-DE7"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="hSd-fM-qKd" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="2jm-k3-CLB"/>
<constraint firstItem="kbJ-If-gUR" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="7id-li-IXL"/>
<constraint firstItem="Z8y-bh-6dN" firstAttribute="top" secondItem="kbJ-If-gUR" secondAttribute="bottom" id="8pw-s7-kk5"/>
<constraint firstItem="kbJ-If-gUR" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="EW9-WF-5Ww"/>
<constraint firstItem="hSd-fM-qKd" firstAttribute="width" secondItem="kbJ-If-gUR" secondAttribute="width" id="ZyG-aC-n5g"/>
<constraint firstItem="nYy-JN-hGA" firstAttribute="width" secondItem="kbJ-If-gUR" secondAttribute="width" id="aPf-C5-OHV"/>
<constraint firstItem="nYy-JN-hGA" firstAttribute="top" secondItem="kbJ-If-gUR" secondAttribute="bottom" id="dBo-Kv-eJX"/>
<constraint firstItem="Z8y-bh-6dN" firstAttribute="trailing" secondItem="kbJ-If-gUR" secondAttribute="trailing" id="gWJ-W7-dql"/>
<constraint firstItem="nYy-JN-hGA" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="hat-Yn-atq"/>
<constraint firstAttribute="trailing" secondItem="kbJ-If-gUR" secondAttribute="trailing" id="jqh-CM-yl5"/>
<constraint firstItem="hSd-fM-qKd" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="49" id="mSh-nB-1Bt"/>
<constraint firstItem="Z8y-bh-6dN" firstAttribute="leading" secondItem="kbJ-If-gUR" secondAttribute="leading" id="soJ-Iq-iqm"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<nil key="simulatedTopBarMetrics"/>
@ -565,54 +164,13 @@
<connections>
<outlet property="additionalButtons" destination="hSd-fM-qKd" id="Rgj-Fo-JK8"/>
<outlet property="additionalButtonsHeight" destination="fsD-HQ-mF9" id="zki-cR-ZH6"/>
<outlet property="bookmarksButton" destination="qVh-dm-DDH" id="ZaH-0y-b64"/>
<outlet property="distanceLabel" destination="LBZ-kD-25J" id="wbW-B8-oSZ"/>
<outlet property="distanceLegendLabel" destination="5ad-tg-al9" id="bb9-Ou-Jw3"/>
<outlet property="distanceView" destination="mab-rl-ueg" id="wnH-29-JDU"/>
<outlet property="distanceWithLegendLabel" destination="LOZ-cm-r9V" id="Cdx-SJ-kAY"/>
<outlet property="downloadBadge" destination="WLn-2O-Ivv" id="f9u-k6-l9u"/>
<outlet property="elevationHeight" destination="dVz-cc-LUM" id="kBh-29-6zr"/>
<outlet property="elevationImage" destination="FpX-u9-FuR" id="j3J-NH-eKH"/>
<outlet property="estimateLabel" destination="EQy-vz-gyi" id="lVV-FW-8AJ"/>
<outlet property="estimateLabelTopOffset" destination="fOa-qL-A5d" id="7eJ-Go-MBm"/>
<outlet property="goButton" destination="pLD-sZ-ejH" id="Txw-4S-mwR"/>
<outlet property="goButtonWidth" destination="ZHw-Ha-INX" id="H3K-lh-Iyx"/>
<outlet property="heightProfileContainer" destination="4Xc-Kl-hAm" id="ovY-lT-vrD"/>
<outlet property="heightProfileElevation" destination="nD5-wx-7Ui" id="DBa-gs-tSc"/>
<outlet property="heightProfileImage" destination="ViI-p6-hUf" id="8b8-rT-Hpc"/>
<outlet property="mainButtons" destination="kbJ-If-gUR" id="1sk-bi-6xl"/>
<outlet property="mainButtonsHeight" destination="HtR-j8-Qpc" id="eF8-KH-F9n"/>
<outlet property="menuButton" destination="YLY-C4-SBu" id="A5G-Bc-IlQ"/>
<outlet property="menuButtonWidth" destination="ams-2s-vhw" id="Til-tN-VJX"/>
<outlet property="owner" destination="-1" id="qBx-4k-WvI"/>
<outlet property="p2pButton" destination="xQ0-ZK-UXk" id="9m1-MT-C9s"/>
<outlet property="pageControl" destination="7hO-Gk-BGJ" id="f0w-P7-cwm"/>
<outlet property="pageControlTopOffset" destination="QPZ-lb-msg" id="p8z-Q9-GRQ"/>
<outlet property="progressView" destination="qvF-jY-5Gi" id="Sdq-TL-4Qi"/>
<outlet property="routingAdditionalView" destination="Z8y-bh-6dN" id="mI8-4T-Rbi"/>
<outlet property="routingAdditionalViewHeight" destination="7YS-h4-f40" id="24L-Xv-Z9V"/>
<outlet property="routingView" destination="c75-ZF-hKn" id="OdE-md-8FJ"/>
<outlet property="routingViewManuButtonPffset" destination="4e2-YH-he6" id="nie-j7-P27"/>
<outlet property="searchButton" destination="IzQ-aQ-aPH" id="2dy-QI-T39"/>
<outlet property="separator" destination="nYy-JN-hGA" id="z8u-tH-WGu"/>
<outlet property="separatorHeight" destination="Kgm-bO-O6Q" id="RGg-dL-lKg"/>
<outlet property="speedDistanceWidth" destination="gTV-It-Bw2" id="fKs-sD-hDh"/>
<outlet property="speedLabel" destination="Y2P-la-daO" id="Iqa-La-VJP"/>
<outlet property="speedLegendLabel" destination="P9v-a6-EaA" id="oIZ-cZ-BPO"/>
<outlet property="speedView" destination="UhW-en-7qq" id="DOS-6a-5Lq"/>
<outlet property="speedWithLegendLabel" destination="azs-RS-4KE" id="IKs-sU-2y7"/>
<outlet property="taxiCollectionView" destination="pUj-hX-AzZ" id="PoM-nO-aCN"/>
<outlet property="taxiContainer" destination="iYj-za-A2N" id="CHw-td-MRB"/>
<outlet property="timeLabel" destination="jSU-Ns-SpQ" id="FVG-3M-FUa"/>
<outlet property="timeView" destination="Z68-6z-5Ph" id="x9I-5l-x9o"/>
<outlet property="timeWidth" destination="GYP-RF-12U" id="kyM-Ym-X1y"/>
<outlet property="toggleInfoButton" destination="3oJ-Rv-JS7" id="M1f-kU-SY5"/>
<outletCollection property="speedDistanceOffset" destination="ZCC-xJ-5Vg" id="IfJ-Mb-OUw"/>
<outletCollection property="speedDistanceOffset" destination="w4c-fR-znA" id="q0p-e4-syx"/>
<outletCollection property="heightProfileContainerVerticalOrientation" destination="mac-YL-Cyx" id="L7C-H0-A6R"/>
<outletCollection property="heightProfileContainerVerticalOrientation" destination="ZCb-We-WNy" id="uzJ-Eb-Epe"/>
<outletCollection property="heightProfileContainerVerticalOrientation" destination="CRC-g9-WLM" id="Zr9-y7-E9U"/>
<outletCollection property="heightProfileContainerVerticalOrientation" destination="h5a-LJ-T8H" id="89A-IH-XBE"/>
<outletCollection property="mainButtonConstraintsLeftToRight" destination="RMv-Kx-9s6" id="bdV-lr-UW4"/>
<outletCollection property="mainButtonConstraintsLeftToRight" destination="Wda-vl-hB4" id="mlw-3b-7eT"/>
</connections>
@ -620,15 +178,9 @@
</view>
</objects>
<resources>
<image name="ic_elevation" width="10" height="12"/>
<image name="ic_menu" width="48" height="48"/>
<image name="ic_menu_bookmark_list" width="48" height="48"/>
<image name="ic_menu_point_to_point" width="48" height="48"/>
<image name="ic_menu_search" width="48" height="48"/>
<image name="ic_menu_settings" width="28" height="28"/>
<image name="ic_setting_traffic_off" width="24" height="24"/>
<image name="ic_setting_traffic_on" width="24" height="24"/>
<image name="ic_voice_off" width="28" height="28"/>
<image name="ic_voice_on" width="28" height="28"/>
</resources>
</document>

View file

@ -0,0 +1,29 @@
typedef NS_ENUM(NSUInteger, MWMEditorCellType) {
MWMEditorCellTypePostcode = feature::Metadata::EType::FMD_COUNT,
MWMEditorCellTypePhoneNumber,
MWMEditorCellTypeWebsite,
MWMEditorCellTypeURL,
MWMEditorCellTypeEmail,
MWMEditorCellTypeOperator,
MWMEditorCellTypeOpenHours,
MWMEditorCellTypeWiFi,
MWMEditorCellTypeCoordinate,
MWMEditorCellTypeBookmark,
MWMEditorCellTypeEditButton,
MWMEditorCellTypeAddBusinessButton,
MWMEditorCellTypeAddPlaceButton,
MWMEditorCellTypeReportButton,
MWMEditorCellTypeCategory,
MWMEditorCellTypeName,
MWMEditorCellTypeAdditionalName,
MWMEditorCellTypeAddAdditionalName,
MWMEditorCellTypeAddAdditionalNamePlaceholder,
MWMEditorCellTypeStreet,
MWMEditorCellTypeBuilding,
MWMEditorCellTypeZipCode,
MWMEditorCellTypeBuildingLevels,
MWMEditorCellTypeCuisine,
MWMEditorCellTypeNote,
MWMEditorCellTypeBookingMore,
MWMEditorCellTypeCount
};

View file

@ -9,6 +9,7 @@
#import "MWMEditorAdditionalNamesHeader.h"
#import "MWMEditorAdditionalNamesTableViewController.h"
#import "MWMEditorCategoryCell.h"
#import "MWMEditorCellType.h"
#import "MWMEditorCommon.h"
#import "MWMEditorNotesFooter.h"
#import "MWMEditorSelectTableViewCell.h"
@ -17,7 +18,6 @@
#import "MWMNoteCell.h"
#import "MWMObjectsCategorySelectorController.h"
#import "MWMOpeningHoursEditorViewController.h"
#import "MWMPlacePageEntity.h"
#import "MWMPlacePageOpeningHoursCell.h"
#import "MWMStreetEditorViewController.h"
#import "MapViewController.h"
@ -25,6 +25,10 @@
#import "SwiftBridge.h"
#import "UIViewController+Navigation.h"
#include "Framework.h"
#include "indexer/osm_editor.hpp"
#include "std/algorithm.hpp"
namespace
@ -49,35 +53,35 @@ typedef NS_ENUM(NSUInteger, MWMEditorSection) {
MWMEditorSectionButton
};
vector<MWMPlacePageCellType> const kSectionCategoryCellTypes{MWMPlacePageCellTypeCategory};
vector<MWMPlacePageCellType> const kSectionAddressCellTypes{
MWMPlacePageCellTypeStreet, MWMPlacePageCellTypeBuilding, MWMPlacePageCellTypeZipCode};
vector<MWMEditorCellType> const kSectionCategoryCellTypes{MWMEditorCellTypeCategory};
vector<MWMEditorCellType> const kSectionAddressCellTypes{
MWMEditorCellTypeStreet, MWMEditorCellTypeBuilding, MWMEditorCellTypeZipCode};
vector<MWMPlacePageCellType> const kSectionNoteCellTypes{MWMPlacePageCellTypeNote};
vector<MWMPlacePageCellType> const kSectionButtonCellTypes{MWMPlacePageCellTypeReportButton};
vector<MWMEditorCellType> const kSectionNoteCellTypes{MWMEditorCellTypeNote};
vector<MWMEditorCellType> const kSectionButtonCellTypes{MWMEditorCellTypeReportButton};
using MWMPlacePageCellTypeClassMap = map<MWMPlacePageCellType, Class>;
MWMPlacePageCellTypeClassMap const kCellType2Class{
{MWMPlacePageCellTypeCategory, [MWMEditorCategoryCell class]},
{MWMPlacePageCellTypeAdditionalName, [MWMEditorAdditionalNameTableViewCell class]},
{MWMPlacePageCellTypeAddAdditionalName, [MWMEditorAddAdditionalNameTableViewCell class]},
{MWMPlacePageCellTypeAddAdditionalNamePlaceholder,
using MWMEditorCellTypeClassMap = map<MWMEditorCellType, Class>;
MWMEditorCellTypeClassMap const kCellType2Class{
{MWMEditorCellTypeCategory, [MWMEditorCategoryCell class]},
{MWMEditorCellTypeAdditionalName, [MWMEditorAdditionalNameTableViewCell class]},
{MWMEditorCellTypeAddAdditionalName, [MWMEditorAddAdditionalNameTableViewCell class]},
{MWMEditorCellTypeAddAdditionalNamePlaceholder,
[MWMEditorAdditionalNamePlaceholderTableViewCell class]},
{MWMPlacePageCellTypeStreet, [MWMEditorSelectTableViewCell class]},
{MWMPlacePageCellTypeBuilding, [MWMEditorTextTableViewCell class]},
{MWMPlacePageCellTypeZipCode, [MWMEditorTextTableViewCell class]},
{MWMPlacePageCellTypeBuildingLevels, [MWMEditorTextTableViewCell class]},
{MWMPlacePageCellTypeOpenHours, [MWMPlacePageOpeningHoursCell class]},
{MWMPlacePageCellTypePhoneNumber, [MWMEditorTextTableViewCell class]},
{MWMPlacePageCellTypeWebsite, [MWMEditorTextTableViewCell class]},
{MWMPlacePageCellTypeEmail, [MWMEditorTextTableViewCell class]},
{MWMPlacePageCellTypeOperator, [MWMEditorTextTableViewCell class]},
{MWMPlacePageCellTypeCuisine, [MWMEditorSelectTableViewCell class]},
{MWMPlacePageCellTypeWiFi, [MWMEditorSwitchTableViewCell class]},
{MWMPlacePageCellTypeNote, [MWMNoteCell class]},
{MWMPlacePageCellTypeReportButton, [MWMButtonCell class]}};
{MWMEditorCellTypeStreet, [MWMEditorSelectTableViewCell class]},
{MWMEditorCellTypeBuilding, [MWMEditorTextTableViewCell class]},
{MWMEditorCellTypeZipCode, [MWMEditorTextTableViewCell class]},
{MWMEditorCellTypeBuildingLevels, [MWMEditorTextTableViewCell class]},
{MWMEditorCellTypeOpenHours, [MWMPlacePageOpeningHoursCell class]},
{MWMEditorCellTypePhoneNumber, [MWMEditorTextTableViewCell class]},
{MWMEditorCellTypeWebsite, [MWMEditorTextTableViewCell class]},
{MWMEditorCellTypeEmail, [MWMEditorTextTableViewCell class]},
{MWMEditorCellTypeOperator, [MWMEditorTextTableViewCell class]},
{MWMEditorCellTypeCuisine, [MWMEditorSelectTableViewCell class]},
{MWMEditorCellTypeWiFi, [MWMEditorSwitchTableViewCell class]},
{MWMEditorCellTypeNote, [MWMNoteCell class]},
{MWMEditorCellTypeReportButton, [MWMButtonCell class]}};
Class cellClass(MWMPlacePageCellType cellType)
Class cellClass(MWMEditorCellType cellType)
{
auto const it = kCellType2Class.find(cellType);
ASSERT(it != kCellType2Class.end(), ());
@ -98,45 +102,45 @@ void cleanupAdditionalLanguages(vector<osm::LocalizedName> const & names,
newAdditionalLanguages.end());
}
vector<MWMPlacePageCellType> cellsForAdditionalNames(
osm::NamesDataSource const & ds, vector<NSInteger> const & newAdditionalLanguages,
BOOL showAdditionalNames)
vector<MWMEditorCellType> cellsForAdditionalNames(osm::NamesDataSource const & ds,
vector<NSInteger> const & newAdditionalLanguages,
BOOL showAdditionalNames)
{
vector<MWMPlacePageCellType> res;
vector<MWMEditorCellType> res;
auto const allNamesSize = ds.names.size() + newAdditionalLanguages.size();
if (allNamesSize != 0)
{
if (showAdditionalNames)
{
res.insert(res.begin(), allNamesSize, MWMPlacePageCellTypeAdditionalName);
res.insert(res.begin(), allNamesSize, MWMEditorCellTypeAdditionalName);
}
else
{
auto const mandatoryNamesCount = ds.mandatoryNamesCount;
res.insert(res.begin(), mandatoryNamesCount, MWMPlacePageCellTypeAdditionalName);
res.insert(res.begin(), mandatoryNamesCount, MWMEditorCellTypeAdditionalName);
if (allNamesSize > mandatoryNamesCount)
res.push_back(MWMPlacePageCellTypeAddAdditionalNamePlaceholder);
res.push_back(MWMEditorCellTypeAddAdditionalNamePlaceholder);
}
}
res.push_back(MWMPlacePageCellTypeAddAdditionalName);
res.push_back(MWMEditorCellTypeAddAdditionalName);
return res;
}
vector<MWMPlacePageCellType> cellsForProperties(vector<osm::Props> const & props)
vector<MWMEditorCellType> cellsForProperties(vector<osm::Props> const & props)
{
using namespace osm;
vector<MWMPlacePageCellType> res;
vector<MWMEditorCellType> res;
for (auto const p : props)
{
switch (p)
{
case Props::OpeningHours: res.push_back(MWMPlacePageCellTypeOpenHours); break;
case Props::Phone: res.push_back(MWMPlacePageCellTypePhoneNumber); break;
case Props::Website: res.push_back(MWMPlacePageCellTypeWebsite); break;
case Props::Email: res.push_back(MWMPlacePageCellTypeEmail); break;
case Props::Cuisine: res.push_back(MWMPlacePageCellTypeCuisine); break;
case Props::Operator: res.push_back(MWMPlacePageCellTypeOperator); break;
case Props::Internet: res.push_back(MWMPlacePageCellTypeWiFi); break;
case Props::OpeningHours: res.push_back(MWMEditorCellTypeOpenHours); break;
case Props::Phone: res.push_back(MWMEditorCellTypePhoneNumber); break;
case Props::Website: res.push_back(MWMEditorCellTypeWebsite); break;
case Props::Email: res.push_back(MWMEditorCellTypeEmail); break;
case Props::Cuisine: res.push_back(MWMEditorCellTypeCuisine); break;
case Props::Operator: res.push_back(MWMEditorCellTypeOperator); break;
case Props::Internet: res.push_back(MWMEditorCellTypeWiFi); break;
case Props::Wikipedia:
case Props::Fax:
case Props::Stars:
@ -148,7 +152,7 @@ vector<MWMPlacePageCellType> cellsForProperties(vector<osm::Props> const & props
return res;
}
void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITableView * tv)
void registerCellsForTableView(vector<MWMEditorCellType> const & cells, UITableView * tv)
{
for (auto const c : cells)
[tv registerWithCellClass:cellClass(c)];
@ -176,7 +180,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
@implementation MWMEditorViewController
{
vector<MWMEditorSection> m_sections;
map<MWMEditorSection, vector<MWMPlacePageCellType>> m_cells;
map<MWMEditorSection, vector<MWMEditorCellType>> m_cells;
osm::EditableMapObject m_mapObject;
vector<NSInteger> m_newAdditionalLanguages;
}
@ -411,7 +415,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
m_sections.push_back(MWMEditorSectionAddress);
m_cells[MWMEditorSectionAddress] = kSectionAddressCellTypes;
if (m_mapObject.IsBuilding() && !m_mapObject.IsPointType())
m_cells[MWMEditorSectionAddress].push_back(MWMPlacePageCellTypeBuildingLevels);
m_cells[MWMEditorSectionAddress].push_back(MWMEditorCellTypeBuildingLevels);
registerCellsForTableView(kSectionAddressCellTypes, self.tableView);
}
@ -441,7 +445,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
registerCellsForTableView(kSectionButtonCellTypes, self.tableView);
}
- (MWMPlacePageCellType)cellTypeForIndexPath:(NSIndexPath *)indexPath
- (MWMEditorCellType)cellTypeForIndexPath:(NSIndexPath *)indexPath
{
return m_cells[m_sections[indexPath.section]][indexPath.row];
}
@ -458,7 +462,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
BOOL const isValid = ![self.invalidCells containsObject:indexPath];
switch ([self cellTypeForIndexPath:indexPath])
{
case MWMPlacePageCellTypeCategory:
case MWMEditorCellTypeCategory:
{
MWMEditorCategoryCell * cCell = static_cast<MWMEditorCategoryCell *>(cell);
[cCell configureWithDelegate:self
@ -466,7 +470,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
isCreating:self.isCreating];
break;
}
case MWMPlacePageCellTypePhoneNumber:
case MWMEditorCellTypePhoneNumber:
{
MWMEditorTextTableViewCell * tCell = static_cast<MWMEditorTextTableViewCell *>(cell);
[tCell configWithDelegate:self
@ -479,7 +483,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
capitalization:UITextAutocapitalizationTypeNone];
break;
}
case MWMPlacePageCellTypeWebsite:
case MWMEditorCellTypeWebsite:
{
MWMEditorTextTableViewCell * tCell = static_cast<MWMEditorTextTableViewCell *>(cell);
[tCell configWithDelegate:self
@ -492,7 +496,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
capitalization:UITextAutocapitalizationTypeNone];
break;
}
case MWMPlacePageCellTypeEmail:
case MWMEditorCellTypeEmail:
{
MWMEditorTextTableViewCell * tCell = static_cast<MWMEditorTextTableViewCell *>(cell);
[tCell configWithDelegate:self
@ -505,7 +509,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
capitalization:UITextAutocapitalizationTypeNone];
break;
}
case MWMPlacePageCellTypeOperator:
case MWMEditorCellTypeOperator:
{
MWMEditorTextTableViewCell * tCell = static_cast<MWMEditorTextTableViewCell *>(cell);
[tCell configWithDelegate:self
@ -516,14 +520,14 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
capitalization:UITextAutocapitalizationTypeSentences];
break;
}
case MWMPlacePageCellTypeOpenHours:
case MWMEditorCellTypeOpenHours:
{
MWMPlacePageOpeningHoursCell * tCell = static_cast<MWMPlacePageOpeningHoursCell *>(cell);
NSString * text = @(m_mapObject.GetOpeningHours().c_str());
[tCell configWithDelegate:self info:(text.length ? text : L(@"add_opening_hours"))];
break;
}
case MWMPlacePageCellTypeWiFi:
case MWMEditorCellTypeWiFi:
{
MWMEditorSwitchTableViewCell * tCell = static_cast<MWMEditorSwitchTableViewCell *>(cell);
// TODO(Vlad, IgorTomko): Support all other possible Internet statuses.
@ -533,7 +537,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
on:m_mapObject.GetInternet() == osm::Internet::Wlan];
break;
}
case MWMPlacePageCellTypeAdditionalName:
case MWMEditorCellTypeAdditionalName:
{
MWMEditorAdditionalNameTableViewCell * tCell =
static_cast<MWMEditorAdditionalNameTableViewCell *>(cell);
@ -574,15 +578,15 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
}
break;
}
case MWMPlacePageCellTypeAddAdditionalName:
case MWMEditorCellTypeAddAdditionalName:
{
MWMEditorAddAdditionalNameTableViewCell * tCell =
static_cast<MWMEditorAddAdditionalNameTableViewCell *>(cell);
[tCell configWithDelegate:self];
break;
}
case MWMPlacePageCellTypeAddAdditionalNamePlaceholder: break;
case MWMPlacePageCellTypeStreet:
case MWMEditorCellTypeAddAdditionalNamePlaceholder: break;
case MWMEditorCellTypeStreet:
{
MWMEditorSelectTableViewCell * tCell = static_cast<MWMEditorSelectTableViewCell *>(cell);
[tCell configWithDelegate:self
@ -591,7 +595,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
placeholder:L(@"add_street")];
break;
}
case MWMPlacePageCellTypeBuilding:
case MWMEditorCellTypeBuilding:
{
MWMEditorTextTableViewCell * tCell = static_cast<MWMEditorTextTableViewCell *>(cell);
[tCell configWithDelegate:self
@ -604,7 +608,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
capitalization:UITextAutocapitalizationTypeNone];
break;
}
case MWMPlacePageCellTypeZipCode:
case MWMEditorCellTypeZipCode:
{
MWMEditorTextTableViewCell * tCell = static_cast<MWMEditorTextTableViewCell *>(cell);
[tCell configWithDelegate:self
@ -617,7 +621,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
capitalization:UITextAutocapitalizationTypeAllCharacters];
break;
}
case MWMPlacePageCellTypeBuildingLevels:
case MWMEditorCellTypeBuildingLevels:
{
NSString * placeholder =
[NSString stringWithFormat:L(@"editor_storey_number"),
@ -636,7 +640,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
capitalization:UITextAutocapitalizationTypeNone];
break;
}
case MWMPlacePageCellTypeCuisine:
case MWMEditorCellTypeCuisine:
{
MWMEditorSelectTableViewCell * tCell = static_cast<MWMEditorSelectTableViewCell *>(cell);
[tCell configWithDelegate:self
@ -645,7 +649,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
placeholder:L(@"select_cuisine")];
break;
}
case MWMPlacePageCellTypeNote:
case MWMEditorCellTypeNote:
{
MWMNoteCell * tCell = static_cast<MWMNoteCell *>(cell);
[tCell configWithDelegate:self
@ -653,7 +657,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
placeholder:L(@"editor_detailed_description_hint")];
break;
}
case MWMPlacePageCellTypeReportButton:
case MWMEditorCellTypeReportButton:
{
MWMButtonCell * tCell = static_cast<MWMButtonCell *>(cell);
@ -710,13 +714,13 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
Class cls = [self cellClassForIndexPath:indexPath];
auto cell = [self offscreenCellForClass:cls];
[self fillCell:cell atIndexPath:indexPath];
MWMPlacePageCellType const cellType = [self cellTypeForIndexPath:indexPath];
MWMEditorCellType const cellType = [self cellTypeForIndexPath:indexPath];
switch (cellType)
{
case MWMPlacePageCellTypeOpenHours: return ((MWMPlacePageOpeningHoursCell *)cell).cellHeight;
case MWMPlacePageCellTypeCategory:
case MWMPlacePageCellTypeReportButton: return self.tableView.rowHeight;
case MWMPlacePageCellTypeNote: return static_cast<MWMNoteCell *>(cell).cellHeight;
case MWMEditorCellTypeOpenHours: return ((MWMPlacePageOpeningHoursCell *)cell).cellHeight;
case MWMEditorCellTypeCategory:
case MWMEditorCellTypeReportButton: return self.tableView.rowHeight;
case MWMEditorCellTypeNote: return static_cast<MWMNoteCell *>(cell).cellHeight;
default:
{
[cell setNeedsUpdateConstraints];
@ -819,7 +823,7 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
- (void)cellShouldChangeSize:(MWMNoteCell *)cell text:(NSString *)text
{
self.offscreenCells[cellClass(MWMPlacePageCellTypeNote)] = cell;
self.offscreenCells[cellClass(MWMEditorCellTypeNote)] = cell;
self.note = text;
[self.tableView refresh];
NSIndexPath * ip = [self.tableView indexPathForCell:cell];
@ -868,42 +872,42 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
{
NSAssert(changeText != nil, @"String can't be nil!");
NSIndexPath * indexPath = [self.tableView indexPathForRowAtPoint:cell.center];
MWMPlacePageCellType const cellType = [self cellTypeForIndexPath:indexPath];
MWMEditorCellType const cellType = [self cellTypeForIndexPath:indexPath];
string const val = changeText.UTF8String;
switch (cellType)
{
case MWMPlacePageCellTypePhoneNumber:
case MWMEditorCellTypePhoneNumber:
m_mapObject.SetPhone(val);
if (!osm::EditableMapObject::ValidatePhone(val))
[self markCellAsInvalid:indexPath];
break;
case MWMPlacePageCellTypeWebsite:
case MWMEditorCellTypeWebsite:
m_mapObject.SetWebsite(val);
if (!osm::EditableMapObject::ValidateWebsite(val))
[self markCellAsInvalid:indexPath];
break;
case MWMPlacePageCellTypeEmail:
case MWMEditorCellTypeEmail:
m_mapObject.SetEmail(val);
if (!osm::EditableMapObject::ValidateEmail(val))
[self markCellAsInvalid:indexPath];
break;
case MWMPlacePageCellTypeOperator: m_mapObject.SetOperator(val); break;
case MWMPlacePageCellTypeBuilding:
case MWMEditorCellTypeOperator: m_mapObject.SetOperator(val); break;
case MWMEditorCellTypeBuilding:
m_mapObject.SetHouseNumber(val);
if (!osm::EditableMapObject::ValidateHouseNumber(val))
[self markCellAsInvalid:indexPath];
break;
case MWMPlacePageCellTypeZipCode:
case MWMEditorCellTypeZipCode:
m_mapObject.SetPostcode(val);
if (!osm::EditableMapObject::ValidatePostCode(val))
[self markCellAsInvalid:indexPath];
break;
case MWMPlacePageCellTypeBuildingLevels:
case MWMEditorCellTypeBuildingLevels:
m_mapObject.SetBuildingLevels(val);
if (!osm::EditableMapObject::ValidateBuildingLevels(val))
[self markCellAsInvalid:indexPath];
break;
case MWMPlacePageCellTypeAdditionalName:
case MWMEditorCellTypeAdditionalName:
{
MWMEditorAdditionalNameTableViewCell * tCell =
static_cast<MWMEditorAdditionalNameTableViewCell *>(cell);
@ -917,10 +921,10 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
- (void)cell:(UITableViewCell *)cell changeSwitch:(BOOL)changeSwitch
{
NSIndexPath * indexPath = [self.tableView indexPathForCell:cell];
MWMPlacePageCellType const cellType = [self cellTypeForIndexPath:indexPath];
MWMEditorCellType const cellType = [self cellTypeForIndexPath:indexPath];
switch (cellType)
{
case MWMPlacePageCellTypeWiFi:
case MWMEditorCellTypeWiFi:
m_mapObject.SetInternet(changeSwitch ? osm::Internet::Wlan : osm::Internet::Unknown);
break;
default: NSAssert(false, @"Invalid field for changeSwitch"); break;
@ -932,19 +936,19 @@ void registerCellsForTableView(vector<MWMPlacePageCellType> const & cells, UITab
- (void)cellSelect:(UITableViewCell *)cell
{
NSIndexPath * indexPath = [self.tableView indexPathForCell:cell];
MWMPlacePageCellType const cellType = [self cellTypeForIndexPath:indexPath];
MWMEditorCellType const cellType = [self cellTypeForIndexPath:indexPath];
switch (cellType)
{
case MWMPlacePageCellTypeStreet:
case MWMEditorCellTypeStreet:
[self performSegueWithIdentifier:kStreetEditorSegue sender:nil];
break;
case MWMPlacePageCellTypeCuisine:
case MWMEditorCellTypeCuisine:
[self performSegueWithIdentifier:kCuisineEditorSegue sender:nil];
break;
case MWMPlacePageCellTypeCategory:
case MWMEditorCellTypeCategory:
[self performSegueWithIdentifier:kCategoryEditorSegue sender:nil];
break;
case MWMPlacePageCellTypeReportButton: [self tapOnButtonCell:cell]; break;
case MWMEditorCellTypeReportButton: [self tapOnButtonCell:cell]; break;
default: NSAssert(false, @"Invalid field for cellSelect"); break;
}
}

View file

@ -1,84 +0,0 @@
#include "Framework.h"
#include "indexer/feature_meta.hpp"
#include "storage/index.hpp"
typedef NS_ENUM(NSUInteger, MWMPlacePageCellType)
{
MWMPlacePageCellTypePostcode = feature::Metadata::EType::FMD_COUNT,
MWMPlacePageCellTypePhoneNumber,
MWMPlacePageCellTypeWebsite,
MWMPlacePageCellTypeURL,
MWMPlacePageCellTypeEmail,
MWMPlacePageCellTypeOperator,
MWMPlacePageCellTypeOpenHours,
MWMPlacePageCellTypeWiFi,
MWMPlacePageCellTypeCoordinate,
MWMPlacePageCellTypeBookmark,
MWMPlacePageCellTypeEditButton,
MWMPlacePageCellTypeAddBusinessButton,
MWMPlacePageCellTypeAddPlaceButton,
MWMPlacePageCellTypeReportButton,
MWMPlacePageCellTypeCategory,
MWMPlacePageCellTypeName,
MWMPlacePageCellTypeAdditionalName,
MWMPlacePageCellTypeAddAdditionalName,
MWMPlacePageCellTypeAddAdditionalNamePlaceholder,
MWMPlacePageCellTypeStreet,
MWMPlacePageCellTypeBuilding,
MWMPlacePageCellTypeZipCode,
MWMPlacePageCellTypeBuildingLevels,
MWMPlacePageCellTypeCuisine,
MWMPlacePageCellTypeNote,
MWMPlacePageCellTypeBookingMore,
MWMPlacePageCellTypeCount
};
using MWMPlacePageCellTypeValueMap = map<MWMPlacePageCellType, string>;
@class MWMPlacePageViewManager;
@interface MWMPlacePageEntity : NSObject
@property (copy, nonatomic) NSString * title;
@property (copy, nonatomic) NSString * subtitle;
@property (copy, nonatomic) NSString * address;
@property (copy, nonatomic) NSString * bookmarkTitle;
@property (copy, nonatomic) NSString * bookmarkCategory;
@property (copy, nonatomic) NSString * bookmarkDescription;
@property (nonatomic, readonly) BOOL isHTMLDescription;
@property (copy, nonatomic) NSString * bookmarkColor;
@property (copy, nonatomic) NSString * bookingRating;
@property (copy, nonatomic) NSString * bookingPrice;
@property (copy, nonatomic) NSString * bookingOnlinePrice;
@property (nonatomic) BookmarkAndCategory bac;
@property (weak, nonatomic) MWMPlacePageViewManager * manager;
- (FeatureID const &)featureID;
- (BOOL)isMyPosition;
- (BOOL)isBookmark;
- (BOOL)isApi;
- (BOOL)isBooking;
- (BOOL)isOpentable;
- (ms::LatLon)latLon;
- (m2::PointD const &)mercator;
- (NSString *)apiURL;
- (NSURL *)sponsoredURL;
- (NSURL *)sponsoredDescriptionURL;
- (NSString *)sponsoredId;
- (NSString *)phoneNumber;
- (string)titleForNewBookmark;
- (instancetype)initWithInfo:(place_page::Info const &)info;
- (void)synchronize;
- (void)onlinePricingWithCompletionBlock:(MWMVoidBlock)completion failure:(MWMVoidBlock)failure;
- (void)toggleCoordinateSystem;
- (NSString *)getCellValue:(MWMPlacePageCellType)cellType;
- (place_page::Info const &)info;
- (storage::TCountryId const &)countryId;
@end

View file

@ -1,330 +0,0 @@
#import "MWMPlacePageEntity.h"
#import "MWMMapViewControlsManager.h"
#import "MWMNetworkPolicy.h"
#import "MapViewController.h"
#import "MapsAppDelegate.h"
#include "Framework.h"
#include "indexer/osm_editor.hpp"
#include "platform/measurement_utils.hpp"
#include "platform/mwm_version.hpp"
#include "platform/platform.hpp"
using feature::Metadata;
static NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS";
namespace
{
NSUInteger gMetaFieldsMap[MWMPlacePageCellTypeCount] = {};
void putFields(NSUInteger eTypeValue, NSUInteger ppValue)
{
gMetaFieldsMap[eTypeValue] = ppValue;
gMetaFieldsMap[ppValue] = eTypeValue;
}
void initFieldsMap()
{
putFields(Metadata::FMD_URL, MWMPlacePageCellTypeURL);
putFields(Metadata::FMD_WEBSITE, MWMPlacePageCellTypeWebsite);
putFields(Metadata::FMD_PHONE_NUMBER, MWMPlacePageCellTypePhoneNumber);
putFields(Metadata::FMD_OPEN_HOURS, MWMPlacePageCellTypeOpenHours);
putFields(Metadata::FMD_EMAIL, MWMPlacePageCellTypeEmail);
putFields(Metadata::FMD_POSTCODE, MWMPlacePageCellTypePostcode);
putFields(Metadata::FMD_INTERNET, MWMPlacePageCellTypeWiFi);
putFields(Metadata::FMD_CUISINE, MWMPlacePageCellTypeCuisine);
ASSERT_EQUAL(gMetaFieldsMap[Metadata::FMD_URL], MWMPlacePageCellTypeURL, ());
ASSERT_EQUAL(gMetaFieldsMap[MWMPlacePageCellTypeURL], Metadata::FMD_URL, ());
ASSERT_EQUAL(gMetaFieldsMap[Metadata::FMD_WEBSITE], MWMPlacePageCellTypeWebsite, ());
ASSERT_EQUAL(gMetaFieldsMap[MWMPlacePageCellTypeWebsite], Metadata::FMD_WEBSITE, ());
ASSERT_EQUAL(gMetaFieldsMap[Metadata::FMD_POSTCODE], MWMPlacePageCellTypePostcode, ());
ASSERT_EQUAL(gMetaFieldsMap[MWMPlacePageCellTypePostcode], Metadata::FMD_POSTCODE, ());
ASSERT_EQUAL(gMetaFieldsMap[Metadata::FMD_MAXSPEED], 0, ());
}
} // namespace
@implementation MWMPlacePageEntity
{
MWMPlacePageCellTypeValueMap m_values;
place_page::Info m_info;
}
- (instancetype)initWithInfo:(const place_page::Info &)info
{
self = [super init];
if (self)
{
m_info = info;
initFieldsMap();
[self config];
}
return self;
}
- (void)config
{
[self configureDefault];
if (m_info.IsFeature())
[self configureFeature];
if (m_info.IsBookmark())
[self configureBookmark];
}
- (void)setMetaField:(NSUInteger)key value:(string const &)value
{
NSAssert(key >= Metadata::FMD_COUNT, @"Incorrect enum value");
MWMPlacePageCellType const cellType = static_cast<MWMPlacePageCellType>(key);
if (value.empty())
m_values.erase(cellType);
else
m_values[cellType] = value;
}
- (void)configureDefault
{
self.title = @(m_info.GetTitle().c_str());
self.address = @(m_info.GetAddress().c_str());
self.subtitle = @(m_info.GetSubtitle().c_str());
self.bookingRating = @(m_info.GetRatingFormatted().c_str());
self.bookingPrice = @(m_info.GetApproximatePricing().c_str());
}
- (void)configureFeature
{
// Category can also be custom-formatted, please check m_info getters.
// TODO(Vlad): Refactor using osm::Props instead of direct Metadata access.
feature::Metadata const & md = m_info.GetMetadata();
auto const types = md.GetPresentTypes();
for (auto const type : types)
{
switch (type)
{
case Metadata::FMD_URL:
case Metadata::FMD_WEBSITE:
case Metadata::FMD_PHONE_NUMBER:
case Metadata::FMD_OPEN_HOURS:
case Metadata::FMD_EMAIL:
case Metadata::FMD_POSTCODE: [self setMetaField:gMetaFieldsMap[type] value:md.Get(type)]; break;
case Metadata::FMD_INTERNET:
[self setMetaField:gMetaFieldsMap[type] value:L(@"WiFi_available").UTF8String];
break;
default: break;
}
}
}
- (void)onlinePricingWithCompletionBlock:(MWMVoidBlock)completion failure:(MWMVoidBlock)failure
{
if (Platform::ConnectionStatus() == Platform::EConnectionType::CONNECTION_NONE || !self.isBooking)
{
failure();
return;
}
NSNumberFormatter * currencyFormatter = [[NSNumberFormatter alloc] init];
if (currencyFormatter.currencyCode.length != 3)
currencyFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
currencyFormatter.maximumFractionDigits = 0;
string const currency = currencyFormatter.currencyCode.UTF8String;
network_policy::CallPartnersApi([self, completion, failure, currency, currencyFormatter](
platform::NetworkPolicy const & canUseNetwork) {
auto const api = GetFramework().GetBookingApi(canUseNetwork);
if (!api)
{
failure();
return;
}
auto success = [self, completion, failure, currency, currencyFormatter](
string const & hotelId, string const & minPrice, string const & priceCurrency) {
if (currency != priceCurrency)
{
failure();
return;
}
NSNumberFormatter * decimalFormatter = [[NSNumberFormatter alloc] init];
decimalFormatter.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber * currencyNumber = [decimalFormatter
numberFromString:[@(minPrice.c_str())
stringByReplacingOccurrencesOfString:@"."
withString:decimalFormatter
.decimalSeparator]];
NSString * currencyString = [currencyFormatter stringFromNumber:currencyNumber];
NSString * currencyPattern =
[L(@"place_page_starting_from") stringByReplacingOccurrencesOfString:@"%s"
withString:@"%@"];
self.bookingOnlinePrice = [NSString stringWithFormat:currencyPattern, currencyString];
completion();
};
api->GetMinPrice(m_info.GetMetadata().Get(Metadata::FMD_SPONSORED_ID), currency, success);
});
}
- (void)configureBookmark
{
auto const bac = m_info.GetBookmarkAndCategory();
BookmarkCategory * cat = GetFramework().GetBmCategory(bac.m_categoryIndex);
BookmarkData const & data =
static_cast<Bookmark const *>(cat->GetUserMark(bac.m_bookmarkIndex))->GetData();
self.bookmarkTitle = @(data.GetName().c_str());
self.bookmarkCategory = @(m_info.GetBookmarkCategoryName().c_str());
string const & description = data.GetDescription();
self.bookmarkDescription = @(description.c_str());
_isHTMLDescription = strings::IsHTML(description);
self.bookmarkColor = @(data.GetType().c_str());
}
- (void)toggleCoordinateSystem
{
NSUserDefaults * ud = [NSUserDefaults standardUserDefaults];
[ud setBool:![ud boolForKey:kUserDefaultsLatLonAsDMSKey] forKey:kUserDefaultsLatLonAsDMSKey];
[ud synchronize];
}
#pragma mark - Getters
- (NSString *)getCellValue:(MWMPlacePageCellType)cellType
{
auto const s = [MapViewController controller].controlsManager.navigationState;
BOOL const navigationIsHidden = s == MWMNavigationDashboardStateHidden;
switch (cellType)
{
case MWMPlacePageCellTypeName: return self.title;
case MWMPlacePageCellTypeCoordinate: return [self coordinate];
case MWMPlacePageCellTypeAddPlaceButton:
return navigationIsHidden && m_info.ShouldShowAddPlace() ? @"" : nil;
case MWMPlacePageCellTypeBookmark: return m_info.IsBookmark() ? @"" : nil;
case MWMPlacePageCellTypeEditButton:
// TODO(Vlad): It's a really strange way to "display" cell if returned text is not nil.
return navigationIsHidden && m_info.ShouldShowEditPlace() ? @"" : nil;
case MWMPlacePageCellTypeAddBusinessButton:
return navigationIsHidden && m_info.ShouldShowAddBusiness() ? @"" : nil;
case MWMPlacePageCellTypeWebsite:
return self.isBooking ? nil : [self getDefaultField:cellType];
case MWMPlacePageCellTypeBookingMore:
return self.isBooking ? @(m_info.GetSponsoredDescriptionUrl().c_str()) : nil;
default: return [self getDefaultField:cellType];
}
}
- (NSString *)getDefaultField:(MWMPlacePageCellType)cellType
{
auto const it = m_values.find(cellType);
BOOL const haveField = (it != m_values.end());
return haveField ? @(it->second.c_str()) : nil;
}
- (NSURL *)sponsoredURL { return [self sponsoredUrl:NO]; }
- (NSURL *)sponsoredDescriptionURL { return [self sponsoredUrl:YES]; }
- (NSURL *)sponsoredUrl:(BOOL)isDescription
{
auto const & url =
isDescription ? m_info.GetSponsoredDescriptionUrl() : m_info.GetSponsoredUrl();
return url.empty() ? nil : [NSURL URLWithString:@(url.c_str())];
}
- (place_page::Info const &)info { return m_info; }
- (FeatureID const &)featureID { return m_info.GetID(); }
- (storage::TCountryId const &)countryId { return m_info.GetCountryId(); }
- (BOOL)isMyPosition { return m_info.IsMyPosition(); }
- (BOOL)isBookmark { return m_info.IsBookmark(); }
- (BOOL)isApi { return m_info.HasApiUrl(); }
- (BOOL)isBooking { return m_info.GetSponsoredType() == place_page::SponsoredType::Booking; }
- (BOOL)isOpentable { return m_info.GetSponsoredType() == place_page::SponsoredType::Opentable; }
- (BOOL)isSponsored { return m_info.IsSponsored(); }
- (NSString *)sponsoredId
{
return self.isSponsored ? @(m_info.GetMetadata().Get(Metadata::FMD_SPONSORED_ID).c_str()) : nil;
}
- (NSString *)phoneNumber { return [self getCellValue:MWMPlacePageCellTypePhoneNumber]; }
- (ms::LatLon)latLon { return m_info.GetLatLon(); }
- (m2::PointD const &)mercator { return m_info.GetMercator(); }
- (NSString *)apiURL { return @(m_info.GetApiUrl().c_str()); }
- (string)titleForNewBookmark { return m_info.FormatNewBookmarkName(); }
- (NSString *)coordinate
{
BOOL const useDMSFormat =
[[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsLatLonAsDMSKey];
ms::LatLon const & latlon = self.latLon;
return @((useDMSFormat ? measurement_utils::FormatLatLon(latlon.lat, latlon.lon)
: measurement_utils::FormatLatLonAsDMS(latlon.lat, latlon.lon, 2))
.c_str());
}
#pragma mark - Bookmark editing
- (void)setBac:(BookmarkAndCategory)bac { m_info.SetBac(bac); }
- (BookmarkAndCategory)bac { return m_info.GetBookmarkAndCategory(); }
- (NSString *)bookmarkCategory
{
if (!_bookmarkCategory)
{
Framework & f = GetFramework();
BookmarkCategory * category = f.GetBmCategory(f.LastEditedBMCategory());
_bookmarkCategory = @(category->GetName().c_str());
}
return _bookmarkCategory;
}
- (NSString *)bookmarkDescription
{
if (!_bookmarkDescription)
_bookmarkDescription = @"";
return _bookmarkDescription;
}
- (NSString *)bookmarkColor
{
if (!_bookmarkColor)
{
Framework & f = GetFramework();
string type = f.LastEditedBMType();
_bookmarkColor = @(type.c_str());
}
return _bookmarkColor;
}
- (NSString *)bookmarkTitle
{
if (!_bookmarkTitle)
_bookmarkTitle = self.title;
return _bookmarkTitle;
}
- (void)synchronize
{
Framework & f = GetFramework();
BookmarkCategory * category = f.GetBmCategory(self.bac.m_categoryIndex);
if (!category)
return;
Bookmark * bookmark =
static_cast<Bookmark *>(category->GetUserMarkForEdit(self.bac.m_bookmarkIndex));
if (!bookmark)
return;
if (self.bookmarkColor)
bookmark->SetType(self.bookmarkColor.UTF8String);
if (self.bookmarkDescription)
{
string const description(self.bookmarkDescription.UTF8String);
_isHTMLDescription = strings::IsHTML(description);
bookmark->SetDescription(description);
}
if (self.bookmarkTitle)
bookmark->SetName(self.bookmarkTitle.UTF8String);
category->SaveToKMLFile();
category->NotifyChanges();
}
@end

View file

@ -3,7 +3,6 @@
#import "MWMSearch.h"
#import "UIButton+RuntimeAttributes.h"
extern NSString * const kSearchStateWillChangeNotification;
extern NSString * const kSearchStateKey;
@interface MWMSearchChangeModeView ()<MWMSearchObserver>
@ -21,17 +20,12 @@ extern NSString * const kSearchStateKey;
- (void)awakeFromNib
{
[super awakeFromNib];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(searchStateWillChange:)
name:kSearchStateWillChangeNotification
object:nil];
[MWMSearch addObserver:self];
self.changeModeButton.titleLabel.textAlignment = NSTextAlignmentNatural;
self.filterButton.titleLabel.textAlignment = NSTextAlignmentNatural;
self.filterButtoniPadX.priority = IPAD ? UILayoutPriorityDefaultHigh : UILayoutPriorityDefaultLow;
}
- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
- (void)updateForState:(MWMSearchManagerState)state
{
UIButton * changeModeButton = self.changeModeButton;
@ -88,13 +82,5 @@ extern NSString * const kSearchStateKey;
- (void)onSearchStarted { [self updateFilterButtons:[MWMSearch isHotelResults]]; }
- (void)onSearchCompleted { [self updateFilterButtons:[MWMSearch isHotelResults]]; }
#pragma mark - Notifications
- (void)searchStateWillChange:(NSNotification *)notification
{
MWMSearchManagerState const state =
MWMSearchManagerState([[notification userInfo][kSearchStateKey] unsignedIntegerValue]);
[self updateForState:state];
}
@end

View file

@ -1,10 +1,15 @@
#import "MWMAlertViewController.h"
#import "MWMMapDownloaderTypes.h"
#import "MWMSearchTextField.h"
#import "MWMSearchManagerObserver.h"
#import "MWMSearchManagerState.h"
#import "MWMSearchTextField.h"
@interface MWMSearchManager : NSObject
+ (nonnull MWMSearchManager *)manager;
+ (void)addObserver:(nonnull id<MWMSearchManagerObserver>)observer;
+ (void)removeObserver:(nonnull id<MWMSearchManagerObserver>)observer;
@property(nullable, weak, nonatomic) IBOutlet MWMSearchTextField * searchTextField;
@property(nonatomic) MWMSearchManagerState state;

View file

@ -26,7 +26,6 @@
#include "Framework.h"
extern NSString * const kAlohalyticsTapEventKey;
extern NSString * const kSearchStateWillChangeNotification = @"SearchStateWillChangeNotification";
extern NSString * const kSearchStateKey = @"SearchStateKey";
namespace
@ -36,8 +35,17 @@ typedef NS_ENUM(NSUInteger, MWMSearchManagerActionBarState) {
MWMSearchManagerActionBarStateTabBar,
MWMSearchManagerActionBarStateModeFilter
};
using TObserver = id<MWMSearchManagerObserver>;
using TObservers = NSHashTable<__kindof TObserver>;
} // namespace
@interface MWMMapViewControlsManager ()
@property(nonatomic) MWMSearchManager * searchManager;
@end
@interface MWMSearchManager ()<MWMSearchTableViewProtocol, MWMSearchTabbedViewProtocol,
MWMSearchTabButtonsViewProtocol, UITextFieldDelegate,
MWMFrameworkStorageObserver, MWMSearchObserver>
@ -72,10 +80,13 @@ typedef NS_ENUM(NSUInteger, MWMSearchManagerActionBarState) {
@property(nonatomic) MWMSearchFilterTransitioningManager * filterTransitioningManager;
@property(nonatomic) TObservers * observers;
@end
@implementation MWMSearchManager
+ (MWMSearchManager *)manager { return [MWMMapViewControlsManager manager].searchManager; }
- (nullable instancetype)init
{
self = [super init];
@ -84,6 +95,7 @@ typedef NS_ENUM(NSUInteger, MWMSearchManagerActionBarState) {
[NSBundle.mainBundle loadNibNamed:@"MWMSearchView" owner:self options:nil];
self.state = MWMSearchManagerStateHidden;
[MWMSearch addObserver:self];
_observers = [TObservers weakObjectsHashTable];
}
return self;
}
@ -326,6 +338,26 @@ typedef NS_ENUM(NSUInteger, MWMSearchManagerActionBarState) {
}];
}
#pragma mark - Add/Remove Observers
+ (void)addObserver:(id<MWMSearchManagerObserver>)observer
{
[[MWMSearchManager manager].observers addObject:observer];
}
+ (void)removeObserver:(id<MWMSearchManagerObserver>)observer
{
[[MWMSearchManager manager].observers removeObject:observer];
}
#pragma mark - MWMSearchManagerObserver
- (void)onSearchManagerStateChanged
{
for (TObserver observer in self.observers)
[observer onSearchManagerStateChanged];
}
#pragma mark - Filters
- (IBAction)changeMode
@ -410,11 +442,6 @@ typedef NS_ENUM(NSUInteger, MWMSearchManagerActionBarState) {
{
if (_state == state)
return;
[[NSNotificationCenter defaultCenter] postNotificationName:kSearchStateWillChangeNotification
object:nil
userInfo:@{
kSearchStateKey : @(state)
}];
if (_state == MWMSearchManagerStateHidden)
[self endSearch];
_state = state;
@ -438,7 +465,9 @@ typedef NS_ENUM(NSUInteger, MWMSearchManagerActionBarState) {
[self changeToMapSearchState];
break;
}
[[MWMMapViewControlsManager manager] searchViewDidEnterState:state];
[self onSearchManagerStateChanged];
[self.changeModeView updateForState:state];
[[MapViewController controller] updateStatusBarStyle];
}
- (void)viewHidden:(BOOL)hidden
@ -448,11 +477,7 @@ typedef NS_ENUM(NSUInteger, MWMSearchManagerActionBarState) {
UIView * contentView = self.contentView;
UIView * parentView = self.ownerController.view;
if (hidden)
{
[[MWMMapViewControlsManager manager] searchFrameUpdated:{}];
}
else
if (!hidden)
{
if (searchBarView.superview)
{
@ -467,7 +492,6 @@ typedef NS_ENUM(NSUInteger, MWMSearchManagerActionBarState) {
[self layoutTopViews];
CGRect searchAndStatusBarFrame = self.searchBarView.frame;
searchAndStatusBarFrame.size.height += statusBarHeight();
[[MWMMapViewControlsManager manager] searchFrameUpdated:searchAndStatusBarFrame];
}
[UIView animateWithDuration:kDefaultAnimationDuration
animations:^{

View file

@ -0,0 +1,5 @@
@protocol MWMSearchManagerObserver<NSObject>
- (void)onSearchManagerStateChanged;
@end

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>

View file

@ -1,6 +1,4 @@
import UIKit
class SearchBar: SolidTouchView {
final class SearchBar: SolidTouchView {
override var visibleAreaAffectDirections: MWMAvailableAreaAffectDirections { return alternative(iPhone: .top, iPad: .left) }
override var placePageAreaAffectDirections: MWMAvailableAreaAffectDirections { return alternative(iPhone: [], iPad: .left) }
@ -8,4 +6,6 @@ class SearchBar: SolidTouchView {
override var widgetsAreaAffectDirections: MWMAvailableAreaAffectDirections { return alternative(iPhone: [], iPad: .left) }
override var trafficButtonAreaAffectDirections: MWMAvailableAreaAffectDirections { return alternative(iPhone: .top, iPad: .left) }
override var menuAreaAffectDirections: MWMAvailableAreaAffectDirections { return alternative(iPhone: [], iPad: .left) }
}

View file

@ -3,7 +3,7 @@
#import "MWMAuthorizationCommon.h"
#import "MWMNetworkPolicy.h"
#import "MWMSettings.h"
#import "MWMTextToSpeech.h"
#import "MWMTextToSpeech+CPP.h"
#import "Statistics.h"
#import "SwiftBridge.h"
#import "WebViewController.h"

View file

@ -1,6 +1,6 @@
#import "MWMTTSLanguageViewController.h"
#import "MWMTTSSettingsViewController.h"
#import "MWMTextToSpeech.h"
#import "MWMTextToSpeech+CPP.h"
#import "SwiftBridge.h"
static NSString * const kUnwingSegueIdentifier = @"UnwindToTTSSettings";

View file

@ -1,6 +1,6 @@
#import "MWMTTSSettingsViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "MWMTextToSpeech.h"
#import "MWMTextToSpeech+CPP.h"
#import "Statistics.h"
#import "SwiftBridge.h"
#import "WebViewController.h"

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Wns-nH-AQU">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Wns-nH-AQU">
<device id="retina4_0" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
@ -29,6 +29,14 @@
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="65S-M4-TnM" customClass="NavigationInfoArea" customModule="cm_beta" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="1" alpha="0.20000000000000001" colorSpace="calibratedRGB"/>
</view>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TdT-ia-GP9" customClass="MenuArea" customModule="cm_beta" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="1" alpha="0.20000000000000001" colorSpace="calibratedRGB"/>
</view>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="awj-9E-eBS" customClass="PlacePageArea" customModule="cm_beta" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="0.20000000000000001" colorSpace="calibratedRGB"/>
@ -55,8 +63,11 @@
<constraint firstAttribute="bottom" secondItem="QKu-4A-UgP" secondAttribute="bottom" priority="100" id="488-ng-pRw"/>
<constraint firstItem="QKu-4A-UgP" firstAttribute="top" secondItem="USG-6L-Uhw" secondAttribute="top" priority="100" constant="20" id="60l-kI-cp7"/>
<constraint firstAttribute="trailing" secondItem="awj-9E-eBS" secondAttribute="trailing" priority="100" id="6cS-mj-HcX"/>
<constraint firstItem="TdT-ia-GP9" firstAttribute="leading" secondItem="USG-6L-Uhw" secondAttribute="leading" priority="100" id="819-qB-GBD"/>
<constraint firstItem="FFY-Dy-Wou" firstAttribute="leading" secondItem="USG-6L-Uhw" secondAttribute="leading" priority="100" id="AW8-cN-xzE"/>
<constraint firstAttribute="trailing" secondItem="65S-M4-TnM" secondAttribute="trailing" priority="100" id="Bjn-UL-ALa"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="xJx-UU-IdV" secondAttribute="bottom" id="BqM-vp-EnJ"/>
<constraint firstAttribute="bottom" secondItem="65S-M4-TnM" secondAttribute="bottom" priority="100" id="FU7-Pa-O3P"/>
<constraint firstItem="QKu-4A-UgP" firstAttribute="leading" secondItem="USG-6L-Uhw" secondAttribute="leading" priority="100" id="Gw4-fq-sLY"/>
<constraint firstAttribute="bottom" secondItem="NI8-tV-i2B" secondAttribute="bottom" priority="100" id="HW4-dR-LNu"/>
<constraint firstAttribute="bottomMargin" secondItem="awj-9E-eBS" secondAttribute="bottom" priority="100" id="Kf4-GM-1aY"/>
@ -64,12 +75,17 @@
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="FFY-Dy-Wou" secondAttribute="bottom" id="QQc-TF-hhE"/>
<constraint firstAttribute="trailing" secondItem="QKu-4A-UgP" secondAttribute="trailing" priority="100" id="SNy-Ck-trF"/>
<constraint firstItem="NI8-tV-i2B" firstAttribute="leading" secondItem="USG-6L-Uhw" secondAttribute="leading" priority="100" id="Uf3-sL-39L"/>
<constraint firstAttribute="trailing" secondItem="TdT-ia-GP9" secondAttribute="trailing" priority="100" id="UvG-fn-nF1"/>
<constraint firstAttribute="bottom" secondItem="TdT-ia-GP9" secondAttribute="bottom" priority="100" id="Wmw-ON-0aO"/>
<constraint firstAttribute="top" secondItem="65S-M4-TnM" secondAttribute="top" priority="100" id="XrN-7f-l3w"/>
<constraint firstItem="awj-9E-eBS" firstAttribute="leading" secondItem="USG-6L-Uhw" secondAttribute="leading" priority="100" id="YBB-Wd-lq6"/>
<constraint firstItem="65S-M4-TnM" firstAttribute="leading" secondItem="USG-6L-Uhw" secondAttribute="leading" priority="100" id="YiU-Dr-KCp"/>
<constraint firstAttribute="bottom" secondItem="FFY-Dy-Wou" secondAttribute="bottom" priority="100" id="ZFU-IG-uZh"/>
<constraint firstItem="FFY-Dy-Wou" firstAttribute="top" secondItem="USG-6L-Uhw" secondAttribute="top" priority="100" id="aOI-yX-CJY"/>
<constraint firstAttribute="trailing" secondItem="NI8-tV-i2B" secondAttribute="trailing" priority="100" id="bPj-dO-SIK"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="awj-9E-eBS" secondAttribute="bottom" id="dNo-wc-hvO"/>
<constraint firstItem="xJx-UU-IdV" firstAttribute="leading" secondItem="USG-6L-Uhw" secondAttribute="leading" priority="100" id="fUZ-NK-6GU"/>
<constraint firstAttribute="top" secondItem="TdT-ia-GP9" secondAttribute="top" priority="100" id="ihO-7V-XPf"/>
<constraint firstAttribute="top" secondItem="NI8-tV-i2B" secondAttribute="top" priority="100" id="kvw-Gs-ady"/>
<constraint firstAttribute="bottom" secondItem="xJx-UU-IdV" secondAttribute="bottom" priority="100" id="pur-5a-SQA"/>
<constraint firstAttribute="trailing" secondItem="FFY-Dy-Wou" secondAttribute="trailing" priority="100" id="qdF-Ru-TYd"/>