<commit_before>//
//  PagingMenuController.swift
//  PagingMenuController
//
//  Created by <NAME> on 3/18/15.
//  Copyright (c) 2015 kitasuke. All rights reserved.
//

import UIKit

@objc public protocol PagingMenuControllerDelegate: class {
    optional func willMoveToPageMenuController(menuController: UIViewController, previousMenuController: UIViewController)
    optional func didMoveToPageMenuController(menuController: UIViewController, previousMenuController: UIViewController)
    optional func willMoveToMenuItemView(menuItemView: MenuItemView, previousMenuItemView: MenuItemView)
    optional func didMoveToMenuItemView(menuItemView: MenuItemView, previousMenuItemView: MenuItemView)
}

internal let MinimumSupportedViewCount = 1
internal let VisiblePagingViewNumber = 3

public class PagingMenuController: UIViewController, PagingValidator {
    weak public var delegate: PagingMenuControllerDelegate?
    public private(set) var menuView: MenuView? {
        didSet {
            guard let menuView = menuView else { return }
            
            menuView.delegate = self
            menuView.viewDelegate = delegate
            view.addSubview(menuView)
        }
    }
    public private(set) var pagingViewController: PagingViewController? {
        didSet {
            guard let pagingViewController = pagingViewController else { return }
            
            pagingViewController.contentScrollView.delegate = self
            view.addSubview(pagingViewController.view)
            addChildViewController(pagingViewController)
            pagingViewController.didMoveToParentViewController(self)
        }
    }
    
    private var options: PagingMenuControllerCustomizable! {
        didSet {
            cleanup()
            
            validate(options)
        }
    }
    private var menuOptions: MenuViewCustomizable?
    
    // MARK: - Lifecycle
    
    public init(options: PagingMenuControllerCustomizable) {
        super.init(nibName: nil, bundle: nil)
        
        setup(options)
    }
    
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    override public func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        // fix unnecessary inset for menu view when implemented by programmatically
        menuView?.contentInset.top = 0
    }
    
    override public func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
        
        if let menuView = menuView, let menuOptions = menuOptions {
            menuView.updateMenuViewConstraints(size)
            
            coordinator.animateAlongsideTransition({ [unowned self] (_) -> Void in
                self.view.setNeedsLayout()
                self.view.layoutIfNeeded()
                
                // reset selected menu item view position
                switch menuOptions.mode {
                case .Standard, .Infinite:
                    self.moveToMenuPage(menuView.currentPage, animated: true)
                default: break
                }
                }, completion: nil)
        }
    }
    
    // MARK: - Public
    
    public func setup(options: PagingMenuControllerCustomizable) {
        self.options = options
        
        switch options.componentType {
        case .All(let menuOptions, _): self.menuOptions = menuOptions
        case .MenuView(let menuOptions): self.menuOptions = menuOptions
        default: break
        }
        
        setupMenuView()
        setupMenuController()
        
        moveToMenuPage(currentPage, animated: false)
    }
    
    private func setupMenuView() {
        switch options.componentType {
        case .PagingController: return
        default: break
        }
        
        constructMenuView()
        layoutMenuView()
    }
    
    private func setupMenuController() {
        switch options.componentType {
        case .MenuView: return
        default: break
        }

        constructPagingViewController()
        layoutPagingViewController()
    }
    
    public func moveToMenuPage(page: Int, animated: Bool = true) {
        switch options.componentType {
        case .MenuView, .All:
            // ignore an unexpected page number
            guard let menuView = menuView where page < menuView.menuItemCount else { return }
            
            let lastPage = menuView.currentPage
            guard page != lastPage else {
                // place views on appropriate position
                menuView.moveToMenu(page, animated: animated)
                pagingViewController?.positionMenuController()
                return
            }
            
            switch options.componentType {
            case .All: break
            default:
                menuView.moveToMenu(page, animated: animated)
                return
            }
        case .PagingController:
            guard let pagingViewController = pagingViewController where page < pagingViewController.controllers.count else { return }
            guard page != pagingViewController.currentPage else { return }
        }
        
        guard let pagingViewController = pagingViewController else { return }
        
        // hide paging views if it's moving to far away
        hidePagingMenuControllers(page)
        
        let previousViewController = pagingViewController.currentViewController
        
        let nextPage = page % pagingViewController.controllers.count
        let nextPagingViewController = pagingViewController.controllers[nextPage]
        delegate?.willMoveToPageMenuController?(nextPagingViewController, previousMenuController: previousViewController)
        menuView?.moveToMenu(page)
        
        pagingViewController.updateCurrentPage(nextPage)<commit_msg>Fix a bug that causes incorrect scrolling behavior<commit_after>//
//  PagingMenuController.swift
//  PagingMenuController
//
//  Created by <NAME> on 3/18/15.
//  Copyright (c) 2015 kitasuke. All rights reserved.
//

import UIKit

@objc public protocol PagingMenuControllerDelegate: class {
    optional func willMoveToPageMenuController(menuController: UIViewController, previousMenuController: UIViewController)
    optional func didMoveToPageMenuController(menuController: UIViewController, previousMenuController: UIViewController)
    optional func willMoveToMenuItemView(menuItemView: MenuItemView, previousMenuItemView: MenuItemView)
    optional func didMoveToMenuItemView(menuItemView: MenuItemView, previousMenuItemView: MenuItemView)
}

internal let MinimumSupportedViewCount = 1
internal let VisiblePagingViewNumber = 3

public class PagingMenuController: UIViewController, PagingValidator {
    weak public var delegate: PagingMenuControllerDelegate?
    public private(set) var menuView: MenuView? {
        didSet {
            guard let menuView = menuView else { return }
            
            menuView.delegate = self
            menuView.viewDelegate = delegate
            view.addSubview(menuView)
        }
    }
    public private(set) var pagingViewController: PagingViewController? {
        didSet {
            guard let pagingViewController = pagingViewController else { return }
            
            pagingViewController.contentScrollView.delegate = self
            view.addSubview(pagingViewController.view)
            addChildViewController(pagingViewController)
            pagingViewController.didMoveToParentViewController(self)
        }
    }
    
    private var options: PagingMenuControllerCustomizable! {
        didSet {
            cleanup()
            
            validate(options)
        }
    }
    private var menuOptions: MenuViewCustomizable?
    
    // MARK: - Lifecycle
    
    public init(options: PagingMenuControllerCustomizable) {
        super.init(nibName: nil, bundle: nil)
        
        setup(options)
    }
    
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    override public func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        // fix unnecessary inset for menu view when implemented by programmatically
        menuView?.contentInset.top = 0
    }
    
    override public func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
        
        if let menuView = menuView, let menuOptions = menuOptions {
            menuView.updateMenuViewConstraints(size)
            
            coordinator.animateAlongsideTransition({ [unowned self] (_) -> Void in
                self.view.setNeedsLayout()
                self.view.layoutIfNeeded()
                
                // reset selected menu item view position
                switch menuOptions.mode {
                case .Standard, .Infinite:
                    self.moveToMenuPage(menuView.currentPage)
                default: break
                }
                }, completion: nil)
        }
    }
    
    // MARK: - Public
    
    public func setup(options: PagingMenuControllerCustomizable) {
        self.options = options
        
        switch options.componentType {
        case .All(let menuOptions, _): self.menuOptions = menuOptions
        case .MenuView(let menuOptions): self.menuOptions = menuOptions
        default: break
        }
        
        setupMenuView()
        setupMenuController()
        
        moveToMenuPage(currentPage, animated: false)
    }
    
    private func setupMenuView() {
        switch options.componentType {
        case .PagingController: return
        default: break
        }
        
        constructMenuView()
        layoutMenuView()
    }
    
    private func setupMenuController() {
        switch options.componentType {
        case .MenuView: return
        default: break
        }

        constructPagingViewController()
        layoutPagingViewController()
    }
    
    public func moveToMenuPage(page: Int, animated: Bool = true) {
        switch options.componentType {
        case .MenuView, .All:
            // ignore an unexpected page number
            guard let menuView = menuView where page < menuView.menuItemCount else { return }
            
            let lastPage = menuView.currentPage
            guard page != lastPage else {
                // place views on appropriate position
                menuView.moveToMenu(page, animated: animated)
                pagingViewController?.positionMenuController()
                return
            }
            
            switch options.componentType {
            case .All: break
            default:
                menuView.moveToMenu(page, animated: animated)
                return
            }
        case .PagingController:
            guard let pagingViewController = pagingViewController where page < pagingViewController.controllers.count else { return }
            guard page != pagingViewController.currentPage || !animated else { return }
        }
        
        guard let pagingViewController = pagingViewController else { return }
        
        // hide paging views if it's moving to far away
        hidePagingMenuControllers(page)
        
        let previousViewController = pagingViewController.currentViewController
        
        let nextPage = page % pagingViewController.controllers.count
        let nextPagingViewController = pagingViewController.controllers[nextPage]
        delegate?.willMoveToPageMenuController?(nextPagingViewController, previousMenuController: previousViewController)
        menuView?.moveToMenu(page)
        
        pagingViewController.updateCurrentPage(nextPage)
{'fraction_non_alphanumeric': 0.061710725711399225, 'fraction_numerical': 0.0020205421788179827, 'mean_word_length': 2.2209869848156183, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1771645', 'n_tokens_mistral': 2919, 'n_tokens_neox': 2770, 'n_words': 681}