diff --git a/iphone/Maps/Classes/CustomAlert/DefaultAlert/MWMDefaultAlert.mm b/iphone/Maps/Classes/CustomAlert/DefaultAlert/MWMDefaultAlert.mm index 56fd386875..56de398587 100644 --- a/iphone/Maps/Classes/CustomAlert/DefaultAlert/MWMDefaultAlert.mm +++ b/iphone/Maps/Classes/CustomAlert/DefaultAlert/MWMDefaultAlert.mm @@ -1,7 +1,6 @@ #import "MWMDefaultAlert.h" #import "MWMAlertViewController.h" #import "MWMDefaultAlert_Protected.h" -#import "MWMPlacePageViewManager.h" #import "MapViewController.h" #import "MapsAppDelegate.h" #import "Statistics.h" diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h index 5af2b8b449..a17e2ce56a 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h @@ -8,7 +8,6 @@ #include "platform/location.hpp" @class MapViewController; -@class MWMPlacePageEntity; @protocol MWMFeatureHolder; @interface MWMMapViewControlsManager : NSObject @@ -43,7 +42,6 @@ - (void)dismissPlacePage; - (void)showPlacePage:(place_page::Info const &)info; -- (void)addPlacePageViews:(NSArray *)views; - (void)addPlace:(BOOL)isBusiness hasPoint:(BOOL)hasPoint point:(m2::PointD const &)point; - (void)dragPlacePage:(CGRect)frame; diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm index eef6d9ef33..1518b27cdb 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm @@ -9,9 +9,7 @@ #import "MWMButton.h" #import "MWMFrameworkListener.h" #import "MWMObjectsCategorySelectorController.h" -#import "MWMPlacePageEntity.h" #import "MWMPlacePageManager.h" -#import "MWMPlacePageViewManager.h" #import "MWMRoutePreview.h" #import "MWMRouter.h" #import "MWMSearchManager.h" @@ -133,7 +131,18 @@ extern NSString * const kAlohalyticsTapEventKey; #pragma mark - MWMPlacePageViewManager - (void)dismissPlacePage { [self.placePageManager hidePlacePage]; } -- (void)showPlacePage:(place_page::Info const &)info { [self.placePageManager showPlacePage:info]; } + +- (void)showPlacePage:(place_page::Info const &)info +{ + [self.placePageManager showPlacePage:info]; + if (IPAD) + { + auto ownerView = self.ownerController.view; + [ownerView bringSubviewToFront:self.menuController.view]; + [ownerView bringSubviewToFront:self.navigationManager.routePreview]; + } +} + - (MWMAlertViewController *)alertController { return self.ownerController.alertController; } - (void)searchViewDidEnterState:(MWMSearchManagerState)state { @@ -295,20 +304,6 @@ extern NSString * const kAlohalyticsTapEventKey; [self.sideButtons setBottomBound:frame.origin.y]; } -- (void)addPlacePageViews:(NSArray *)views -{ - UIView * ownerView = self.ownerController.view; - for (UIView * view in views) - [ownerView addSubview:view]; - for (UIView * view in self.searchManager.topViews) - [ownerView bringSubviewToFront:view]; - if (IPAD) - { - [ownerView bringSubviewToFront:self.menuController.view]; - [ownerView bringSubviewToFront:self.navigationManager.routePreview]; - } -} - #pragma mark - MWMNavigationDashboardManager - (void)routePreviewDidChangeFrame:(CGRect)newFrame @@ -454,10 +449,8 @@ extern NSString * const kAlohalyticsTapEventKey; - (id)placePageManager { - auto const PlacePageClass = IPAD ? [MWMPlacePageViewManager class] : [MWMPlacePageManager class]; - if (!_placePageManager) - _placePageManager = [[PlacePageClass alloc] init]; + _placePageManager = [[MWMPlacePageManager alloc] init]; return _placePageManager; } diff --git a/iphone/Maps/Classes/MWMActionBarButton.h b/iphone/Maps/Classes/MWMActionBarButton.h index 5b5b56befd..04cbf42f7e 100644 --- a/iphone/Maps/Classes/MWMActionBarButton.h +++ b/iphone/Maps/Classes/MWMActionBarButton.h @@ -1,6 +1,7 @@ enum class EButton // Required button's order { Api, + Download, Booking, Opentable, Call, @@ -15,6 +16,7 @@ enum class EButton // Required button's order NSString * titleForButton(EButton type, BOOL isSelected); @class MWMActionBarButton; +@class MWMCircularProgress; @protocol MWMActionBarButtonDelegate @@ -31,4 +33,8 @@ NSString * titleForButton(EButton type, BOOL isSelected); buttonType:(EButton)type isSelected:(BOOL)isSelected; +- (EButton)type; +- (MWMCircularProgress *)mapDownloadProgress; + + @end diff --git a/iphone/Maps/Classes/MWMActionBarButton.mm b/iphone/Maps/Classes/MWMActionBarButton.mm index c19522524b..f926d30b0e 100644 --- a/iphone/Maps/Classes/MWMActionBarButton.mm +++ b/iphone/Maps/Classes/MWMActionBarButton.mm @@ -1,6 +1,7 @@ #import "MWMActionBarButton.h" #import "Common.h" #import "MWMButton.h" +#import "MWMCircularProgress.h" #import "UIColor+MapsMeColor.h" NSString * titleForButton(EButton type, BOOL isSelected) @@ -9,6 +10,8 @@ NSString * titleForButton(EButton type, BOOL isSelected) { case EButton::Api: return L(@"back"); + case EButton::Download: + return L(@"download"); case EButton::Booking: case EButton::Opentable: return L(@"book_button"); @@ -29,13 +32,15 @@ NSString * titleForButton(EButton type, BOOL isSelected) } } -@interface MWMActionBarButton () +@interface MWMActionBarButton () @property (weak, nonatomic) IBOutlet MWMButton * button; @property (weak, nonatomic) IBOutlet UILabel * label; @property (weak, nonatomic) id delegate; @property (nonatomic) EButton type; +@property(nonatomic) MWMCircularProgress * mapDownloadProgress; +@property(nonatomic) UIView * progressWrapper; @end @@ -56,6 +61,24 @@ NSString * titleForButton(EButton type, BOOL isSelected) case EButton::Api: [self.button setImage:[UIImage imageNamed:@"ic_back_api"] forState:UIControlStateNormal]; break; + case EButton::Download: + { + if (self.mapDownloadProgress) + return; + + self.progressWrapper = [[UIView alloc] init]; + [self.button addSubview:self.progressWrapper]; + + self.mapDownloadProgress = [MWMCircularProgress downloaderProgressForParentView:self.progressWrapper]; + self.mapDownloadProgress.delegate = self; + + MWMCircularProgressStateVec const affectedStates = {MWMCircularProgressStateNormal, + MWMCircularProgressStateSelected}; + + [self.mapDownloadProgress setImageName:@"ic_download" forStates:affectedStates]; + [self.mapDownloadProgress setColoring:MWMButtonColoringBlue forStates:affectedStates]; + break; + } case EButton::Booking: [self.button setImage:[UIImage imageNamed:@"ic_booking_logo"] forState:UIControlStateNormal]; self.label.textColor = [UIColor whiteColor]; @@ -105,6 +128,11 @@ NSString * titleForButton(EButton type, BOOL isSelected) [button configButton:isSelected]; } +- (void)progressButtonPressed:(MWMCircularProgress *)progress +{ + [self.delegate tapOnButtonWithType:EButton::Download]; +} + - (IBAction)tap { if (self.type == EButton::Bookmark) @@ -143,8 +171,11 @@ NSString * titleForButton(EButton type, BOOL isSelected) - (void)layoutSubviews { - self.frame = self.superview.bounds; [super layoutSubviews]; + self.frame = self.superview.bounds; + CGFloat constexpr designOffset = 4; + self.progressWrapper.size = {self.button.height - designOffset, self.button.height - designOffset}; + self.progressWrapper.center = self.button.center; } @end diff --git a/iphone/Maps/Classes/MWMAnimator.h b/iphone/Maps/Classes/MWMAnimator.h deleted file mode 100644 index 71555ba27a..0000000000 --- a/iphone/Maps/Classes/MWMAnimator.h +++ /dev/null @@ -1,21 +0,0 @@ -#import - -@protocol Animation - -- (void)animationTick:(CFTimeInterval)dt finished:(BOOL *)finished; - -@end - -@interface MWMAnimator : NSObject - -+ (instancetype)animatorWithScreen:(UIScreen *)screen; -- (void)addAnimation:(id)animatable; -- (void)removeAnimation:(id)animatable; - -@end - -@interface UIView (AnimatorAdditions) - -- (MWMAnimator *)animator; - -@end diff --git a/iphone/Maps/Classes/MWMAnimator.mm b/iphone/Maps/Classes/MWMAnimator.mm deleted file mode 100644 index f191ff8ff3..0000000000 --- a/iphone/Maps/Classes/MWMAnimator.mm +++ /dev/null @@ -1,85 +0,0 @@ -#import "MWMAnimator.h" -#import - -@interface MWMAnimator () - -@property (nonatomic) CADisplayLink * displayLink; -@property (nonatomic) NSMutableSet * animations; - -@end - -@implementation MWMAnimator - -+ (instancetype)animatorWithScreen:(UIScreen *)screen -{ - if (!screen) - screen = [UIScreen mainScreen]; - - MWMAnimator * animator = objc_getAssociatedObject(screen, _cmd); - if (!animator) - { - animator = [[self alloc] initWithScreen:screen]; - objc_setAssociatedObject(screen, _cmd, animator, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } - return animator; -} - -- (instancetype)initWithScreen:(UIScreen *)screen -{ - self = [super init]; - if (self) - { - self.displayLink = [screen displayLinkWithTarget:self selector:@selector(animationTick:)]; - self.displayLink.paused = YES; - [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; - self.animations = [NSMutableSet set]; - } - return self; -} - -- (void)animationTick:(CADisplayLink *)displayLink -{ - CFTimeInterval const dt = displayLink.duration; - for (id a in self.animations.copy) - { - BOOL finished = NO; - [a animationTick:dt finished:&finished]; - - if (finished) - [self.animations removeObject:a]; - - } - - if (self.animations.count == 0) - self.displayLink.paused = YES; -} - -- (void)addAnimation:(id)animation -{ - [self.animations addObject:animation]; - - if (self.animations.count == 1) - self.displayLink.paused = NO; -} - -- (void)removeAnimation:(id )animatable -{ - if (animatable == nil) - return; - - [self.animations removeObject:animatable]; - - if (self.animations.count == 0) - self.displayLink.paused = YES; -} - -@end - -@implementation UIView (AnimatorAdditions) - -- (MWMAnimator *)animator -{ - return [MWMAnimator animatorWithScreen:self.window.screen]; -} - -@end diff --git a/iphone/Maps/Classes/MWMBasePlacePageView.h b/iphone/Maps/Classes/MWMBasePlacePageView.h deleted file mode 100644 index dde6e9651d..0000000000 --- a/iphone/Maps/Classes/MWMBasePlacePageView.h +++ /dev/null @@ -1,29 +0,0 @@ -@class MWMPlacePageEntity, MWMDirectionView, MWMPlacePageTypeDescriptionView; - -@interface MWMBasePlacePageView : SolidTouchView - -@property (weak, nonatomic) IBOutlet UILabel * titleLabel; -@property (weak, nonatomic) IBOutlet UIView * downloadProgressView; -@property (weak, nonatomic) IBOutlet UILabel * externalTitleLabel; -@property (weak, nonatomic) IBOutlet UILabel * subtitleLabel; -@property (weak, nonatomic) IBOutlet UILabel * placeScheduleLabel; -@property (weak, nonatomic) IBOutlet UILabel * addressLabel; -@property (weak, nonatomic) IBOutlet UILabel * distanceLabel; -@property (weak, nonatomic) IBOutlet UIImageView * directionArrow; -@property (weak, nonatomic) IBOutlet UITableView * featureTable; -@property (weak, nonatomic) IBOutlet UIView * separatorView; -@property (weak, nonatomic) IBOutlet UIButton * directionButton; -@property (weak, nonatomic) IBOutlet UIView * ppPreview; -@property (weak, nonatomic) IBOutlet UIView * bookingView; -@property (weak, nonatomic) IBOutlet UILabel * bookingRatingLabel; -@property (weak, nonatomic) IBOutlet UILabel * bookingPriceLabel; -@property (weak, nonatomic) IBOutlet UIImageView * bookingSeparator; - -- (void)configureWithEntity:(MWMPlacePageEntity *)entity; -- (void)addBookmark; -- (void)removeBookmark; -- (void)reloadBookmarkCell; -- (void)updateAndLayoutMyPositionSpeedAndAltitude:(NSString *)text; -- (void)setDistance:(NSString *)distance; - -@end diff --git a/iphone/Maps/Classes/MWMBasePlacePageView.mm b/iphone/Maps/Classes/MWMBasePlacePageView.mm deleted file mode 100644 index a3830df112..0000000000 --- a/iphone/Maps/Classes/MWMBasePlacePageView.mm +++ /dev/null @@ -1,793 +0,0 @@ -#import "MWMBasePlacePageView.h" -#import "Common.h" -#import "MWMCircularProgress.h" -#import "MWMFrameworkListener.h" -#import "MWMLocationHelpers.h" -#import "MWMPlacePage.h" -#import "MWMPlacePageActionBar.h" -#import "MWMPlacePageBookmarkCell.h" -#import "MWMPlacePageBookmarkDelegate.h" -#import "MWMPlacePageButtonCell.h" -#import "MWMPlacePageEntity.h" -#import "MWMPlacePageInfoCell.h" -#import "MWMPlacePageOpeningHoursCell.h" -#import "MWMPlacePageViewManager.h" -#import "MWMStorage.h" -#import "MWMViewController.h" -#import "MapViewController.h" -#import "MapsAppDelegate.h" -#import "NSString+Categories.h" -#import "Statistics.h" -#import "UIColor+MapsMeColor.h" - -#include "map/place_page_info.hpp" - -#include "3party/opening_hours/opening_hours.hpp" -#include "editor/opening_hours_ui.hpp" -#include "editor/ui2oh.hpp" -#include "platform/local_country_file_utils.hpp" - -namespace -{ -CGFloat const kDownloadProgressViewLeftOffset = 12.; -CGFloat const kDownloadProgressViewTopOffset = 4.; -CGFloat const kLabelsBetweenMainOffset = 8.; -CGFloat const kLabelsBetweenSmallOffset = 4.; -CGFloat const kBottomPlacePageOffset = 16.; -CGFloat const kLeftOffset = 16.; -CGFloat const kDefaultHeaderHeight = 16.; -CGFloat const kLabelsPadding = kLeftOffset * 2; -CGFloat const kDirectionArrowSide = 20.; -CGFloat const kOffsetFromLabelsToDistance = 8.; -CGFloat const kOffsetFromDistanceToArrow = 5.; -CGFloat const kMaximumWidth = 360.; - -enum class PlacePageSection -{ - Bookmark, - Metadata, - Editing, - Booking -}; - -vector const kSectionBookmarkCellTypes{MWMPlacePageCellTypeBookmark}; - -vector const kSectionMetadataCellTypes{ - MWMPlacePageCellTypePostcode, MWMPlacePageCellTypePhoneNumber, MWMPlacePageCellTypeWebsite, - MWMPlacePageCellTypeURL, MWMPlacePageCellTypeEmail, MWMPlacePageCellTypeOpenHours, - MWMPlacePageCellTypeWiFi, MWMPlacePageCellTypeCoordinate}; - -vector const kSectionEditingCellTypes{MWMPlacePageCellTypeEditButton, - MWMPlacePageCellTypeAddBusinessButton, - MWMPlacePageCellTypeAddPlaceButton}; - -vector const kSectionBookingCellTypes{MWMPlacePageCellTypeBookingMore}; - -using TCellTypesSectionMap = pair, PlacePageSection>; - -vector const kCellTypesSectionMap{ - {kSectionBookmarkCellTypes, PlacePageSection::Bookmark}, - {kSectionMetadataCellTypes, PlacePageSection::Metadata}, - {kSectionEditingCellTypes, PlacePageSection::Editing}, - {kSectionBookingCellTypes, PlacePageSection::Booking}}; - -MWMPlacePageCellTypeValueMap const kCellType2ReuseIdentifier{ - {MWMPlacePageCellTypeWiFi, "PlacePageInfoCell"}, - {MWMPlacePageCellTypeCoordinate, "PlacePageInfoCell"}, - {MWMPlacePageCellTypePostcode, "PlacePageInfoCell"}, - {MWMPlacePageCellTypeURL, "PlacePageLinkCell"}, - {MWMPlacePageCellTypeWebsite, "PlacePageLinkCell"}, - {MWMPlacePageCellTypeEmail, "PlacePageLinkCell"}, - {MWMPlacePageCellTypePhoneNumber, "PlacePageLinkCell"}, - {MWMPlacePageCellTypeOpenHours, "MWMPlacePageOpeningHoursCell"}, - {MWMPlacePageCellTypeBookmark, "PlacePageBookmarkCell"}, - {MWMPlacePageCellTypeEditButton, "MWMPlacePageButtonCell"}, - {MWMPlacePageCellTypeAddBusinessButton, "MWMPlacePageButtonCell"}, - {MWMPlacePageCellTypeAddPlaceButton, "MWMPlacePageButtonCell"}, - {MWMPlacePageCellTypeBookingMore, "MWMPlacePageButtonCell"}}; - -NSString * reuseIdentifier(MWMPlacePageCellType cellType) -{ - auto const it = kCellType2ReuseIdentifier.find(cellType); - BOOL const haveCell = (it != kCellType2ReuseIdentifier.end()); - ASSERT(haveCell, ()); - return haveCell ? @(it->second.c_str()) : @""; -} - -CGFloat placePageWidth() -{ - CGSize const size = UIScreen.mainScreen.bounds.size; - return IPAD ? kMaximumWidth - : (size.width > size.height ? MIN(kMaximumWidth, size.height) : size.width); -} - -enum class AttributePosition -{ - Title, - ExternalTitle, - Subtitle, - Schedule, - Address -}; -} // namespace - -using namespace storage; - -@interface MWMBasePlacePageView ()< - UITableViewDelegate, UITableViewDataSource, MWMPlacePageOpeningHoursCellProtocol, - MWMPlacePageBookmarkDelegate, MWMCircularProgressProtocol, MWMFrameworkStorageObserver> -{ - vector m_sections; - map> m_cells; -} - -@property(weak, nonatomic) MWMPlacePageEntity * entity; -@property(weak, nonatomic) IBOutlet MWMPlacePage * ownerPlacePage; - -@property(nonatomic, readwrite) BOOL openingHoursCellExpanded; -@property(nonatomic) BOOL isBookmarkCellExpanded; - -@property(nonatomic) MWMCircularProgress * mapDownloadProgress; -@property(nonatomic) TMwmSize downloadMapSize; - -@property(nonatomic) MWMPlacePageBookmarkCell * bookmarkCell; -@property(nonatomic) MWMPlacePageOpeningHoursCell * openingHoursCell; - -@end - -@implementation MWMBasePlacePageView - -- (void)awakeFromNib -{ - [super awakeFromNib]; - self.featureTable.delegate = self; - self.featureTable.dataSource = self; - self.featureTable.separatorColor = [UIColor blackDividers]; - - for (auto const & type : kCellType2ReuseIdentifier) - { - NSString * identifier = @(type.second.c_str()); - [self.featureTable registerNib:[UINib nibWithNibName:identifier bundle:nil] - forCellReuseIdentifier:identifier]; - } - - self.directionArrow.autoresizingMask = UIViewAutoresizingNone; -} - -- (void)configureWithEntity:(MWMPlacePageEntity *)entity -{ - self.entity = entity; - self.isBookmarkCellExpanded = NO; - [self configTable]; - [self configure]; -} - -- (void)configTable -{ - m_sections.clear(); - m_cells.clear(); - self.openingHoursCell = nil; - self.bookmarkCell = nil; - for (auto const cellSection : kCellTypesSectionMap) - { - for (auto const cellType : cellSection.first) - { - if (![self.entity getCellValue:cellType]) - continue; - m_sections.push_back(cellSection.second); - m_cells[cellSection.second].push_back(cellType); - } - } - - sort(m_sections.begin(), m_sections.end()); - m_sections.erase(unique(m_sections.begin(), m_sections.end()), m_sections.end()); -} - -- (void)configure -{ - [self configureMapDownloader]; - - MWMPlacePageEntity * entity = self.entity; - if (entity.isBookmark) - { - if (![entity.bookmarkTitle isEqualToString:entity.title] && entity.bookmarkTitle.length > 0) - { - self.titleLabel.text = entity.bookmarkTitle; - self.externalTitleLabel.text = entity.title; - } - else - { - self.titleLabel.text = entity.title; - self.externalTitleLabel.text = @""; - } - } - else - { - self.titleLabel.text = entity.title; - self.externalTitleLabel.text = @""; - } - - NSMutableString * subtitle = [entity.subtitle mutableCopy]; - NSString * sizeStr = self.downloadProgressView.hidden ? nil : formattedSize(self.downloadMapSize); - if (subtitle) - { - NSString * separator = @(place_page::Info::kSubtitleSeparator); - if (sizeStr) - [subtitle appendString:[NSString stringWithFormat:@"%@%@", separator, sizeStr]]; - NSMutableAttributedString * str = [[NSMutableAttributedString alloc] initWithString:subtitle]; - auto const separatorRanges = [subtitle rangesOfString:separator]; - if (!separatorRanges.empty()) - { - for (auto const & r : separatorRanges) - [str addAttributes:@{ NSForegroundColorAttributeName : [UIColor blackHintText] } range:r]; - } - - auto const starsRanges = [subtitle rangesOfString:@(place_page::Info::kStarSymbol)]; - if (!starsRanges.empty()) - { - for (auto const & r : starsRanges) - [str addAttributes:@{ NSForegroundColorAttributeName : [UIColor yellow] } range:r]; - } - - self.subtitleLabel.attributedText = str; - } - else - { - self.subtitleLabel.text = sizeStr; - } - - BOOL const isMyPosition = entity.isMyPosition; - self.addressLabel.text = entity.address; - - if (!entity.bookingOnlinePrice.length) - { - self.bookingPriceLabel.text = entity.bookingPrice; - [entity onlinePricingWithCompletionBlock:^{ - if (!entity.bookingOnlinePrice.length) - return; - self.bookingPriceLabel.text = entity.bookingOnlinePrice; - [self setNeedsLayout]; - [UIView animateWithDuration:kDefaultAnimationDuration - animations:^{ - [self layoutIfNeeded]; - }]; - } - failure:^{ - // TODO(Vlad): Process an error. - }]; - } - else - { - self.bookingPriceLabel.text = entity.bookingOnlinePrice; - } - - self.bookingRatingLabel.text = entity.bookingRating; - self.bookingView.hidden = !entity.bookingPrice.length && !entity.bookingRating.length; - BOOL const isHeadingAvaible = [CLLocationManager headingAvailable]; - BOOL const noLocation = location_helpers::isMyPositionPendingOrNoPosition(); - self.distanceLabel.hidden = noLocation || isMyPosition; - BOOL const hideDirection = noLocation || isMyPosition || !isHeadingAvaible; - self.directionArrow.hidden = hideDirection; - self.directionButton.hidden = hideDirection; - - [self.featureTable reloadData]; - [self configureCurrentShedule]; - [MWMFrameworkListener addObserver:self]; - [self setNeedsLayout]; - [self layoutIfNeeded]; -} - -- (void)configureMapDownloader -{ - TCountryId const & countryId = self.entity.countryId; - if (countryId == kInvalidCountryId || platform::migrate::NeedMigrate()) - { - self.downloadProgressView.hidden = YES; - } - else - { - self.downloadProgressView.hidden = NO; - [self setNeedsLayout]; - NodeAttrs nodeAttrs; - GetFramework().GetStorage().GetNodeAttrs(countryId, nodeAttrs); - MWMCircularProgress * progress = self.mapDownloadProgress; - self.downloadMapSize = nodeAttrs.m_mwmSize - nodeAttrs.m_localMwmSize; - switch (nodeAttrs.m_status) - { - case NodeStatus::NotDownloaded: - case NodeStatus::Partly: - { - MWMCircularProgressStateVec const affectedStates = {MWMCircularProgressStateNormal, - MWMCircularProgressStateSelected}; - [progress setImageName:@"ic_download" forStates:affectedStates]; - [progress setColoring:MWMButtonColoringBlue forStates:affectedStates]; - progress.state = MWMCircularProgressStateNormal; - break; - } - case NodeStatus::Downloading: - { - auto const & prg = nodeAttrs.m_downloadingProgress; - progress.progress = static_cast(prg.first) / prg.second; - break; - } - case NodeStatus::InQueue: progress.state = MWMCircularProgressStateSpinner; break; - case NodeStatus::Undefined: - case NodeStatus::Error: progress.state = MWMCircularProgressStateFailed; break; - case NodeStatus::OnDisk: - case NodeStatus::OnDiskOutOfDate: - { - self.downloadProgressView.hidden = YES; - [self setNeedsLayout]; - [UIView animateWithDuration:kDefaultAnimationDuration - animations:^{ - [self layoutIfNeeded]; - }]; - break; - } - } - } -} - -- (void)configureCurrentShedule -{ - MWMPlacePageOpeningHoursCell * cell = self.openingHoursCell; - if (cell) - { - self.placeScheduleLabel.text = cell.isClosed ? L(@"closed_now") : L(@"editor_time_open"); - self.placeScheduleLabel.textColor = - cell.isClosed ? [UIColor red] : [UIColor blackSecondaryText]; - } - else - { - self.placeScheduleLabel.text = @""; - } -} - -#pragma mark - Layout - -- (AttributePosition)distanceAttributePosition -{ - if (self.addressLabel.text.length) - return AttributePosition::Address; - else if (!self.addressLabel.text.length && self.placeScheduleLabel.text.length) - return AttributePosition::Schedule; - else if (!self.placeScheduleLabel.text.length && self.subtitleLabel.text.length) - return AttributePosition::Subtitle; - else if (self.externalTitleLabel.text.length) - return AttributePosition::ExternalTitle; - else - return AttributePosition::Title; -} - -- (void)setupLabelsWidthWithBoundedWidth:(CGFloat)bound distancePosition:(AttributePosition)position -{ - auto const defaultMaxWidth = placePageWidth() - kLabelsPadding; - CGFloat const labelsMaxWidth = - self.downloadProgressView.hidden - ? defaultMaxWidth - : defaultMaxWidth - 2 * kDownloadProgressViewLeftOffset - self.downloadProgressView.width; - switch (position) - { - case AttributePosition::Title: - self.titleLabel.width = labelsMaxWidth - bound; - self.subtitleLabel.width = self.addressLabel.width = self.externalTitleLabel.width = - self.placeScheduleLabel.width = 0; - break; - case AttributePosition::ExternalTitle: - self.addressLabel.width = self.subtitleLabel.width = self.placeScheduleLabel.width = 0; - self.externalTitleLabel.width = labelsMaxWidth - bound; - self.titleLabel.width = self.titleLabel.text.length > 0 ? labelsMaxWidth : 0; - break; - case AttributePosition::Subtitle: - self.addressLabel.width = self.placeScheduleLabel.width = 0; - self.titleLabel.width = self.titleLabel.text.length > 0 ? labelsMaxWidth : 0; - self.externalTitleLabel.width = self.externalTitleLabel.text.length > 0 ? labelsMaxWidth : 0; - self.subtitleLabel.width = labelsMaxWidth - bound; - break; - case AttributePosition::Schedule: - self.addressLabel.width = 0; - self.titleLabel.width = self.titleLabel.text.length > 0 ? labelsMaxWidth : 0; - self.externalTitleLabel.width = self.externalTitleLabel.text.length > 0 ? labelsMaxWidth : 0; - self.subtitleLabel.width = self.subtitleLabel.text.length > 0 ? labelsMaxWidth : 0; - self.placeScheduleLabel.width = labelsMaxWidth - bound; - break; - case AttributePosition::Address: - self.titleLabel.width = self.titleLabel.text.length > 0 ? labelsMaxWidth : 0; - self.subtitleLabel.width = self.subtitleLabel.text.length > 0 ? labelsMaxWidth : 0; - self.externalTitleLabel.width = self.externalTitleLabel.text.length > 0 ? labelsMaxWidth : 0; - self.placeScheduleLabel.width = self.placeScheduleLabel.text.length > 0 ? labelsMaxWidth : 0; - self.addressLabel.width = labelsMaxWidth - bound; - break; - } - - self.externalTitleLabel.width = self.entity.isBookmark ? labelsMaxWidth : 0; - - CGFloat const bookingWidth = labelsMaxWidth / 2; - self.bookingRatingLabel.width = bookingWidth; - self.bookingPriceLabel.width = bookingWidth - kLabelsBetweenSmallOffset; - self.bookingView.width = labelsMaxWidth; - - [self.titleLabel sizeToFit]; - [self.subtitleLabel sizeToFit]; - [self.addressLabel sizeToFit]; - [self.externalTitleLabel sizeToFit]; - [self.placeScheduleLabel sizeToFit]; - [self.bookingRatingLabel sizeToFit]; - [self.bookingPriceLabel sizeToFit]; -} - -- (void)setDistance:(NSString *)distance -{ - self.distanceLabel.text = distance; - self.distanceLabel.width = placePageWidth() - kLabelsPadding; - [self.distanceLabel sizeToFit]; - [self layoutDistanceBoxWithPosition:[self distanceAttributePosition]]; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - CGFloat const bound = self.distanceLabel.width + kDirectionArrowSide + - kOffsetFromDistanceToArrow + kOffsetFromLabelsToDistance; - AttributePosition const position = [self distanceAttributePosition]; - [self setupLabelsWidthWithBoundedWidth:bound distancePosition:position]; - [self setupBookingView]; - [self layoutLabelsAndBooking]; - [self layoutTableViewWithPosition:position]; - [self setDistance:self.distanceLabel.text]; - self.height = self.featureTable.height + self.ppPreview.height; -} - -- (void)setupBookingView -{ - self.bookingRatingLabel.origin = {}; - self.bookingPriceLabel.origin = {self.bookingView.width - self.bookingPriceLabel.width, 0}; - self.bookingSeparator.origin = {0, self.bookingRatingLabel.maxY + kLabelsBetweenMainOffset}; - self.bookingView.height = self.bookingSeparator.maxY + kLabelsBetweenMainOffset; -} - -- (void)layoutLabelsAndBooking -{ - BOOL const isDownloadProgressViewHidden = self.downloadProgressView.hidden; - if (!isDownloadProgressViewHidden) - self.downloadProgressView.origin = {kDownloadProgressViewLeftOffset, - kDownloadProgressViewTopOffset}; - - CGFloat const leftOffset = isDownloadProgressViewHidden - ? kLeftOffset - : self.downloadProgressView.maxX + kDownloadProgressViewLeftOffset; - - auto originFrom = ^CGPoint(UIView * v, BOOL isBigOffset) { - CGFloat const offset = isBigOffset ? kLabelsBetweenMainOffset : kLabelsBetweenSmallOffset; - if ([v isKindOfClass:[UILabel class]]) - return {leftOffset, (static_cast(v).text.length == 0 ? v.minY : v.maxY) + offset}; - return {leftOffset, v.hidden ? v.minY : v.maxY + offset}; - }; - - self.titleLabel.origin = {leftOffset, kLabelsBetweenSmallOffset}; - self.externalTitleLabel.origin = originFrom(self.titleLabel, NO); - self.subtitleLabel.origin = originFrom(self.externalTitleLabel, NO); - self.placeScheduleLabel.origin = originFrom(self.subtitleLabel, NO); - self.bookingView.origin = originFrom(self.placeScheduleLabel, NO); - self.addressLabel.origin = originFrom(self.bookingView, YES); -} - -- (void)layoutDistanceBoxWithPosition:(AttributePosition)position -{ - auto getY = ^CGFloat(AttributePosition p) { - // Have to align distance box for the first label's line. - CGFloat const defaultCenter = p == AttributePosition::Title ? 12 : 8; - switch (position) - { - case AttributePosition::Title: return self.titleLabel.minY + defaultCenter; - case AttributePosition::ExternalTitle: return self.externalTitleLabel.minY + defaultCenter; - case AttributePosition::Subtitle: return self.subtitleLabel.minY + defaultCenter; - case AttributePosition::Schedule: return self.placeScheduleLabel.minY + defaultCenter; - case AttributePosition::Address: return self.addressLabel.minY + defaultCenter; - } - }; - - CGFloat const distanceX = placePageWidth() - kLeftOffset - self.distanceLabel.width; - CGFloat const directionX = distanceX - kOffsetFromDistanceToArrow - kDirectionArrowSide; - CGFloat const y = getY(position); - CGPoint const center = {directionX + kDirectionArrowSide / 2, y}; - self.directionArrow.center = center; - self.directionButton.origin = {center.x - self.directionButton.width / 2, - center.y - self.directionButton.height / 2}; - self.distanceLabel.center = {distanceX + self.distanceLabel.width / 2, - self.directionArrow.center.y}; -} - -- (void)layoutTableViewWithPosition:(AttributePosition)position -{ - auto getY = ^CGFloat(AttributePosition p) { - if (self.bookingView.hidden) - { - switch (position) - { - case AttributePosition::Title: return self.titleLabel.maxY + kBottomPlacePageOffset; - case AttributePosition::ExternalTitle: - return self.externalTitleLabel.maxY + kBottomPlacePageOffset; - case AttributePosition::Subtitle: return self.subtitleLabel.maxY + kBottomPlacePageOffset; - case AttributePosition::Schedule: - return self.placeScheduleLabel.maxY + kBottomPlacePageOffset; - case AttributePosition::Address: return self.addressLabel.maxY + kBottomPlacePageOffset; - } - } - else - { - switch (position) - { - case AttributePosition::Title: - case AttributePosition::ExternalTitle: - case AttributePosition::Subtitle: - case AttributePosition::Schedule: return self.bookingView.maxY + kBottomPlacePageOffset; - case AttributePosition::Address: return self.addressLabel.maxY + kBottomPlacePageOffset; - } - } - }; - - self.separatorView.minY = getY(position); - self.ppPreview.frame = {{}, {self.ppPreview.superview.width, self.separatorView.maxY}}; - self.featureTable.minY = self.separatorView.maxY; - self.featureTable.height = self.featureTable.contentSize.height; -} - -#pragma mark - Actions - -- (void)addBookmark -{ - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatToggleBookmark) - withParameters:@{kStatValue : kStatAdd}]; - [self.subtitleLabel sizeToFit]; - - m_sections.push_back(PlacePageSection::Bookmark); - m_cells[PlacePageSection::Bookmark].push_back(MWMPlacePageCellTypeBookmark); - sort(m_sections.begin(), m_sections.end()); - [self configure]; -} - -- (void)removeBookmark -{ - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatToggleBookmark) - withParameters:@{kStatValue : kStatRemove}]; - - auto const it = find(m_sections.begin(), m_sections.end(), PlacePageSection::Bookmark); - if (it != m_sections.end()) - { - m_sections.erase(it); - m_cells.erase(PlacePageSection::Bookmark); - } - - self.bookmarkCell = nil; - - [self configure]; -} - -- (void)reloadBookmarkCell -{ - MWMPlacePageCellType const type = MWMPlacePageCellTypeBookmark; - [self fillCell:self.bookmarkCell withType:type]; - [self configure]; - [CATransaction begin]; - [CATransaction setCompletionBlock:^{ - [self setNeedsLayout]; - dispatch_async(dispatch_get_main_queue(), ^{ - [self.ownerPlacePage refresh]; - }); - }]; - [CATransaction commit]; -} - -- (IBAction)directionButtonTap -{ - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatCompass)]; - [self.ownerPlacePage.manager showDirectionViewWithTitle:self.titleLabel.text - type:self.subtitleLabel.text]; -} - -- (void)updateAndLayoutMyPositionSpeedAndAltitude:(NSString *)text -{ - self.subtitleLabel.text = text; - [self setNeedsLayout]; -} - -#pragma mark - MWMPlacePageBookmarkDelegate - -- (void)reloadBookmark { [self reloadBookmarkCell]; } -- (void)editBookmarkTap { [self.ownerPlacePage editBookmark]; } -- (void)moreTap -{ - self.isBookmarkCellExpanded = YES; - [self reloadBookmarkCell]; -} - -#pragma mark - MWMPlacePageOpeningHoursCellProtocol - -- (BOOL)forcedButton { return NO; } -- (BOOL)isPlaceholder { return NO; } -- (BOOL)isEditor { return NO; } -- (void)setOpeningHoursCellExpanded:(BOOL)openingHoursCellExpanded -{ - _openingHoursCellExpanded = openingHoursCellExpanded; - UITableView * tv = self.featureTable; - MWMPlacePageCellType const type = MWMPlacePageCellTypeOpenHours; - [self fillCell:self.openingHoursCell withType:type]; - [tv beginUpdates]; - [CATransaction begin]; - [CATransaction setCompletionBlock:^{ - [self setNeedsLayout]; - dispatch_async(dispatch_get_main_queue(), ^{ - [self.ownerPlacePage refresh]; - }); - }]; - [tv endUpdates]; - [CATransaction commit]; -} - -#pragma mark - UITableView - -- (MWMPlacePageCellType)cellTypeForIndexPath:(NSIndexPath *)indexPath -{ - return [self cellsForSection:indexPath.section][indexPath.row]; -} - -- (NSString *)cellIdentifierForIndexPath:(NSIndexPath *)indexPath -{ - MWMPlacePageCellType const cellType = [self cellTypeForIndexPath:indexPath]; - return reuseIdentifier(cellType); -} - -- (void)fillCell:(UITableViewCell *)cell withType:(MWMPlacePageCellType)cellType -{ - MWMPlacePageEntity * entity = self.entity; - switch (cellType) - { - case MWMPlacePageCellTypeBookmark: - [static_cast(cell) configWithText:entity.bookmarkDescription - delegate:self - placePageWidth:placePageWidth() - isOpen:self.isBookmarkCellExpanded - isHtml:entity.isHTMLDescription]; - break; - case MWMPlacePageCellTypeOpenHours: - [(MWMPlacePageOpeningHoursCell *)cell configWithDelegate:self - info:[entity getCellValue:cellType]]; - break; - case MWMPlacePageCellTypeEditButton: - case MWMPlacePageCellTypeAddBusinessButton: - case MWMPlacePageCellTypeAddPlaceButton: - case MWMPlacePageCellTypeBookingMore: - [static_cast(cell) config:self.ownerPlacePage.manager - forType:cellType]; - break; - default: - { - MWMPlacePageInfoCell * tCell = (MWMPlacePageInfoCell *)cell; - tCell.currentEntity = entity; - [tCell configureWithType:cellType info:[entity getCellValue:cellType]]; - break; - } - } -} - -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath -{ - MWMPlacePageCellType const cellType = [self cellTypeForIndexPath:indexPath]; - switch (cellType) - { - case MWMPlacePageCellTypeBookmark: return self.bookmarkCell.cellHeight; - case MWMPlacePageCellTypeOpenHours: return self.openingHoursCell.cellHeight; - default: return UITableViewAutomaticDimension; - } -} - -- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath -{ - return UITableViewAutomaticDimension; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - return [self cellsForSection:section].size(); -} - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return m_sections.size(); } -- (UITableViewCell *)tableView:(UITableView *)tableView - cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - MWMPlacePageCellType const type = [self cellTypeForIndexPath:indexPath]; - NSString * identifier = reuseIdentifier(type); - UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier]; - switch (type) - { - case MWMPlacePageCellTypeBookmark: - if (self.bookmarkCell) - return self.bookmarkCell; - - self.bookmarkCell = static_cast(cell); - break; - case MWMPlacePageCellTypeOpenHours: - if (self.openingHoursCell) - return self.openingHoursCell; - - self.openingHoursCell = static_cast(cell); - break; - default: break; - } - [self fillCell:cell withType:type]; - return cell; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section -{ - return section == m_sections.size() - 1 ? kDefaultHeaderHeight : 0.; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section -{ - if (m_sections[section] == PlacePageSection::Bookmark) - return 0.001; - return kDefaultHeaderHeight; -} - -- (vector)cellsForSection:(NSInteger)section -{ - NSAssert(m_sections.size() > section, @"Invalid section"); - return m_cells[m_sections[section]]; -} - -#pragma mark - MWMFrameworkStorageObserver - -- (void)processCountryEvent:(TCountryId const &)countryId -{ - if (countryId != self.entity.countryId) - return; - [self configureMapDownloader]; -} - -- (void)processCountry:(TCountryId const &)countryId - progress:(MapFilesDownloader::TProgress const &)progress -{ - if (countryId != self.entity.countryId) - return; - self.mapDownloadProgress.progress = static_cast(progress.first) / progress.second; -} - -#pragma mark - MWMCircularProgressProtocol - -- (void)progressButtonPressed:(nonnull MWMCircularProgress *)progress -{ - TCountryId const & countryId = self.entity.countryId; - NodeAttrs nodeAttrs; - GetFramework().GetStorage().GetNodeAttrs(countryId, nodeAttrs); - MWMAlertViewController * avc = self.ownerPlacePage.manager.ownerViewController.alertController; - switch (nodeAttrs.m_status) - { - case NodeStatus::NotDownloaded: - case NodeStatus::Partly: - [MWMStorage downloadNode:countryId alertController:avc onSuccess:nil]; - break; - case NodeStatus::Undefined: - case NodeStatus::Error: [MWMStorage retryDownloadNode:countryId alertController:avc]; break; - case NodeStatus::OnDiskOutOfDate: [MWMStorage updateNode:countryId alertController:avc]; break; - case NodeStatus::Downloading: - case NodeStatus::InQueue: [MWMStorage cancelDownloadNode:countryId]; break; - case NodeStatus::OnDisk: break; - } -} - -#pragma mark - Properties - -- (MWMCircularProgress *)mapDownloadProgress -{ - if (!_mapDownloadProgress) - { - _mapDownloadProgress = - [MWMCircularProgress downloaderProgressForParentView:self.downloadProgressView]; - _mapDownloadProgress.delegate = self; - } - return _mapDownloadProgress; -} - -@end diff --git a/iphone/Maps/Classes/MWMBookmarkCell.mm b/iphone/Maps/Classes/MWMBookmarkCell.mm index cf377a7985..eab86eb4d4 100644 --- a/iphone/Maps/Classes/MWMBookmarkCell.mm +++ b/iphone/Maps/Classes/MWMBookmarkCell.mm @@ -72,7 +72,7 @@ NSString * const kTextViewContentSizeKeyPath = @"contentSize"; [self stateOpen:NO]; [self setNeedsLayout]; - [self.updateCellDelegate updateCellWithForceReposition:NO]; + [self.updateCellDelegate cellUpdated]; return; } @@ -202,4 +202,5 @@ NSString * const kTextViewContentSizeKeyPath = @"contentSize"; } - (IBAction)editTap { [self.editBookmarkDelegate editBookmark]; } + @end diff --git a/iphone/Maps/Classes/MWMDirectionView.h b/iphone/Maps/Classes/MWMDirectionView.h index e9f8d99ee9..830862dcc6 100644 --- a/iphone/Maps/Classes/MWMDirectionView.h +++ b/iphone/Maps/Classes/MWMDirectionView.h @@ -10,14 +10,11 @@ @property (weak, nonatomic) IBOutlet UIImageView * directionArrow; @property (weak, nonatomic) IBOutlet UIView * contentView; -- (instancetype)initWithManager:(MWMPlacePageViewManager *)manager; - (void)setDirectionArrowTransform:(CGAffineTransform)transform; - (void)show; - (instancetype)initWithCoder:(NSCoder *)aDecoder __attribute__((unavailable("initWithCoder is not available"))); - (instancetype)initWithFrame:(CGRect)frame __attribute__((unavailable("initWithFrame is not available"))); -- (instancetype)init __attribute__((unavailable("init is not available"))); - @end diff --git a/iphone/Maps/Classes/MWMDirectionView.mm b/iphone/Maps/Classes/MWMDirectionView.mm index 9026fc4638..73eb046cd7 100644 --- a/iphone/Maps/Classes/MWMDirectionView.mm +++ b/iphone/Maps/Classes/MWMDirectionView.mm @@ -1,6 +1,5 @@ #import "MWMDirectionView.h" #import "MWMMapViewControlsManager.h" -#import "MWMPlacePageViewManager.h" #import "MapViewController.h" #import "MapsAppDelegate.h" #import "UIFont+MapsMeFonts.h" @@ -10,23 +9,21 @@ static CGFloat const kDirectionArrowSide = IPAD ? 260. : 160.; @interface MWMDirectionView () -@property (weak, nonatomic) MWMPlacePageViewManager * manager; @property (nonatomic) CGSize defaultSize; @end @implementation MWMDirectionView -- (instancetype)initWithManager:(MWMPlacePageViewManager *)manager +- (instancetype)init { self = [[[NSBundle mainBundle] loadNibNamed:kDirectionViewNibName owner:nil options:nil] firstObject]; - [self setup:manager]; + [self setup]; return self; } -- (void)setup:(MWMPlacePageViewManager *)manager +- (void)setup { - self.manager = manager; self.directionArrow.size = CGSizeMake(kDirectionArrowSide, kDirectionArrowSide); self.directionArrow.image = [UIImage imageNamed:IPAD ? @"direction_big" : @"direction_mini"]; diff --git a/iphone/Maps/Classes/MWMEditBookmarkController.h b/iphone/Maps/Classes/MWMEditBookmarkController.h index 1f0ae89665..d8d47c6e20 100644 --- a/iphone/Maps/Classes/MWMEditBookmarkController.h +++ b/iphone/Maps/Classes/MWMEditBookmarkController.h @@ -1,11 +1,9 @@ #import "MWMTableViewController.h" -@class MWMPlacePageViewManager; @class MWMPlacePageData; @interface MWMEditBookmarkController : MWMTableViewController @property(weak, nonatomic) MWMPlacePageData * data; -@property (nonatomic) MWMPlacePageViewManager * manager; @end diff --git a/iphone/Maps/Classes/MWMEditBookmarkController.mm b/iphone/Maps/Classes/MWMEditBookmarkController.mm index a55220872e..85d24e99c1 100644 --- a/iphone/Maps/Classes/MWMEditBookmarkController.mm +++ b/iphone/Maps/Classes/MWMEditBookmarkController.mm @@ -5,8 +5,6 @@ #import "MWMButtonCell.h" #import "MWMNoteCell.h" #import "MWMPlacePageData.h" -#import "MWMPlacePageEntity.h" -#import "MWMPlacePageViewManager.h" #import "SelectSetVC.h" #import "UIImageView+Coloring.h" #import "UIViewController+Navigation.h" @@ -53,25 +51,12 @@ enum RowInMetaInfo { [super viewDidLoad]; auto data = self.data; - NSAssert(self.manager || data, @"Entity and data can't be nil both!"); - if (IPAD) - { - MWMPlacePageEntity * en = self.manager.entity; - self.cachedDescription = en.bookmarkDescription; - self.cachedTitle = en.bookmarkTitle; - self.cachedCategory = en.bookmarkCategory; - self.cachedColor = en.bookmarkColor; - m_cachedBac = en.bac; - } - else - { - self.cachedDescription = data.bookmarkDescription; - self.cachedTitle = data.externalTitle ? data.externalTitle : data.title; - self.cachedCategory = data.bookmarkCategory; - self.cachedColor = data.bookmarkColor; - m_cachedBac = data.bac; - } - + NSAssert(data, @"Data can't be nil!"); + self.cachedDescription = data.bookmarkDescription; + self.cachedTitle = data.externalTitle ? data.externalTitle : data.title; + self.cachedCategory = data.bookmarkCategory; + self.cachedColor = data.bookmarkColor; + m_cachedBac = data.bac; [self configNavBar]; [self registerCells]; } @@ -109,48 +94,25 @@ enum RowInMetaInfo - (void)onSave { [self.view endEditing:YES]; - if (IPAD) + auto & f = GetFramework(); + BookmarkCategory * category = f.GetBmCategory(m_cachedBac.m_categoryIndex); + if (!category) + return; + { - MWMPlacePageEntity * en = self.manager.entity; - en.bookmarkDescription = self.cachedDescription; - en.bookmarkColor = self.cachedColor; - en.bookmarkCategory = self.cachedCategory; - en.bookmarkTitle = self.cachedTitle; - en.bac = m_cachedBac; - [en synchronize]; - [self.manager reloadBookmark]; - } - else - { - Framework & f = GetFramework(); - BookmarkCategory * category = f.GetBmCategory(m_cachedBac.m_categoryIndex); - if (!category) + BookmarkCategory::Guard guard(*category); + auto bookmark = static_cast(guard.m_controller.GetUserMarkForEdit(m_cachedBac.m_bookmarkIndex)); + if (!bookmark) return; - { - BookmarkCategory::Guard guard(*category); - Bookmark * bookmark = - static_cast(guard.m_controller.GetUserMarkForEdit(m_cachedBac.m_bookmarkIndex)); - if (!bookmark) - return; - - bookmark->SetType(self.cachedColor.UTF8String); - bookmark->SetDescription(self.cachedDescription.UTF8String); - bookmark->SetName(self.cachedTitle.UTF8String); - } - - category->SaveToKMLFile(); - f.UpdatePlacePageInfoForCurrentSelection(); + bookmark->SetType(self.cachedColor.UTF8String); + bookmark->SetDescription(self.cachedDescription.UTF8String); + bookmark->SetName(self.cachedTitle.UTF8String); } - [self backTap]; -} -- (void)backTap -{ - if (IPAD) - [self dismissViewControllerAnimated:YES completion:nil]; - else - [super backTap]; + category->SaveToKMLFile(); + f.UpdatePlacePageInfoForCurrentSelection(); + [self backTap]; } #pragma mark - UITableView @@ -277,15 +239,8 @@ enum RowInMetaInfo - (void)cellSelect:(UITableViewCell *)cell { - if (IPAD) - { - [self.manager removeBookmark]; - } - else - { - [self.data updateBookmarkStatus:NO]; - GetFramework().UpdatePlacePageInfoForCurrentSelection(); - } + [self.data updateBookmarkStatus:NO]; + GetFramework().UpdatePlacePageInfoForCurrentSelection(); [self backTap]; } diff --git a/iphone/Maps/Classes/MWMExtendedPlacePageView.h b/iphone/Maps/Classes/MWMExtendedPlacePageView.h deleted file mode 100644 index 59143b9e2e..0000000000 --- a/iphone/Maps/Classes/MWMExtendedPlacePageView.h +++ /dev/null @@ -1,3 +0,0 @@ -@interface MWMExtendedPlacePageView : SolidTouchView - -@end diff --git a/iphone/Maps/Classes/MWMExtendedPlacePageView.mm b/iphone/Maps/Classes/MWMExtendedPlacePageView.mm deleted file mode 100644 index 4a03cfc352..0000000000 --- a/iphone/Maps/Classes/MWMExtendedPlacePageView.mm +++ /dev/null @@ -1,13 +0,0 @@ -#import "MWMExtendedPlacePageView.h" - -@implementation MWMExtendedPlacePageView - -- (instancetype)initWithCoder:(NSCoder *)aDecoder -{ - self = [super initWithCoder:aDecoder]; - if (self) - self.autoresizingMask = UIViewAutoresizingNone; - return self; -} - -@end diff --git a/iphone/Maps/Classes/MWMOpeningHoursCell.h b/iphone/Maps/Classes/MWMOpeningHoursCell.h deleted file mode 100644 index b310ed1035..0000000000 --- a/iphone/Maps/Classes/MWMOpeningHoursCell.h +++ /dev/null @@ -1,10 +0,0 @@ -#import "MWMTableViewCell.h" - -@protocol MWMPlacePageCellUpdateProtocol; - -@interface MWMOpeningHoursCell : MWMTableViewCell - -- (void)configureWithOpeningHours:(NSString *)openingHours - updateLayoutDelegate:(id)delegate - isClosedNow:(BOOL)isClosedNow; -@end diff --git a/iphone/Maps/Classes/MWMOpeningHoursCell.mm b/iphone/Maps/Classes/MWMOpeningHoursCell.mm deleted file mode 100644 index dafc55ef8e..0000000000 --- a/iphone/Maps/Classes/MWMOpeningHoursCell.mm +++ /dev/null @@ -1,243 +0,0 @@ -#import "MWMOpeningHoursCell.h" -#import "Common.h" -#import "MWMOpeningHours.h" -#import "MWMPlacePageCellUpdateProtocol.h" -#import "UIColor+MapsMeColor.h" -#import "UIFont+MapsMeFonts.h" - -#include "std/array.hpp" - -namespace -{ -array kOHClasses = {{@"_MWMOHHeaderCell", @"_MWMOHSubCell"}}; -void * kContext = &kContext; -NSString * const kTableViewContentSizeKeyPath = @"contentSize"; - -NSAttributedString * richStringFromDay(osmoh::Day const & day, BOOL isClosedNow) -{ - auto const richString = ^NSMutableAttributedString * (NSString * str, UIFont * font, UIColor * color) - { - return [[NSMutableAttributedString alloc] initWithString:str - attributes:@{NSFontAttributeName : font, - NSForegroundColorAttributeName : color}]; - }; - - auto str = richString(day.TodayTime(), [UIFont regular17], day.m_isOpen ? [UIColor blackPrimaryText] : - [UIColor red]); - if (day.m_isOpen) - { - auto lineBreak = [[NSAttributedString alloc] initWithString:@"\n"]; - - if (day.m_breaks.length) - { - [str appendAttributedString:lineBreak]; - [str appendAttributedString:richString(day.m_breaks, [UIFont regular13], [UIColor blackSecondaryText])]; - } - - if (isClosedNow) - { - [str appendAttributedString:lineBreak]; - [str appendAttributedString:richString(L(@"closed_now"), [UIFont regular13], [UIColor red])]; - } - - auto paragraphStyle = [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.lineSpacing = 4; - - [str addAttributes:@{NSParagraphStyleAttributeName : paragraphStyle} range:{0, str.length}]; - } - return str; -} - -} // namespace - -#pragma mark - _MWMOHHeaderCell - -@interface _MWMOHHeaderCell : MWMTableViewCell - -@property(weak, nonatomic) IBOutlet UILabel * text; -@property(weak, nonatomic) IBOutlet UIImageView * arrowIcon; - -@property(copy, nonatomic) TMWMVoidBlock tapAction; - -@end - -@implementation _MWMOHHeaderCell - -- (IBAction)extendTap -{ - if (!self.tapAction) - return; - - self.tapAction(); - [UIView animateWithDuration:kDefaultAnimationDuration - animations:^{ - self.arrowIcon.transform = - CGAffineTransformIsIdentity(self.arrowIcon.transform) - ? CGAffineTransformMakeRotation(M_PI) - : CGAffineTransformIdentity; - }]; -} - -@end - -#pragma mark - _MWMOHSubCell - -@interface _MWMOHSubCell : MWMTableViewCell - -@property(weak, nonatomic) IBOutlet UILabel * days; -@property(weak, nonatomic) IBOutlet UILabel * schedule; -@property(weak, nonatomic) IBOutlet UILabel * breaks; -@property(weak, nonatomic) IBOutlet UIImageView * separator; - -@end - -@implementation _MWMOHSubCell - -@end - -@interface MWMOpeningHoursCell () - -@property(weak, nonatomic) IBOutlet UITableView * tableView; -@property(weak, nonatomic) IBOutlet NSLayoutConstraint * tableViewHeight; -@property(copy, nonatomic) NSString * rawString; - -@property(weak, nonatomic) id delegate; - -@property(nonatomic) BOOL isExtended; -@property(nonatomic) BOOL isClosedNow; - -@end - -@implementation MWMOpeningHoursCell -{ - vector m_days; -} - -- (void)awakeFromNib -{ - [super awakeFromNib]; - for (auto s : kOHClasses) - [self.tableView registerNib:[UINib nibWithNibName:s bundle:nil] forCellReuseIdentifier:s]; - - self.tableView.estimatedRowHeight = 48; - self.tableView.rowHeight = UITableViewAutomaticDimension; - [self registerObserver]; -} - -- (void)configureWithOpeningHours:(NSString *)openingHours - updateLayoutDelegate:(id)delegate - isClosedNow:(BOOL)isClosedNow; -{ - self.tableView.delegate = nil; - self.tableView.dataSource = nil; - self.isExtended = NO; - self.delegate = delegate; - self.isClosedNow = isClosedNow; - // If we can't parse opening hours string then leave it as is. - self.rawString = openingHours; - - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ - self->m_days = [MWMOpeningHours processRawString:openingHours]; - dispatch_async(dispatch_get_main_queue(), ^{ - self.tableView.delegate = self; - self.tableView.dataSource = self; - [self.tableView reloadData]; - }); - }); -} - -#pragma mark - UITableView - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - return self.isExtended && !m_days.empty() ? m_days.size() : 1; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView - cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - auto const & day = m_days[indexPath.row]; - - if (indexPath.row == 0) - { - _MWMOHHeaderCell * cell = - [tableView dequeueReusableCellWithIdentifier:[_MWMOHHeaderCell className]]; - - if (m_days.size() > 1) - { - cell.tapAction = ^{ - self.isExtended = !self.isExtended; - - NSMutableArray * ip = [@[] mutableCopy]; - - for (auto i = 1; i < self->m_days.size(); i++) - [ip addObject:[NSIndexPath indexPathForRow:i inSection:0]]; - - if (self.isExtended) - [self.tableView insertRowsAtIndexPaths:ip - withRowAnimation:UITableViewRowAnimationAutomatic]; - else - [self.tableView deleteRowsAtIndexPaths:ip - withRowAnimation:UITableViewRowAnimationAutomatic]; - }; - cell.arrowIcon.hidden = NO; - } - else - { - cell.tapAction = nil; - cell.arrowIcon.hidden = YES; - } - - // This means that we couldn't parse opening hours string. - if (m_days.empty()) - cell.text.text = self.rawString; - else - cell.text.attributedText = richStringFromDay(day, self.isClosedNow); - - return cell; - } - else - { - _MWMOHSubCell * cell = [tableView dequeueReusableCellWithIdentifier:[_MWMOHSubCell className]]; - cell.days.text = day.m_workingDays; - cell.schedule.text = day.m_workingTimes ? day.m_workingTimes : L(@"closed"); - cell.breaks.text = day.m_breaks; - cell.separator.hidden = indexPath.row == m_days.size() - 1; - return cell; - } -} - -#pragma mark - Observer's methods - -- (void)dealloc { [self unregisterObserver]; } -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context -{ - if (context == kContext) - { - NSValue * s = change[@"new"]; - CGFloat const height = s.CGSizeValue.height; - self.tableViewHeight.constant = height; - [self setNeedsLayout]; - [self.delegate updateCellWithForceReposition:NO]; - return; - } - - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; -} - -- (void)unregisterObserver -{ - [self.tableView removeObserver:self forKeyPath:kTableViewContentSizeKeyPath context:kContext]; -} - -- (void)registerObserver -{ - [self.tableView addObserver:self - forKeyPath:kTableViewContentSizeKeyPath - options:NSKeyValueObservingOptionNew - context:kContext]; -} -@end diff --git a/iphone/Maps/Classes/MWMOpeningHoursLayoutHelper.h b/iphone/Maps/Classes/MWMOpeningHoursLayoutHelper.h new file mode 100644 index 0000000000..7da07515a6 --- /dev/null +++ b/iphone/Maps/Classes/MWMOpeningHoursLayoutHelper.h @@ -0,0 +1,9 @@ +@class MWMPlacePageData; + +@interface MWMOpeningHoursLayoutHelper : NSObject + +- (instancetype)initWithTableView:(UITableView *)tableView; +- (void)configWithData:(MWMPlacePageData *)data; +- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath; + +@end diff --git a/iphone/Maps/Classes/MWMOpeningHoursLayoutHelper.mm b/iphone/Maps/Classes/MWMOpeningHoursLayoutHelper.mm new file mode 100644 index 0000000000..814f6881ea --- /dev/null +++ b/iphone/Maps/Classes/MWMOpeningHoursLayoutHelper.mm @@ -0,0 +1,229 @@ +#import "MWMOpeningHoursLayoutHelper.h" +#import "Common.h" +#import "MWMOpeningHours.h" +#import "MWMPlacePageData.h" +#import "MWMTableViewCell.h" +#import "UIColor+MapsMeColor.h" +#import "UIFont+MapsMeFonts.h" + +#include "std/array.hpp" + +namespace +{ +array const kCells = {{@"_MWMOHHeaderCell", @"_MWMOHSubCell"}}; + +NSAttributedString * richStringFromDay(osmoh::Day const & day, BOOL isClosedNow) +{ + auto const richString = ^NSMutableAttributedString * (NSString * str, UIFont * font, UIColor * color) + { + return [[NSMutableAttributedString alloc] initWithString:str + attributes:@{NSFontAttributeName : font, + NSForegroundColorAttributeName : color}]; + }; + + auto str = richString(day.TodayTime(), [UIFont regular17], day.m_isOpen ? [UIColor blackPrimaryText] : + [UIColor red]); + if (day.m_isOpen) + { + auto lineBreak = [[NSAttributedString alloc] initWithString:@"\n"]; + + if (day.m_breaks.length) + { + [str appendAttributedString:lineBreak]; + [str appendAttributedString:richString(day.m_breaks, [UIFont regular13], [UIColor blackSecondaryText])]; + } + + if (isClosedNow) + { + [str appendAttributedString:lineBreak]; + [str appendAttributedString:richString(L(@"closed_now"), [UIFont regular13], [UIColor red])]; + } + + auto paragraphStyle = [[NSMutableParagraphStyle alloc] init]; + paragraphStyle.lineSpacing = 4; + + [str addAttributes:@{NSParagraphStyleAttributeName : paragraphStyle} range:{0, str.length}]; + } + return str; +} + +} // namespace + +@interface MWMPlacePageData() + +- (vector &)mutableMetainfoRows; + +@end + +#pragma mark - _MWMOHHeaderCell + +@interface _MWMOHHeaderCell : MWMTableViewCell + +@property(weak, nonatomic) IBOutlet UILabel * text; +@property(weak, nonatomic) IBOutlet UIImageView * arrowIcon; + +@property(copy, nonatomic) TMWMVoidBlock tapAction; + +@end + +@implementation _MWMOHHeaderCell + +- (IBAction)extendTap +{ + if (!self.tapAction) + return; + + self.tapAction(); + [UIView animateWithDuration:kDefaultAnimationDuration + animations:^{ + self.arrowIcon.transform = + CGAffineTransformIsIdentity(self.arrowIcon.transform) + ? CGAffineTransformMakeRotation(M_PI) + : CGAffineTransformIdentity; + }]; +} + +@end + +#pragma mark - _MWMOHSubCell + +@interface _MWMOHSubCell : MWMTableViewCell + +@property(weak, nonatomic) IBOutlet UILabel * days; +@property(weak, nonatomic) IBOutlet UILabel * schedule; +@property(weak, nonatomic) IBOutlet UILabel * breaks; + +@end + +@implementation _MWMOHSubCell + +@end + + +@interface MWMOpeningHoursLayoutHelper() +{ + vector m_days; +} + +@property(weak, nonatomic) UITableView * tableView; +@property(weak, nonatomic) MWMPlacePageData * data; + +@property(copy, nonatomic) NSString * rawString; +@property(nonatomic) BOOL isClosed; +@property(nonatomic) BOOL isExtended; + +@end + +@implementation MWMOpeningHoursLayoutHelper + +- (instancetype)initWithTableView:(UITableView *)tableView +{ + self = [super init]; + if (self) + { + _tableView = tableView; + [self registerCells]; + } + return self; +} + +- (void)registerCells +{ + for (auto name : kCells) + [self.tableView registerNib:[UINib nibWithNibName:name bundle:nil] forCellReuseIdentifier:name]; +} + +- (void)configWithData:(MWMPlacePageData *)data +{ + self.data = data; + self.rawString = [data stringForRow:place_page::MetainfoRows::OpeningHours]; + self.isClosed = data.schedule == place_page::OpeningHours::Closed; + m_days = [MWMOpeningHours processRawString:self.rawString]; +} + +- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + auto tableView = self.tableView; + auto const & day = m_days[indexPath.row]; + + if (self.data.metainfoRows[indexPath.row] == place_page::MetainfoRows::OpeningHours) + { + _MWMOHHeaderCell * cell = [tableView dequeueReusableCellWithIdentifier:[_MWMOHHeaderCell className]]; + + if (m_days.size() > 1) + { + cell.tapAction = ^{ + self.isExtended = !self.isExtended; + + NSMutableArray * ip = [@[] mutableCopy]; + + for (auto i = 1; i < self->m_days.size(); i++) + [ip addObject:[NSIndexPath indexPathForRow:i inSection:1]]; + + if (self.isExtended) + { + [self extendMetainfoRowsWithSize:ip.count]; + [tableView insertRowsAtIndexPaths:ip + withRowAnimation:UITableViewRowAnimationLeft]; + } + else + { + [self reduceMetainfoRows]; + [tableView deleteRowsAtIndexPaths:ip + withRowAnimation:UITableViewRowAnimationLeft]; + } + }; + cell.arrowIcon.hidden = NO; + } + else + { + cell.tapAction = nil; + cell.arrowIcon.hidden = YES; + } + + // This means that we couldn't parse opening hours string. + if (m_days.empty()) + cell.text.text = self.rawString; + else + cell.text.attributedText = richStringFromDay(day, self.isClosed); + + return cell; + } + else + { + _MWMOHSubCell * cell = [tableView dequeueReusableCellWithIdentifier:[_MWMOHSubCell className]]; + cell.days.text = day.m_workingDays; + cell.schedule.text = day.m_workingTimes ? day.m_workingTimes : L(@"closed"); + cell.breaks.text = day.m_breaks; + return cell; + } +} + +- (void)extendMetainfoRowsWithSize:(NSUInteger)size +{ + if (size == 0) + { + NSAssert(false, @"Incorrect number of days!"); + return; + } + + auto & metainfoRows = self.data.mutableMetainfoRows; + using place_page::MetainfoRows; + + auto it = find(metainfoRows.begin(), metainfoRows.end(), MetainfoRows::OpeningHours); + if (it == metainfoRows.end()) + { + LOG(LERROR, ("Incorrect state!")); + return; + } + + metainfoRows.insert(++it, size, MetainfoRows::ExtendedOpeningHours); +} + +- (void)reduceMetainfoRows +{ + auto & metainfoRows = self.data.mutableMetainfoRows; + metainfoRows.erase(remove(metainfoRows.begin(), metainfoRows.end(), place_page::MetainfoRows::ExtendedOpeningHours), metainfoRows.end()); +} + +@end diff --git a/iphone/Maps/Classes/MWMPPPreviewLayoutHelper.h b/iphone/Maps/Classes/MWMPPPreviewLayoutHelper.h new file mode 100644 index 0000000000..580237abf0 --- /dev/null +++ b/iphone/Maps/Classes/MWMPPPreviewLayoutHelper.h @@ -0,0 +1,13 @@ +@class MWMPlacePageData; + +@interface MWMPPPreviewLayoutHelper : NSObject + +- (instancetype)initWithTableView:(UITableView *)tableView; +- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath + withData:(MWMPlacePageData *)data; + +- (void)rotateDirectionArrowToAngle:(CGFloat)angle; +- (void)setDistanceToObject:(NSString *)distance; +- (CGFloat)height; + +@end diff --git a/iphone/Maps/Classes/MWMPPPreviewLayoutHelper.mm b/iphone/Maps/Classes/MWMPPPreviewLayoutHelper.mm new file mode 100644 index 0000000000..e2b821a724 --- /dev/null +++ b/iphone/Maps/Classes/MWMPPPreviewLayoutHelper.mm @@ -0,0 +1,279 @@ +#import "MWMPPPreviewLayoutHelper.h" +#import "Common.h" +#import "MWMDirectionView.h" +#import "MWMPlacePageData.h" +#import "MWMTableViewCell.h" +#import "UIColor+MapsmeColor.h" + +#include "std/array.hpp" + +namespace +{ +array const kPreviewCells = {{@"_MWMPPPTitle", @"_MWMPPPExternalTitle", @"_MWMPPPSubtitle", + @"_MWMPPPSchedule", @"_MWMPPPBooking", @"_MWMPPPAddress", @"_MWMPPPSpace"}}; +} // namespace + +#pragma mark - Base +// Base class for avoiding copy-paste in inheriting cells. +@interface _MWMPPPCellBase : MWMTableViewCell + +@property(weak, nonatomic) IBOutlet UILabel * distance; +@property(weak, nonatomic) IBOutlet UIImageView * compass; +@property(weak, nonatomic) IBOutlet UIView * distanceView; +@property(weak, nonatomic) IBOutlet NSLayoutConstraint * trailing; +@property(copy, nonatomic) TMWMVoidBlock tapOnDistance; + +@end + +@implementation _MWMPPPCellBase + +- (void)layoutSubviews +{ + [super layoutSubviews]; + auto const inset = self.width / 2; + self.separatorInset = {0, inset, 0, inset}; +} + +- (IBAction)tap +{ + if (self.tapOnDistance) + self.tapOnDistance(); +} + +@end + +#pragma mark - Title + +@interface _MWMPPPTitle : _MWMPPPCellBase + +@property(weak, nonatomic) IBOutlet UILabel * title; + +@end + +@implementation _MWMPPPTitle +@end + +#pragma mark - External Title + +@interface _MWMPPPExternalTitle : _MWMPPPCellBase + +@property(weak, nonatomic) IBOutlet UILabel * externalTitle; + +@end + +@implementation _MWMPPPExternalTitle +@end + +#pragma mark - Subtitle + +@interface _MWMPPPSubtitle : _MWMPPPCellBase + +@property(weak, nonatomic) IBOutlet UILabel * subtitle; + +@end + +@implementation _MWMPPPSubtitle +@end + +#pragma mark - Schedule + +@interface _MWMPPPSchedule : _MWMPPPCellBase + +@property(weak, nonatomic) IBOutlet UILabel * schedule; + +@end + +@implementation _MWMPPPSchedule +@end + +#pragma mark - Booking + +@interface _MWMPPPBooking : MWMTableViewCell + +@property(weak, nonatomic) IBOutlet UILabel * rating; +@property(weak, nonatomic) IBOutlet UILabel * pricing; + +- (void)configWithRating:(NSString *)rating pricing:(NSString *)pricing; + +@end + +@implementation _MWMPPPBooking + +- (void)configWithRating:(NSString *)rating pricing:(NSString *)pricing +{ + self.rating.text = rating; + self.pricing.text = pricing; +} + +@end + +#pragma mark - Address + +@interface _MWMPPPAddress : _MWMPPPCellBase + +@property(weak, nonatomic) IBOutlet UILabel * address; + +@end + +@implementation _MWMPPPAddress +@end + +@interface MWMPPPreviewLayoutHelper () + +@property(weak, nonatomic) UITableView * tableView; + +@property(weak, nonatomic) NSLayoutConstraint * distanceCellTrailing; +@property(weak, nonatomic) UIView * distanceView; + +@property(nonatomic) CGFloat leading; +@property(nonatomic) MWMDirectionView * directionView; +@property(copy, nonatomic) NSString * distance; +@property(weak, nonatomic) UIImageView * compass; +@property(nonatomic) NSIndexPath * lastCellIndexPath; +@end + +@implementation MWMPPPreviewLayoutHelper + +- (instancetype)initWithTableView:(UITableView *)tableView +{ + self = [super init]; + if (self) + { + _tableView = tableView; + [self registerCells]; + } + + return self; +} + +- (void)registerCells +{ + for (auto name : kPreviewCells) + [self.tableView registerNib:[UINib nibWithNibName:name bundle:nil] forCellReuseIdentifier:name]; +} + +- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath withData:(MWMPlacePageData *)data +{ + using namespace place_page; + auto tableView = self.tableView; + auto const row = data.previewRows[indexPath.row]; + auto cellName = kPreviewCells[static_cast(row)]; + + // -2 because last cell is always the spacer cell. + BOOL const isNeedToShowDistance = (indexPath.row == data.previewRows.size() - 2); + + auto * c = [tableView dequeueReusableCellWithIdentifier:cellName]; + switch(row) + { + case PreviewRows::Title: + static_cast<_MWMPPPTitle *>(c).title.text = data.title; + break; + case PreviewRows::ExternalTitle: + static_cast<_MWMPPPExternalTitle *>(c).externalTitle.text = data.externalTitle; + break; + case PreviewRows::Subtitle: + static_cast<_MWMPPPSubtitle *>(c).subtitle.text = data.subtitle; + break; + case PreviewRows::Schedule: + { + auto scheduleCell = static_cast<_MWMPPPSchedule *>(c); + switch (data.schedule) + { + case place_page::OpeningHours::AllDay: + scheduleCell.schedule.text = L(@"twentyfour_seven"); + scheduleCell.schedule.textColor = [UIColor blackSecondaryText]; + break; + case place_page::OpeningHours::Open: + scheduleCell.schedule.text = L(@"editor_time_open"); + scheduleCell.schedule.textColor = [UIColor blackSecondaryText]; + break; + case place_page::OpeningHours::Closed: + scheduleCell.schedule.text = L(@"closed_now"); + scheduleCell.schedule.textColor = [UIColor red]; + break; + case place_page::OpeningHours::Unknown: NSAssert(false, @"Incorrect schedule!"); break; + } + break; + } + case PreviewRows::Booking: + { + auto bookingCell = static_cast<_MWMPPPBooking *>(c); + [bookingCell configWithRating:data.bookingRating pricing:data.bookingApproximatePricing]; + [data assignOnlinePriceToLabel:bookingCell.pricing]; + return c; + } + case PreviewRows::Address: + static_cast<_MWMPPPAddress *>(c).address.text = data.address; + break; + case PreviewRows::Space: + return c; + } + + auto baseCell = static_cast<_MWMPPPCellBase *>(c); + if (isNeedToShowDistance) + { + [self showDistanceOnCell:baseCell withData:data]; + self.lastCellIndexPath = indexPath; + } + else + [self hideDistanceOnCell:baseCell]; + + return c; +} + +- (void)showDistanceOnCell:(_MWMPPPCellBase *)cell withData:(MWMPlacePageData *)data +{ + cell.trailing.priority = UILayoutPriorityDefaultLow; + cell.distance.text = self.distance; + cell.tapOnDistance = ^{ + [self.directionView show]; + }; + [cell.contentView setNeedsLayout]; + self.compass = cell.compass; + self.distanceCellTrailing = cell.trailing; + self.distanceView = cell.distanceView; + cell.distanceView.hidden = NO; + + auto dv = self.directionView; + dv.titleLabel.text = data.title; + dv.typeLabel.text = data.subtitle; + dv.distanceLabel.text = self.distance; +} + +- (void)hideDistanceOnCell:(_MWMPPPCellBase *)cell +{ + cell.trailing.priority = UILayoutPriorityDefaultHigh; + [cell.contentView setNeedsLayout]; + cell.distanceView.hidden = YES; +} + +- (void)rotateDirectionArrowToAngle:(CGFloat)angle +{ + auto const t = CATransform3DMakeRotation(M_PI_2 - angle, 0, 0, 1); + self.compass.layer.transform = t; + self.directionView.directionArrow.layer.transform = t; +} + +- (void)setDistanceToObject:(NSString *)distance +{ + if (!distance.length || [self.distance isEqualToString:distance]) + return; + + self.distance = distance; + self.directionView.distanceLabel.text = distance; +} + +- (CGFloat)height +{ + auto const rect = [self.tableView rectForRowAtIndexPath:self.lastCellIndexPath]; + return rect.origin.y + rect.size.height; +} + +- (MWMDirectionView *)directionView +{ + if (!_directionView) + _directionView = [[MWMDirectionView alloc] init]; + return _directionView; +} + +@end diff --git a/iphone/Maps/Classes/MWMPPView.mm b/iphone/Maps/Classes/MWMPPView.mm index 8fa1f3c359..7ff5088869 100644 --- a/iphone/Maps/Classes/MWMPPView.mm +++ b/iphone/Maps/Classes/MWMPPView.mm @@ -62,7 +62,7 @@ CGFloat const kTableViewTopInset = -36; { NSValue * s = change[@"new"]; CGFloat const height = s.CGSizeValue.height; - if (!equalScreenDimensions(height, self.currentContentHeight)) + if (!equalScreenDimensions(height, self.currentContentHeight) && !self.tableView.scrollEnabled) { self.currentContentHeight = height; self.height = height + self.top.height; @@ -85,7 +85,9 @@ CGFloat const kTableViewTopInset = -36; self.tableView.estimatedRowHeight = 44.; self.tableView.rowHeight = UITableViewAutomaticDimension; - self.tableView.contentInset = {.top = kTableViewTopInset}; + self.tableView.contentInset = {.top = kTableViewTopInset, .bottom = - kTableViewTopInset}; + if (IPAD) + self.autoresizingMask = UIViewAutoresizingNone; } - (void)dealloc diff --git a/iphone/Maps/Classes/MWMPPView.xib b/iphone/Maps/Classes/MWMPPView.xib index 39b26841b5..944b455060 100644 --- a/iphone/Maps/Classes/MWMPPView.xib +++ b/iphone/Maps/Classes/MWMPPView.xib @@ -39,7 +39,7 @@ - + @@ -47,7 +47,6 @@ - diff --git a/iphone/Maps/Classes/MWMPlacePage+Animation.h b/iphone/Maps/Classes/MWMPlacePage+Animation.h deleted file mode 100644 index 6f01dec9a5..0000000000 --- a/iphone/Maps/Classes/MWMPlacePage+Animation.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "MWMPlacePage.h" -#import "MWMSpringAnimation.h" - -@class MWMSpringAnimation; - -@interface MWMPlacePage (Animation) - -@property (nonatomic) MWMSpringAnimation * springAnimation; - -- (void)cancelSpringAnimation; -- (void)startAnimatingPlacePage:(MWMPlacePage *)placePage initialVelocity:(CGPoint)velocity completion:(TMWMVoidBlock)completion; -- (CGPoint)targetPoint; - -@end diff --git a/iphone/Maps/Classes/MWMPlacePage+Animation.mm b/iphone/Maps/Classes/MWMPlacePage+Animation.mm deleted file mode 100644 index 3dc7837823..0000000000 --- a/iphone/Maps/Classes/MWMPlacePage+Animation.mm +++ /dev/null @@ -1,37 +0,0 @@ -#import "MWMPlacePage+Animation.h" -#import "MWMPlacePageViewManager.h" -#import "MWMViewController.h" -#import - -@implementation MWMPlacePage (Animation) - -- (void)setSpringAnimation:(MWMSpringAnimation *)springAnimation -{ - objc_setAssociatedObject(self, @selector(springAnimation), springAnimation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -- (MWMSpringAnimation *)springAnimation -{ - return objc_getAssociatedObject(self, @selector(springAnimation)); -} - -- (CGPoint)targetPoint -{ - [self doesNotRecognizeSelector:_cmd]; - return CGPointZero; -} - -- (void)cancelSpringAnimation -{ - [self.manager.ownerViewController.view.animator removeAnimation:self.springAnimation]; - self.springAnimation = nil; -} - -- (void)startAnimatingPlacePage:(MWMPlacePage *)placePage initialVelocity:(CGPoint)velocity completion:(TMWMVoidBlock)completion -{ - [self cancelSpringAnimation]; - self.springAnimation = [MWMSpringAnimation animationWithView:placePage.extendedPlacePageView target:placePage.targetPoint velocity:velocity completion:completion]; - [self.manager.ownerViewController.view.animator addAnimation:self.springAnimation]; -} - -@end diff --git a/iphone/Maps/Classes/MWMPlacePage.h b/iphone/Maps/Classes/MWMPlacePage.h deleted file mode 100644 index ac4ae5b5f5..0000000000 --- a/iphone/Maps/Classes/MWMPlacePage.h +++ /dev/null @@ -1,41 +0,0 @@ -#import - -@class MWMBasePlacePageView, MWMPlacePageViewManager, MWMPlacePageActionBar; - -@interface MWMPlacePage : NSObject - -@property (nonatomic) IBOutlet MWMBasePlacePageView * basePlacePageView; -@property (nonatomic) IBOutlet UIView * extendedPlacePageView; -@property (nonatomic) IBOutlet UIImageView * anchorImageView; -@property (nonatomic) IBOutlet UIPanGestureRecognizer * panRecognizer; -@property (weak, nonatomic, readonly) MWMPlacePageViewManager * manager; -@property (nonatomic) MWMPlacePageActionBar * actionBar; -@property (nonatomic) CGFloat topBound; -@property (nonatomic) CGFloat leftBound; -@property (nonatomic) CGFloat parentViewHeight; -@property (nonatomic) CGFloat keyboardHeight; - -- (instancetype)initWithManager:(MWMPlacePageViewManager *)manager; -- (void)show; -- (void)hide; -- (void)dismiss; -- (void)configure; - -#pragma mark - Actions -- (void)addBookmark; -- (void)removeBookmark; -- (void)editBookmark; -- (void)reloadBookmark; -- (void)addPlacePageShadowToView:(UIView *)view offset:(CGSize)offset; - -- (IBAction)didTap:(UITapGestureRecognizer *)sender; - -- (void)setDirectionArrowTransform:(CGAffineTransform)transform; -- (void)setDistance:(NSString *)distance; -- (void)updateMyPositionStatus:(NSString *)status; - -- (void)refresh; - -- (instancetype)init __attribute__((unavailable("call initWithManager: instead"))); - -@end diff --git a/iphone/Maps/Classes/MWMPlacePage.mm b/iphone/Maps/Classes/MWMPlacePage.mm deleted file mode 100644 index 9d411d5e9e..0000000000 --- a/iphone/Maps/Classes/MWMPlacePage.mm +++ /dev/null @@ -1,167 +0,0 @@ -#import "MapsAppDelegate.h" -#import "MapViewController.h" -#import "MWMBasePlacePageView.h" -#import "MWMDirectionView.h" -#import "MWMPlacePage.h" -#import "MWMPlacePageActionBar.h" -#import "MWMPlacePageEntity.h" -#import "MWMPlacePageViewManager.h" -#import "Statistics.h" - -static NSString * const kPlacePageNibIdentifier = @"PlacePageView"; -static NSString * const kPlacePageViewCenterKeyPath = @"center"; -static NSString * const kPP2BookmarkEditingSegue = @"PP2BookmarkEditing"; -extern NSString * const kPP2BookmarkEditingIPADSegue = @"PP2BookmarkEditingIPAD"; - -@interface MWMPlacePage () - -@property (weak, nonatomic, readwrite) MWMPlacePageViewManager * manager; - -@end - -@implementation MWMPlacePage - -- (instancetype)initWithManager:(MWMPlacePageViewManager *)manager -{ - self = [super init]; - if (self) - { - [[NSBundle mainBundle] loadNibNamed:kPlacePageNibIdentifier owner:self options:nil]; - self.manager = manager; - if (!IPAD) - [self.extendedPlacePageView addObserver:self - forKeyPath:kPlacePageViewCenterKeyPath - options:NSKeyValueObservingOptionNew - context:nullptr]; - } - return self; -} - -- (void)dealloc -{ - if (!IPAD) - [self.extendedPlacePageView removeObserver:self forKeyPath:kPlacePageViewCenterKeyPath]; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context -{ - if ([self.extendedPlacePageView isEqual:object] && [keyPath isEqualToString:kPlacePageViewCenterKeyPath]) - [self.manager dragPlacePage:self.extendedPlacePageView.frame]; -} - -- (void)configure -{ - MWMPlacePageViewManager * manager = self.manager; - MWMPlacePageEntity * entity = manager.entity; - [self.basePlacePageView configureWithEntity:entity]; - BOOL const isPrepareRouteMode = MapsAppDelegate.theApp.routingPlaneMode != MWMRoutingPlaneModeNone; - if (self.actionBar.isPrepareRouteMode == isPrepareRouteMode) - { - [self.actionBar configureWithPlacePageManager:manager]; - } - else - { - [self.actionBar removeFromSuperview]; - self.actionBar = [MWMPlacePageActionBar actionBarForPlacePageManager:manager]; - } -} - -- (void)show -{ - // Should override this method if you want to show place page with custom animation. -} - -- (void)hide -{ - // Should override this method if you want to hide place page with custom animation. -} - -- (void)dismiss -{ - [self.extendedPlacePageView removeFromSuperview]; - [self.actionBar removeFromSuperview]; - self.actionBar = nil; -} - -#pragma mark - Actions - -- (void)addBookmark -{ - [self.basePlacePageView addBookmark]; - self.actionBar.isBookmark = YES; -} - -- (void)removeBookmark -{ - [self.basePlacePageView removeBookmark]; - self.actionBar.isBookmark = NO; -} - -- (void)addPlacePageShadowToView:(UIView *)view offset:(CGSize)offset -{ - CALayer * layer = view.layer; - layer.masksToBounds = NO; - layer.shadowColor = UIColor.blackColor.CGColor; - layer.shadowRadius = 4.; - layer.shadowOpacity = 0.24f; - layer.shadowOffset = offset; - layer.shouldRasterize = YES; - layer.rasterizationScale = [[UIScreen mainScreen] scale]; -} - -- (void)setDirectionArrowTransform:(CGAffineTransform)transform -{ - self.basePlacePageView.directionArrow.transform = transform; -} - -- (void)setDistance:(NSString *)distance -{ - self.basePlacePageView.distance = distance; -} - -- (void)updateMyPositionStatus:(NSString *)status -{ - [self.basePlacePageView updateAndLayoutMyPositionSpeedAndAltitude:status]; -} - -- (void)editBookmark -{ - MWMPlacePageViewManager * manager = self.manager; - [manager.ownerViewController - performSegueWithIdentifier:IPAD ? kPP2BookmarkEditingIPADSegue : kPP2BookmarkEditingSegue - sender:manager]; -} - -- (void)reloadBookmark -{ - [self.basePlacePageView reloadBookmarkCell]; -} - -- (IBAction)didTap:(UITapGestureRecognizer *)sender -{ -// This method should be оverridden if you want to process custom tap. -} - -- (IBAction)didPan:(UIPanGestureRecognizer *)sender -{ - // This method should be оverridden if you want to process custom pan. -} - -- (void)refresh -{ - // This method should be оverridden. -} - -#pragma mark - Properties - -- (MWMPlacePageActionBar *)actionBar -{ - if (!_actionBar) - _actionBar = [MWMPlacePageActionBar actionBarForPlacePageManager:self.manager]; - return _actionBar; -} - -@end diff --git a/iphone/Maps/Classes/MWMPlacePageActionBar.h b/iphone/Maps/Classes/MWMPlacePageActionBar.h index 599099a1d2..b04e7666c1 100644 --- a/iphone/Maps/Classes/MWMPlacePageActionBar.h +++ b/iphone/Maps/Classes/MWMPlacePageActionBar.h @@ -1,6 +1,7 @@ -@class MWMPlacePageViewManager; @class MWMPlacePageData; +#import "MWMCircularProgress.h" + @protocol MWMActionBarSharedData - (BOOL)isBookmark; @@ -21,14 +22,15 @@ + (MWMPlacePageActionBar *)actionBarWithDelegate:(id)delegate; - (void)configureWithData:(id)data; -@property (nonatomic) BOOL isBookmark; +@property(nonatomic) BOOL isBookmark; +@property(nonatomic) BOOL isAreaNotDownloaded; + +- (void)setDownloadingProgress:(CGFloat)progress; +- (void)setDownloadingState:(MWMCircularProgressState)state; - (UIView *)shareAnchor; - (BOOL)isPrepareRouteMode; -+ (MWMPlacePageActionBar *)actionBarForPlacePageManager:(MWMPlacePageViewManager *)placePageManager; -- (void)configureWithPlacePageManager:(MWMPlacePageViewManager *)placePageManager; - - (instancetype)init __attribute__((unavailable("call actionBarForPlacePage: instead"))); - (instancetype)initWithCoder:(NSCoder *)aDecoder __attribute__((unavailable("call actionBarForPlacePage: instead"))); - (instancetype)initWithFrame:(CGRect)frame __attribute__((unavailable("call actionBarForPlacePage: instead"))); diff --git a/iphone/Maps/Classes/MWMPlacePageActionBar.mm b/iphone/Maps/Classes/MWMPlacePageActionBar.mm index 992f3c5af6..5047972117 100644 --- a/iphone/Maps/Classes/MWMPlacePageActionBar.mm +++ b/iphone/Maps/Classes/MWMPlacePageActionBar.mm @@ -1,10 +1,7 @@ #import "MWMPlacePageActionBar.h" #import "Common.h" #import "MWMActionBarButton.h" -#import "MWMBasePlacePageView.h" -#import "MWMPlacePageEntity.h" #import "MWMPlacePageProtocol.h" -#import "MWMPlacePageViewManager.h" #import "MapViewController.h" #import "MapsAppDelegate.h" @@ -20,7 +17,6 @@ extern NSString * const kAlohalyticsTapEventKey; vector m_additionalButtons; } -@property(weak, nonatomic) MWMPlacePageViewManager * placePageManager; @property(copy, nonatomic) IBOutletCollection(UIView) NSArray * buttons; @property(weak, nonatomic) IBOutlet UIImageView * separator; @property(nonatomic) BOOL isPrepareRouteMode; @@ -49,29 +45,11 @@ extern NSString * const kAlohalyticsTapEventKey; self.autoresizingMask = UIViewAutoresizingNone; } -+ (MWMPlacePageActionBar *)actionBarForPlacePageManager:(MWMPlacePageViewManager *)placePageManager -{ - MWMPlacePageActionBar * bar = - [[NSBundle.mainBundle loadNibNamed:[self className] owner:nil options:nil] firstObject]; - [bar configureWithPlacePageManager:placePageManager]; - return bar; -} - -- (void)configureWithPlacePageManager:(MWMPlacePageViewManager *)placePageManager -{ - self.placePageManager = placePageManager; - self.isPrepareRouteMode = MapsAppDelegate.theApp.routingPlaneMode != MWMRoutingPlaneModeNone; - self.isBookmark = placePageManager.entity.isBookmark; - [self configureButtons]; - self.autoresizingMask = UIViewAutoresizingNone; -} - - (void)configureButtons { m_visibleButtons.clear(); m_additionalButtons.clear(); - auto data = - static_cast>(IPAD ? self.placePageManager.entity : self.data); + auto data = self.data; NSString * phone = data.phoneNumber; BOOL const isIphone = [[UIDevice currentDevice].model isEqualToString:@"iPhone"]; @@ -86,7 +64,14 @@ extern NSString * const kAlohalyticsTapEventKey; EButton const sponsoredButton = isBooking ? EButton::Booking : EButton::Opentable; - if (isMyPosition) + if (self.isAreaNotDownloaded) + { + m_visibleButtons.push_back(EButton::Download); + m_visibleButtons.push_back(EButton::Bookmark); + m_visibleButtons.push_back(EButton::RouteTo); + m_visibleButtons.push_back(EButton::Share); + } + else if (isMyPosition) { m_visibleButtons.push_back(EButton::Spacer); m_visibleButtons.push_back(EButton::Bookmark); @@ -157,7 +142,7 @@ extern NSString * const kAlohalyticsTapEventKey; m_visibleButtons.push_back(EButton::RouteFrom); } - if (!isMyPosition) + if (!isMyPosition || !self.isAreaNotDownloaded) { m_visibleButtons.push_back(EButton::RouteTo); m_visibleButtons.push_back(m_additionalButtons.empty() ? EButton::Share : EButton::More); @@ -174,6 +159,42 @@ extern NSString * const kAlohalyticsTapEventKey; } } +- (void)setDownloadingState:(MWMCircularProgressState)state +{ + self.progressFromActiveButton.state = state; +} + +- (void)setDownloadingProgress:(CGFloat)progress +{ + self.progressFromActiveButton.progress = progress; +} + +- (MWMCircularProgress *)progressFromActiveButton +{ + if (!self.isAreaNotDownloaded) + return nil; + + for (UIView * view in self.buttons) + { + NSAssert(view.subviews.count, @"Subviews can't be empty!"); + MWMActionBarButton * button = view.subviews[0]; + if (button.type != EButton::Download) + continue; + + return button.mapDownloadProgress; + } + return nil; +} + +- (void)setIsAreaNotDownloaded:(BOOL)isAreaNotDownloaded +{ + if (_isAreaNotDownloaded == isAreaNotDownloaded) + return; + + _isAreaNotDownloaded = isAreaNotDownloaded; + [self configureButtons]; +} + - (UIView *)shareAnchor { UIView * last = nil; @@ -190,11 +211,12 @@ extern NSString * const kAlohalyticsTapEventKey; - (void)tapOnButtonWithType:(EButton)type { - id delegate = IPAD ? self.placePageManager : self.delegate; + id delegate = self.delegate; switch (type) { case EButton::Api: [delegate apiBack]; break; + case EButton::Download: [delegate downloadSelectedArea]; break; case EButton::Opentable: case EButton::Booking: [delegate book:NO]; break; case EButton::Call: [delegate call]; break; @@ -219,8 +241,7 @@ extern NSString * const kAlohalyticsTapEventKey; - (void)showActionSheet { NSString * cancel = L(@"cancel"); - auto data = - static_cast>(IPAD ? self.placePageManager.entity : self.data); + auto data = self.data; BOOL const isTitleNotEmpty = data.title.length > 0; NSString * title = isTitleNotEmpty ? data.title : data.subtitle; NSString * subtitle = isTitleNotEmpty ? data.subtitle : nil; @@ -272,7 +293,7 @@ extern NSString * const kAlohalyticsTapEventKey; [super layoutSubviews]; self.width = self.superview.width; if (IPAD) - self.origin = {0, self.superview.height - self.height}; + self.maxY = self.superview.height; self.separator.width = self.width; CGFloat const buttonWidth = self.width / self.buttons.count; diff --git a/iphone/Maps/Classes/MWMPlacePageBookmarkCell.h b/iphone/Maps/Classes/MWMPlacePageBookmarkCell.h deleted file mode 100644 index ac32f2671f..0000000000 --- a/iphone/Maps/Classes/MWMPlacePageBookmarkCell.h +++ /dev/null @@ -1,16 +0,0 @@ -#import "MWMTableViewCell.h" - -@protocol MWMPlacePageBookmarkDelegate; -@class MWMPlacePage; - -@interface MWMPlacePageBookmarkCell : MWMTableViewCell - -- (void)configWithText:(NSString *)text - delegate:(id)delegate - placePageWidth:(CGFloat)width - isOpen:(BOOL)isOpen - isHtml:(BOOL)isHtml; - -- (CGFloat)cellHeight; - -@end diff --git a/iphone/Maps/Classes/MWMPlacePageBookmarkCell.mm b/iphone/Maps/Classes/MWMPlacePageBookmarkCell.mm deleted file mode 100644 index c9a256babd..0000000000 --- a/iphone/Maps/Classes/MWMPlacePageBookmarkCell.mm +++ /dev/null @@ -1,210 +0,0 @@ -#import "MWMPlacePageBookmarkCell.h" -#import "Common.h" -#import "MWMPlacePageBookmarkDelegate.h" -#import "MapViewController.h" -#import "Statistics.h" -#import "UIColor+MapsMeColor.h" -#import "UIFont+MapsMeFonts.h" - -namespace -{ -CGFloat const kBoundedTextViewHeight = 240.; -CGFloat const kTextViewTopOffset = 12.; -CGFloat const kMoreButtonHeight = 33.; -CGFloat const kTextViewLeft = 16.; - -void performRenderingInConcurrentQueue(TMWMVoidBlock block) -{ - if (block) - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block); -} - -} // namespace - -@interface MWMPlacePageBookmarkCell () - -@property(weak, nonatomic) IBOutlet UITextView * textView; -@property(weak, nonatomic) IBOutlet UIButton * moreButton; -@property(weak, nonatomic) IBOutlet UIButton * editButton; -@property(weak, nonatomic) IBOutlet UIImageView * separator; -@property(weak, nonatomic) IBOutlet UIImageView * gradient; -@property(weak, nonatomic) IBOutlet UIImageView * spinner; - -@property(weak, nonatomic) IBOutlet NSLayoutConstraint * textViewTopOffset; -@property(weak, nonatomic) IBOutlet NSLayoutConstraint * textViewBottomOffset; -@property(weak, nonatomic) IBOutlet NSLayoutConstraint * textViewHeight; -@property(weak, nonatomic) IBOutlet NSLayoutConstraint * moreButtonHeight; - -@property(weak, nonatomic) id delegate; - -@property(copy, nonatomic) NSAttributedString * attributedHtml; -@property(copy, nonatomic) NSString * cachedHtml; - -@end - -@implementation MWMPlacePageBookmarkCell - -- (void)configWithText:(NSString *)text - delegate:(id)delegate - placePageWidth:(CGFloat)width - isOpen:(BOOL)isOpen - isHtml:(BOOL)isHtml -{ - self.delegate = delegate; - self.textView.width = width - 2 * kTextViewLeft; - self.textView.keyboardAppearance = - [UIColor isNightMode] ? UIKeyboardAppearanceDark : UIKeyboardAppearanceDefault; - BOOL const isEmpty = text.length == 0; - if (isEmpty) - [self configEmptyDescription]; - else if (isHtml) - [self configHtmlDescription:text isOpen:isOpen]; - else - [self configPlaintTextDescription:text isOpen:isOpen]; -} - -- (void)configEmptyDescription -{ - self.textView.hidden = self.separator.hidden = self.gradient.hidden = self.moreButton.hidden = - self.spinner.hidden = YES; - self.textViewTopOffset.constant = self.textViewBottomOffset.constant = - self.textViewHeight.constant = self.moreButtonHeight.constant = 0; -} - -- (void)startSpinner -{ - self.editButton.hidden = YES; - NSUInteger const animationImagesCount = 12; - NSMutableArray * animationImages = [NSMutableArray arrayWithCapacity:animationImagesCount]; - NSString * postfix = [UIColor isNightMode] ? @"dark" : @"light"; - for (NSUInteger i = 0; i < animationImagesCount; ++i) - animationImages[i] = - [UIImage imageNamed:[NSString stringWithFormat:@"Spinner_%@_%@", @(i + 1), postfix]]; - - self.spinner.animationDuration = 0.8; - self.spinner.animationImages = animationImages; - self.spinner.hidden = NO; - [self.spinner startAnimating]; -} - -- (void)stopSpinner -{ - [self.spinner stopAnimating]; - self.editButton.hidden = NO; - self.spinner.hidden = YES; -} - -- (void)configPlaintTextDescription:(NSString *)text isOpen:(BOOL)isOpen -{ - self.spinner.hidden = YES; - [self textViewScrollEnabled:YES]; - self.textViewTopOffset.constant = kTextViewTopOffset; - self.textView.hidden = self.separator.hidden = NO; - self.textView.text = text; - CGFloat const textViewHeight = self.textView.contentSize.height; - if (textViewHeight > kBoundedTextViewHeight && !isOpen) - { - self.textViewHeight.constant = kBoundedTextViewHeight; - self.moreButton.hidden = self.gradient.hidden = NO; - self.moreButtonHeight.constant = kMoreButtonHeight; - self.textViewBottomOffset.constant = 0; - } - else - { - self.textViewHeight.constant = textViewHeight; - self.moreButton.hidden = self.gradient.hidden = YES; - self.moreButtonHeight.constant = 0; - self.textViewBottomOffset.constant = kTextViewTopOffset; - } - [self textViewScrollEnabled:NO]; -} - -- (void)configHtmlDescription:(NSString *)text isOpen:(BOOL)isOpen -{ - // html already was rendered and text is same as text which was cached into html - if (self.attributedHtml && [self.cachedHtml isEqualToString:text]) - { - [self textViewScrollEnabled:YES]; - self.textViewTopOffset.constant = kTextViewTopOffset; - self.textView.hidden = self.separator.hidden = NO; - self.textView.attributedText = self.attributedHtml; - CGFloat const textViewHeight = self.textView.contentSize.height; - if (textViewHeight > kBoundedTextViewHeight && !isOpen) - { - self.textViewHeight.constant = kBoundedTextViewHeight; - self.moreButton.hidden = self.gradient.hidden = NO; - self.moreButtonHeight.constant = kMoreButtonHeight; - self.textViewBottomOffset.constant = 0; - } - else - { - self.textViewHeight.constant = textViewHeight; - self.moreButton.hidden = self.gradient.hidden = YES; - self.moreButtonHeight.constant = 0; - self.textViewBottomOffset.constant = kTextViewTopOffset; - } - [self textViewScrollEnabled:NO]; - } - else - { - [self configEmptyDescription]; - [self startSpinner]; - performRenderingInConcurrentQueue(^{ - self.cachedHtml = text; - NSDictionary * attr = @{ - NSForegroundColorAttributeName : [UIColor blackPrimaryText], - NSFontAttributeName : [UIFont regular12] - }; - NSError * error = nil; - NSMutableAttributedString * str = [[NSMutableAttributedString alloc] - initWithData:[text dataUsingEncoding:NSUnicodeStringEncoding] - options:@{ - NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType - } - documentAttributes:nil - error:&error]; - if (error) - { - // If we failed while attempting to render html than just show plain text in bookmark. - // Ussualy there is a problem only in iOS7. - self.attributedHtml = [[NSAttributedString alloc] initWithString:text attributes:attr]; - } - else - { - [str addAttributes:attr range:{0, str.length}]; - self.attributedHtml = str; - } - dispatch_async(dispatch_get_main_queue(), ^{ - [self stopSpinner]; - [self.delegate reloadBookmark]; - }); - }); - } -} - -- (void)textViewScrollEnabled:(BOOL)isEnabled -{ - self.textView.scrollEnabled = isEnabled; -} - -- (IBAction)moreTap { [self.delegate moreTap]; } -- (IBAction)editTap { [self.delegate editBookmarkTap]; } -- (CGFloat)cellHeight -{ - return self.textViewTopOffset.constant + self.textViewHeight.constant + - self.textViewBottomOffset.constant + self.moreButtonHeight.constant + - self.separator.height + self.editButton.height; -} - -#pragma mark - UITextViewDelegate - -- (BOOL)textView:(UITextView *)textView - shouldInteractWithURL:(NSURL *)URL - inRange:(NSRange)characterRange -{ - UIViewController * vc = static_cast([MapViewController controller]); - [vc openUrl:URL]; - return NO; -} - -@end diff --git a/iphone/Maps/Classes/MWMPlacePageButtonCell.h b/iphone/Maps/Classes/MWMPlacePageButtonCell.h index 2f431e5453..52a94b01b1 100644 --- a/iphone/Maps/Classes/MWMPlacePageButtonCell.h +++ b/iphone/Maps/Classes/MWMPlacePageButtonCell.h @@ -1,20 +1,14 @@ #import "MWMPlacePageData.h" -#import "MWMPlacePageEntity.h" #import "MWMTableViewCell.h" -@class MWMPlacePageViewManager; - @protocol MWMPlacePageButtonsProtocol; @interface MWMPlacePageButtonCell : MWMTableViewCell -- (void)config:(MWMPlacePageViewManager *)manager - forType:(MWMPlacePageCellType)type NS_DEPRECATED_IOS(7_0, 8_0, "Use configForRow:withDelegate: instead"); - - (void)configForRow:(place_page::ButtonsRows)row - withDelegate:(id)delegate NS_AVAILABLE_IOS(8_0); + withDelegate:(id)delegate; -- (void)setEnabled:(BOOL)enabled NS_AVAILABLE_IOS(8_0); -- (BOOL)isEnabled NS_AVAILABLE_IOS(8_0); +- (void)setEnabled:(BOOL)enabled; +- (BOOL)isEnabled; @end diff --git a/iphone/Maps/Classes/MWMPlacePageButtonCell.mm b/iphone/Maps/Classes/MWMPlacePageButtonCell.mm index 7e2cf08950..e454b90e09 100644 --- a/iphone/Maps/Classes/MWMPlacePageButtonCell.mm +++ b/iphone/Maps/Classes/MWMPlacePageButtonCell.mm @@ -1,16 +1,11 @@ #import "MWMPlacePageButtonCell.h" #import "Common.h" -#import "MWMFrameworkListener.h" #import "MWMPlacePageProtocol.h" -#import "MWMPlacePageViewManager.h" #import "UIColor+MapsMeColor.h" -@interface MWMPlacePageButtonCell () +@interface MWMPlacePageButtonCell () -@property(weak, nonatomic) MWMPlacePageViewManager * manager; @property(weak, nonatomic) IBOutlet UIButton * titleButton; -@property(nonatomic) MWMPlacePageCellType type; -@property(nonatomic) storage::TCountryId countryId; @property(weak, nonatomic) id delegate; @property(nonatomic) place_page::ButtonsRows rowType; @@ -25,14 +20,6 @@ [self.titleButton setTitleColor:[UIColor linkBlue] forState:UIControlStateNormal]; } -- (void)config:(MWMPlacePageViewManager *)manager forType:(MWMPlacePageCellType)type -{ - self.countryId = GetFramework().GetCountryInfoGetter().GetRegionCountryId(manager.entity.mercator); - self.manager = manager; - self.type = type; - [self refreshButtonEnabledState]; -} - - (void)setEnabled:(BOOL)enabled { self.titleButton.enabled = enabled; } - (BOOL)isEnabled { return self.titleButton.isEnabled; } - (void)configForRow:(place_page::ButtonsRows)row @@ -63,20 +50,6 @@ - (IBAction)buttonTap { - if (IPAD) - { - auto m = self.manager; - switch (self.type) - { - case MWMPlacePageCellTypeEditButton: [m editPlace]; break; - case MWMPlacePageCellTypeAddBusinessButton: [m addBusiness]; break; - case MWMPlacePageCellTypeAddPlaceButton: [m addPlace]; break; - case MWMPlacePageCellTypeBookingMore: [m book:YES]; break; - default: NSAssert(false, @"Incorrect cell type!"); break; - } - return; - } - using namespace place_page; auto d = self.delegate; switch (self.rowType) @@ -88,56 +61,4 @@ } } -- (void)refreshButtonEnabledState -{ - if (self.countryId == kInvalidCountryId) - { - self.titleButton.enabled = YES; - return; - } - NodeStatuses nodeStatuses; - GetFramework().GetStorage().GetNodeStatuses(self.countryId, nodeStatuses); - auto const & status = nodeStatuses.m_status; - self.titleButton.enabled = status == NodeStatus::OnDisk || status == NodeStatus::OnDiskOutOfDate; -} - -#pragma mark - MWMFrameworkStorageObserver - -- (void)processCountryEvent:(TCountryId const &)countryId -{ - if (self.countryId != countryId) - return; - [self refreshButtonEnabledState]; -} - -#pragma mark - Properties - -- (void)setType:(MWMPlacePageCellType)type -{ - _type = type; - NSString * title; - switch (type) - { - case MWMPlacePageCellTypeAddBusinessButton: - title = L(@"placepage_add_business_button"); - [MWMFrameworkListener addObserver:self]; - break; - case MWMPlacePageCellTypeEditButton: - title = L(@"edit_place"); - [MWMFrameworkListener addObserver:self]; - break; - case MWMPlacePageCellTypeAddPlaceButton: - title = L(@"placepage_add_place_button"); - [MWMFrameworkListener addObserver:self]; - break; - case MWMPlacePageCellTypeBookingMore: - title = L(@"details"); - break; - default: NSAssert(false, @"Invalid place page cell type!"); break; - } - - [self.titleButton setTitle:title forState:UIControlStateNormal]; - [self.titleButton setTitle:title forState:UIControlStateDisabled]; -} - @end diff --git a/iphone/Maps/Classes/MWMPlacePageCellUpdateProtocol.h b/iphone/Maps/Classes/MWMPlacePageCellUpdateProtocol.h index de12777fcb..b051d67856 100644 --- a/iphone/Maps/Classes/MWMPlacePageCellUpdateProtocol.h +++ b/iphone/Maps/Classes/MWMPlacePageCellUpdateProtocol.h @@ -1,5 +1,5 @@ @protocol MWMPlacePageCellUpdateProtocol -- (void)updateCellWithForceReposition:(BOOL)isForceReposition; +- (void)cellUpdated; @end diff --git a/iphone/Maps/Classes/MWMPlacePageData.h b/iphone/Maps/Classes/MWMPlacePageData.h index de0d5a0837..8f5d112cd8 100644 --- a/iphone/Maps/Classes/MWMPlacePageData.h +++ b/iphone/Maps/Classes/MWMPlacePageData.h @@ -12,9 +12,21 @@ enum class Sections Buttons }; +enum class PreviewRows +{ + Title, + ExternalTitle, + Subtitle, + Schedule, + Booking, + Address, + Space +}; + enum class MetainfoRows { OpeningHours, + ExtendedOpeningHours, Phone, Address, Website, @@ -81,6 +93,7 @@ enum class OpeningHours // Table view's data - (vector const &)sections; +- (vector const &)previewRows; - (vector const &)metainfoRows; - (vector const &)buttonsRows; diff --git a/iphone/Maps/Classes/MWMPlacePageData.mm b/iphone/Maps/Classes/MWMPlacePageData.mm index 5e3a0128fb..0b3942765b 100644 --- a/iphone/Maps/Classes/MWMPlacePageData.mm +++ b/iphone/Maps/Classes/MWMPlacePageData.mm @@ -19,6 +19,7 @@ using namespace place_page; Info m_info; vector m_sections; + vector m_previewRows; vector m_metainfoRows; vector m_buttonsRows; } @@ -38,10 +39,12 @@ using namespace place_page; - (void)fillSections { m_sections.clear(); + m_previewRows.clear(); m_metainfoRows.clear(); m_buttonsRows.clear(); m_sections.push_back(Sections::Preview); + [self fillPreviewSection]; // It's bookmark. if (m_info.IsBookmark()) @@ -60,6 +63,19 @@ using namespace place_page; } } +- (void)fillPreviewSection +{ + if (self.title.length) m_previewRows.push_back(PreviewRows::Title); + if (self.externalTitle.length) m_previewRows.push_back(PreviewRows::ExternalTitle); + if (self.subtitle.length) m_previewRows.push_back(PreviewRows::Subtitle); + if (self.schedule != OpeningHours::Unknown) m_previewRows.push_back(PreviewRows::Schedule); + if (self.isBooking) m_previewRows.push_back(PreviewRows::Booking); + if (self.address.length) m_previewRows.push_back(PreviewRows::Address); + + NSAssert(!m_previewRows.empty(), @"Preview row's can't be empty!"); + m_previewRows.push_back(PreviewRows::Space); +} + - (void)fillMetaInfoSection { using namespace osm; @@ -207,7 +223,6 @@ using namespace place_page; - (void)assignOnlinePriceToLabel:(UILabel *)label { - // TODO(Vlad): Remove similar code from MWMPlacePageEntity.mm when new iPAD place page will be finished. NSAssert(self.isBooking, @"Online price must be assigned to booking object!"); if (Platform::ConnectionStatus() == Platform::EConnectionType::CONNECTION_NONE) return; @@ -282,12 +297,15 @@ using namespace place_page; } - (vector const &)sections { return m_sections; } +- (vector const &)previewRows { return m_previewRows; } - (vector const &)metainfoRows { return m_metainfoRows; } +- (vector &)mutableMetainfoRows { return m_metainfoRows; } - (vector const &)buttonsRows { return m_buttonsRows; } - (NSString *)stringForRow:(MetainfoRows)row { switch (row) { + case MetainfoRows::ExtendedOpeningHours: return nil; case MetainfoRows::OpeningHours: return @(m_info.GetOpeningHours().c_str()); case MetainfoRows::Phone: return @(m_info.GetPhone().c_str()); case MetainfoRows::Address: return @(m_info.GetAddress().c_str()); diff --git a/iphone/Maps/Classes/MWMPlacePageEntity.mm b/iphone/Maps/Classes/MWMPlacePageEntity.mm index aadc989775..cd64a9d8a2 100644 --- a/iphone/Maps/Classes/MWMPlacePageEntity.mm +++ b/iphone/Maps/Classes/MWMPlacePageEntity.mm @@ -1,6 +1,5 @@ #import "MWMPlacePageEntity.h" #import "MWMMapViewControlsManager.h" -#import "MWMPlacePageViewManager.h" #import "MapViewController.h" #import "MapsAppDelegate.h" diff --git a/iphone/Maps/Classes/MWMPlacePageInfoCell.h b/iphone/Maps/Classes/MWMPlacePageInfoCell.h index 5a57318b23..576b5e1b17 100644 --- a/iphone/Maps/Classes/MWMPlacePageInfoCell.h +++ b/iphone/Maps/Classes/MWMPlacePageInfoCell.h @@ -1,18 +1,13 @@ -#import "MWMPlacePageEntity.h" #import "MWMTableViewCell.h" #import "MWMPlacePageData.h" @interface MWMPlacePageInfoCell : MWMTableViewCell -- (void)configureWithType:(MWMPlacePageCellType)type - info:(NSString *)info NS_DEPRECATED_IOS(7_0, 8_0, "Use configWithRow:data: instead"); - - (void)configWithRow:(place_page::MetainfoRows)row - data:(MWMPlacePageData *)data NS_AVAILABLE_IOS(8_0); + data:(MWMPlacePageData *)data; @property(weak, nonatomic, readonly) IBOutlet UIImageView * icon; @property(weak, nonatomic, readonly) IBOutlet id textContainer; -@property(nonatomic) MWMPlacePageEntity * currentEntity; @end diff --git a/iphone/Maps/Classes/MWMPlacePageInfoCell.mm b/iphone/Maps/Classes/MWMPlacePageInfoCell.mm index 37b42c547b..6a59942f39 100644 --- a/iphone/Maps/Classes/MWMPlacePageInfoCell.mm +++ b/iphone/Maps/Classes/MWMPlacePageInfoCell.mm @@ -18,9 +18,8 @@ @property(weak, nonatomic) IBOutlet UIButton * upperButton; @property(weak, nonatomic) IBOutlet UIImageView * toggleImage; -@property(nonatomic) MWMPlacePageCellType type NS_DEPRECATED_IOS(7_0, 8_0, "Use rowType instead"); -@property(nonatomic) place_page::MetainfoRows rowType NS_AVAILABLE_IOS(8_0); -@property(weak, nonatomic) MWMPlacePageData * data NS_AVAILABLE_IOS(8_0); +@property(nonatomic) place_page::MetainfoRows rowType; +@property(weak, nonatomic) MWMPlacePageData * data; @end @@ -83,43 +82,6 @@ [self configWithIconName:name data:[data stringForRow:row]]; } -- (void)configureWithType:(MWMPlacePageCellType)type info:(NSString *)info; -{ - self.type = type; - NSString * typeName; - switch (type) - { - case MWMPlacePageCellTypeURL: - case MWMPlacePageCellTypeWebsite: - self.toggleImage.hidden = YES; - typeName = @"website"; - break; - case MWMPlacePageCellTypeEmail: - self.toggleImage.hidden = YES; - typeName = @"email"; - break; - case MWMPlacePageCellTypePhoneNumber: - self.toggleImage.hidden = YES; - typeName = @"phone_number"; - break; - case MWMPlacePageCellTypeCoordinate: - self.toggleImage.hidden = NO; - typeName = @"coordinate"; - break; - case MWMPlacePageCellTypePostcode: - self.toggleImage.hidden = YES; - typeName = @"postcode"; - break; - case MWMPlacePageCellTypeWiFi: - self.toggleImage.hidden = YES; - typeName = @"wifi"; - break; - default: NSAssert(false, @"Incorrect type!"); break; - } - - [self configWithIconName:typeName data:info]; -} - - (void)configWithIconName:(NSString *)name data:(NSString *)data { UIImage * image = @@ -166,30 +128,6 @@ - (IBAction)cellTap { - if (IPAD) - { - switch (self.type) - { - case MWMPlacePageCellTypeURL: - case MWMPlacePageCellTypeWebsite: - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatOpenSite)]; - break; - case MWMPlacePageCellTypeEmail: - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatSendEmail)]; - break; - case MWMPlacePageCellTypePhoneNumber: - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatCallPhoneNumber)]; - break; - case MWMPlacePageCellTypeCoordinate: - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatToggleCoordinates)]; - [self.currentEntity toggleCoordinateSystem]; - [self changeText:[self.currentEntity getCellValue:MWMPlacePageCellTypeCoordinate]]; - break; - default: break; - } - return; - } - switch (self.rowType) { case place_page::MetainfoRows::Phone: diff --git a/iphone/Maps/Classes/MWMPlacePageLayout.h b/iphone/Maps/Classes/MWMPlacePageLayout.h index a1ee45a0e4..a0e3a1e4df 100644 --- a/iphone/Maps/Classes/MWMPlacePageLayout.h +++ b/iphone/Maps/Classes/MWMPlacePageLayout.h @@ -2,7 +2,7 @@ @protocol MWMPlacePageLayoutDelegate -- (void)onTopBoundChanged:(CGFloat)bound; +- (void)onPlacePageTopBoundChanged:(CGFloat)bound; - (void)shouldDestroyLayout; @end @@ -11,6 +11,8 @@ - (NSString *)distanceToObject; - (void)downloadSelectedArea; +- (CGFloat)leftBound; +- (CGFloat)topBound; @end @@ -40,4 +42,10 @@ - (void)processDownloaderEventWithStatus:(storage::NodeStatus)status progress:(CGFloat)progress; +#pragma mark - iPad only + +- (void)updateTopBound; +- (void)updateLeftBound; + @end + diff --git a/iphone/Maps/Classes/MWMPlacePageLayout.mm b/iphone/Maps/Classes/MWMPlacePageLayout.mm index e0ce5f1987..1369b11295 100644 --- a/iphone/Maps/Classes/MWMPlacePageLayout.mm +++ b/iphone/Maps/Classes/MWMPlacePageLayout.mm @@ -1,70 +1,43 @@ #import "MWMPlacePageLayout.h" +#import "MWMBookmarkCell.h" #import "MWMCircularProgress.h" -#import "MWMPPView.h" -#import "MWMPlacePageActionBar.h" +#import "MWMiPadPlacePageLayoutImpl.h" +#import "MWMiPhonePlacePageLayoutImpl.h" +#import "MWMPlacePageButtonCell.h" #import "MWMPlacePageCellUpdateProtocol.h" #import "MWMPlacePageData.h" -#import "MWMBookmarkCell.h" -#import "MWMOpeningHoursCell.h" -#import "MWMPlacePageBookmarkCell.h" -#import "MWMPlacePageButtonCell.h" #import "MWMPlacePageInfoCell.h" -#import "MWMPlacePagePreviewCell.h" +#import "MWMPlacePageLayoutImpl.h" +#import "MWMOpeningHoursLayoutHelper.h" +#import "MWMPPPreviewLayoutHelper.h" #import "UIColor+MapsMeColor.h" #include "storage/storage.hpp" #include "std/array.hpp" +#include "std/map.hpp" namespace { -enum class ScrollDirection -{ - Up, - Down -}; +array const kBookmarkCells = {{@"MWMBookmarkCell"}}; -enum class State -{ - Bottom, - Top -}; +using place_page::MetainfoRows; -// Minimal offset for collapse. If place page offset is below this value we should hide place page. -CGFloat const kMinOffset = 1; -CGFloat const kOpenPlacePageStopValue = 0.7; -CGFloat const kLuftDraggingOffset = 30; +map const kMetaInfoCells = { + {MetainfoRows::Website, @"PlacePageLinkCell"}, + {MetainfoRows::Address, @"PlacePageInfoCell"}, + {MetainfoRows::Email, @"PlacePageLinkCell"}, + {MetainfoRows::Phone, @"PlacePageLinkCell"}, + {MetainfoRows::Cuisine, @"PlacePageInfoCell"}, + {MetainfoRows::Operator, @"PlacePageInfoCell"}, + {MetainfoRows::Coordinate, @"PlacePageInfoCell"}, + {MetainfoRows::Internet, @"PlacePageInfoCell"}}; -array kPreviewCells = {{@"MWMPlacePagePreviewCell"}}; - -array kBookmarkCells = {{@"MWMBookmarkCell"}}; - -array kMetaInfoCells = { - {@"MWMOpeningHoursCell", @"PlacePageLinkCell", @"PlacePageInfoCell", @"PlacePageLinkCell", - @"PlacePageLinkCell", @"PlacePageInfoCell", @"PlacePageInfoCell", @"PlacePageInfoCell", - @"PlacePageInfoCell"}}; - -array kButtonsCells = {{@"MWMPlacePageButtonCell"}}; - -NSTimeInterval const kAnimationDuration = 0.25; - -void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) -{ - [UIView animateWithDuration:kAnimationDuration - delay:0 - options:UIViewAnimationOptionCurveEaseIn - animations:^{ - animate(); - } - completion:^(BOOL finished) { - if (completion) - completion(); - }]; -} +array const kButtonsCells = {{@"MWMPlacePageButtonCell"}}; } // namespace -@interface MWMPlacePageLayout () @property(weak, nonatomic) MWMPlacePageData * data; @@ -74,19 +47,8 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) id delegate; @property(weak, nonatomic) id dataSource; - -@property(nonatomic) MWMPPScrollView * scrollView; @property(nonatomic) IBOutlet MWMPPView * placePageView; -@property(nonatomic) ScrollDirection direction; -@property(nonatomic) State state; - -@property(nonatomic) CGFloat portraitOpenContentOffset; -@property(nonatomic) CGFloat landscapeOpenContentOffset; -@property(nonatomic) CGFloat lastContentOffset; -@property(nonatomic) CGFloat expandedContentOffset; - -@property(nonatomic) MWMPlacePagePreviewCell * ppPreviewCell; @property(nonatomic) MWMBookmarkCell * bookmarkCell; @property(nonatomic) MWMPlacePageActionBar * actionBar; @@ -94,6 +56,11 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) @property(nonatomic) BOOL isPlacePageButtonsEnabled; @property(nonatomic) BOOL isDownloaderViewShown; +@property(nonatomic) id layoutImpl; + +@property(nonatomic) MWMPPPreviewLayoutHelper * previewLayoutHelper; +@property(nonatomic) MWMOpeningHoursLayoutHelper * openingHoursLayoutHelper; + @end @implementation MWMPlacePageLayout @@ -109,17 +76,18 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) _ownerView = view; _delegate = delegate; _dataSource = dataSource; - [[NSBundle mainBundle] loadNibNamed:[MWMPPView className] owner:self options:nil]; - auto view = self.ownerView; - auto const & size = view.size; - _placePageView.frame = {{0, size.height}, size}; _placePageView.delegate = self; - _scrollView = [[MWMPPScrollView alloc] initWithFrame:view.frame inactiveView:_placePageView]; - _portraitOpenContentOffset = MAX(size.width, size.height) * kOpenPlacePageStopValue; - _landscapeOpenContentOffset = MIN(size.width, size.height) * kOpenPlacePageStopValue; - [view addSubview:_scrollView]; - [_scrollView addSubview:_placePageView]; + auto const Impl = IPAD ? [MWMiPadPlacePageLayoutImpl class] : [MWMiPhonePlacePageLayoutImpl class]; + _layoutImpl = [[Impl alloc] initOwnerView:view placePageView:_placePageView delegate:delegate]; + + if ([_layoutImpl respondsToSelector:@selector(setInitialTopBound:leftBound:)]) + [_layoutImpl setInitialTopBound:dataSource.topBound leftBound:dataSource.leftBound]; + + auto tableView = _placePageView.tableView; + _previewLayoutHelper = [[MWMPPPreviewLayoutHelper alloc] + initWithTableView:tableView]; + _openingHoursLayoutHelper = [[MWMOpeningHoursLayoutHelper alloc] initWithTableView:tableView]; [self registerCells]; } return self; @@ -129,26 +97,22 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) { auto tv = self.placePageView.tableView; - [tv registerNib:[UINib nibWithNibName:kPreviewCells[0] bundle:nil] - forCellReuseIdentifier:kPreviewCells[0]]; [tv registerNib:[UINib nibWithNibName:kButtonsCells[0] bundle:nil] forCellReuseIdentifier:kButtonsCells[0]]; [tv registerNib:[UINib nibWithNibName:kBookmarkCells[0] bundle:nil] forCellReuseIdentifier:kBookmarkCells[0]]; // Register all meta info cells. - for (auto const name : kMetaInfoCells) + for (auto const & pair : kMetaInfoCells) + { + NSString * name = pair.second; [tv registerNib:[UINib nibWithNibName:name bundle:nil] forCellReuseIdentifier:name]; - + } } - (void)layoutWithSize:(CGSize const &)size { - self.scrollView.frame = {{}, size}; - self.placePageView.origin = {0., size.height}; - self.actionBar.frame = {{0., size.height - self.actionBar.height}, - {size.width, self.actionBar.height}}; - [self.delegate onTopBoundChanged:self.scrollView.contentOffset.y]; + [self.layoutImpl onScreenResize:size]; } - (UIView *)shareAnchor { return self.actionBar.shareAnchor; } @@ -156,26 +120,27 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) { self.isPlacePageButtonsEnabled = YES; self.data = data; - self.ppPreviewCell = nil; self.bookmarkCell = nil; - - self.scrollView.delegate = self; - self.state = State::Bottom; - - [self collapse]; + [self.layoutImpl onShow]; [self.actionBar configureWithData:static_cast>(data)]; + [self.openingHoursLayoutHelper configWithData:data]; [self.placePageView.tableView reloadData]; + + dispatch_async(dispatch_get_main_queue(), ^{ + if ([self.layoutImpl respondsToSelector:@selector(onExpandWithPlacePagePreviewHeight:)]) + [self.layoutImpl onExpandWithPlacePagePreviewHeight:self.previewLayoutHelper.height]; + }); } - (void)rotateDirectionArrowToAngle:(CGFloat)angle { - [self.ppPreviewCell rotateDirectionArrowToAngle:angle]; + [self.previewLayoutHelper rotateDirectionArrowToAngle:angle]; } - (void)setDistanceToObject:(NSString *)distance { - [self.ppPreviewCell setDistanceToObject:distance]; + [self.previewLayoutHelper setDistanceToObject:distance]; } - (MWMPlacePageActionBar *)actionBar @@ -183,25 +148,14 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) if (!_actionBar) { _actionBar = [MWMPlacePageActionBar actionBarWithDelegate:self.delegate]; - UIView * superview = self.ownerView; - _actionBar.origin = {0., superview.height}; - [superview addSubview:_actionBar]; + [self.layoutImpl onActionBarInit:_actionBar]; } return _actionBar; } - (void)close { - animate( - ^{ - self.actionBar.origin = {0., self.ownerView.height}; - [self.scrollView setContentOffset:{} animated:YES]; - }, - ^{ - [self.actionBar removeFromSuperview]; - self.actionBar = nil; - [self.delegate shouldDestroyLayout]; - }); + [self.layoutImpl onClose]; } - (void)mwm_refreshUI @@ -230,56 +184,6 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) } } -- (void)collapse -{; - self.scrollView.scrollEnabled = NO; - [self.placePageView hideTableView:YES]; - - animate(^{ - [self.scrollView setContentOffset:{ 0., kMinOffset } animated:YES]; - }); -} - -- (void)expand -{ - self.actionBar.hidden = NO; - self.scrollView.scrollEnabled = YES; - - animate(^{ - [self.placePageView hideTableView:NO]; - self.actionBar.minY = self.actionBar.superview.height - self.actionBar.height; - - // We decrease expanded offset for 2 pixels because it looks more clear. - auto constexpr designOffset = 2; - self.expandedContentOffset = - self.ppPreviewCell.height + self.placePageView.top.height + self.actionBar.height - designOffset; - - auto const targetOffset = - self.state == State::Bottom ? self.expandedContentOffset : self.topContentOffset; - [self.scrollView setContentOffset:{ 0, targetOffset } animated:YES]; - }); -} - -- (BOOL)isPortrait -{ - auto const & s = self.ownerView.size; - return s.height > s.width; -} - -- (CGFloat)openContentOffset -{ - return self.isPortrait ? self.portraitOpenContentOffset : self.landscapeOpenContentOffset; -} - -- (CGFloat)topContentOffset -{ - auto const target = self.openContentOffset; - if (target > self.placePageView.height) - return self.placePageView.height; - - return target; -} - #pragma mark - Downloader event - (void)processDownloaderEventWithStatus:(storage::NodeStatus)status progress:(CGFloat)progress @@ -300,27 +204,25 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) reloadSections:[NSIndexSet indexSetWithIndex:distance(sections.begin(), it)] withRowAnimation:UITableViewRowAnimationAutomatic]; } - - if (self.ppPreviewCell) - [self.ppPreviewCell setDownloaderViewHidden:YES animated:NO]; - else - self.isDownloaderViewShown = NO; - + self.actionBar.isAreaNotDownloaded = NO; break; } case NodeStatus::Downloading: { - self.ppPreviewCell.mapDownloadProgress.progress = progress; + self.actionBar.isAreaNotDownloaded = YES; + self.actionBar.downloadingProgress = progress; break; } case NodeStatus::InQueue: { - self.ppPreviewCell.mapDownloadProgress.state = MWMCircularProgressStateSpinner; + self.actionBar.isAreaNotDownloaded = YES; + self.actionBar.downloadingState = MWMCircularProgressStateSpinner; break; } case NodeStatus::Error: { - self.ppPreviewCell.mapDownloadProgress.state = MWMCircularProgressStateFailed; + self.actionBar.isAreaNotDownloaded = YES; + self.actionBar.downloadingState = MWMCircularProgressStateFailed; break; } case NodeStatus::Partly: break; @@ -334,122 +236,40 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) reloadSections:[NSIndexSet indexSetWithIndex:distance(sections.begin(), it)] withRowAnimation:UITableViewRowAnimationAutomatic]; } - [self.ppPreviewCell setDownloaderViewHidden:YES animated:NO]; + self.actionBar.isAreaNotDownloaded = NO; break; } case NodeStatus::NotDownloaded: { self.isPlacePageButtonsEnabled = NO; - if (self.ppPreviewCell) - [self.ppPreviewCell setDownloaderViewHidden:NO animated:NO]; - else - self.isDownloaderViewShown = YES; - + self.actionBar.isAreaNotDownloaded = YES; break; } } } -#pragma mark - UIScrollViewDelegate +#pragma mark - iPad only -- (void)scrollViewDidScroll:(MWMPPScrollView *)scrollView +- (void)updateTopBound { - if ([scrollView isEqual:self.placePageView.tableView]) - return; - - auto const & offset = scrollView.contentOffset; - id delegate = self.delegate; - if (offset.y <= 0) + if (![self.layoutImpl respondsToSelector:@selector(updateLayoutWithTopBound:)]) { - [self.scrollView removeFromSuperview]; - [self.actionBar removeFromSuperview]; - [delegate shouldDestroyLayout]; + NSAssert(!IPAD, @"iPad layout must implement updateLayoutWithTopBound:!"); return; } - if (offset.y > self.placePageView.height + kLuftDraggingOffset) - { - auto const bounded = self.placePageView.height + kLuftDraggingOffset; - [scrollView setContentOffset:{0, bounded}]; - [delegate onTopBoundChanged:bounded]; - } - else - { - [delegate onTopBoundChanged:offset.y]; - } - - self.direction = self.lastContentOffset < offset.y ? ScrollDirection::Up : ScrollDirection::Down; - self.lastContentOffset = offset.y; + [self.layoutImpl updateLayoutWithTopBound:self.dataSource.topBound]; } -- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView - withVelocity:(CGPoint)velocity - targetContentOffset:(inout CGPoint *)targetContentOffset +- (void)updateLeftBound { - auto const actualOffset = scrollView.contentOffset.y; - auto const openOffset = self.openContentOffset; - auto const targetOffset = (*targetContentOffset).y; - - if (actualOffset > self.expandedContentOffset && actualOffset < openOffset) + if (![self.layoutImpl respondsToSelector:@selector(updateLayoutWithLeftBound:)]) { - auto const isDirectionUp = self.direction == ScrollDirection::Up; - self.state = isDirectionUp ? State::Top : State::Bottom; - (*targetContentOffset).y = - isDirectionUp ? openOffset : self.expandedContentOffset; - } - else if (actualOffset > openOffset && targetOffset < openOffset) - { - self.state = State::Top; - (*targetContentOffset).y = openOffset; - } - else if (actualOffset < self.expandedContentOffset) - { - (*targetContentOffset).y = 0; - animate(^{ - self.actionBar.origin = {0., self.ownerView.height}; - }); - } - else - { - self.state = State::Top; - } -} - -- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate -{ - if (decelerate) + NSAssert(!IPAD, @"iPad layout must implement updateLayoutWithLeftBound:!"); return; - - auto const actualOffset = scrollView.contentOffset.y; - auto const openOffset = self.openContentOffset; - - if (actualOffset < self.expandedContentOffset + kLuftDraggingOffset) - { - self.state = State::Bottom; - animate(^{ - [scrollView setContentOffset:{ 0, self.expandedContentOffset } animated:YES]; - }); } - else if (actualOffset < openOffset) - { - auto const isDirectionUp = self.direction == ScrollDirection::Up; - self.state = isDirectionUp ? State::Top : State::Bottom; - animate(^{ - [scrollView setContentOffset:{0, isDirectionUp ? openOffset : self.expandedContentOffset} - animated:YES]; - }); - } - else - { - self.state = State::Top; - } -} -- (void)setState:(State)state -{ - _state = state; - self.placePageView.anchorImage.transform = state == State::Top ? CGAffineTransformMakeRotation(M_PI) - : CGAffineTransformIdentity; + [self.layoutImpl updateLayoutWithLeftBound:self.dataSource.leftBound]; } #pragma mark - UITableViewDelegate & UITableViewDataSource @@ -469,8 +289,8 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) auto data = self.data; switch (data.sections[section]) { - case Sections::Preview: case Sections::Bookmark: return 1; + case Sections::Preview: return data.previewRows.size(); case Sections::Metainfo: return data.metainfoRows.size(); case Sections::Buttons: return data.buttonsRows.size(); } @@ -487,29 +307,7 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) { case Sections::Preview: { - if (!self.ppPreviewCell) - self.ppPreviewCell = - [tableView dequeueReusableCellWithIdentifier:[MWMPlacePagePreviewCell className]]; - - [self.ppPreviewCell configure:data updateLayoutDelegate:self dataSource:self.dataSource tapAction:^ - { - CGFloat offset = 0; - if (self.state == State::Top) - { - self.state = State::Bottom; - offset = self.expandedContentOffset; - } - else - { - self.state = State::Top; - offset = self.topContentOffset; - } - animate(^{ [self.scrollView setContentOffset:{0, offset} animated:YES]; }); - }]; - - [self.ppPreviewCell setDownloaderViewHidden:!self.isDownloaderViewShown animated:NO]; - - return self.ppPreviewCell; + return [self.previewLayoutHelper cellForRowAtIndexPath:indexPath withData:data]; } case Sections::Bookmark: { @@ -523,19 +321,11 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) case Sections::Metainfo: { auto const row = data.metainfoRows[indexPath.row]; - auto cellName = kMetaInfoCells[static_cast(row)]; - UITableViewCell * c = [tableView dequeueReusableCellWithIdentifier:cellName]; - switch (row) { case MetainfoRows::OpeningHours: - { - [static_cast(c) - configureWithOpeningHours:[data stringForRow:row] - updateLayoutDelegate:self - isClosedNow:data.schedule == OpeningHours::Closed]; - break; - } + case MetainfoRows::ExtendedOpeningHours: + return [self.openingHoursLayoutHelper cellForRowAtIndexPath:indexPath]; case MetainfoRows::Phone: case MetainfoRows::Address: case MetainfoRows::Website: @@ -545,11 +335,11 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) case MetainfoRows::Internet: case MetainfoRows::Coordinate: { - [static_cast(c) configWithRow:row data:data]; - break; + MWMPlacePageInfoCell * c = [tableView dequeueReusableCellWithIdentifier:kMetaInfoCells.at(row)]; + [c configWithRow:row data:data]; + return c; } } - return c; } case Sections::Buttons: { @@ -569,9 +359,9 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) #pragma mark - MWMPlacePageCellUpdateProtocol -- (void)updateCellWithForceReposition:(BOOL)isForceReposition +- (void)cellUpdated { - auto const update = isForceReposition ? @selector(updateWithExpand) : @selector(update); + auto const update = @selector(update); [NSObject cancelPreviousPerformRequestsWithTarget:self selector:update object:nil]; [self performSelector:update withObject:nil afterDelay:0.1]; } @@ -583,18 +373,18 @@ void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) [tableView endUpdates]; } -- (void)updateWithExpand -{ - [self update]; - [self expand]; -} - #pragma mark - MWMPlacePageViewUpdateProtocol - (void)updateWithHeight:(CGFloat)height { - auto const & size = self.ownerView.size; - self.scrollView.contentSize = {size.width, size.height + height}; + auto const sel = @selector(updatePlacePageHeight); + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:sel object:nil]; + [self performSelector:sel withObject:nil afterDelay:0.1]; +} + +- (void)updatePlacePageHeight +{ + [self.layoutImpl onUpdatePlacePageWithHeight:self.placePageView.tableView.contentSize.height]; } @end diff --git a/iphone/Maps/Classes/MWMPlacePageLayoutImpl.h b/iphone/Maps/Classes/MWMPlacePageLayoutImpl.h new file mode 100644 index 0000000000..1d6e014215 --- /dev/null +++ b/iphone/Maps/Classes/MWMPlacePageLayoutImpl.h @@ -0,0 +1,47 @@ +#import "MWMPlacePageActionBar.h" +#import "MWMPPView.h" + +namespace place_page_layout +{ +NSTimeInterval const kAnimationSpeed = IPAD ? 0.15 : 0.25; + +inline void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil) +{ + [UIView animateWithDuration:kAnimationSpeed + delay:0 + options:UIViewAnimationOptionCurveEaseIn + animations:^{ + animate(); + } + completion:^(BOOL finished) { + if (completion) + completion(); + }]; +} +} // namepsace place_page_layout + +@protocol MWMPlacePageLayoutDelegate; + +@protocol MWMPlacePageLayoutImpl + +- (instancetype)initOwnerView:(UIView *)ownerView + placePageView:(MWMPPView *)placePageView + delegate:(id)delegate; +- (void)onShow; +- (void)onClose; +- (void)onScreenResize:(CGSize const &)size; +- (void)onUpdatePlacePageWithHeight:(CGFloat)height; +- (void)onActionBarInit:(MWMPlacePageActionBar *)actionBar; + +@property(weak, nonatomic) UIView * ownerView; +@property(weak, nonatomic) MWMPPView * placePageView; +@property(weak, nonatomic) id delegate; +@property(weak, nonatomic) MWMPlacePageActionBar * actionBar; + +@optional +- (void)onExpandWithPlacePagePreviewHeight:(CGFloat)height; +- (void)updateLayoutWithTopBound:(CGFloat)topBound; +- (void)updateLayoutWithLeftBound:(CGFloat)leftBound; +- (void)setInitialTopBound:(CGFloat)topBound leftBound:(CGFloat)leftBound; + +@end diff --git a/iphone/Maps/Classes/MWMPlacePageManager.mm b/iphone/Maps/Classes/MWMPlacePageManager.mm index 0ab3ec0a94..9d047a7361 100644 --- a/iphone/Maps/Classes/MWMPlacePageManager.mm +++ b/iphone/Maps/Classes/MWMPlacePageManager.mm @@ -22,8 +22,6 @@ @interface MWMPlacePageManager () -@property(nonatomic) MWMPlacePageEntity * entity; - @property(nonatomic) MWMPlacePageLayout * layout; @property(nonatomic) MWMPlacePageData * data; @@ -47,13 +45,13 @@ dataSource:self]; } - [self.layout showWithData:self.data]; - - // Call for the first time to produce changes - [self processCountryEvent:self.data.countryId]; - [MWMLocationManager addObserver:self]; [self.layout setDistanceToObject:self.distanceToObject]; + + [self.layout showWithData:self.data]; + + // Call for the first time to produce changes + [self processCountryEvent:self.data.countryId]; } - (void)closePlacePage @@ -134,7 +132,7 @@ #pragma mark - MWMPlacePageLayout -- (void)onTopBoundChanged:(CGFloat)bound +- (void)onPlacePageTopBoundChanged:(CGFloat)bound { [[MWMMapViewControlsManager manager] dragPlacePage:{{0, self.ownerViewController.view.height - bound}, {}}]; @@ -307,15 +305,34 @@ #pragma mark - MWMFeatureHolder - (FeatureID const &)featureId { return self.data.featureId; } + #pragma mark - Owner - (MapViewController *)ownerViewController { return [MapViewController controller]; } + #pragma mark - Deprecated @synthesize leftBound = _leftBound; @synthesize topBound = _topBound; -- (void)setTopBound:(CGFloat)topBound { _topBound = 0; } -- (void)setLeftBound:(CGFloat)leftBound { _leftBound = 0; } + +- (void)setTopBound:(CGFloat)topBound +{ + if (_topBound == topBound) + return; + + _topBound = topBound; + [self.layout updateTopBound]; +} + +- (void)setLeftBound:(CGFloat)leftBound +{ + if (_leftBound == leftBound) + return; + + _leftBound = leftBound; + [self.layout updateLeftBound]; +} + - (void)addSubviews:(NSArray *)views withNavigationController:(UINavigationController *)controller { } diff --git a/iphone/Maps/Classes/MWMPlacePageNavigationBar.h b/iphone/Maps/Classes/MWMPlacePageNavigationBar.h deleted file mode 100644 index 43de973807..0000000000 --- a/iphone/Maps/Classes/MWMPlacePageNavigationBar.h +++ /dev/null @@ -1,13 +0,0 @@ -@class MWMiPhonePortraitPlacePage; - -@interface MWMPlacePageNavigationBar : SolidTouchView - -+ (void)dismissNavigationBar; -+ (void)showNavigationBarForPlacePage:(MWMiPhonePortraitPlacePage *)placePage; -+ (void)remove; - -- (instancetype)init __attribute__((unavailable("call navigationBarWithPlacePage: instead"))); -- (instancetype)initWithCoder:(NSCoder *)aDecoder __attribute__((unavailable("call navigationBarWithPlacePage: instead"))); -- (instancetype)initWithFrame:(CGRect)frame __attribute__((unavailable("call navigationBarWithPlacePage: instead"))); - -@end diff --git a/iphone/Maps/Classes/MWMPlacePageNavigationBar.mm b/iphone/Maps/Classes/MWMPlacePageNavigationBar.mm deleted file mode 100644 index 52f364ac2d..0000000000 --- a/iphone/Maps/Classes/MWMPlacePageNavigationBar.mm +++ /dev/null @@ -1,112 +0,0 @@ -#import "Common.h" -#import "MWMBasePlacePageView.h" -#import "MWMiPhonePortraitPlacePage.h" -#import "MWMPlacePageEntity.h" -#import "MWMPlacePageNavigationBar.h" -#import "MWMPlacePageViewManager.h" -#import "MWMViewController.h" -#import "Statistics.h" -#import - -static NSString * const kPlacePageNavigationBarNibName = @"PlacePageNavigationBar"; -static CGFloat const kNavigationBarHeight = 36.; - -static inline CGPoint const openCenter(CGFloat xPosition) -{ - return CGPointMake(xPosition, kNavigationBarHeight / 2.); -} - -static inline CGPoint const dismissCenter(CGFloat xPosition) -{ - return CGPointMake(xPosition, - kNavigationBarHeight / 2.); -} - -@interface MWMPlacePageNavigationBar () - -@property (weak, nonatomic) MWMiPhonePortraitPlacePage * placePage; - -@end - -@implementation MWMPlacePageNavigationBar - -+ (void)remove -{ - UIScreen * screen = [UIScreen mainScreen]; - MWMPlacePageNavigationBar * navBar = objc_getAssociatedObject(screen, @selector(navigationBarWithPlacePage:)); - if (!navBar) - return; - - [navBar removeFromSuperview]; - objc_setAssociatedObject(screen, @selector(navigationBarWithPlacePage:), nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -+ (void)showNavigationBarForPlacePage:(MWMiPhonePortraitPlacePage *)placePage -{ - UIView const * superview = placePage.manager.ownerViewController.view; - UIScreen * screen = [UIScreen mainScreen]; - MWMPlacePageNavigationBar * navBar = objc_getAssociatedObject(screen, @selector(navigationBarWithPlacePage:)); - if (!navBar) - { - navBar = [self navigationBarWithPlacePage:placePage]; - objc_setAssociatedObject(screen, @selector(navigationBarWithPlacePage:), navBar, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - [superview addSubview:navBar]; - } - - navBar.placePage = placePage; - [navBar show]; -} - -+ (void)dismissNavigationBar -{ - UIScreen * screen = [UIScreen mainScreen]; - MWMPlacePageNavigationBar * navBar = objc_getAssociatedObject(screen, @selector(navigationBarWithPlacePage:)); - if (!navBar) - return; - - [navBar dismiss]; -} - -- (void)dismiss -{ - [UIView animateWithDuration:kDefaultAnimationDuration animations:^ - { - self.center = dismissCenter(self.center.x); - }]; -} - -- (void)show -{ - [UIView animateWithDuration:kDefaultAnimationDuration animations:^ - { - self.center = openCenter(self.center.x); - }]; -} - -+ (instancetype)navigationBarWithPlacePage:(MWMiPhonePortraitPlacePage *)placePage -{ - MWMPlacePageNavigationBar * navBar = [[[NSBundle mainBundle] loadNibNamed:kPlacePageNavigationBarNibName owner:nil options:nil] firstObject]; - navBar.placePage = placePage; - navBar.autoresizingMask = UIViewAutoresizingNone; - UIView const * superview = placePage.manager.ownerViewController.view; - navBar.center = dismissCenter(superview.center.x); - CGSize const size = [[UIScreen mainScreen] bounds].size; - BOOL const isLandscape = size.width > size.height; - CGFloat const width = isLandscape ? size.height : size.width; - navBar.width = width; - return navBar; -} - -- (IBAction)dismissTap -{ - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatBack)]; - [self dismiss]; - [self.placePage.manager refreshPlacePage]; -} - -- (void)layoutSubviews -{ - if (self) - self.origin = CGPointZero; -} - -@end diff --git a/iphone/Maps/Classes/MWMPlacePagePreviewCell.h b/iphone/Maps/Classes/MWMPlacePagePreviewCell.h deleted file mode 100644 index 0695b38d50..0000000000 --- a/iphone/Maps/Classes/MWMPlacePagePreviewCell.h +++ /dev/null @@ -1,24 +0,0 @@ -#import "MWMTableViewCell.h" - -@class MWMPlacePageData; -@class MWMCircularProgress; - -@protocol MWMPlacePageCellUpdateProtocol; -@protocol MWMPlacePageLayoutDataSource; - -@interface MWMPlacePagePreviewCell : MWMTableViewCell - -- (void)setDistanceToObject:(NSString *)distance; -- (void)rotateDirectionArrowToAngle:(CGFloat)angle; - -- (void)setDownloaderViewHidden:(BOOL)isHidden animated:(BOOL)isAnimated; -- (void)setDownloadingProgress:(CGFloat)progress; - -- (void)configure:(MWMPlacePageData *)data - updateLayoutDelegate:(id)delegate - dataSource:(id)dataSource - tapAction:(TMWMVoidBlock)tapAction; - -- (MWMCircularProgress *)mapDownloadProgress; - -@end diff --git a/iphone/Maps/Classes/MWMPlacePagePreviewCell.mm b/iphone/Maps/Classes/MWMPlacePagePreviewCell.mm deleted file mode 100644 index 897794cc9a..0000000000 --- a/iphone/Maps/Classes/MWMPlacePagePreviewCell.mm +++ /dev/null @@ -1,440 +0,0 @@ -#import "MWMPlacePagePreviewCell.h" -#import "Common.h" -#import "MWMCircularProgress.h" -#import "MWMDirectionView.h" -#import "MWMPlacePageCellUpdateProtocol.h" -#import "MWMPlacePageData.h" -#import "MWMPlacePageLayout.h" -#import "UIColor+MapsmeColor.h" - -#include "std/array.hpp" -#include "std/vector.hpp" - -namespace -{ -array kPPPClasses = {{@"_MWMPPPTitle", @"_MWMPPPExternalTitle", @"_MWMPPPSubtitle", - @"_MWMPPPSchedule", @"_MWMPPPBooking", @"_MWMPPPAddress"}}; - -enum class Labels -{ - Title, - ExternalTitle, - Subtitle, - Schedule, - Booking, - Address -}; - -void * kContext = &kContext; -NSString * const kTableViewContentSizeKeyPath = @"contentSize"; -CGFloat const kDefaultTableViewLeading = 16; -CGFloat const kCompressedTableViewLeading = 56; - -} // namespace - -#pragma mark - Base - -// Base class for avoiding copy-paste in inheriting cells. -@interface _MWMPPPCellBase : MWMTableViewCell - -@property(weak, nonatomic) IBOutlet UILabel * distance; -@property(weak, nonatomic) IBOutlet UIImageView * compass; -@property(weak, nonatomic) IBOutlet UIView * distanceView; -@property(weak, nonatomic) IBOutlet NSLayoutConstraint * trailing; -@property(copy, nonatomic) TMWMVoidBlock tapOnDistance; - -@end - -@implementation _MWMPPPCellBase - -- (IBAction)tap -{ - if (self.tapOnDistance) - self.tapOnDistance(); -} - -@end - -#pragma mark - Title - -@interface _MWMPPPTitle : _MWMPPPCellBase - -@property(weak, nonatomic) IBOutlet UILabel * title; - -@end - -@implementation _MWMPPPTitle -@end - -#pragma mark - External Title - -@interface _MWMPPPExternalTitle : _MWMPPPCellBase - -@property(weak, nonatomic) IBOutlet UILabel * externalTitle; - -@end - -@implementation _MWMPPPExternalTitle -@end - -#pragma mark - Subtitle - -@interface _MWMPPPSubtitle : _MWMPPPCellBase - -@property(weak, nonatomic) IBOutlet UILabel * subtitle; - -@end - -@implementation _MWMPPPSubtitle -@end - -#pragma mark - Schedule - -@interface _MWMPPPSchedule : _MWMPPPCellBase - -@property(weak, nonatomic) IBOutlet UILabel * schedule; - -@end - -@implementation _MWMPPPSchedule -@end - -#pragma mark - Booking - -@interface _MWMPPPBooking : MWMTableViewCell - -@property(weak, nonatomic) IBOutlet UILabel * rating; -@property(weak, nonatomic) IBOutlet UILabel * pricing; - -@end - -@implementation _MWMPPPBooking -@end - -#pragma mark - Address - -@interface _MWMPPPAddress : _MWMPPPCellBase - -@property(weak, nonatomic) IBOutlet UILabel * address; - -@end - -@implementation _MWMPPPAddress -@end - -#pragma mark - Public - -@interface MWMPlacePagePreviewCell () -{ - vector m_cells; -} - -@property(weak, nonatomic) IBOutlet UITableView * tableView; -@property(weak, nonatomic) IBOutlet NSLayoutConstraint * tableViewHeight; -@property(weak, nonatomic) NSLayoutConstraint * trailing; -@property(weak, nonatomic) UIView * distanceView; - -@property(weak, nonatomic) IBOutlet UIView * downloaderParentView; -@property(weak, nonatomic) IBOutlet NSLayoutConstraint * tableViewLeading; - -@property(nonatomic) MWMCircularProgress * mapDownloadProgress; - -@property(nonatomic) BOOL isDirectionViewAvailable; - -@property(weak, nonatomic) MWMPlacePageData * data; -@property(weak, nonatomic) id delegate; -@property(weak, nonatomic) id dataSource; - -@property(copy, nonatomic) NSString * distance; -@property(weak, nonatomic) UIImageView * compass; -@property(nonatomic) CGFloat currentContentHeight; - -@property(nonatomic) MWMDirectionView * directionView; - -@property(copy, nonatomic) TMWMVoidBlock tapAction; - -@end - -@implementation MWMPlacePagePreviewCell - -- (void)awakeFromNib -{ - [super awakeFromNib]; - for (auto const s : kPPPClasses) - [self.tableView registerNib:[UINib nibWithNibName:s bundle:nil] forCellReuseIdentifier:s]; - - self.tableView.estimatedRowHeight = 20; - self.tableView.rowHeight = UITableViewAutomaticDimension; - [self registerObserver]; - - UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)]; - [self addGestureRecognizer:tap]; -} - -- (void)dealloc { [self unregisterObserver]; } -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context -{ - if (context == kContext) - { - NSValue * s = change[@"new"]; - CGFloat const height = s.CGSizeValue.height; - if (!equalScreenDimensions(height, self.currentContentHeight)) - { - self.currentContentHeight = height; - self.tableViewHeight.constant = height; - [self setNeedsLayout]; - [self.delegate updateCellWithForceReposition:YES]; - } - return; - } - - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; -} - -- (MWMDirectionView *)directionView -{ - if (!_directionView) - _directionView = [[MWMDirectionView alloc] initWithManager:nil]; - return _directionView; -} - -- (void)setIsDirectionViewAvailable:(BOOL)isDirectionViewAvailable -{ - if (_isDirectionViewAvailable == isDirectionViewAvailable) - return; - _isDirectionViewAvailable = isDirectionViewAvailable; - [self setNeedsLayout]; -} - -- (void)rotateDirectionArrowToAngle:(CGFloat)angle -{ - auto const t = CATransform3DMakeRotation(M_PI_2 - angle, 0, 0, 1); - self.compass.layer.transform = t; - self.directionView.directionArrow.layer.transform = t; -} - -- (void)setDistanceToObject:(NSString *)distance -{ - if (!distance.length) - { - self.isDirectionViewAvailable = NO; - [self setNeedsLayout]; - return; - } - - if ([self.distance isEqualToString:distance]) - return; - - self.distance = distance; - self.directionView.distanceLabel.text = distance; - self.isDirectionViewAvailable = YES; -} - -- (void)unregisterObserver -{ - [self.tableView removeObserver:self forKeyPath:kTableViewContentSizeKeyPath context:kContext]; -} - -- (void)registerObserver -{ - [self.tableView addObserver:self - forKeyPath:kTableViewContentSizeKeyPath - options:NSKeyValueObservingOptionNew - context:kContext]; -} - -- (void)setDownloadingProgress:(CGFloat)progress { self.mapDownloadProgress.progress = progress; } -- (void)setDownloaderViewHidden:(BOOL)isHidden animated:(BOOL)isAnimated -{ - self.downloaderParentView.hidden = isHidden; - self.tableViewLeading.constant = - isHidden ? kDefaultTableViewLeading : kCompressedTableViewLeading; - [self setNeedsLayout]; - - if (!isHidden) - self.mapDownloadProgress.state = MWMCircularProgressStateNormal; - - if (!isAnimated) - return; - - [UIView animateWithDuration:kDefaultAnimationDuration - animations:^{ - [self layoutIfNeeded]; - }]; -} - -- (void)configure:(MWMPlacePageData *)data - updateLayoutDelegate:(id)delegate - dataSource:(id)dataSource - tapAction:(TMWMVoidBlock)tapAction -{ - self.data = data; - self.delegate = delegate; - self.dataSource = dataSource; - [self setDistanceToObject:dataSource.distanceToObject]; - - m_cells.clear(); - - if (data.title.length) - m_cells.push_back(Labels::Title); - - if (data.externalTitle.length) - m_cells.push_back(Labels::ExternalTitle); - - if (data.subtitle.length) - m_cells.push_back(Labels::Subtitle); - - if (data.schedule != place_page::OpeningHours::Unknown) - m_cells.push_back(Labels::Schedule); - - if (data.bookingRating.length) - m_cells.push_back(Labels::Booking); - - if (data.address.length) - m_cells.push_back(Labels::Address); - - [self.tableView reloadData]; - - NSAssert(tapAction, @"Cell must be tappable!"); - self.tapAction = tapAction; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - return m_cells.size(); -} - -- (UITableViewCell *)tableView:(UITableView *)tableView - cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - auto data = self.data; - _MWMPPPCellBase * c = nil; - BOOL const isNeedToShowDistance = - self.isDirectionViewAvailable && (indexPath.row == m_cells.size() - 1); - - switch (m_cells[indexPath.row]) - { - case Labels::Title: - { - c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPTitle className]]; - static_cast<_MWMPPPTitle *>(c).title.text = data.title; - break; - } - case Labels::ExternalTitle: - { - c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPExternalTitle className]]; - static_cast<_MWMPPPExternalTitle *>(c).externalTitle.text = data.externalTitle; - break; - } - case Labels::Subtitle: - { - c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPSubtitle className]]; - static_cast<_MWMPPPSubtitle *>(c).subtitle.text = data.subtitle; - break; - } - case Labels::Schedule: - { - c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPSchedule className]]; - auto castedCell = static_cast<_MWMPPPSchedule *>(c); - switch (data.schedule) - { - case place_page::OpeningHours::AllDay: - castedCell.schedule.text = L(@"twentyfour_seven"); - castedCell.schedule.textColor = [UIColor blackSecondaryText]; - break; - case place_page::OpeningHours::Open: - castedCell.schedule.text = L(@"editor_time_open"); - castedCell.schedule.textColor = [UIColor blackSecondaryText]; - break; - case place_page::OpeningHours::Closed: - castedCell.schedule.text = L(@"closed_now"); - castedCell.schedule.textColor = [UIColor red]; - break; - case place_page::OpeningHours::Unknown: NSAssert(false, @"Incorrect schedule!"); break; - } - break; - } - case Labels::Booking: - { - _MWMPPPBooking * c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPBooking className]]; - c.rating.text = data.bookingRating; - c.pricing.text = data.bookingApproximatePricing; - [data assignOnlinePriceToLabel:c.pricing]; - return c; - } - case Labels::Address: - { - c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPAddress className]]; - static_cast<_MWMPPPAddress *>(c).address.text = data.address; - break; - } - } - - if (isNeedToShowDistance) - [self showDistanceOnCell:c]; - else - [self hideDistanceOnCell:c]; - - return c; -} - -- (void)showDistanceOnCell:(_MWMPPPCellBase *)cell -{ - cell.trailing.priority = UILayoutPriorityDefaultLow; - cell.distance.text = self.distance; - cell.tapOnDistance = ^{ - [self.directionView show]; - }; - [cell.contentView setNeedsLayout]; - self.compass = cell.compass; - self.trailing = cell.trailing; - self.distanceView = cell.distanceView; - cell.distanceView.hidden = NO; -} - -- (void)hideDistanceOnCell:(_MWMPPPCellBase *)cell -{ - cell.trailing.priority = UILayoutPriorityDefaultHigh; - [cell.contentView setNeedsLayout]; - cell.distanceView.hidden = YES; -} - -#pragma mark - MWMCircularProgressProtocol - -- (void)progressButtonPressed:(MWMCircularProgress *)progress -{ - [self.dataSource downloadSelectedArea]; -} - -#pragma mark - Properties - -- (MWMCircularProgress *)mapDownloadProgress -{ - if (!_mapDownloadProgress) - { - _mapDownloadProgress = - [MWMCircularProgress downloaderProgressForParentView:self.downloaderParentView]; - _mapDownloadProgress.delegate = self; - - MWMCircularProgressStateVec const affectedStates = {MWMCircularProgressStateNormal, - MWMCircularProgressStateSelected}; - - [_mapDownloadProgress setImageName:@"ic_download" forStates:affectedStates]; - [_mapDownloadProgress setColoring:MWMButtonColoringBlue forStates:affectedStates]; - } - return _mapDownloadProgress; -} - -#pragma mark - Tap - -- (void)tap -{ - if (self.tapAction) - self.tapAction(); -} - -@end diff --git a/iphone/Maps/Classes/MWMPlacePageProtocol.h b/iphone/Maps/Classes/MWMPlacePageProtocol.h index f9d26162aa..8a5a4c2835 100644 --- a/iphone/Maps/Classes/MWMPlacePageProtocol.h +++ b/iphone/Maps/Classes/MWMPlacePageProtocol.h @@ -2,7 +2,7 @@ #include "Framework.h" -@class MWMPlacePageEntity, MWMViewController; +@class MWMViewController; @protocol MWMActionBarProtocol @@ -18,6 +18,7 @@ - (void)book:(BOOL)isDecription; - (void)apiBack; +- (void)downloadSelectedArea; @end diff --git a/iphone/Maps/Classes/MWMPlacePageViewManager.h b/iphone/Maps/Classes/MWMPlacePageViewManager.h deleted file mode 100644 index f495df9592..0000000000 --- a/iphone/Maps/Classes/MWMPlacePageViewManager.h +++ /dev/null @@ -1,42 +0,0 @@ -#import "MWMMapViewControlsManager.h" - -#include "Framework.h" - -#include "MWMPlacePageProtocol.h" - -@class MWMPlacePageEntity, MWMPlacePageNavigationBar, MWMViewController; - -@interface MWMPlacePageViewManager : NSObject - -@property(weak, nonatomic, readonly) MWMViewController * ownerViewController; -@property(nonatomic, readonly) MWMPlacePageEntity * entity; -@property(nonatomic) CGFloat topBound; -@property(nonatomic) CGFloat leftBound; - -- (void)showPlacePage:(place_page::Info const &)info; -- (void)refreshPlacePage; -- (void)mwm_refreshUI; -- (BOOL)hasPlacePage; -- (void)dismissPlacePage; -- (void)hidePlacePage; -- (void)routeFrom; -- (void)routeTo; -- (void)share; -- (void)editPlace; -- (void)addBusiness; -- (void)addPlace; -- (void)addBookmark; -- (void)removeBookmark; -- (void)book:(BOOL)isDecription; -- (void)call; -- (void)apiBack; -- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation; -- (void)viewWillTransitionToSize:(CGSize)size - withTransitionCoordinator:(id)coordinator; -- (void)reloadBookmark; -- (void)dragPlacePage:(CGRect)frame; -- (void)showDirectionViewWithTitle:(NSString *)title type:(NSString *)type; -- (void)addSubviews:(NSArray *)views withNavigationController:(UINavigationController *)controller; -- (void)changeHeight:(CGFloat)height; - -@end diff --git a/iphone/Maps/Classes/MWMPlacePageViewManager.mm b/iphone/Maps/Classes/MWMPlacePageViewManager.mm deleted file mode 100644 index cb2b99709f..0000000000 --- a/iphone/Maps/Classes/MWMPlacePageViewManager.mm +++ /dev/null @@ -1,397 +0,0 @@ -#import "MWMPlacePageViewManager.h" -#import -#import "Common.h" -#import "MWMAPIBar.h" -#import "MWMActivityViewController.h" -#import "MWMBasePlacePageView.h" -#import "MWMDirectionView.h" -#import "MWMFrameworkListener.h" -#import "MWMLocationHelpers.h" -#import "MWMLocationManager.h" -#import "MWMPlacePage.h" -#import "MWMPlacePageActionBar.h" -#import "MWMPlacePageEntity.h" -#import "MWMPlacePageNavigationBar.h" -#import "MWMRouter.h" -#import "MWMiPadPlacePage.h" -#import "MWMiPhoneLandscapePlacePage.h" -#import "MWMiPhonePortraitPlacePage.h" -#import "MapViewController.h" -#import "MapsAppDelegate.h" -#import "Statistics.h" - -#import "3party/Alohalytics/src/alohalytics_objc.h" - -#include "MWMRoutePoint.h" - -#include "geometry/distance_on_sphere.hpp" -#include "map/place_page_info.hpp" -#include "platform/measurement_utils.hpp" - -extern NSString * const kAlohalyticsTapEventKey; -extern NSString * const kBookmarksChangedNotification; - -@interface MWMPlacePageViewManager () - -@property(nonatomic, readwrite) MWMPlacePageEntity * entity; -@property(nonatomic) MWMPlacePage * placePage; -@property(nonatomic) MWMDirectionView * directionView; - -@end - -@implementation MWMPlacePageViewManager - -- (void)hidePlacePage { [self.placePage hide]; } -- (void)dismissPlacePage -{ - [self.placePage dismiss]; - [MWMLocationManager removeObserver:self]; - GetFramework().DeactivateMapSelection(false); - self.placePage = nil; -} - -- (void)showPlacePage:(place_page::Info const &)info -{ - [MWMLocationManager addObserver:self]; - self.entity = [[MWMPlacePageEntity alloc] initWithInfo:info]; - if (IPAD) - [self setPlacePageForiPad]; - else - [self setPlacePageForiPhoneWithOrientation:self.ownerViewController.interfaceOrientation]; - [self configPlacePage]; -} - -- (FeatureID const &)featureId { return self.entity.featureID; } -#pragma mark - Layout - -- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation -{ - [self rotateToOrientation:orientation]; -} - -- (void)viewWillTransitionToSize:(CGSize)size - withTransitionCoordinator:(id)coordinator -{ - [self rotateToOrientation:size.height > size.width ? UIInterfaceOrientationPortrait - : UIInterfaceOrientationLandscapeLeft]; -} - -- (void)rotateToOrientation:(UIInterfaceOrientation)orientation -{ - if (!self.placePage) - return; - - if (IPAD) - { - self.placePage.parentViewHeight = self.ownerViewController.view.width; - [(MWMiPadPlacePage *)self.placePage updatePlacePageLayoutAnimated:NO]; - } - else - { - [self.placePage dismiss]; - [self setPlacePageForiPhoneWithOrientation:orientation]; - [self configPlacePage]; - } -} - -- (void)configPlacePage -{ - if (self.entity.isMyPosition) - self.entity.subtitle = - location_helpers::formattedSpeedAndAltitude([MWMLocationManager lastLocation]); - self.placePage.parentViewHeight = self.ownerViewController.view.height; - [self.placePage configure]; - self.placePage.topBound = self.topBound; - self.placePage.leftBound = self.leftBound; - [self refreshPlacePage]; -} - -- (void)refreshPlacePage -{ - [self.placePage show]; - [self updateDistance]; -} - -- (void)mwm_refreshUI -{ - [self.placePage.extendedPlacePageView mwm_refreshUI]; - [self.placePage.actionBar mwm_refreshUI]; -} - -- (BOOL)hasPlacePage { return self.placePage != nil; } -- (void)setPlacePageForiPad -{ - [self.placePage dismiss]; - self.placePage = [[MWMiPadPlacePage alloc] initWithManager:self]; -} - -- (void)updateMyPositionSpeedAndAltitude -{ - if (self.entity.isMyPosition) - [self.placePage updateMyPositionStatus:location_helpers::formattedSpeedAndAltitude( - [MWMLocationManager lastLocation])]; -} - -- (void)setPlacePageForiPhoneWithOrientation:(UIInterfaceOrientation)orientation -{ - switch (orientation) - { - case UIInterfaceOrientationLandscapeLeft: - case UIInterfaceOrientationLandscapeRight: - if (![self.placePage isKindOfClass:[MWMiPhoneLandscapePlacePage class]]) - self.placePage = [[MWMiPhoneLandscapePlacePage alloc] initWithManager:self]; - break; - - case UIInterfaceOrientationPortrait: - case UIInterfaceOrientationPortraitUpsideDown: - if (![self.placePage isKindOfClass:[MWMiPhonePortraitPlacePage class]]) - self.placePage = [[MWMiPhonePortraitPlacePage alloc] initWithManager:self]; - break; - - case UIInterfaceOrientationUnknown: break; - } -} - -- (void)addSubviews:(NSArray *)views withNavigationController:(UINavigationController *)controller -{ - if (controller) - [self.ownerViewController addChildViewController:controller]; - [[MWMMapViewControlsManager manager] addPlacePageViews:views]; -} - -- (void)routeFrom -{ - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatBuildRoute) - withParameters:@{kStatValue : kStatSource}]; - [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"ppRoute"]; - [[MWMRouter router] buildFromPoint:self.target bestRouter:YES]; - [self hidePlacePage]; -} - -- (void)routeTo -{ - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatBuildRoute) - withParameters:@{kStatValue : kStatDestination}]; - [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"ppRoute"]; - auto r = [MWMRouter router]; - [r buildToPoint:self.target bestRouter:YES]; - [self hidePlacePage]; -} - -- (MWMRoutePoint)target -{ - NSString * name = nil; - if (self.entity.title.length > 0) - name = self.entity.title; - else if (self.entity.address.length > 0) - name = self.entity.address; - else if (self.entity.subtitle.length > 0) - name = self.entity.subtitle; - else if (self.entity.isBookmark) - name = self.entity.bookmarkTitle; - else - name = L(@"placepage_unknown_place"); - - m2::PointD const & org = self.entity.mercator; - return self.entity.isMyPosition ? MWMRoutePoint(org) : MWMRoutePoint(org, name); -} - -- (void)share -{ - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatShare)]; - [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"ppShare"]; - MWMPlacePageEntity * entity = self.entity; - MWMActivityViewController * shareVC = [MWMActivityViewController - shareControllerForPlacePageObject:static_cast>(entity)]; - [shareVC presentInParentViewController:self.ownerViewController - anchorView:self.placePage.actionBar.shareAnchor]; -} - -- (void)book:(BOOL)isDescription -{ - MWMPlacePageEntity * data = self.entity; - BOOL const isBooking = data.isBooking; - auto const & latLon = data.latLon; - NSMutableDictionary * stat = [@{} mutableCopy]; - if (isBooking) - { - stat[kStatProvider] = kStatBooking; - stat[kStatHotel] = data.sponsoredId; - stat[kStatHotelLat] = @(latLon.lat); - stat[kStatHotelLon] = @(latLon.lon); - } - else - { - stat[kStatProvider] = kStatOpentable; - stat[kStatRestaurant] = data.sponsoredId; - stat[kStatRestaurantLat] = @(latLon.lat); - stat[kStatRestaurantLon] = @(latLon.lon); - } - - NSString * eventName = isBooking ? kPlacePageHotelBook : kPlacePageRestaurantBook; - [Statistics logEvent:isDescription ? kPlacePageHotelDetails : eventName - withParameters:stat - atLocation:[MWMLocationManager lastLocation]]; - - UIViewController * vc = static_cast([MapViewController controller]); - NSURL * url = isDescription ? self.entity.sponsoredDescriptionURL : self.entity.sponsoredURL; - NSAssert(url, @"Sponsored url can't be nil!"); - [vc openUrl:url]; -} - -- (void)call -{ - NSString * tel = [self.entity getCellValue:MWMPlacePageCellTypePhoneNumber]; - NSAssert(tel, @"Phone number can't be nil!"); - NSString * phoneNumber = [[@"telprompt:" stringByAppendingString:tel] - stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:phoneNumber]]; -} - -- (void)apiBack -{ - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatAPI)]; - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:self.entity.apiURL]]; - [((MapViewController *)self.ownerViewController).apiBar back]; -} - -- (void)editPlace -{ - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatEdit)]; - GetPlatform().GetMarketingService().SendPushWooshTag(marketing::kEditorEditDiscovered); - [(MapViewController *)self.ownerViewController openEditor]; -} - -- (void)addBusiness -{ - [Statistics logEvent:kStatEditorAddClick withParameters:@{kStatValue : kStatPlacePage}]; - [[MWMMapViewControlsManager manager] addPlace:YES hasPoint:NO point:m2::PointD()]; -} - -- (void)addPlace -{ - [Statistics logEvent:kStatEditorAddClick - withParameters:@{kStatValue : kStatPlacePageNonBuilding}]; - [[MWMMapViewControlsManager manager] addPlace:NO hasPoint:YES point:self.entity.mercator]; -} - -- (void)addBookmark -{ - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatBookmarks) - withParameters:@{kStatValue : kStatAdd}]; - Framework & f = GetFramework(); - BookmarkData bmData = {self.entity.titleForNewBookmark, f.LastEditedBMType()}; - auto const categoryIndex = f.LastEditedBMCategory(); - auto const bookmarkIndex = f.GetBookmarkManager().AddBookmark(categoryIndex, self.entity.mercator, bmData); - self.entity.bac = {bookmarkIndex, categoryIndex}; - self.entity.bookmarkTitle = @(bmData.GetName().c_str()); - self.entity.bookmarkCategory = @(f.GetBmCategory(categoryIndex)->GetName().c_str()); - [NSNotificationCenter.defaultCenter postNotificationName:kBookmarksChangedNotification - object:nil - userInfo:nil]; - [self updateDistance]; - [self.placePage addBookmark]; -} - -- (void)removeBookmark -{ - [Statistics logEvent:kStatEventName(kStatPlacePage, kStatBookmarks) - withParameters:@{kStatValue : kStatRemove}]; - Framework & f = GetFramework(); - BookmarkCategory * bookmarkCategory = - f.GetBookmarkManager().GetBmCategory(self.entity.bac.m_categoryIndex); - if (bookmarkCategory) - { - { - BookmarkCategory::Guard guard(*bookmarkCategory); - guard.m_controller.DeleteUserMark(self.entity.bac.m_bookmarkIndex); - } - bookmarkCategory->SaveToKMLFile(); - } - self.entity.bac = {}; - self.entity.bookmarkTitle = nil; - self.entity.bookmarkCategory = nil; - [NSNotificationCenter.defaultCenter postNotificationName:kBookmarksChangedNotification - object:nil - userInfo:nil]; - [self updateDistance]; - [self.placePage removeBookmark]; -} - -- (void)reloadBookmark -{ - [self.entity synchronize]; - [self.placePage reloadBookmark]; - [self updateDistance]; -} - -- (void)dragPlacePage:(CGRect)frame { [[MWMMapViewControlsManager manager] dragPlacePage:frame]; } -- (void)updateDistance -{ - NSString * distance = [self distance]; - self.directionView.distanceLabel.text = distance; - [self.placePage setDistance:distance]; -} - -- (NSString *)distance -{ - CLLocation * lastLocation = [MWMLocationManager lastLocation]; - if (!lastLocation) - return @""; - string distance; - CLLocationCoordinate2D const coord = lastLocation.coordinate; - ms::LatLon const & target = self.entity.latLon; - measurement_utils::FormatDistance( - ms::DistanceOnEarth(coord.latitude, coord.longitude, target.lat, target.lon), distance); - return @(distance.c_str()); -} - -- (void)showDirectionViewWithTitle:(NSString *)title type:(NSString *)type -{ - MWMDirectionView * directionView = self.directionView; - directionView.titleLabel.text = title; - directionView.typeLabel.text = type; - [directionView show]; - [self updateDistance]; -} - -- (void)changeHeight:(CGFloat)height -{ - if (!IPAD) - return; - ((MWMiPadPlacePage *)self.placePage).height = height; -} - -#pragma mark - MWMLocationObserver - -- (void)onHeadingUpdate:(location::CompassInfo const &)info -{ - CLLocation * lastLocation = [MWMLocationManager lastLocation]; - if (!lastLocation) - return; - CGFloat const angle = ang::AngleTo(lastLocation.mercator, self.entity.mercator) + info.m_bearing; - CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI_2 - angle); - [self.placePage setDirectionArrowTransform:transform]; - [self.directionView setDirectionArrowTransform:transform]; -} - -- (void)onLocationUpdate:(location::GpsInfo const &)locationInfo -{ - [self updateDistance]; - [self updateMyPositionSpeedAndAltitude]; -} - -#pragma mark - Properties - -- (MWMDirectionView *)directionView -{ - if (!_directionView) - _directionView = [[MWMDirectionView alloc] initWithManager:self]; - return _directionView; -} - -- (MapViewController *)ownerViewController { return [MapViewController controller]; } -- (void)setTopBound:(CGFloat)topBound { _topBound = self.placePage.topBound = topBound; } -- (void)setLeftBound:(CGFloat)leftBound { _leftBound = self.placePage.leftBound = leftBound; } -- (void)editBookmark {} -@end diff --git a/iphone/Maps/Classes/MWMSpringAnimation.h b/iphone/Maps/Classes/MWMSpringAnimation.h deleted file mode 100644 index 783b363569..0000000000 --- a/iphone/Maps/Classes/MWMSpringAnimation.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "MWMAnimator.h" - -@interface MWMSpringAnimation : NSObject - -@property (nonatomic, readonly) CGPoint velocity; - -+ (instancetype)animationWithView:(UIView *)view target:(CGPoint)target velocity:(CGPoint)velocity completion:(TMWMVoidBlock)completion; - -+ (CGFloat)approxTargetFor:(CGFloat)startValue velocity:(CGFloat)velocity; - -@end diff --git a/iphone/Maps/Classes/MWMSpringAnimation.mm b/iphone/Maps/Classes/MWMSpringAnimation.mm deleted file mode 100644 index 71b0d46cb6..0000000000 --- a/iphone/Maps/Classes/MWMSpringAnimation.mm +++ /dev/null @@ -1,65 +0,0 @@ -#import "MWMSpringAnimation.h" - -@interface MWMSpringAnimation () - -@property (nonatomic) CGPoint velocity; -@property (nonatomic) CGPoint targetPoint; -@property (nonatomic) UIView * view; -@property (copy, nonatomic) TMWMVoidBlock completion; - -@end - -@implementation MWMSpringAnimation - -+ (instancetype)animationWithView:(UIView *)view target:(CGPoint)target velocity:(CGPoint)velocity completion:(TMWMVoidBlock)completion -{ - return [[self alloc] initWithView:view target:target velocity:velocity completion:completion]; -} - -- (instancetype)initWithView:(UIView *)view target:(CGPoint)target velocity:(CGPoint)velocity completion:(TMWMVoidBlock)completion -{ - self = [super init]; - if (self) - { - self.view = view; - self.targetPoint = target; - self.velocity = velocity; - self.completion = completion; - } - return self; -} - -- (void)animationTick:(CFTimeInterval)dt finished:(BOOL *)finished -{ - CGFloat const frictionConstant = 25.; - CGFloat const springConstant = 300.; - - // friction force = velocity * friction constant - CGPoint const frictionForce = MultiplyCGPoint(self.velocity, frictionConstant); - // spring force = (target point - current position) * spring constant - CGPoint const springForce = MultiplyCGPoint(SubtractCGPoint(self.targetPoint, self.view.center), springConstant); - // force = spring force - friction force - CGPoint const force = SubtractCGPoint(springForce, frictionForce); - // velocity = current velocity + force * time / mass - self.velocity = AddCGPoint(self.velocity, MultiplyCGPoint(force, dt)); - // position = current position + velocity * time - self.view.center = AddCGPoint(self.view.center, MultiplyCGPoint(self.velocity, dt)); - - CGFloat const speed = LengthCGPoint(self.velocity); - CGFloat const distanceToGoal = LengthCGPoint(SubtractCGPoint(self.targetPoint, self.view.center)); - if (speed < 0.05 && distanceToGoal < 1) - { - self.view.center = self.targetPoint; - *finished = YES; - if (self.completion) - self.completion(); - } -} - -+ (CGFloat)approxTargetFor:(CGFloat)startValue velocity:(CGFloat)velocity -{ - CGFloat const decelaration = (velocity > 0 ? -1.0 : 1.0) * 300.0; - return startValue - (velocity * velocity) / (2.0 * decelaration); -} - -@end diff --git a/iphone/Maps/Classes/MWMiPadPlacePage.h b/iphone/Maps/Classes/MWMiPadPlacePage.h deleted file mode 100644 index f2c3991269..0000000000 --- a/iphone/Maps/Classes/MWMiPadPlacePage.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "MWMPlacePage.h" - -@interface MWMiPadPlacePage : MWMPlacePage - -@property (nonatomic) CGFloat height; - -- (void)updatePlacePageLayoutAnimated:(BOOL)animated; - -@end diff --git a/iphone/Maps/Classes/MWMiPadPlacePage.mm b/iphone/Maps/Classes/MWMiPadPlacePage.mm deleted file mode 100644 index 50ac0e8c62..0000000000 --- a/iphone/Maps/Classes/MWMiPadPlacePage.mm +++ /dev/null @@ -1,314 +0,0 @@ -#import "Common.h" -#import "MWMBasePlacePageView.h" -#import "MWMiPadPlacePage.h" -#import "MWMPlacePageActionBar.h" -#import "MWMPlacePageViewManager.h" -#import "MWMViewController.h" -#import "UIColor+MapsMeColor.h" -#import "UIViewController+Navigation.h" - -static CGFloat const kLeftOffset = 12.; -static CGFloat const kTopOffset = 36.; -static CGFloat const kBottomOffset = 60.; -static CGFloat const kKeyboardOffset = 12.; - -@interface MWMiPadPlacePageViewController : MWMViewController - -@property (nonatomic) UIView * placePageView; -@property (nonatomic) UIView * actionBarView; - -@end - -@implementation MWMiPadPlacePageViewController - -- (instancetype)initWithPlacepageView:(UIView *)ppView actionBar:(UIView *)actionBar -{ - self = [super init]; - if (self) - { - self.view.backgroundColor = [UIColor white]; - self.placePageView = ppView; - self.actionBarView = actionBar; - [self.view addSubview:ppView]; - [self.view addSubview:actionBar]; - } - return self; -} - -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - [self.navigationController setNavigationBarHidden:YES]; - self.view.autoresizingMask = UIViewAutoresizingNone; -} - -@end - -@interface MWMiPadNavigationController : UINavigationController - -@property (weak, nonatomic) MWMiPadPlacePage * placePage; -@property (nonatomic) CGFloat height; - -@end - -@implementation MWMiPadNavigationController - -- (instancetype)initWithViewController:(UIViewController *)viewController frame:(CGRect)frame -{ - self = [super initWithRootViewController:viewController]; - if (self) - { - self.view.frame = viewController.view.frame = frame; - [self setNavigationBarHidden:YES]; - [self.navigationBar setTranslucent:NO]; - self.view.autoresizingMask = UIViewAutoresizingNone; - } - return self; -} - -- (void)backTap:(id)sender -{ - [self popViewControllerAnimated:YES]; -} - -- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated -{ - viewController.view.frame = self.view.bounds; - [super pushViewController:viewController animated:animated]; -} - -- (UIViewController *)popViewControllerAnimated:(BOOL)animated -{ - [self.view endEditing:YES]; - NSUInteger const count = self.viewControllers.count; - UIViewController * viewController = self.viewControllers.lastObject; - if (count == 2) - { - [super popViewControllerAnimated:animated]; - [self.placePage updatePlacePageLayoutAnimated:YES]; - } - else - { - CGFloat const height = count > 1 ? ((UIViewController *)self.viewControllers[count - 2]).view.height : 0.0; - - [UIView animateWithDuration:kDefaultAnimationDuration animations:^ - { - self.height = height; - } - completion:^(BOOL finished) - { - [super popViewControllerAnimated:animated]; - }]; - } - return viewController; -} - -- (void)setHeight:(CGFloat)height -{ - self.view.height = height; - UIViewController * vc = self.topViewController; - vc.view.height = height; - if ([vc isKindOfClass:[MWMiPadPlacePageViewController class]]) - { - MWMiPadPlacePageViewController * ppVC = (MWMiPadPlacePageViewController *)vc; - ppVC.placePageView.height = height; - ppVC.actionBarView.origin = {0, height - ppVC.actionBarView.height}; - } -} - -- (CGFloat)height -{ - return self.view.height; -} - -@end - -@interface MWMiPadPlacePage () - -@property (nonatomic) MWMiPadNavigationController * navigationController; - -@end - -@implementation MWMiPadPlacePage - -- (void)configure -{ - [super configure]; - - CGFloat const defaultWidth = 360.; - CGFloat const actionBarHeight = self.actionBar.height; - self.height = - self.basePlacePageView.height + self.anchorImageView.height + actionBarHeight - 1; - self.extendedPlacePageView.frame = {{0, 0}, {defaultWidth, self.height}}; - self.actionBar.frame = {{0, self.height - actionBarHeight},{defaultWidth, actionBarHeight}}; - MWMiPadPlacePageViewController * viewController = - [[MWMiPadPlacePageViewController alloc] initWithPlacepageView:self.extendedPlacePageView - actionBar:self.actionBar]; - self.navigationController = [[MWMiPadNavigationController alloc] - initWithViewController:viewController - frame:{{-defaultWidth, self.topBound + kTopOffset}, - {defaultWidth, self.height}}]; - self.navigationController.placePage = self; - [self updatePlacePagePosition]; - [self addPlacePageShadowToView:self.navigationController.view offset:{0, -2}]; - - [self.manager addSubviews:@[ self.navigationController.view ] - withNavigationController:self.navigationController]; - self.anchorImageView.image = nil; - self.anchorImageView.backgroundColor = [UIColor white]; - [self configureContentInset]; -} - -- (void)show -{ - UIView * view = self.navigationController.view; - [UIView animateWithDuration:kDefaultAnimationDuration animations:^ - { - view.minY = self.topBound + kTopOffset; - view.minX = self.leftBound + kLeftOffset; - view.alpha = 1.0; - }]; -} - -- (void)hide -{ - [self.manager dismissPlacePage]; -} - -- (void)dismiss -{ - UIView * view = self.navigationController.view; - UIViewController * controller = self.navigationController; - [UIView animateWithDuration:kDefaultAnimationDuration animations:^ - { - view.maxX = 0.0; - view.alpha = 0.0; - } - completion:^(BOOL finished) - { - [view removeFromSuperview]; - [controller removeFromParentViewController]; - [super dismiss]; - }]; -} - -- (void)addBookmark -{ - [super addBookmark]; - [self refresh]; -} - -- (void)removeBookmark -{ - [super removeBookmark]; - [self refresh]; -} - -- (void)reloadBookmark -{ - [super reloadBookmark]; - [self refresh]; -} - -- (void)refresh -{ - [self updatePlacePageLayoutAnimated:YES]; -} - -- (IBAction)didPan:(UIPanGestureRecognizer *)sender -{ - UIView * view = self.navigationController.view; - UIView * superview = view.superview; - - CGFloat const leftOffset = self.leftBound + kLeftOffset; - view.minX += [sender translationInView:superview].x; - view.minX = MIN(view.minX, leftOffset); - [sender setTranslation:CGPointZero inView:superview]; - - CGFloat const alpha = MAX(0.0, view.maxX) / (view.width + leftOffset); - view.alpha = alpha; - UIGestureRecognizerState const state = sender.state; - if (state == UIGestureRecognizerStateEnded || state == UIGestureRecognizerStateCancelled) - { - if (alpha < 0.8) - [self.manager dismissPlacePage]; - else - [self show]; - } -} - -- (void)updatePlacePageLayoutAnimated:(BOOL)animated -{ - if (![self.navigationController.topViewController isKindOfClass:[MWMiPadPlacePageViewController class]]) - return; - [UIView animateWithDuration:animated ? kDefaultAnimationDuration : 0.0 animations:^ - { - CGFloat const ppHeight = self.basePlacePageView.height; - CGFloat const anchorHeight = self.anchorImageView.height; - CGFloat const actionBarHeight = self.actionBar.height; - self.height = ppHeight + anchorHeight + actionBarHeight - 1; - [self updatePlacePagePosition]; - }]; -} - -- (void)updatePlacePagePosition -{ - UIView * view = self.navigationController.view; - view.minY = MIN([self getAvailableHeight] + kTopOffset - view.height, self.topBound + kTopOffset); - [self configureContentInset]; -} - -- (void)configureContentInset -{ - UITableView * featureTable = self.basePlacePageView.featureTable; - CGFloat const height = self.navigationController.view.height; - CGFloat const tableContentHeight = featureTable.contentSize.height; - CGFloat const headerHeight = self.basePlacePageView.ppPreview.height; - CGFloat const actionBarHeight = self.actionBar.height; - CGFloat const anchorHeight = self.anchorImageView.height; - CGFloat const availableTableHeight = height - headerHeight - actionBarHeight - anchorHeight; - CGFloat const externalHeight = tableContentHeight - availableTableHeight; - if (externalHeight > 0.) - { - featureTable.contentInset = UIEdgeInsetsMake(0., 0., externalHeight, 0.); - featureTable.scrollEnabled = YES; - } - else - { - featureTable.contentInset = UIEdgeInsetsZero; - featureTable.scrollEnabled = NO; - } -} - -- (CGFloat)getAvailableHeight -{ - CGFloat const bottomOffset = self.keyboardHeight > 0.0 ? kKeyboardOffset : kBottomOffset; - CGFloat const availableHeight = self.parentViewHeight - self.keyboardHeight - kTopOffset - bottomOffset; - return availableHeight; -} - -#pragma mark - Properties - -- (void)setHeight:(CGFloat)height -{ - _height = self.navigationController.height = MIN(height, [self getAvailableHeight]); -} - -- (void)setTopBound:(CGFloat)topBound -{ - super.topBound = topBound; - [UIView animateWithDuration:kDefaultAnimationDuration animations:^ - { - self.navigationController.view.minY = topBound + kTopOffset; - }]; -} - -- (void)setLeftBound:(CGFloat)leftBound -{ - super.leftBound = leftBound; - [UIView animateWithDuration:kDefaultAnimationDuration animations:^ - { - self.navigationController.view.minX = leftBound + kLeftOffset; - }]; -} -@end diff --git a/iphone/Maps/Classes/MWMiPadPlacePageLayoutImpl.h b/iphone/Maps/Classes/MWMiPadPlacePageLayoutImpl.h new file mode 100644 index 0000000000..ddea80a07e --- /dev/null +++ b/iphone/Maps/Classes/MWMiPadPlacePageLayoutImpl.h @@ -0,0 +1,5 @@ +#import "MWMPlacePageLayoutImpl.h" + +@interface MWMiPadPlacePageLayoutImpl : NSObject + +@end diff --git a/iphone/Maps/Classes/MWMiPadPlacePageLayoutImpl.mm b/iphone/Maps/Classes/MWMiPadPlacePageLayoutImpl.mm new file mode 100644 index 0000000000..f7dda429de --- /dev/null +++ b/iphone/Maps/Classes/MWMiPadPlacePageLayoutImpl.mm @@ -0,0 +1,220 @@ +#import "MWMiPadPlacePageLayoutImpl.h" +#import "MWMPlacePageLayout.h" + +namespace +{ +CGFloat const kPlacePageWidth = 360; +CGFloat const kLeftOffset = 12; +CGFloat const kTopOffset = 36; +CGFloat const kBottomOffset = 60; +} // namespace + +@interface MWMPPView (ActionBarLayout) + +@end + +@implementation MWMPPView (ActionBarLayout) + +- (void)layoutSubviews +{ + [super layoutSubviews]; + if (!IPAD) + return; + + for (UIView * sv in self.subviews) + { + if (![sv isKindOfClass:[MWMPlacePageActionBar class]]) + continue; + sv.maxY = self.height; + break; + } +} + +@end + +@interface MWMiPadPlacePageLayoutImpl () + +@property(nonatomic) CGFloat topBound; +@property(nonatomic) CGFloat leftBound; + +@end + +@implementation MWMiPadPlacePageLayoutImpl + +@synthesize ownerView = _ownerView; +@synthesize placePageView = _placePageView; +@synthesize delegate = _delegate; +@synthesize actionBar = _actionBar; + +- (instancetype)initOwnerView:(UIView *)ownerView + placePageView:(MWMPPView *)placePageView + delegate:(id)delegate +{ + self = [super init]; + if (self) + { + _ownerView = ownerView; + _placePageView = placePageView; + _delegate = delegate; + placePageView.width = kPlacePageWidth; + placePageView.anchorImage.hidden = YES; + [self addShadow]; + auto pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didPan:)]; + [placePageView addGestureRecognizer:pan]; + } + return self; +} + +- (void)addShadow +{ + CALayer * layer = self.placePageView.layer; + layer.masksToBounds = NO; + layer.shadowColor = UIColor.blackColor.CGColor; + layer.shadowRadius = 4.; + layer.shadowOpacity = 0.24f; + layer.shadowOffset = {0, -2}; + layer.shouldRasterize = YES; + layer.rasterizationScale = [[UIScreen mainScreen] scale]; +} + +- (void)onShow +{ + auto ppView = self.placePageView; + auto actionBar = self.actionBar; + ppView.tableView.scrollEnabled = NO; + actionBar.alpha = 0; + ppView.alpha = 0; + ppView.origin = {- kPlacePageWidth, self.topBound}; + [self.ownerView addSubview:ppView]; + + place_page_layout::animate(^{ + ppView.alpha = 1; + actionBar.alpha = 1; + ppView.minX = self.leftBound; + }); +} + +- (void)onClose +{ + auto ppView = self.placePageView; + place_page_layout::animate(^{ + ppView.maxX = 0; + ppView.alpha = 0; + },^{ + [self.placePageView removeFromSuperview]; + [self.actionBar removeFromSuperview]; + self.actionBar = nil; + [self.delegate shouldDestroyLayout]; + }); +} + +- (void)onScreenResize:(CGSize const &)size +{ + [self layoutPlacePage:self.placePageView.tableView.contentSize.height onScreen:size.height]; +} + +- (void)onUpdatePlacePageWithHeight:(CGFloat)height +{ + [self layoutPlacePage:height onScreen:self.ownerView.height]; +} + +- (void)onActionBarInit:(MWMPlacePageActionBar *)actionBar +{ + UIView * superview = self.placePageView; + self.actionBar = actionBar; + [superview addSubview:actionBar]; + actionBar.origin = {0., superview.height - actionBar.height}; +} + +- (void)setInitialTopBound:(CGFloat)topBound leftBound:(CGFloat)leftBound +{ + self.topBound = topBound; + self.leftBound = leftBound; +} + +- (void)updateLayoutWithTopBound:(CGFloat)topBound +{ + self.topBound = topBound; + [self layoutPlacePage:self.placePageView.tableView.contentSize.height onScreen:self.ownerView.height]; +} + +- (void)updateLayoutWithLeftBound:(CGFloat)leftBound +{ + self.leftBound = leftBound; + place_page_layout::animate(^{ + self.placePageView.minX = self.leftBound; + }); +} + +- (void)layoutPlacePage:(CGFloat)placePageHeight onScreen:(CGFloat)screenHeight +{ + BOOL const isPlacePageWithinScreen = [self isPlacePage:placePageHeight withinScreen:screenHeight]; + auto ppView = self.placePageView; + + place_page_layout::animate(^{ + ppView.minY = self.topBound; + }); + + ppView.height = [self actualPlacePageViewHeightWithPlacePageHeight:placePageHeight + screenHeight:screenHeight]; + + if (!ppView.tableView.scrollEnabled && !isPlacePageWithinScreen) + ppView.tableView.scrollEnabled = YES; +} + +- (CGFloat)actualPlacePageViewHeightWithPlacePageHeight:(CGFloat)placePageHeight + screenHeight:(CGFloat)screenHeight +{ + auto ppView = self.placePageView; + if ([self isPlacePage:placePageHeight withinScreen:screenHeight]) + return placePageHeight + ppView.top.height; + + return screenHeight - kBottomOffset - self.topBound + (ppView.tableView.scrollEnabled ? + self.actionBar.height : 0); +} + +- (BOOL)isPlacePage:(CGFloat)placePageHeight withinScreen:(CGFloat)screenHeight +{ + auto const placePageFullHeight = placePageHeight; + auto const availableSpace = screenHeight - self.topBound - kBottomOffset; + return availableSpace > placePageFullHeight; +} + +#pragma mark - Pan + +- (void)didPan:(UIPanGestureRecognizer *)pan +{ + MWMPPView * view = self.placePageView; + auto superview = view.superview; + + CGFloat const leftOffset = self.leftBound; + view.minX += [pan translationInView:superview].x; + view.minX = MIN(view.minX, leftOffset); + [pan setTranslation:CGPointZero inView:superview]; + + CGFloat const alpha = MAX(0.0, view.maxX) / (view.width + leftOffset); + view.alpha = alpha; + UIGestureRecognizerState const state = pan.state; + if (state == UIGestureRecognizerStateEnded || state == UIGestureRecognizerStateCancelled) + { + CGFloat constexpr designAlpha = 0.8; + if (alpha < designAlpha) + { + [self onClose]; + } + else + { + place_page_layout::animate(^{ + view.minX = leftOffset; + view.alpha = 1; + }); + } + } +} + +#pragma mark - Top and left bound + +- (CGFloat)topBound { return _topBound + kTopOffset; } +- (CGFloat)leftBound { return _leftBound + kLeftOffset; } + +@end diff --git a/iphone/Maps/Classes/MWMiPhoneLandscapePlacePage.h b/iphone/Maps/Classes/MWMiPhoneLandscapePlacePage.h deleted file mode 100644 index ed4b2eb618..0000000000 --- a/iphone/Maps/Classes/MWMiPhoneLandscapePlacePage.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MWMPlacePage.h" - -@interface MWMiPhoneLandscapePlacePage : MWMPlacePage - -@end diff --git a/iphone/Maps/Classes/MWMiPhoneLandscapePlacePage.mm b/iphone/Maps/Classes/MWMiPhoneLandscapePlacePage.mm deleted file mode 100644 index 75d5df3262..0000000000 --- a/iphone/Maps/Classes/MWMiPhoneLandscapePlacePage.mm +++ /dev/null @@ -1,183 +0,0 @@ -#import "Common.h" -#import "MWMBasePlacePageView.h" -#import "MWMiPhoneLandscapePlacePage.h" -#import "MWMPlacePage+Animation.h" -#import "MWMPlacePageActionBar.h" -#import "MWMPlacePageViewManager.h" -#import "MWMSpringAnimation.h" -#import "UIColor+MapsMeColor.h" - -#include "Framework.h" - -static CGFloat const kMaximumPlacePageWidth = 360.; -extern CGFloat const kBookmarkCellHeight; - -typedef NS_ENUM(NSUInteger, MWMiPhoneLandscapePlacePageState) -{ - MWMiPhoneLandscapePlacePageStateClosed, - MWMiPhoneLandscapePlacePageStateOpen -}; - -@interface MWMiPhoneLandscapePlacePage () - -@property (nonatomic) MWMiPhoneLandscapePlacePageState state; -@property (nonatomic) CGPoint targetPoint; -@property (nonatomic) CGFloat panVelocity; - -@end - -@implementation MWMiPhoneLandscapePlacePage - -- (void)configure -{ - [super configure]; - self.anchorImageView.backgroundColor = [UIColor white]; - self.anchorImageView.image = nil; - [self refresh]; - [self addPlacePageShadowToView:self.extendedPlacePageView offset:CGSizeMake(2.0, 4.0)]; - [self.extendedPlacePageView addSubview:self.actionBar]; - [self.manager addSubviews:@[self.extendedPlacePageView] withNavigationController:nil]; -} - -- (void)show -{ - if (self.state == MWMiPhoneLandscapePlacePageStateOpen) - return; - CGSize const size = self.extendedPlacePageView.superview.size; - CGFloat const height = MIN(size.width, size.height); - CGFloat const offset = MIN(height, kMaximumPlacePageWidth); - self.extendedPlacePageView.minX = -offset; - self.extendedPlacePageView.width = offset; - self.actionBar.width = offset; - self.actionBar.minX = 0.0; - self.state = MWMiPhoneLandscapePlacePageStateOpen; -} - -- (void)hide -{ - if (self.state == MWMiPhoneLandscapePlacePageStateClosed) - return; - self.state = MWMiPhoneLandscapePlacePageStateClosed; -} - -- (void)configureContentInset -{ - CGFloat const height = self.extendedPlacePageView.height - self.anchorImageView.height; - CGFloat const actionBarHeight = self.actionBar.height; - UITableView * featureTable = self.basePlacePageView.featureTable; - CGFloat const tableContentHeight = featureTable.contentSize.height; - CGFloat const headerViewHeight = self.basePlacePageView.ppPreview.height; - CGFloat const availableTableHeight = height - headerViewHeight - actionBarHeight; - CGFloat const externalHeight = tableContentHeight - availableTableHeight; - if (externalHeight > 0) - { - featureTable.contentInset = UIEdgeInsetsMake(0., 0., externalHeight, 0.); - featureTable.scrollEnabled = YES; - } - else - { - [featureTable setContentOffset:CGPointZero animated:YES]; - featureTable.scrollEnabled = NO; - } -} - -- (void)addBookmark -{ - [super addBookmark]; - [self refresh]; -} - -- (void)removeBookmark -{ - [super removeBookmark]; - [self refresh]; -} - -- (void)reloadBookmark -{ - [super reloadBookmark]; - [self refresh]; -} - -- (void)refresh -{ - [self configureContentInset]; -} - -- (void)updateTargetPoint -{ - CGSize const size = UIScreen.mainScreen.bounds.size; - CGFloat const height = MIN(size.width, size.height); - CGFloat const offset = MIN(height, kMaximumPlacePageWidth); - switch (self.state) - { - case MWMiPhoneLandscapePlacePageStateClosed: - self.targetPoint = CGPointMake(-offset / 2., (height + self.topBound) / 2.); - break; - case MWMiPhoneLandscapePlacePageStateOpen: - self.targetPoint = CGPointMake(offset / 2., (height + self.topBound) / 2.); - break; - } -} -#pragma mark - Actions - -- (IBAction)didPan:(UIPanGestureRecognizer *)sender -{ - UIView * ppv = self.extendedPlacePageView; - UIView * ppvSuper = ppv.superview; - ppv.midX = MIN(ppv.midX + [sender translationInView:ppvSuper].x, ppv.width / 2.0); - [sender setTranslation:CGPointZero inView:ppvSuper]; - [self cancelSpringAnimation]; - UIGestureRecognizerState const state = sender.state; - if (state == UIGestureRecognizerStateEnded || state == UIGestureRecognizerStateCancelled) - { - self.panVelocity = [sender velocityInView:ppvSuper].x; - self.state = self.panVelocity > 0 ? MWMiPhoneLandscapePlacePageStateOpen : MWMiPhoneLandscapePlacePageStateClosed; - [self updateTargetPoint]; - } -} - -#pragma mark - Properties - -- (void)setState:(MWMiPhoneLandscapePlacePageState)state -{ - if (_state == state) - return; - _state = state; - [self updateTargetPoint]; -} - -- (void)setTopBound:(CGFloat)topBound -{ - super.topBound = topBound; - CGRect const frame = self.extendedPlacePageView.frame; - CGSize const size = self.extendedPlacePageView.superview.size; - CGFloat const height = MIN(size.width, size.height) - topBound; - CGFloat const width = frame.size.width; - CGFloat const actionBarHeight = self.actionBar.height; - self.extendedPlacePageView.frame = {{frame.origin.x, topBound}, {width, height}}; - self.actionBar.frame = {{0, height - actionBarHeight}, {width, actionBarHeight}}; - if (self.state == MWMiPhoneLandscapePlacePageStateOpen) - [self updateTargetPoint]; - [self refresh]; -} - -- (void)setTargetPoint:(CGPoint)targetPoint -{ - _targetPoint = targetPoint; - __weak MWMiPhoneLandscapePlacePage * weakSelf = self; - BOOL const stateClosed = self.state == MWMiPhoneLandscapePlacePageStateClosed; - if (stateClosed) - GetFramework().DeactivateMapSelection(false); - - self.panRecognizer.enabled = !stateClosed; - [self startAnimatingPlacePage:self initialVelocity:CGPointMake(self.panVelocity, 0.0) completion:^ - { - __strong MWMiPhoneLandscapePlacePage * self = weakSelf; - if (stateClosed) - [self.manager dismissPlacePage]; - }]; - self.panVelocity = 0.0; -} - -@end diff --git a/iphone/Maps/Classes/MWMiPhonePlacePageLayoutImpl.h b/iphone/Maps/Classes/MWMiPhonePlacePageLayoutImpl.h new file mode 100644 index 0000000000..ea2797efff --- /dev/null +++ b/iphone/Maps/Classes/MWMiPhonePlacePageLayoutImpl.h @@ -0,0 +1,5 @@ +#import "MWMPlacePageLayoutImpl.h" + +@interface MWMiPhonePlacePageLayoutImpl : NSObject + +@end diff --git a/iphone/Maps/Classes/MWMiPhonePlacePageLayoutImpl.mm b/iphone/Maps/Classes/MWMiPhonePlacePageLayoutImpl.mm new file mode 100644 index 0000000000..cd9f37845b --- /dev/null +++ b/iphone/Maps/Classes/MWMiPhonePlacePageLayoutImpl.mm @@ -0,0 +1,281 @@ +#import "MWMPlacePageLayout.h" +#import "MWMiPhonePlacePageLayoutImpl.h" + +namespace +{ +enum class ScrollDirection +{ + Up, + Down +}; + +enum class State +{ + Bottom, + Top +}; + +// Minimal offset for collapse. If place page offset is below this value we should hide place page. +CGFloat const kMinOffset = 1; +CGFloat const kOpenPlacePageStopValue = 0.7; +CGFloat const kLuftDraggingOffset = 30; +} // namespace + +@interface MWMiPhonePlacePageLayoutImpl () + +@property(nonatomic) MWMPPScrollView * scrollView; +@property(nonatomic) ScrollDirection direction; +@property(nonatomic) State state; + +@property(nonatomic) CGFloat portraitOpenContentOffset; +@property(nonatomic) CGFloat landscapeOpenContentOffset; +@property(nonatomic) CGFloat lastContentOffset; +@property(nonatomic) CGFloat expandedContentOffset; + +@end + +@implementation MWMiPhonePlacePageLayoutImpl + +@synthesize ownerView = _ownerView; +@synthesize placePageView = _placePageView; +@synthesize delegate = _delegate; +@synthesize actionBar = _actionBar; + +- (instancetype)initOwnerView:(UIView *)ownerView + placePageView:(MWMPPView *)placePageView + delegate:(id)delegate +{ + self = [super init]; + if (self) + { + auto const & size = ownerView.size; + _ownerView = ownerView; + _placePageView = placePageView; + placePageView.tableView.delegate = self; + _delegate = delegate; + _scrollView = [[MWMPPScrollView alloc] initWithFrame:ownerView.frame inactiveView:placePageView]; + _scrollView.delegate = self; + _portraitOpenContentOffset = MAX(size.width, size.height) * kOpenPlacePageStopValue; + _landscapeOpenContentOffset = MIN(size.width, size.height) * kOpenPlacePageStopValue; + placePageView.frame = {{0, size.height}, size}; + [ownerView addSubview:self.scrollView]; + [_scrollView addSubview:placePageView]; + } + return self; +} + +- (void)onShow +{ + self.state = State::Bottom; + [self collapse]; +} + +- (void)onClose +{ + place_page_layout::animate(^{ + self.actionBar.minY = self.ownerView.height; + [self.scrollView setContentOffset:{} animated:YES]; + },^{ + [self.actionBar removeFromSuperview]; + self.actionBar = nil; + [self.delegate shouldDestroyLayout]; + }); +} + +- (void)onScreenResize:(CGSize const &)size +{ + self.scrollView.frame = {{}, size}; + self.placePageView.minY = size.height; + auto actionBar = self.actionBar; + actionBar.frame = {{0., size.height - actionBar.height}, + {size.width, actionBar.height}}; + [self.delegate onPlacePageTopBoundChanged:self.scrollView.contentOffset.y]; +} + +- (void)onUpdatePlacePageWithHeight:(CGFloat)height +{ + auto const & size = self.ownerView.size; + self.scrollView.contentSize = {size.width, size.height + self.placePageView.height}; +} + +- (void)onActionBarInit:(MWMPlacePageActionBar *)actionBar +{ + auto superview = self.ownerView; + self.actionBar = actionBar; + actionBar.minY = superview.height; + [superview addSubview:_actionBar]; +} + +- (void)onExpandWithPlacePagePreviewHeight:(CGFloat)height +{ + self.actionBar.hidden = NO; + self.scrollView.scrollEnabled = YES; + + place_page_layout::animate(^{ + auto ppView = self.placePageView; + [ppView hideTableView:NO]; + auto actionBar = self.actionBar; + actionBar.minY = actionBar.superview.height - actionBar.height; + + // We decrease expanded offset for 2 pixels because it looks more clear. + CGFloat constexpr designOffset = 2; + self.expandedContentOffset = height + actionBar.height - designOffset; + + auto const targetOffset = self.state == State::Bottom ? self.expandedContentOffset : self.topContentOffset; + [self.scrollView setContentOffset:{ 0, targetOffset } animated:YES]; + }); +} + +- (void)collapse +{ + self.scrollView.scrollEnabled = NO; + [self.placePageView hideTableView:YES]; + + place_page_layout::animate(^{ + [self.scrollView setContentOffset:{ 0., kMinOffset } animated:YES]; + }); +} + +#pragma mark - UIScrollViewDelegate + +- (BOOL)isPortrait +{ + auto const & s = self.ownerView.size; + return s.height > s.width; +} + +- (CGFloat)openContentOffset +{ + return self.isPortrait ? self.portraitOpenContentOffset : self.landscapeOpenContentOffset; +} + +- (CGFloat)topContentOffset +{ + auto const target = self.openContentOffset; + auto const ppView = self.placePageView; + return MIN(target, ppView.height); +} + +- (void)scrollViewDidScroll:(MWMPPScrollView *)scrollView +{ + auto ppView = self.placePageView; + if ([scrollView isEqual:ppView.tableView]) + return; + + auto const & offset = scrollView.contentOffset; + id delegate = self.delegate; + if (offset.y <= 0) + { + [self.scrollView removeFromSuperview]; + [self.actionBar removeFromSuperview]; + [delegate shouldDestroyLayout]; + return; + } + + if (offset.y > ppView.height + kLuftDraggingOffset) + { + auto const bounded = ppView.height + kLuftDraggingOffset; + [scrollView setContentOffset:{0, bounded}]; + [delegate onPlacePageTopBoundChanged:bounded]; + } + else + { + [delegate onPlacePageTopBoundChanged:offset.y]; + } + + self.direction = self.lastContentOffset < offset.y ? ScrollDirection::Up : ScrollDirection::Down; + self.lastContentOffset = offset.y; +} + +- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView + withVelocity:(CGPoint)velocity + targetContentOffset:(inout CGPoint *)targetContentOffset +{ + auto const actualOffset = scrollView.contentOffset.y; + auto const openOffset = self.openContentOffset; + auto const targetOffset = (*targetContentOffset).y; + + if (actualOffset > self.expandedContentOffset && actualOffset < openOffset) + { + auto const isDirectionUp = self.direction == ScrollDirection::Up; + self.state = isDirectionUp ? State::Top : State::Bottom; + (*targetContentOffset).y = isDirectionUp ? openOffset : self.expandedContentOffset; + } + else if (actualOffset > openOffset && targetOffset < openOffset) + { + self.state = State::Top; + (*targetContentOffset).y = openOffset; + } + else if (actualOffset < self.expandedContentOffset) + { + (*targetContentOffset).y = 0; + place_page_layout::animate(^{ + self.actionBar.minY = self.ownerView.height; + }); + } + else + { + self.state = State::Top; + } +} + +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate +{ + if (decelerate) + return; + + auto const actualOffset = scrollView.contentOffset.y; + auto const openOffset = self.openContentOffset; + + if (actualOffset < self.expandedContentOffset + kLuftDraggingOffset) + { + self.state = State::Bottom; + place_page_layout::animate(^{ + [scrollView setContentOffset:{ 0, self.expandedContentOffset } animated:YES]; + }); + } + else if (actualOffset < openOffset) + { + auto const isDirectionUp = self.direction == ScrollDirection::Up; + self.state = isDirectionUp ? State::Top : State::Bottom; + place_page_layout::animate(^{ + [scrollView setContentOffset:{0, isDirectionUp ? openOffset : self.expandedContentOffset} + animated:YES]; + }); + } + else + { + self.state = State::Top; + } +} + +- (void)setState:(State)state +{ + _state = state; + self.placePageView.anchorImage.transform = state == State::Top ? CGAffineTransformMakeRotation(M_PI) + : CGAffineTransformIdentity; +} + +#pragma mark - UITableViewDelegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (indexPath.section != 0) + return; + + CGFloat offset = 0; + if (self.state == State::Top) + { + self.state = State::Bottom; + offset = self.expandedContentOffset; + } + else + { + self.state = State::Top; + offset = self.topContentOffset; + } + place_page_layout::animate(^{ [self.scrollView setContentOffset:{0, offset} animated:YES]; }); +} + +@end + diff --git a/iphone/Maps/Classes/MWMiPhonePortraitPlacePage.h b/iphone/Maps/Classes/MWMiPhonePortraitPlacePage.h deleted file mode 100644 index 384e8e00a4..0000000000 --- a/iphone/Maps/Classes/MWMiPhonePortraitPlacePage.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MWMPlacePage.h" - -@interface MWMiPhonePortraitPlacePage : MWMPlacePage - -@end diff --git a/iphone/Maps/Classes/MWMiPhonePortraitPlacePage.mm b/iphone/Maps/Classes/MWMiPhonePortraitPlacePage.mm deleted file mode 100644 index f8d36a4415..0000000000 --- a/iphone/Maps/Classes/MWMiPhonePortraitPlacePage.mm +++ /dev/null @@ -1,332 +0,0 @@ -#import "Common.h" -#import "MapViewController.h" -#import "MWMBasePlacePageView.h" -#import "MWMiPhonePortraitPlacePage.h" -#import "MWMMapViewControlsManager.h" -#import "MWMPlacePage+Animation.h" -#import "MWMPlacePageActionBar.h" -#import "MWMPlacePageEntity.h" -#import "MWMPlacePageNavigationBar.h" -#import "MWMPlacePageViewManager.h" -#import "MWMSpringAnimation.h" -#import "UIImageView+Coloring.h" - -#include "Framework.h" - -typedef NS_ENUM(NSUInteger, MWMiPhonePortraitPlacePageState) -{ - MWMiPhonePortraitPlacePageStateClosed, - MWMiPhonePortraitPlacePageStatePreview, - MWMiPhonePortraitPlacePageStateOpen, - MWMiPhonePortraitPlacePageStateHover -}; - -@interface MWMiPhonePortraitPlacePage () - -@property (nonatomic) MWMiPhonePortraitPlacePageState state; -@property (nonatomic) CGPoint targetPoint; -@property (nonatomic) CGFloat panVelocity; -@property (nonatomic) BOOL isHover; - -@end - -@implementation MWMiPhonePortraitPlacePage - -- (void)configure -{ - [super configure]; - self.basePlacePageView.featureTable.scrollEnabled = NO; - CGSize const size = UIScreen.mainScreen.bounds.size; - CGFloat const width = MIN(size.width, size.height); - CGFloat const height = MAX(size.width, size.height); - UIView * ppv = self.extendedPlacePageView; - [self determineIfIsHover]; - ppv.frame = CGRectMake(0., height, width, 2 * height); - _targetPoint = ppv.center; - self.actionBar.width = width; - self.actionBar.center = {width / 2, height + self.actionBar.height / 2}; - [self.manager addSubviews:@[ppv, self.actionBar] withNavigationController:nil]; - [UIView animateWithDuration:kDefaultAnimationDuration delay:0. options:UIViewAnimationOptionCurveEaseOut animations:^ - { - self.actionBar.center = {width / 2, height - self.actionBar.height / 2}; - } - completion:nil]; -} - -- (void)determineIfIsHover -{ - CGSize const size = UIScreen.mainScreen.bounds.size; - CGFloat const height = MAX(size.width, size.height); - CGFloat const maximumY = height / 4.; - self.isHover = self.topY < maximumY; -} - -- (void)show -{ - self.state = MWMiPhonePortraitPlacePageStatePreview; -} - -- (void)hide -{ - self.state = MWMiPhonePortraitPlacePageStateClosed; -} - -- (void)dismiss -{ - [MWMPlacePageNavigationBar remove]; - [super dismiss]; -} - -- (void)addBookmark -{ - [super addBookmark]; - self.state = MWMiPhonePortraitPlacePageStateOpen; -} - -- (void)removeBookmark -{ - [super removeBookmark]; - self.state = MWMiPhonePortraitPlacePageStatePreview; -} - -- (void)reloadBookmark -{ - [super reloadBookmark]; - [self refresh]; -} - -- (void)updateMyPositionStatus:(NSString *)status -{ - [super updateMyPositionStatus:status]; - [self refresh]; -} - -- (void)refresh -{ - [self updateTargetPoint]; -} - -- (void)setState:(MWMiPhonePortraitPlacePageState)state -{ - _state = state; - [self refresh]; - switch (state) - { - case MWMiPhonePortraitPlacePageStateClosed: - [self.actionBar removeFromSuperview]; - [MWMPlacePageNavigationBar remove]; - break; - case MWMiPhonePortraitPlacePageStatePreview: - [MWMPlacePageNavigationBar remove]; - break; - case MWMiPhonePortraitPlacePageStateOpen: - case MWMiPhonePortraitPlacePageStateHover: - break; - } - [self setAnchorImage]; -} - -- (void)updateTargetPoint -{ - [self determineIfIsHover]; - UIView * ppv = self.extendedPlacePageView; - switch (self.state) - { - case MWMiPhonePortraitPlacePageStateClosed: - self.targetPoint = {ppv.width / 2, ppv.height * 2}; - break; - case MWMiPhonePortraitPlacePageStatePreview: - self.targetPoint = [self getPreviewTargetPoint]; - break; - case MWMiPhonePortraitPlacePageStateOpen: - self.targetPoint = [self getOpenTargetPoint]; - break; - case MWMiPhonePortraitPlacePageStateHover: - self.targetPoint = [self getHoverTargetPoint]; - break; - } -} - -- (CGPoint)getPreviewTargetPoint -{ - CGSize const size = UIScreen.mainScreen.bounds.size; - BOOL const isLandscape = size.width > size.height; - CGFloat const width = isLandscape ? size.height : size.width; - CGFloat const height = isLandscape ? size.width : size.height; - CGFloat const h = height - (self.topPlacePageHeight); - return {width / 2, height + h}; -} - -- (CGPoint)getOpenTargetPoint -{ - CGSize const size = UIScreen.mainScreen.bounds.size; - BOOL const isLandscape = size.width > size.height; - CGFloat const width = isLandscape ? size.height : size.width; - CGFloat const height = isLandscape ? size.width : size.height; - return {width / 2, height + self.topY}; -} - -- (CGPoint)getHoverTargetPoint -{ - CGSize const size = UIScreen.mainScreen.bounds.size; - CGFloat const height = size.height; - return {size.width / 2, height + height / 4}; -} - -- (CGFloat)topY -{ - MWMBasePlacePageView * basePPV = self.basePlacePageView; - CGSize const size = UIScreen.mainScreen.bounds.size; - CGFloat const height = MAX(size.width, size.height); - CGFloat const tableViewHeight = basePPV.featureTable.height; - return height - (self.topPlacePageHeight + tableViewHeight); -} - -- (CGFloat)topPlacePageHeight -{ - MWMBasePlacePageView * basePPV = self.basePlacePageView; - CGFloat const anchorHeight = self.anchorImageView.height; - CGFloat const actionBarHeight = self.actionBar.height; - return anchorHeight + basePPV.ppPreview.height + actionBarHeight - 1; -} - -#pragma mark - Actions - -- (IBAction)didPan:(UIPanGestureRecognizer *)sender -{ - UIView * ppv = self.extendedPlacePageView; - UIView * ppvSuper = ppv.superview; - - ppv.midY = MAX(ppv.midY + [sender translationInView:ppvSuper].y, [self getOpenTargetPoint].y); - _targetPoint = ppv.center; - if (ppv.minY <= 0.0) - [MWMPlacePageNavigationBar showNavigationBarForPlacePage:self]; - else - [MWMPlacePageNavigationBar dismissNavigationBar]; - [sender setTranslation:CGPointZero inView:ppvSuper]; - [self cancelSpringAnimation]; - UIGestureRecognizerState const state = sender.state; - if (state == UIGestureRecognizerStateEnded || state == UIGestureRecognizerStateCancelled) - { - self.panVelocity = [sender velocityInView:ppvSuper].y; - CGFloat const estimatedYPosition = [MWMSpringAnimation approxTargetFor:ppv.frame.origin.y velocity:self.panVelocity]; - CGFloat const bound1 = ppvSuper.height * 0.2; - CGFloat const bound2 = ppvSuper.height * (self.isHover ? 0.72 : 0.5); - - if (estimatedYPosition < bound1) - { - if (self.isHover) - { - if (self.state != MWMiPhonePortraitPlacePageStateHover) - self.state = MWMiPhonePortraitPlacePageStateHover; - } - else - { - self.state = MWMiPhonePortraitPlacePageStateOpen; - } - } - else if (self.panVelocity <= 0.0) - { - self.state = self.isHover ? MWMiPhonePortraitPlacePageStateHover : MWMiPhonePortraitPlacePageStateOpen; - } - else if (ppv.minY < bound2) - { - if (self.isHover && self.state == MWMiPhonePortraitPlacePageStateHover) - { - if (self.targetPoint.y > self.getHoverTargetPoint.y) - self.state = MWMiPhonePortraitPlacePageStatePreview; - } - else - { - self.state = MWMiPhonePortraitPlacePageStatePreview; - } - } - else - { - [self.manager dismissPlacePage]; - } - } -} - -- (IBAction)didTap:(UITapGestureRecognizer *)sender -{ - [super didTap:sender]; - switch (self.state) - { - case MWMiPhonePortraitPlacePageStateClosed: - self.state = MWMiPhonePortraitPlacePageStatePreview; - break; - case MWMiPhonePortraitPlacePageStatePreview: - self.state = self.isHover ? MWMiPhonePortraitPlacePageStateHover : MWMiPhonePortraitPlacePageStateOpen; - break; - case MWMiPhonePortraitPlacePageStateOpen: - self.state = MWMiPhonePortraitPlacePageStatePreview; - case MWMiPhonePortraitPlacePageStateHover: - if (!self.isHover) - { - self.state = MWMiPhonePortraitPlacePageStatePreview; - } - else - { - if (self.targetPoint.y < self.getHoverTargetPoint.y) - self.state = MWMiPhonePortraitPlacePageStateHover; - else - self.state = MWMiPhonePortraitPlacePageStatePreview; - } - break; - } -} - -- (void)setAnchorImage -{ - NSString * anchorImageName = nil; - switch (self.state) - { - case MWMiPhonePortraitPlacePageStateClosed: - break; - case MWMiPhonePortraitPlacePageStatePreview: - anchorImageName = @"bg_placepage_tablet_normal_"; - break; - case MWMiPhonePortraitPlacePageStateOpen: - case MWMiPhonePortraitPlacePageStateHover: - anchorImageName = @"bg_placepage_tablet_open_"; - break; - } - if (anchorImageName) - { - CGSize const size = UIScreen.mainScreen.bounds.size; - CGFloat const width = MIN(size.height, size.width); - self.anchorImageView.mwm_name = [anchorImageName stringByAppendingString:@((NSUInteger)width).stringValue]; - } -} - -#pragma mark - Properties - -- (void)setTargetPoint:(CGPoint)targetPoint -{ - if (CGPointEqualToPoint(_targetPoint, targetPoint)) - return; - _targetPoint = targetPoint; - __weak MWMiPhonePortraitPlacePage * weakSelf = self; - if (self.state == MWMiPhonePortraitPlacePageStateClosed) - GetFramework().DeactivateMapSelection(false); - - [self startAnimatingPlacePage:self initialVelocity:{0.0, self.panVelocity} completion:^ - { - __strong MWMiPhonePortraitPlacePage * self = weakSelf; - if (self.state == MWMiPhonePortraitPlacePageStateClosed) - { - [self.manager dismissPlacePage]; - } - else - { - if (self.extendedPlacePageView.minY <= 0.0) - [MWMPlacePageNavigationBar showNavigationBarForPlacePage:self]; - else - [MWMPlacePageNavigationBar dismissNavigationBar]; - } - }]; - self.panVelocity = 0.0; -} - -@end diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm index 060a7c3ff5..f71e9e3bb7 100644 --- a/iphone/Maps/Classes/MapViewController.mm +++ b/iphone/Maps/Classes/MapViewController.mm @@ -19,7 +19,6 @@ #import "MWMMapDownloaderViewController.h" #import "MWMMapViewControlsManager.h" #import "MWMPlacePageData.h" -#import "MWMPlacePageEntity.h" #import "MWMPlacePageProtocol.h" #import "MWMRouter.h" #import "MWMRouterSavedState.h" @@ -587,17 +586,6 @@ BOOL gIsFirstMyPositionMode = YES; MWMAuthorizationWebViewLoginViewController * dvc = segue.destinationViewController; dvc.authType = MWMWebViewAuthorizationTypeGoogle; } - else if ([segue.identifier isEqualToString:@"PP2BookmarkEditingIPAD"]) - { - UINavigationController * nav = segue.destinationViewController; - MWMEditBookmarkController * dvc = nav.viewControllers.firstObject; - dvc.manager = sender; - } - else if ([segue.identifier isEqualToString:@"PP2BookmarkEditing"]) - { - MWMEditBookmarkController * dvc = segue.destinationViewController; - dvc.manager = sender; - } } #pragma mark - Properties diff --git a/iphone/Maps/Classes/PlacePageBookmarkCell.xib b/iphone/Maps/Classes/PlacePageBookmarkCell.xib deleted file mode 100644 index 684449d1c5..0000000000 --- a/iphone/Maps/Classes/PlacePageBookmarkCell.xib +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/iphone/Maps/Classes/PlacePageNavigationBar.xib b/iphone/Maps/Classes/PlacePageNavigationBar.xib deleted file mode 100644 index 49efc607db..0000000000 --- a/iphone/Maps/Classes/PlacePageNavigationBar.xib +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/iphone/Maps/Classes/PlacePageView.xib b/iphone/Maps/Classes/PlacePageView.xib deleted file mode 100644 index 4be95a80ba..0000000000 --- a/iphone/Maps/Classes/PlacePageView.xib +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/iphone/Maps/Classes/Share/MWMShareActivityItem.mm b/iphone/Maps/Classes/Share/MWMShareActivityItem.mm index 10071719df..501114b89f 100644 --- a/iphone/Maps/Classes/Share/MWMShareActivityItem.mm +++ b/iphone/Maps/Classes/Share/MWMShareActivityItem.mm @@ -1,5 +1,4 @@ #import "MWMShareActivityItem.h" -#import "MWMPlacePageEntity.h" #import "Macros.h" #import "Statistics.h" diff --git a/iphone/Maps/Classes/_MWMOHSubCell.xib b/iphone/Maps/Classes/_MWMOHSubCell.xib index 912829519e..9ec1ac64e2 100644 --- a/iphone/Maps/Classes/_MWMOHSubCell.xib +++ b/iphone/Maps/Classes/_MWMOHSubCell.xib @@ -1,6 +1,7 @@ + @@ -11,7 +12,7 @@ - + - - - - - - - - - - - - + @@ -70,14 +60,10 @@ - - - - diff --git a/iphone/Maps/Classes/_MWMPPPAddress.xib b/iphone/Maps/Classes/_MWMPPPAddress.xib index 165f3091d5..f34e9f1869 100644 --- a/iphone/Maps/Classes/_MWMPPPAddress.xib +++ b/iphone/Maps/Classes/_MWMPPPAddress.xib @@ -9,11 +9,11 @@ - - + + - + - + - + @@ -84,7 +84,7 @@ - + diff --git a/iphone/Maps/Classes/_MWMPPPBooking.xib b/iphone/Maps/Classes/_MWMPPPBooking.xib index e79fa99db6..afc77b46e8 100644 --- a/iphone/Maps/Classes/_MWMPPPBooking.xib +++ b/iphone/Maps/Classes/_MWMPPPBooking.xib @@ -1,5 +1,5 @@ - - + + @@ -8,7 +8,7 @@ - + @@ -26,7 +26,7 @@ - +