X-Git-Url: https://git.mdrn.pl/wl-app.git/blobdiff_plain/53b27422d140022594fc241cca91c3183be57bca..48b2fe9f7c2dc3d9aeaaa6dbfb27c7da4f3235ff:/iOS/Pods/SideMenu/Pod/Classes/UISideMenuNavigationController.swift diff --git a/iOS/Pods/SideMenu/Pod/Classes/UISideMenuNavigationController.swift b/iOS/Pods/SideMenu/Pod/Classes/UISideMenuNavigationController.swift new file mode 100644 index 0000000..0c6963c --- /dev/null +++ b/iOS/Pods/SideMenu/Pod/Classes/UISideMenuNavigationController.swift @@ -0,0 +1,343 @@ +// +// UISideMenuNavigationController.swift +// +// Created by Jon Kent on 1/14/16. +// Copyright © 2016 Jon Kent. All rights reserved. +// + +import UIKit + +@objc public protocol UISideMenuNavigationControllerDelegate { + @objc optional func sideMenuWillAppear(menu: UISideMenuNavigationController, animated: Bool) + @objc optional func sideMenuDidAppear(menu: UISideMenuNavigationController, animated: Bool) + @objc optional func sideMenuWillDisappear(menu: UISideMenuNavigationController, animated: Bool) + @objc optional func sideMenuDidDisappear(menu: UISideMenuNavigationController, animated: Bool) +} + +@objcMembers +open class UISideMenuNavigationController: UINavigationController { + + fileprivate weak var foundDelegate: UISideMenuNavigationControllerDelegate? + fileprivate weak var activeDelegate: UISideMenuNavigationControllerDelegate? { + get { + guard !view.isHidden else { + return nil + } + + return sideMenuDelegate ?? foundDelegate ?? findDelegate(forViewController: presentingViewController) + } + } + fileprivate func findDelegate(forViewController: UIViewController?) -> UISideMenuNavigationControllerDelegate? { + if let navigationController = forViewController as? UINavigationController { + return findDelegate(forViewController: navigationController.topViewController) + } + if let tabBarController = forViewController as? UITabBarController { + return findDelegate(forViewController: tabBarController.selectedViewController) + } + if let splitViewController = forViewController as? UISplitViewController { + return findDelegate(forViewController: splitViewController.viewControllers.last) + } + + foundDelegate = forViewController as? UISideMenuNavigationControllerDelegate + return foundDelegate + } + fileprivate var usingInterfaceBuilder = false + internal var locked = false + internal var originalMenuBackgroundColor: UIColor? + internal var transition: SideMenuTransition { + get { + return sideMenuManager.transition + } + } + + /// Delegate for receiving appear and disappear related events. If `nil` the visible view controller that displays a `UISideMenuNavigationController` automatically receives these events. + open weak var sideMenuDelegate: UISideMenuNavigationControllerDelegate? + + /// SideMenuManager instance associated with this menu. Default is `SideMenuManager.default`. This property cannot be changed after the menu has loaded. + open weak var sideMenuManager: SideMenuManager! = SideMenuManager.default { + didSet { + if locked && oldValue != nil { + print("SideMenu Warning: a menu's sideMenuManager property cannot be changed after it has loaded.") + sideMenuManager = oldValue + } + } + } + + /// Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is zero. When zero, `sideMenuManager.menuWidth` is used. This property cannot be changed while the isHidden property is false. + @IBInspectable open var menuWidth: CGFloat = 0 { + didSet { + if !isHidden && oldValue != menuWidth { + print("SideMenu Warning: a menu's width property can only be changed when it is hidden.") + menuWidth = oldValue + } + } + } + + /// Whether the menu appears on the right or left side of the screen. Right is the default. This property cannot be changed after the menu has loaded. + @IBInspectable open var leftSide: Bool = false { + didSet { + if locked && leftSide != oldValue { + print("SideMenu Warning: a menu's leftSide property cannot be changed after it has loaded.") + leftSide = oldValue + } + } + } + + /// Indicates if the menu is anywhere in the view hierarchy, even if covered by another view controller. + open var isHidden: Bool { + get { + return self.presentingViewController == nil + } + } + + #if !STFU_SIDEMENU + // This override prevents newbie developers from creating black/blank menus and opening newbie issues. + // If you would like to remove this override, define STFU_SIDEMENU in the Active Compilation Conditions of your .plist file. + // Sorry for the inconvenience experienced developers :( + @available(*, unavailable, renamed: "init(rootViewController:)") + public init() { + fatalError("init is not available") + } + + public override init(rootViewController: UIViewController) { + super.init(rootViewController: rootViewController) + } + + public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + #endif + + open override func awakeFromNib() { + super.awakeFromNib() + + usingInterfaceBuilder = true + } + + override open func viewDidLoad() { + super.viewDidLoad() + + if !locked && usingInterfaceBuilder { + if leftSide { + sideMenuManager.menuLeftNavigationController = self + } else { + sideMenuManager.menuRightNavigationController = self + } + } + } + + open override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + // Dismiss keyboard to prevent weird keyboard animations from occurring during transition + presentingViewController?.view.endEditing(true) + + foundDelegate = nil + activeDelegate?.sideMenuWillAppear?(menu: self, animated: animated) + } + + override open func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + // We had presented a view before, so lets dismiss ourselves as already acted upon + if view.isHidden { + transition.hideMenuComplete() + dismiss(animated: false, completion: { () -> Void in + self.view.isHidden = false + }) + + return + } + + activeDelegate?.sideMenuDidAppear?(menu: self, animated: animated) + + #if !STFU_SIDEMENU + if topViewController == nil { + print("SideMenu Warning: the menu doesn't have a view controller to show! UISideMenuNavigationController needs a view controller to display just like a UINavigationController.") + } + #endif + } + + override open func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + // When presenting a view controller from the menu, the menu view gets moved into another transition view above our transition container + // which can break the visual layout we had before. So, we move the menu view back to its original transition view to preserve it. + if !isBeingDismissed { + guard let sideMenuManager = sideMenuManager else { + return + } + + if let mainView = transition.mainViewController?.view { + switch sideMenuManager.menuPresentMode { + case .viewSlideOut, .viewSlideInOut: + mainView.superview?.insertSubview(view, belowSubview: mainView) + case .menuSlideIn, .menuDissolveIn: + if let tapView = transition.tapView { + mainView.superview?.insertSubview(view, aboveSubview: tapView) + } else { + mainView.superview?.insertSubview(view, aboveSubview: mainView) + } + } + } + + // We're presenting a view controller from the menu, so we need to hide the menu so it isn't showing when the presented view is dismissed. + UIView.animate(withDuration: animated ? sideMenuManager.menuAnimationDismissDuration : 0, + delay: 0, + usingSpringWithDamping: sideMenuManager.menuAnimationUsingSpringWithDamping, + initialSpringVelocity: sideMenuManager.menuAnimationInitialSpringVelocity, + options: sideMenuManager.menuAnimationOptions, + animations: { + self.transition.hideMenuStart() + self.activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated) + }) { (finished) -> Void in + self.activeDelegate?.sideMenuDidDisappear?(menu: self, animated: animated) + self.view.isHidden = true + } + + return + } + + activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated) + } + + override open func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + // Work-around: if the menu is dismissed without animation the transition logic is never called to restore the + // the view hierarchy leaving the screen black/empty. This is because the transition moves views within a container + // view, but dismissing without animation removes the container view before the original hierarchy is restored. + // This check corrects that. + if let sideMenuDelegate = activeDelegate as? UIViewController, sideMenuDelegate.view.window == nil { + transition.hideMenuStart().hideMenuComplete() + } + + activeDelegate?.sideMenuDidDisappear?(menu: self, animated: animated) + + // Clear selecton on UITableViewControllers when reappearing using custom transitions + guard let tableViewController = topViewController as? UITableViewController, + let tableView = tableViewController.tableView, + let indexPaths = tableView.indexPathsForSelectedRows, + tableViewController.clearsSelectionOnViewWillAppear else { + return + } + + for indexPath in indexPaths { + tableView.deselectRow(at: indexPath, animated: false) + } + } + + override open func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) + + // Don't bother resizing if the view isn't visible + guard !view.isHidden else { + return + } + + NotificationCenter.default.removeObserver(self.transition, name: NSNotification.Name.UIApplicationWillChangeStatusBarFrame, object: nil) + coordinator.animate(alongsideTransition: { (context) in + self.transition.presentMenuStart() + }) { (context) in + NotificationCenter.default.addObserver(self.transition, selector:#selector(SideMenuTransition.handleNotification), name: NSNotification.Name.UIApplicationWillChangeStatusBarFrame, object: nil) + } + } + + override open func pushViewController(_ viewController: UIViewController, animated: Bool) { + guard let sideMenuManager = sideMenuManager, viewControllers.count > 0 && sideMenuManager.menuPushStyle != .subMenu else { + // NOTE: pushViewController is called by init(rootViewController: UIViewController) + // so we must perform the normal super method in this case. + super.pushViewController(viewController, animated: animated) + return + } + + let splitViewController = presentingViewController as? UISplitViewController + let tabBarController = presentingViewController as? UITabBarController + let potentialNavigationController = (splitViewController?.viewControllers.first ?? tabBarController?.selectedViewController) ?? presentingViewController + guard let navigationController = potentialNavigationController as? UINavigationController else { + print("SideMenu Warning: attempt to push a View Controller from \(String(describing: potentialNavigationController.self)) where its navigationController == nil. It must be embedded in a Navigation Controller for this to work.") + return + } + + let activeDelegate = self.activeDelegate + foundDelegate = nil + + // To avoid overlapping dismiss & pop/push calls, create a transaction block where the menu + // is dismissed after showing the appropriate screen + CATransaction.begin() + if sideMenuManager.menuDismissOnPush { + let animated = animated || sideMenuManager.menuAlwaysAnimate + + CATransaction.setCompletionBlock( { () -> Void in + activeDelegate?.sideMenuDidDisappear?(menu: self, animated: animated) + if !animated { + self.transition.hideMenuStart().hideMenuComplete() + } + self.dismiss(animated: animated, completion: nil) + }) + + if animated { + let areAnimationsEnabled = UIView.areAnimationsEnabled + UIView.setAnimationsEnabled(true) + UIView.animate(withDuration: sideMenuManager.menuAnimationDismissDuration, + delay: 0, + usingSpringWithDamping: sideMenuManager.menuAnimationUsingSpringWithDamping, + initialSpringVelocity: sideMenuManager.menuAnimationInitialSpringVelocity, + options: sideMenuManager.menuAnimationOptions, + animations: { + activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated) + self.transition.hideMenuStart() + }) + UIView.setAnimationsEnabled(areAnimationsEnabled) + } + } + + if let lastViewController = navigationController.viewControllers.last, !sideMenuManager.menuAllowPushOfSameClassTwice && type(of: lastViewController) == type(of: viewController) { + CATransaction.commit() + return + } + + switch sideMenuManager.menuPushStyle { + case .subMenu, .defaultBehavior: break // .subMenu handled earlier, .defaultBehavior falls through to end + case .popWhenPossible: + for subViewController in navigationController.viewControllers.reversed() { + if type(of: subViewController) == type(of: viewController) { + navigationController.popToViewController(subViewController, animated: animated) + CATransaction.commit() + return + } + } + case .preserve, .preserveAndHideBackButton: + var viewControllers = navigationController.viewControllers + let filtered = viewControllers.filter { preservedViewController in type(of: preservedViewController) == type(of: viewController) } + if let preservedViewController = filtered.last { + viewControllers = viewControllers.filter { subViewController in subViewController !== preservedViewController } + if sideMenuManager.menuPushStyle == .preserveAndHideBackButton { + preservedViewController.navigationItem.hidesBackButton = true + } + viewControllers.append(preservedViewController) + navigationController.setViewControllers(viewControllers, animated: animated) + CATransaction.commit() + return + } + if sideMenuManager.menuPushStyle == .preserveAndHideBackButton { + viewController.navigationItem.hidesBackButton = true + } + case .replace: + viewController.navigationItem.hidesBackButton = true + navigationController.setViewControllers([viewController], animated: animated) + CATransaction.commit() + return + } + + navigationController.pushViewController(viewController, animated: animated) + CATransaction.commit() + } + +} + +