Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
|
|
@ -0,0 +1,8 @@
|
|||
typedef NS_ENUM(NSInteger, MWMRouteManagerPointType) {
|
||||
MWMRouteManagerPointTypeStart,
|
||||
MWMRouteManagerPointTypeA,
|
||||
MWMRouteManagerPointTypeB,
|
||||
MWMRouteManagerPointTypeC,
|
||||
MWMRouteManagerPointTypeFinish,
|
||||
MWMRouteManagerPointTypeMyPosition
|
||||
};
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
final class RouteManagerCell: MWMTableViewCell {
|
||||
@IBOutlet private weak var typeImage: UIImageView!
|
||||
@IBOutlet private weak var titleLabel: UILabel!
|
||||
@IBOutlet weak var subtitleLabel: UILabel!
|
||||
@IBOutlet private weak var dragImage: UIImageView! {
|
||||
didSet {
|
||||
dragImage.image = #imageLiteral(resourceName: "ic_route_manager_move")
|
||||
dragImage.tintColor = UIColor.blackHintText()
|
||||
}
|
||||
}
|
||||
|
||||
@IBOutlet private weak var separator1: UIView! {
|
||||
didSet {
|
||||
separator1.layer.cornerRadius = 2
|
||||
}
|
||||
}
|
||||
|
||||
@IBOutlet weak var separator2: UIView!
|
||||
private var index: Int!
|
||||
private var model: MWMRoutePoint!
|
||||
@IBOutlet var subtitleConstraints: [NSLayoutConstraint]!
|
||||
|
||||
override var snapshot: UIView {
|
||||
let skipViews: [UIView] = [typeImage, separator1, separator2]
|
||||
skipViews.forEach { $0.isHidden = true }
|
||||
let snapshot = super.snapshot
|
||||
setStyle(.background)
|
||||
skipViews.forEach { $0.isHidden = false }
|
||||
return snapshot
|
||||
}
|
||||
|
||||
func set(model: MWMRoutePoint, atIndex index: Int) {
|
||||
self.model = model
|
||||
self.index = index
|
||||
|
||||
setupTypeImage()
|
||||
setupLabels()
|
||||
setupSeparators()
|
||||
}
|
||||
|
||||
private func setupTypeImage() {
|
||||
if model.isMyPosition && index == 0 {
|
||||
typeImage.image = #imageLiteral(resourceName: "ic_route_manager_my_position")
|
||||
typeImage.tintColor = UIColor.linkBlue()
|
||||
} else {
|
||||
switch model.type {
|
||||
case .start:
|
||||
typeImage.image = #imageLiteral(resourceName: "ic_route_manager_start")
|
||||
typeImage.tintColor = UIColor.linkBlue()
|
||||
case .intermediate:
|
||||
let i = model.intermediateIndex + 1
|
||||
// TODO: Properly support more than 20 icons.
|
||||
var iconName = "route-point-20"
|
||||
if (i >= 1 && i < 20) {
|
||||
iconName = "route-point-" + String(i)
|
||||
}
|
||||
typeImage.image = #imageLiteral(resourceName: iconName)
|
||||
typeImage.tintColor = UIColor.primary()
|
||||
case .finish:
|
||||
typeImage.image = #imageLiteral(resourceName: "ic_route_manager_finish")
|
||||
typeImage.tintColor = UIColor.blackPrimaryText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func setupLabels() {
|
||||
let subtitle: String?
|
||||
if model.isMyPosition && index != 0 {
|
||||
titleLabel.text = model.latLonString
|
||||
subtitle = model.title
|
||||
} else {
|
||||
titleLabel.text = model.title
|
||||
subtitle = model.subtitle
|
||||
}
|
||||
var subtitleConstraintsActive = false
|
||||
if let subtitle = subtitle, !subtitle.isEmpty {
|
||||
subtitleLabel.text = subtitle
|
||||
subtitleConstraintsActive = true
|
||||
}
|
||||
subtitleLabel.isHidden = !subtitleConstraintsActive
|
||||
subtitleConstraints.forEach { $0.isActive = subtitleConstraintsActive }
|
||||
}
|
||||
|
||||
private func setupSeparators() {
|
||||
let isSeparatorsHidden = model.type == .finish
|
||||
separator1.isHidden = isSeparatorsHidden
|
||||
separator2.isHidden = isSeparatorsHidden
|
||||
}
|
||||
|
||||
override func applyTheme() {
|
||||
super.applyTheme()
|
||||
self.setupTypeImage()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="KGk-i7-Jjw" customClass="RouteManagerCell" customModule="CoMaps" customModuleProvider="target" propertyAccessControl="none">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="66"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="66"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="We3-dE-JYe">
|
||||
<rect key="frame" x="16" y="21" width="24" height="24"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="We3-dE-JYe" secondAttribute="height" multiplier="1:1" id="LD8-kb-Haz"/>
|
||||
<constraint firstAttribute="width" constant="24" id="jtH-Dc-l1B"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="E8T-WR-b4P">
|
||||
<rect key="frame" x="60" y="12" width="212" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="regular16:blackPrimaryText"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ec0-Sc-NrV">
|
||||
<rect key="frame" x="60" y="36.5" width="212" height="17.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="regular16:blackSecondaryText"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="a6S-xz-wDs">
|
||||
<rect key="frame" x="280" y="21" width="24" height="24"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="24" id="4YZ-4p-E4H"/>
|
||||
<constraint firstAttribute="width" secondItem="a6S-xz-wDs" secondAttribute="height" multiplier="1:1" id="QCB-eE-cuO"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="e4S-qN-tx8">
|
||||
<rect key="frame" x="26" y="62" width="4" height="4"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="e4S-qN-tx8" secondAttribute="height" multiplier="1:1" id="Fec-Pg-5YG"/>
|
||||
<constraint firstAttribute="width" constant="4" id="bHk-pR-fsG"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="Divider"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="E4r-3f-9l2">
|
||||
<rect key="frame" x="60" y="65" width="260" height="1"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="iTg-i0-sIJ"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="Divider"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="a6S-xz-wDs" secondAttribute="trailing" constant="16" id="2b1-Ud-Ffh"/>
|
||||
<constraint firstItem="ec0-Sc-NrV" firstAttribute="leading" secondItem="E8T-WR-b4P" secondAttribute="leading" id="Bqj-Da-466"/>
|
||||
<constraint firstItem="E8T-WR-b4P" firstAttribute="leading" secondItem="We3-dE-JYe" secondAttribute="trailing" constant="20" id="Ezt-Qw-m9Q"/>
|
||||
<constraint firstAttribute="bottom" secondItem="ec0-Sc-NrV" secondAttribute="bottom" constant="12" id="OFV-X4-OWD"/>
|
||||
<constraint firstItem="E4r-3f-9l2" firstAttribute="leading" secondItem="E8T-WR-b4P" secondAttribute="leading" id="S3g-BB-Afo"/>
|
||||
<constraint firstItem="We3-dE-JYe" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="V68-v7-Y2a"/>
|
||||
<constraint firstAttribute="bottom" secondItem="e4S-qN-tx8" secondAttribute="bottom" id="Yah-Vt-8Jb"/>
|
||||
<constraint firstItem="ec0-Sc-NrV" firstAttribute="top" secondItem="E8T-WR-b4P" secondAttribute="bottom" constant="4" id="cbi-Y9-8Be"/>
|
||||
<constraint firstAttribute="bottom" secondItem="E4r-3f-9l2" secondAttribute="bottom" id="gFy-Bp-fJL"/>
|
||||
<constraint firstItem="ec0-Sc-NrV" firstAttribute="trailing" secondItem="E8T-WR-b4P" secondAttribute="trailing" id="jGc-UQ-TLl"/>
|
||||
<constraint firstItem="We3-dE-JYe" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="16" id="m1w-0i-ELt"/>
|
||||
<constraint firstItem="e4S-qN-tx8" firstAttribute="centerX" secondItem="We3-dE-JYe" secondAttribute="centerX" id="neB-SX-zce"/>
|
||||
<constraint firstItem="a6S-xz-wDs" firstAttribute="leading" secondItem="E8T-WR-b4P" secondAttribute="trailing" constant="8" id="q6T-54-sGO"/>
|
||||
<constraint firstAttribute="trailing" secondItem="E4r-3f-9l2" secondAttribute="trailing" id="s0v-JX-fRN"/>
|
||||
<constraint firstAttribute="bottom" secondItem="E8T-WR-b4P" secondAttribute="bottom" priority="500" constant="14" id="s4P-2g-gnj"/>
|
||||
<constraint firstItem="E8T-WR-b4P" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" priority="500" constant="14" id="uVb-l1-ce1"/>
|
||||
<constraint firstItem="E8T-WR-b4P" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="12" id="vdO-bJ-CRg"/>
|
||||
<constraint firstItem="a6S-xz-wDs" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="w85-cS-Uky"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<viewLayoutGuide key="safeArea" id="Kac-Pe-J2L"/>
|
||||
<connections>
|
||||
<outlet property="dragImage" destination="a6S-xz-wDs" id="zxX-KV-uIQ"/>
|
||||
<outlet property="separator1" destination="e4S-qN-tx8" id="tXc-oD-GpR"/>
|
||||
<outlet property="separator2" destination="E4r-3f-9l2" id="dVo-Qx-Nf1"/>
|
||||
<outlet property="subtitleLabel" destination="ec0-Sc-NrV" id="XfG-GI-QSP"/>
|
||||
<outlet property="titleLabel" destination="E8T-WR-b4P" id="hNR-bg-Aik"/>
|
||||
<outlet property="typeImage" destination="We3-dE-JYe" id="yzw-GT-nXU"/>
|
||||
<outletCollection property="subtitleConstraints" destination="vdO-bJ-CRg" collectionClass="NSMutableArray" id="YBl-7I-Qow"/>
|
||||
<outletCollection property="subtitleConstraints" destination="OFV-X4-OWD" collectionClass="NSMutableArray" id="0A7-Qz-hws"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="139" y="154"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
final class RouteManagerDimView: UIView {
|
||||
@IBOutlet private weak var image: UIImageView!
|
||||
@IBOutlet private weak var label: UILabel!
|
||||
@IBOutlet private weak var messageView: UIView!
|
||||
@IBOutlet private weak var messageViewContainer: UIView!
|
||||
@IBOutlet private var messageViewVerticalCenter: NSLayoutConstraint!
|
||||
@IBOutlet private var labelVerticalCenter: NSLayoutConstraint!
|
||||
|
||||
enum State {
|
||||
case visible
|
||||
case binOpenned
|
||||
case hidden
|
||||
}
|
||||
|
||||
var state = State.hidden {
|
||||
didSet {
|
||||
guard state != oldValue else { return }
|
||||
switch state {
|
||||
case .visible:
|
||||
isVisible = true
|
||||
image.image = #imageLiteral(resourceName: "ic_route_manager_trash")
|
||||
case .binOpenned:
|
||||
isVisible = true
|
||||
image.image = #imageLiteral(resourceName: "ic_route_manager_trash_open")
|
||||
case .hidden:
|
||||
isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var binDropPoint: CGPoint {
|
||||
return convert(image.isHidden ? label.center : image.center, from: messageView)
|
||||
}
|
||||
|
||||
private var isVisible = false {
|
||||
didSet {
|
||||
guard isVisible != oldValue else { return }
|
||||
let componentsAlpha: CGFloat = 0.5
|
||||
setStyle(.blackStatusBarBackground)
|
||||
alpha = isVisible ? 0 : 1
|
||||
image.alpha = isVisible ? 0 : componentsAlpha
|
||||
label.alpha = isVisible ? 0 : componentsAlpha
|
||||
UIView.animate(withDuration: kDefaultAnimationDuration,
|
||||
animations: {
|
||||
self.alpha = self.isVisible ? 1 : 0
|
||||
self.image.alpha = self.isVisible ? componentsAlpha : 0
|
||||
self.label.alpha = self.isVisible ? componentsAlpha : 0
|
||||
},
|
||||
completion: { _ in
|
||||
self.alpha = 1
|
||||
if !self.isVisible {
|
||||
self.backgroundColor = UIColor.clear
|
||||
}
|
||||
})
|
||||
setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
func setViews(container: UIView, controller: UIView, manager: UIView) {
|
||||
alpha = 0
|
||||
|
||||
alternative(iPhone: {
|
||||
controller.insertSubview(self, at: 0)
|
||||
|
||||
NSLayoutConstraint(item: self, attribute: .left, relatedBy: .equal, toItem: self.messageViewContainer, attribute: .left, multiplier: 1, constant: 0).isActive = true
|
||||
NSLayoutConstraint(item: manager, attribute: .top, relatedBy: .equal, toItem: self.messageViewContainer, attribute: .bottom, multiplier: 1, constant: 0).isActive = true
|
||||
},
|
||||
iPad: {
|
||||
container.insertSubview(self, at: 0)
|
||||
|
||||
NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: self.messageViewContainer, attribute: .bottom, multiplier: 1, constant: 0).isActive = true
|
||||
NSLayoutConstraint(item: controller, attribute: .right, relatedBy: .equal, toItem: self.messageViewContainer, attribute: .left, multiplier: 1, constant: 0).isActive = true
|
||||
})()
|
||||
|
||||
NSLayoutConstraint(item: container, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0).isActive = true
|
||||
NSLayoutConstraint(item: container, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0).isActive = true
|
||||
NSLayoutConstraint(item: container, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1, constant: 0).isActive = true
|
||||
NSLayoutConstraint(item: container, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1, constant: 0).isActive = true
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
let isImageHidden = messageView.height > messageViewContainer.height
|
||||
image.isHidden = isImageHidden
|
||||
messageViewVerticalCenter.isActive = !isImageHidden
|
||||
labelVerticalCenter.isActive = isImageHidden
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
final class RouteManagerFooterView: UIView {
|
||||
@IBOutlet private weak var cancelButton: UIButton!
|
||||
@IBOutlet private weak var planButton: UIButton!
|
||||
@IBOutlet weak var separator: UIView!
|
||||
@IBOutlet weak var background: UIView!
|
||||
var isPlanButtonEnabled = true {
|
||||
didSet {
|
||||
planButton.isEnabled = isPlanButtonEnabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
final class RouteManagerHeaderView: UIView {
|
||||
@IBOutlet private weak var titleLabel: UILabel!
|
||||
@IBOutlet private weak var addLocationButton: UIButton! {
|
||||
didSet {
|
||||
// TODO(igrechuhin): Uncomment when start_from_my_position translation is ready.
|
||||
// addLocationButton.setTitle(L("start_from_my_position"), for: .normal)
|
||||
// addLocationButton.setTitleColor(UIColor.linkBlue(), for: .normal)
|
||||
// addLocationButton.setTitleColor(UIColor.buttonDisabledBlueText(), for: .disabled)
|
||||
// addLocationButton.tintColor = UIColor.linkBlue()
|
||||
//
|
||||
// let flipLR = CGAffineTransform(scaleX: -1.0, y: 1.0)
|
||||
// addLocationButton.transform = flipLR
|
||||
// addLocationButton.titleLabel?.transform = flipLR
|
||||
// addLocationButton.imageView?.transform = flipLR
|
||||
}
|
||||
}
|
||||
@IBOutlet weak var separator: UIView!
|
||||
|
||||
var isLocationButtonEnabled = true {
|
||||
didSet {
|
||||
addLocationButton.isEnabled = isLocationButtonEnabled
|
||||
addLocationButton.tintColor = isLocationButtonEnabled ? UIColor.linkBlue() : UIColor.buttonDisabledBlueText()
|
||||
}
|
||||
}
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
}
|
||||
|
||||
override func applyTheme() {
|
||||
super.applyTheme()
|
||||
addLocationButton.tintColor = isLocationButtonEnabled ? UIColor.linkBlue() : UIColor.buttonDisabledBlueText()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
final class RouteManagerPresentationController: UIPresentationController {
|
||||
override func containerViewWillLayoutSubviews() {
|
||||
super.containerViewWillLayoutSubviews()
|
||||
(presentedViewController as? RouteManagerViewController)?.chromeView.frame = containerView!.bounds
|
||||
presentedView?.frame = frameOfPresentedViewInContainerView
|
||||
}
|
||||
|
||||
override func presentationTransitionWillBegin() {
|
||||
super.presentationTransitionWillBegin()
|
||||
guard let presentedViewController = presentedViewController as? RouteManagerViewController,
|
||||
let coordinator = presentedViewController.transitionCoordinator,
|
||||
let containerView = containerView else { return }
|
||||
|
||||
containerView.addSubview(presentedView!)
|
||||
presentedViewController.containerView = containerView
|
||||
presentedViewController.chromeView.frame = containerView.bounds
|
||||
presentedViewController.chromeView.alpha = 0
|
||||
|
||||
coordinator.animate(alongsideTransition: { _ in
|
||||
presentedViewController.chromeView.alpha = 1
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
override func dismissalTransitionWillBegin() {
|
||||
super.dismissalTransitionWillBegin()
|
||||
guard let presentedViewController = presentedViewController as? RouteManagerViewController,
|
||||
let coordinator = presentedViewController.transitionCoordinator,
|
||||
let presentedView = presentedView else { return }
|
||||
|
||||
coordinator.animate(alongsideTransition: { _ in
|
||||
presentedViewController.chromeView.alpha = 0
|
||||
}, completion: { _ in
|
||||
presentedView.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
final class RouteManagerTableView: UITableView {
|
||||
@IBOutlet private weak var tableViewHeight: NSLayoutConstraint!
|
||||
|
||||
enum HeightUpdateStyle {
|
||||
case animated
|
||||
case deferred
|
||||
case off
|
||||
}
|
||||
|
||||
var heightUpdateStyle = HeightUpdateStyle.deferred
|
||||
|
||||
private var scheduledUpdate: DispatchWorkItem?
|
||||
|
||||
override var contentSize: CGSize {
|
||||
didSet {
|
||||
guard contentSize != oldValue else { return }
|
||||
scheduledUpdate?.cancel()
|
||||
let update = { [weak self] in
|
||||
guard let s = self else { return }
|
||||
s.tableViewHeight.constant = s.contentSize.height
|
||||
}
|
||||
switch heightUpdateStyle {
|
||||
case .animated: superview?.animateConstraints(animations: update)
|
||||
case .deferred:
|
||||
scheduledUpdate = DispatchWorkItem(block: update)
|
||||
DispatchQueue.main.async(execute: scheduledUpdate!)
|
||||
case .off: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
final class RouteManagerTransitioning: NSObject, UIViewControllerAnimatedTransitioning {
|
||||
private let isPresentation: Bool
|
||||
|
||||
init(isPresentation: Bool) {
|
||||
self.isPresentation = isPresentation
|
||||
super.init()
|
||||
}
|
||||
|
||||
func transitionDuration(using _: UIViewControllerContextTransitioning?) -> TimeInterval {
|
||||
return kDefaultAnimationDuration
|
||||
}
|
||||
|
||||
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
|
||||
guard let fromVC = transitionContext.viewController(forKey: .from),
|
||||
let toVC = transitionContext.viewController(forKey: .to) else { return }
|
||||
|
||||
let animatingVC = isPresentation ? toVC : fromVC
|
||||
guard let animatingView = animatingVC.view else { return }
|
||||
|
||||
let finalFrameForVC = transitionContext.finalFrame(for: animatingVC)
|
||||
var initialFrameForVC = finalFrameForVC
|
||||
initialFrameForVC.origin.y += initialFrameForVC.size.height
|
||||
|
||||
let initialFrame = isPresentation ? initialFrameForVC : finalFrameForVC
|
||||
let finalFrame = isPresentation ? finalFrameForVC : initialFrameForVC
|
||||
|
||||
animatingView.frame = initialFrame
|
||||
|
||||
UIView.animate(withDuration: transitionDuration(using: transitionContext),
|
||||
animations: { animatingView.frame = finalFrame },
|
||||
completion: { _ in
|
||||
transitionContext.completeTransition(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
@objc(MWMRouteManagerTransitioningManager)
|
||||
final class RouteManagerTransitioningManager: NSObject, UIViewControllerTransitioningDelegate {
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source _: UIViewController) -> UIPresentationController? {
|
||||
RouteManagerPresentationController(presentedViewController: presented,
|
||||
presenting: presenting)
|
||||
}
|
||||
|
||||
func animationController(forPresented _: UIViewController, presenting _: UIViewController, source _: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
return RouteManagerTransitioning(isPresentation: true)
|
||||
}
|
||||
|
||||
func animationController(forDismissed _: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
return RouteManagerTransitioning(isPresentation: false)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
@objc(MWMRouteManagerViewController)
|
||||
final class RouteManagerViewController: MWMViewController, UITableViewDataSource, UITableViewDelegate {
|
||||
let viewModel: RouteManagerViewModelProtocol
|
||||
|
||||
@IBOutlet private var dimView: RouteManagerDimView!
|
||||
@IBOutlet private weak var footerViewHeight: NSLayoutConstraint!
|
||||
@IBOutlet private weak var headerView: RouteManagerHeaderView!
|
||||
@IBOutlet private weak var footerView: RouteManagerFooterView!
|
||||
@IBOutlet private weak var headerViewHeight: NSLayoutConstraint!
|
||||
@IBOutlet private weak var managerView: UIView!
|
||||
@IBOutlet private weak var managerWidth: NSLayoutConstraint!
|
||||
@IBOutlet private weak var minManagerTopOffset: NSLayoutConstraint!
|
||||
@IBOutlet private weak var tableView: RouteManagerTableView!
|
||||
|
||||
lazy var chromeView: UIView = {
|
||||
let view = UIView()
|
||||
view.setStyle(.blackStatusBarBackground)
|
||||
return view
|
||||
}()
|
||||
|
||||
weak var containerView: UIView!
|
||||
|
||||
private var canDeleteRow: Bool { return viewModel.routePoints.count > 2 }
|
||||
|
||||
final class DragCell {
|
||||
weak var controller: RouteManagerViewController!
|
||||
let snapshot: UIView
|
||||
var indexPath: IndexPath
|
||||
|
||||
init(controller: RouteManagerViewController, cell: UITableViewCell, dragPoint: CGPoint, indexPath: IndexPath) {
|
||||
self.controller = controller
|
||||
snapshot = cell.snapshot
|
||||
self.indexPath = indexPath
|
||||
addSubView(cell: cell, dragPoint: dragPoint)
|
||||
controller.tableView.heightUpdateStyle = .off
|
||||
if controller.canDeleteRow {
|
||||
controller.dimView.state = .visible
|
||||
}
|
||||
}
|
||||
|
||||
private func addSubView(cell: UITableViewCell, dragPoint: CGPoint) {
|
||||
let view = controller.containerView!
|
||||
view.addSubview(snapshot)
|
||||
snapshot.center = view.convert(cell.center, from: controller.tableView)
|
||||
cell.isHidden = true
|
||||
UIView.animate(withDuration: kDefaultAnimationDuration,
|
||||
animations: { [snapshot] in
|
||||
snapshot.center = dragPoint
|
||||
let scaleFactor: CGFloat = 1.05
|
||||
snapshot.transform = CGAffineTransform(scaleX: scaleFactor, y: scaleFactor)
|
||||
})
|
||||
}
|
||||
|
||||
func move(dragPoint: CGPoint, indexPath: IndexPath?, inManagerView: Bool) {
|
||||
snapshot.center = dragPoint
|
||||
if controller.canDeleteRow {
|
||||
controller.dimView.state = inManagerView ? .visible : .binOpenned
|
||||
}
|
||||
guard let newIP = indexPath else { return }
|
||||
let tv = controller.tableView!
|
||||
let cell = tv.cellForRow(at: newIP)
|
||||
let canMoveCell: Bool
|
||||
if let cell = cell {
|
||||
let (centerX, centerY) = (snapshot.width / 2, snapshot.height / 2)
|
||||
canMoveCell = cell.point(inside: cell.convert(CGPoint(x: centerX, y: 1.5 * centerY), from: snapshot), with: nil) &&
|
||||
cell.point(inside: cell.convert(CGPoint(x: centerX, y: 0.5 * centerY), from: snapshot), with: nil)
|
||||
} else {
|
||||
canMoveCell = true
|
||||
}
|
||||
guard canMoveCell else { return }
|
||||
let currentIP = self.indexPath
|
||||
if newIP != currentIP {
|
||||
let (currentRow, newRow) = (currentIP.row, newIP.row)
|
||||
controller.viewModel.movePoint(at: currentRow, to: newRow)
|
||||
|
||||
tv.moveRow(at: currentIP, to: newIP)
|
||||
let reloadRows = (min(currentRow, newRow) ... max(currentRow, newRow)).map { IndexPath(row: $0, section: 0) }
|
||||
tv.reloadRows(at: reloadRows, with: .fade)
|
||||
tv.cellForRow(at: newIP)?.isHidden = true
|
||||
|
||||
self.indexPath = newIP
|
||||
}
|
||||
}
|
||||
|
||||
func drop(inManagerView: Bool) {
|
||||
let removeSnapshot = {
|
||||
self.snapshot.removeFromSuperview()
|
||||
self.controller.dimView.state = .hidden
|
||||
}
|
||||
let containerView = controller.containerView!
|
||||
let tv = controller.tableView!
|
||||
if inManagerView || !controller.canDeleteRow {
|
||||
let dropCenter = tv.cellForRow(at: indexPath)?.center ?? snapshot.center
|
||||
UIView.animate(withDuration: kDefaultAnimationDuration,
|
||||
animations: { [snapshot] in
|
||||
snapshot.center = containerView.convert(dropCenter, from: tv)
|
||||
snapshot.transform = CGAffineTransform.identity
|
||||
},
|
||||
completion: { [indexPath] _ in
|
||||
tv.reloadRows(at: [indexPath], with: .none)
|
||||
removeSnapshot()
|
||||
})
|
||||
} else {
|
||||
tv.heightUpdateStyle = .animated
|
||||
tv.update {
|
||||
controller.viewModel.deletePoint(at: indexPath.row)
|
||||
tv.deleteRows(at: [indexPath], with: .automatic)
|
||||
}
|
||||
let dimView = controller.dimView!
|
||||
UIView.animate(withDuration: kDefaultAnimationDuration,
|
||||
animations: { [snapshot] in
|
||||
snapshot.center = containerView.convert(dimView.binDropPoint, from: dimView)
|
||||
let scaleFactor: CGFloat = 0.2
|
||||
snapshot.transform = CGAffineTransform(scaleX: scaleFactor, y: scaleFactor)
|
||||
},
|
||||
completion: { _ in
|
||||
removeSnapshot()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
controller.tableView.heightUpdateStyle = .deferred
|
||||
}
|
||||
}
|
||||
|
||||
var dragCell: DragCell?
|
||||
|
||||
@objc init(viewModel: RouteManagerViewModelProtocol) {
|
||||
self.viewModel = viewModel
|
||||
super.init(nibName: toString(type(of: self)), bundle: nil)
|
||||
}
|
||||
|
||||
required init?(coder _: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setupTableView()
|
||||
setupLayout()
|
||||
|
||||
viewModel.refreshControlsCallback = { [unowned viewModel, unowned self] in
|
||||
let points = viewModel.routePoints
|
||||
self.footerView.isPlanButtonEnabled = points.count >= 2
|
||||
self.headerView.isLocationButtonEnabled = true
|
||||
points.forEach {
|
||||
if $0.isMyPosition {
|
||||
self.headerView.isLocationButtonEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
viewModel.refreshControlsCallback()
|
||||
|
||||
viewModel.reloadCallback = { [tableView] in
|
||||
tableView?.reloadSections(IndexSet(integer: 0), with: .fade)
|
||||
}
|
||||
|
||||
viewModel.startTransaction()
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
dimView.setViews(container: containerView, controller: view, manager: managerView)
|
||||
containerView.insertSubview(chromeView, at: 0)
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
}
|
||||
|
||||
override func viewWillLayoutSubviews() {
|
||||
super.viewWillLayoutSubviews()
|
||||
if preferredContentSize != managerView.size {
|
||||
preferredContentSize = managerView.size
|
||||
}
|
||||
}
|
||||
|
||||
private func setupLayout() {
|
||||
alternative(iPhone: { self.managerWidth.isActive = false },
|
||||
iPad: { self.minManagerTopOffset.isActive = false })()
|
||||
}
|
||||
|
||||
private func setupTableView() {
|
||||
tableView.registerNib(cellClass: RouteManagerCell.self)
|
||||
tableView.estimatedRowHeight = 48
|
||||
tableView.rowHeight = UITableView.automaticDimension
|
||||
}
|
||||
|
||||
@IBAction func onCancel() {
|
||||
viewModel.cancelTransaction()
|
||||
dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@IBAction func onPlan() {
|
||||
viewModel.finishTransaction()
|
||||
dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@IBAction func onAdd() {
|
||||
viewModel.addLocationPoint()
|
||||
tableView.heightUpdateStyle = .off
|
||||
tableView.update({
|
||||
tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .fade)
|
||||
}, completion: {
|
||||
self.tableView.heightUpdateStyle = .deferred
|
||||
})
|
||||
}
|
||||
|
||||
@IBAction private func gestureRecognized(_ longPress: UIGestureRecognizer) {
|
||||
let locationInView = gestureLocation(longPress, in: containerView)
|
||||
let locationInTableView = gestureLocation(longPress, in: tableView)
|
||||
switch longPress.state {
|
||||
case .began:
|
||||
guard let indexPath = tableView.indexPathForRow(at: locationInTableView),
|
||||
let cell = tableView.cellForRow(at: indexPath) else { return }
|
||||
dragCell = DragCell(controller: self, cell: cell, dragPoint: locationInView, indexPath: indexPath)
|
||||
case .changed:
|
||||
guard let dragCell = dragCell else { return }
|
||||
let indexPath = tableView.indexPathForRow(at: locationInTableView)
|
||||
let inManagerView = managerView.point(inside: gestureLocation(longPress, in: managerView), with: nil)
|
||||
dragCell.move(dragPoint: locationInView, indexPath: indexPath, inManagerView: inManagerView)
|
||||
default:
|
||||
guard let dragCell = dragCell else { return }
|
||||
let inManagerView = managerView.point(inside: gestureLocation(longPress, in: managerView), with: nil)
|
||||
dragCell.drop(inManagerView: inManagerView)
|
||||
self.dragCell = nil
|
||||
}
|
||||
}
|
||||
|
||||
private func gestureLocation(_ gestureRecognizer: UIGestureRecognizer, in view: UIView) -> CGPoint {
|
||||
var location = gestureRecognizer.location(in: view)
|
||||
iPhoneSpecific { location.x = view.width / 2 }
|
||||
return location
|
||||
}
|
||||
|
||||
// MARK: - UITableViewDataSource
|
||||
func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
|
||||
return viewModel.routePoints.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withCellClass: RouteManagerCell.self, indexPath: indexPath) as! RouteManagerCell
|
||||
let row = indexPath.row
|
||||
cell.set(model: viewModel.routePoints[row], atIndex: row)
|
||||
return cell
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, commit _: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
|
||||
viewModel.deletePoint(at: indexPath.row)
|
||||
}
|
||||
|
||||
// MARK: - UITableViewDelegate
|
||||
func tableView(_: UITableView, editingStyleForRowAt _: IndexPath) -> UITableViewCell.EditingStyle {
|
||||
return canDeleteRow ? .delete : .none
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,293 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MWMRouteManagerViewController">
|
||||
<connections>
|
||||
<outlet property="dimView" destination="3y4-jh-JUF" id="Eto-KX-XRu"/>
|
||||
<outlet property="footerView" destination="mqc-M4-MPb" id="8im-uy-Rgm"/>
|
||||
<outlet property="footerViewHeight" destination="1qG-Md-L9w" id="ffF-cw-Lp0"/>
|
||||
<outlet property="headerView" destination="s0L-ul-gog" id="X5t-Xe-g5Y"/>
|
||||
<outlet property="headerViewHeight" destination="e4y-UI-hxr" id="ERb-fS-AcU"/>
|
||||
<outlet property="managerView" destination="i5M-Pr-FkT" id="zz4-k2-Tf1"/>
|
||||
<outlet property="managerWidth" destination="6Nm-Md-fZo" id="7X5-IX-4cy"/>
|
||||
<outlet property="minManagerTopOffset" destination="sYB-lu-PhM" id="C8h-tU-enB"/>
|
||||
<outlet property="tableView" destination="Zqd-YQ-ksD" id="ROT-An-z3D"/>
|
||||
<outlet property="view" destination="TKX-qe-h4F" id="ORc-Ju-S5N"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3y4-jh-JUF" customClass="RouteManagerDimView" customModule="CoMaps" customModuleProvider="target" propertyAccessControl="none">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<subviews>
|
||||
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TC7-xW-EwE">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kTd-fr-ia7">
|
||||
<rect key="frame" x="186" y="380" width="42" height="136.5"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ic_route_manager_trash" translatesAutoresizingMaskIntoConstraints="NO" id="ZEN-kK-2CA">
|
||||
<rect key="frame" x="-3" y="40" width="48" height="48"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="48" id="QJJ-DB-WF7"/>
|
||||
<constraint firstAttribute="width" secondItem="ZEN-kK-2CA" secondAttribute="height" multiplier="1:1" id="YdZ-dM-iEr"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" alpha="0.0" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1ks-iR-Wia">
|
||||
<rect key="frame" x="0.0" y="96" width="42" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="regular18:whiteText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="planning_route_remove_title"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="MessageView"/>
|
||||
<constraints>
|
||||
<constraint firstItem="1ks-iR-Wia" firstAttribute="leading" secondItem="kTd-fr-ia7" secondAttribute="leading" id="OZ4-Jc-PiA"/>
|
||||
<constraint firstAttribute="bottom" secondItem="1ks-iR-Wia" secondAttribute="bottom" constant="20" id="PXJ-Xl-pHA"/>
|
||||
<constraint firstItem="1ks-iR-Wia" firstAttribute="top" secondItem="ZEN-kK-2CA" secondAttribute="bottom" constant="8" id="iOV-1C-4Ak"/>
|
||||
<constraint firstItem="ZEN-kK-2CA" firstAttribute="top" secondItem="kTd-fr-ia7" secondAttribute="top" constant="40" id="jma-ai-kFd"/>
|
||||
<constraint firstItem="ZEN-kK-2CA" firstAttribute="centerX" secondItem="kTd-fr-ia7" secondAttribute="centerX" id="kue-ke-ivS"/>
|
||||
<constraint firstAttribute="trailing" secondItem="1ks-iR-Wia" secondAttribute="trailing" id="oTF-hI-m7B"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="MessageContainerView"/>
|
||||
<constraints>
|
||||
<constraint firstItem="kTd-fr-ia7" firstAttribute="centerX" secondItem="TC7-xW-EwE" secondAttribute="centerX" id="3Xc-xT-Z2O"/>
|
||||
<constraint firstItem="kTd-fr-ia7" firstAttribute="centerY" secondItem="TC7-xW-EwE" secondAttribute="centerY" priority="700" id="EcF-uM-iaP"/>
|
||||
<constraint firstItem="1ks-iR-Wia" firstAttribute="centerY" secondItem="TC7-xW-EwE" secondAttribute="centerY" priority="600" id="F2s-Or-gaN"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="72" id="niX-df-uVo"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="DimView"/>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="TC7-xW-EwE" secondAttribute="bottom" placeholder="YES" id="2x4-NF-KU5"/>
|
||||
<constraint firstItem="TC7-xW-EwE" firstAttribute="leading" secondItem="3y4-jh-JUF" secondAttribute="leading" placeholder="YES" id="D86-wV-E74"/>
|
||||
<constraint firstAttribute="trailing" secondItem="TC7-xW-EwE" secondAttribute="trailing" id="kvp-My-OQZ"/>
|
||||
<constraint firstItem="TC7-xW-EwE" firstAttribute="top" secondItem="3y4-jh-JUF" secondAttribute="top" id="lfE-MZ-Cvp"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="aNC-Xj-cAv"/>
|
||||
<connections>
|
||||
<outlet property="image" destination="ZEN-kK-2CA" id="zkv-Ag-qOp"/>
|
||||
<outlet property="label" destination="1ks-iR-Wia" id="jsa-mi-iZ2"/>
|
||||
<outlet property="labelVerticalCenter" destination="F2s-Or-gaN" id="Ztj-AC-Re4"/>
|
||||
<outlet property="messageView" destination="kTd-fr-ia7" id="dq4-iL-VA4"/>
|
||||
<outlet property="messageViewContainer" destination="TC7-xW-EwE" id="gfd-5J-Tc3"/>
|
||||
<outlet property="messageViewVerticalCenter" destination="EcF-uM-iaP" id="zyb-VY-6pA"/>
|
||||
<outletCollection property="gestureRecognizers" destination="deN-Z9-rbS" appends="YES" id="Mcr-eR-ObL"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="288" y="-49"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" id="TKX-qe-h4F" propertyAccessControl="none">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="i5M-Pr-FkT">
|
||||
<rect key="frame" x="0.0" y="758" width="414" height="138"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s0L-ul-gog" customClass="RouteManagerHeaderView" customModule="CoMaps" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="48"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="760" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dQh-uc-65J">
|
||||
<rect key="frame" x="16" y="14" width="42" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="bold22:blackPrimaryText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="planning_route_manage_route"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0Fo-Ae-QrQ">
|
||||
<rect key="frame" x="370" y="0.0" width="28" height="48"/>
|
||||
<inset key="contentEdgeInsets" minX="8" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="-8" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<state key="normal" image="ic_get_position"/>
|
||||
<connections>
|
||||
<action selector="onAdd" destination="-1" eventType="touchUpInside" id="zGx-NU-Hzq"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MJB-bK-y5c">
|
||||
<rect key="frame" x="16" y="47" width="398" height="1"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="aOa-8P-yGw"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="Divider"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="MJB-bK-y5c" firstAttribute="leading" secondItem="s0L-ul-gog" secondAttribute="leading" constant="16" id="0en-v6-Ij2"/>
|
||||
<constraint firstItem="0Fo-Ae-QrQ" firstAttribute="top" secondItem="s0L-ul-gog" secondAttribute="top" id="8Bf-WP-AF2"/>
|
||||
<constraint firstAttribute="bottom" secondItem="0Fo-Ae-QrQ" secondAttribute="bottom" id="BjQ-l3-bKd"/>
|
||||
<constraint firstAttribute="trailing" secondItem="MJB-bK-y5c" secondAttribute="trailing" id="F3U-0x-OCM"/>
|
||||
<constraint firstItem="dQh-uc-65J" firstAttribute="centerY" secondItem="s0L-ul-gog" secondAttribute="centerY" id="GNV-n4-tfI"/>
|
||||
<constraint firstItem="0Fo-Ae-QrQ" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="dQh-uc-65J" secondAttribute="trailing" constant="8" id="Zke-bf-VcT"/>
|
||||
<constraint firstAttribute="height" constant="48" id="e4y-UI-hxr"/>
|
||||
<constraint firstAttribute="bottom" secondItem="MJB-bK-y5c" secondAttribute="bottom" id="qQD-HE-tWa"/>
|
||||
<constraint firstItem="dQh-uc-65J" firstAttribute="leading" secondItem="s0L-ul-gog" secondAttribute="leading" constant="16" id="qSi-Cf-iFz"/>
|
||||
<constraint firstAttribute="trailing" secondItem="0Fo-Ae-QrQ" secondAttribute="trailing" constant="16" id="zfn-hK-yiy"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="Background"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="addLocationButton" destination="0Fo-Ae-QrQ" id="svZ-xA-Txe"/>
|
||||
<outlet property="separator" destination="MJB-bK-y5c" id="xZC-xh-fJh"/>
|
||||
<outlet property="titleLabel" destination="dQh-uc-65J" id="xKP-bY-mQP"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="mqc-M4-MPb" customClass="RouteManagerFooterView" customModule="CoMaps" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="48" width="414" height="48"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="or0-Gy-0su">
|
||||
<rect key="frame" x="-100" y="0.0" width="614" height="148"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="BlackOpaqueBackground"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pjx-6o-NWS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="1"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="jFT-3E-Yrc"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="Divider"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2WE-hS-hzl">
|
||||
<rect key="frame" x="16" y="0.0" width="46" height="48"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="FlatNormalTransButton"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="cancel"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onCancel" destination="-1" eventType="touchUpInside" id="Lzk-mL-6Jg"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="u3h-0s-UBo">
|
||||
<rect key="frame" x="352" y="0.0" width="46" height="48"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="FlatNormalTransButton"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="button_plan"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onPlan" destination="-1" eventType="touchUpInside" id="M1B-dr-vZS"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="48" id="1qG-Md-L9w"/>
|
||||
<constraint firstAttribute="trailing" secondItem="pjx-6o-NWS" secondAttribute="trailing" id="2pz-i3-nqy"/>
|
||||
<constraint firstItem="2WE-hS-hzl" firstAttribute="leading" secondItem="mqc-M4-MPb" secondAttribute="leading" constant="16" id="5pP-TA-d4M"/>
|
||||
<constraint firstItem="2WE-hS-hzl" firstAttribute="top" secondItem="mqc-M4-MPb" secondAttribute="top" id="CmY-Dg-Oyj"/>
|
||||
<constraint firstAttribute="bottom" secondItem="or0-Gy-0su" secondAttribute="bottom" constant="-100" id="Df9-Xs-6pB"/>
|
||||
<constraint firstAttribute="bottom" secondItem="u3h-0s-UBo" secondAttribute="bottom" id="GPn-YG-Q3q"/>
|
||||
<constraint firstItem="pjx-6o-NWS" firstAttribute="top" secondItem="mqc-M4-MPb" secondAttribute="top" id="JBh-gl-9Zv"/>
|
||||
<constraint firstItem="or0-Gy-0su" firstAttribute="leading" secondItem="mqc-M4-MPb" secondAttribute="leading" constant="-100" id="Nrk-kP-4Bh"/>
|
||||
<constraint firstAttribute="trailing" secondItem="u3h-0s-UBo" secondAttribute="trailing" constant="16" id="QGG-zB-H6Q"/>
|
||||
<constraint firstAttribute="bottom" secondItem="2WE-hS-hzl" secondAttribute="bottom" id="TJH-n6-XZn"/>
|
||||
<constraint firstItem="pjx-6o-NWS" firstAttribute="leading" secondItem="mqc-M4-MPb" secondAttribute="leading" id="isd-2j-Shn"/>
|
||||
<constraint firstItem="u3h-0s-UBo" firstAttribute="top" secondItem="mqc-M4-MPb" secondAttribute="top" id="jC7-jG-YeX"/>
|
||||
<constraint firstAttribute="trailing" secondItem="or0-Gy-0su" secondAttribute="trailing" constant="-100" id="zfL-pn-451"/>
|
||||
<constraint firstItem="or0-Gy-0su" firstAttribute="top" secondItem="mqc-M4-MPb" secondAttribute="top" id="ztB-hC-yRP"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="Background"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="background" destination="or0-Gy-0su" id="aFx-YJ-deT"/>
|
||||
<outlet property="cancelButton" destination="2WE-hS-hzl" id="8op-cA-N4M"/>
|
||||
<outlet property="planButton" destination="u3h-0s-UBo" id="Fb9-pg-kh9"/>
|
||||
<outlet property="separator" destination="pjx-6o-NWS" id="EKT-Ba-Lcy"/>
|
||||
</connections>
|
||||
</view>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="48" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="Zqd-YQ-ksD" customClass="RouteManagerTableView" customModule="CoMaps" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="48" width="414" height="0.0"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" priority="750" id="69R-bB-eQ7"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="TableView"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="-1" id="RZu-Qk-qvN"/>
|
||||
<outlet property="delegate" destination="-1" id="QdP-tL-Afh"/>
|
||||
<outlet property="tableViewHeight" destination="69R-bB-eQ7" id="iLN-YX-m5u"/>
|
||||
<outletCollection property="gestureRecognizers" destination="iVR-Au-pTp" appends="YES" id="abb-Ql-z0p"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="ManagerView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" priority="750" constant="375" id="6Nm-Md-fZo"/>
|
||||
<constraint firstItem="Zqd-YQ-ksD" firstAttribute="top" secondItem="s0L-ul-gog" secondAttribute="bottom" id="9N3-Ti-W95"/>
|
||||
<constraint firstItem="mqc-M4-MPb" firstAttribute="top" secondItem="Zqd-YQ-ksD" secondAttribute="bottom" id="A2s-eg-1CW"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="mqc-M4-MPb" secondAttribute="bottom" id="JoD-oZ-xgY"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="s0L-ul-gog" secondAttribute="trailing" constant="-8" id="Ndx-K2-qQ5"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="mqc-M4-MPb" secondAttribute="trailing" constant="-8" id="WgX-mu-BCG"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Zqd-YQ-ksD" secondAttribute="trailing" id="XkJ-fe-lyj"/>
|
||||
<constraint firstItem="s0L-ul-gog" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leadingMargin" constant="-8" id="aDI-kT-6Ao"/>
|
||||
<constraint firstItem="Zqd-YQ-ksD" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="cgy-zG-Qpu"/>
|
||||
<constraint firstItem="mqc-M4-MPb" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leadingMargin" constant="-8" id="gvJ-kF-Ylk"/>
|
||||
<constraint firstItem="s0L-ul-gog" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="ub9-gl-pdn"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="Background"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="ControllerView"/>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="i5M-Pr-FkT" secondAttribute="trailing" id="Bnz-SA-yXA"/>
|
||||
<constraint firstItem="i5M-Pr-FkT" firstAttribute="leading" secondItem="TKX-qe-h4F" secondAttribute="leading" id="Pui-FF-qOT"/>
|
||||
<constraint firstAttribute="bottom" secondItem="i5M-Pr-FkT" secondAttribute="bottom" id="qXL-Hf-8X6"/>
|
||||
<constraint firstItem="i5M-Pr-FkT" firstAttribute="top" relation="greaterThanOrEqual" secondItem="TKX-qe-h4F" secondAttribute="top" constant="72" id="sYB-lu-PhM"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="hNI-dt-MwJ"/>
|
||||
<point key="canvasLocation" x="-239.5" y="-48.5"/>
|
||||
</view>
|
||||
<tapGestureRecognizer id="deN-Z9-rbS" userLabel="Cancel Tap Gesture Recognizer">
|
||||
<connections>
|
||||
<action selector="onCancel" destination="-1" id="QyM-e1-7JM"/>
|
||||
</connections>
|
||||
</tapGestureRecognizer>
|
||||
<pongPressGestureRecognizer allowableMovement="10" minimumPressDuration="0.10000000000000001" id="iVR-Au-pTp">
|
||||
<connections>
|
||||
<action selector="gestureRecognized:" destination="-1" id="osy-Ks-njV"/>
|
||||
</connections>
|
||||
</pongPressGestureRecognizer>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="ic_get_position" width="20" height="20"/>
|
||||
<image name="ic_route_manager_trash" width="24" height="24"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
@objc(MWMRouteManagerViewModel)
|
||||
final class RouteManagerViewModel: NSObject, RouteManagerViewModelProtocol {
|
||||
var routePoints: [MWMRoutePoint] { return MWMRouter.points() }
|
||||
var refreshControlsCallback: (() -> Void)!
|
||||
var reloadCallback: (() -> Void)!
|
||||
|
||||
func startTransaction() { MWMRouter.openRouteManagerTransaction() }
|
||||
|
||||
func finishTransaction() {
|
||||
MWMRouter.applyRouteManagerTransaction()
|
||||
MWMRouter.rebuild(withBestRouter: false)
|
||||
}
|
||||
|
||||
func cancelTransaction() { MWMRouter.cancelRouteManagerTransaction() }
|
||||
|
||||
func addLocationPoint() {
|
||||
MWMRouter.addPoint(MWMRoutePoint(lastLocationAndType: .start, intermediateIndex: 0))
|
||||
MWMRouter.updatePreviewMode()
|
||||
refreshControlsCallback()
|
||||
}
|
||||
func movePoint(at index: Int, to newIndex: Int) {
|
||||
MWMRouter.movePoint(at: index, to: newIndex)
|
||||
MWMRouter.updatePreviewMode()
|
||||
refreshControlsCallback()
|
||||
}
|
||||
func deletePoint(at index: Int) {
|
||||
MWMRouter.removePoint(routePoints[index])
|
||||
MWMRouter.updatePreviewMode()
|
||||
refreshControlsCallback()
|
||||
reloadCallback()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
@objc(MWMRouteManagerViewModelProtocol)
|
||||
protocol RouteManagerViewModelProtocol: AnyObject {
|
||||
var routePoints: [MWMRoutePoint] { get }
|
||||
|
||||
var refreshControlsCallback: (() -> Void)! { get set }
|
||||
var reloadCallback: (() -> Void)! { get set }
|
||||
|
||||
func startTransaction()
|
||||
func finishTransaction()
|
||||
func cancelTransaction()
|
||||
|
||||
func addLocationPoint()
|
||||
func movePoint(at index: Int, to newIndex: Int)
|
||||
func deletePoint(at index: Int)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue