<commit_before>//
//  Created by <NAME> on 16/07/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import UIKit

/// `AnimatablePresentationController` is a subclass of `UIPresentationController` with `PresentationConfiguration` to specify the dimming view and modal view for presentation.
public class AnimatablePresentationController: UIPresentationController {

  // MARK: Properties

  private let presentationConfiguration: PresentationConfiguration
  private var dimmingView = AnimatableView()

  // MARK: Init

  init(presentedViewController: UIViewController,
       presentingViewController: UIViewController,
       presentationConfiguration: PresentationConfiguration) {
    self.presentationConfiguration = presentationConfiguration
    super.init(presentedViewController: presentedViewController, presentingViewController: presentingViewController)

    setupDimmingView()
    setupPresentedView()
    setupObservers()
  }

  deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)    
  }

  // MARK: Actions

  func chromeViewTapped(gesture: UIGestureRecognizer) {
    if gesture.state == .Ended && presentationConfiguration.dismissOnTap {
      presentingViewController.dismissViewControllerAnimated(true, completion: nil)
    }
  }

}

// MARK: - Setup

private extension AnimatablePresentationController {

  func setupDimmingView() {
    let tap = UITapGestureRecognizer(target: self, action: #selector(chromeViewTapped))
    dimmingView.addGestureRecognizer(tap)
    if let blurEffectStyle =  presentationConfiguration.blurEffectStyle {
      dimmingView.blurEffectStyle = blurEffectStyle
      dimmingView.blurOpacity = presentationConfiguration.blurOpacity
    } else {
      dimmingView.fillColor = presentationConfiguration.backgroundColor.colorWithAlphaComponent(presentationConfiguration.opacity)
    }
  }
  
  func setupPresentedView() {
    if presentationConfiguration.cornerRadius > 0 {
      presentedViewController.view.layer.cornerRadius = presentationConfiguration.cornerRadius
      presentedViewController.view.layer.masksToBounds = true
    }
    
    // Set up shadow
    if presentationConfiguration.shadowRadius > 0 {
      presentedViewController.view.layer.shadowRadius = presentationConfiguration.shadowRadius
      presentedViewController.view.layer.masksToBounds = false
    }
    
    if !presentationConfiguration.shadowOffset.x.isNaN && !presentationConfiguration.shadowOffset.y.isNaN {
      presentedViewController.view.layer.shadowOffset.width = presentationConfiguration.shadowOffset.x
      presentedViewController.view.layer.shadowOffset.height = presentationConfiguration.shadowOffset.y
      presentedViewController.view.layer.masksToBounds = false
    }
    
    if presentationConfiguration.shadowOpacity > 0 {
      presentedViewController.view.layer.shadowOpacity = Float(presentationConfiguration.shadowOpacity)
      presentedViewController.view.layer.masksToBounds = false
    }
    
    if let shadowColor = presentationConfiguration.shadowColor {
      presentedViewController.view.layer.shadowColor = shadowColor.CGColor
      presentedViewController.view.layer.masksToBounds = false
    }
  }

}

// MARK: - Notifications

extension AnimatablePresentationController {

  private func setupObservers() {
    guard presentationConfiguration.keyboardTranslation != .None else {
      return
    }

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(AnimatablePresentationController.keyboardWasShown(_:)), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(AnimatablePresentationController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
  } 

  func keyboardWasShown (notification: NSNotification) {
    if let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey]?.CGRectValue() {
      let presentedFrame = frameOfPresentedViewInContainerView()
      let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue ?? 0.5
      let translatedFrame = presentationConfiguration.keyboardTranslation.translationFrame(keyboardFrame, presentedFrame: presentedFrame)
      UIView.animateWithDuration(duration) {
        self.presentedView()?.frame = translatedFrame
      }
    }
  }

  func keyboardWillHide (notification: NSNotification) {    
    let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue ?? 0.5
    UIView.animateWithDuration(duration) {
      self.presentedView()!.frame = self.frameOfPresentedViewInContainerView()
    }
  }

}

// MARK: - Size & origin helpers

private extension AnimatablePresentationController {

  func modalSize() -> CGSize {
    guard let containerSize = containerView?.bounds.size else {
      return CGSize.zero
    }

    let width = CGFloat(presentationConfiguration.modalSize.0.width(containerSize))
    let height = CGFloat(presentationConfiguration.modalSize.1.height(containerSize))
    return CGSize(width: width, height: height)
  }

  func modalCenter() -> CGPoint? {
    guard let containerBounds = containerView?.bounds else {
      return nil
    }

    return presentationConfiguration.modalPosition.calculateCenter(containerBounds, modalSize: modalSize())<commit_msg>Add curve animation when keyboard is shown / hidden<commit_after>//
//  Created by <NAME> on 16/07/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import UIKit

/// `AnimatablePresentationController` is a subclass of `UIPresentationController` with `PresentationConfiguration` to specify the dimming view and modal view for presentation.
public class AnimatablePresentationController: UIPresentationController {

  // MARK: Properties

  private let presentationConfiguration: PresentationConfiguration
  private var dimmingView = AnimatableView()

  // MARK: Init

  init(presentedViewController: UIViewController,
       presentingViewController: UIViewController,
       presentationConfiguration: PresentationConfiguration) {
    self.presentationConfiguration = presentationConfiguration
    super.init(presentedViewController: presentedViewController, presentingViewController: presentingViewController)

    setupDimmingView()
    setupPresentedView()
    setupObservers()
  }

  deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)    
  }

  // MARK: Actions

  func chromeViewTapped(gesture: UIGestureRecognizer) {
    if gesture.state == .Ended && presentationConfiguration.dismissOnTap {
      presentingViewController.dismissViewControllerAnimated(true, completion: nil)
    }
  }

}

// MARK: - Setup

private extension AnimatablePresentationController {

  func setupDimmingView() {
    let tap = UITapGestureRecognizer(target: self, action: #selector(chromeViewTapped))
    dimmingView.addGestureRecognizer(tap)
    if let blurEffectStyle =  presentationConfiguration.blurEffectStyle {
      dimmingView.blurEffectStyle = blurEffectStyle
      dimmingView.blurOpacity = presentationConfiguration.blurOpacity
    } else {
      dimmingView.fillColor = presentationConfiguration.backgroundColor.colorWithAlphaComponent(presentationConfiguration.opacity)
    }
  }
  
  func setupPresentedView() {
    if presentationConfiguration.cornerRadius > 0 {
      presentedViewController.view.layer.cornerRadius = presentationConfiguration.cornerRadius
      presentedViewController.view.layer.masksToBounds = true
    }
    
    // Set up shadow
    if presentationConfiguration.shadowRadius > 0 {
      presentedViewController.view.layer.shadowRadius = presentationConfiguration.shadowRadius
      presentedViewController.view.layer.masksToBounds = false
    }
    
    if !presentationConfiguration.shadowOffset.x.isNaN && !presentationConfiguration.shadowOffset.y.isNaN {
      presentedViewController.view.layer.shadowOffset.width = presentationConfiguration.shadowOffset.x
      presentedViewController.view.layer.shadowOffset.height = presentationConfiguration.shadowOffset.y
      presentedViewController.view.layer.masksToBounds = false
    }
    
    if presentationConfiguration.shadowOpacity > 0 {
      presentedViewController.view.layer.shadowOpacity = Float(presentationConfiguration.shadowOpacity)
      presentedViewController.view.layer.masksToBounds = false
    }
    
    if let shadowColor = presentationConfiguration.shadowColor {
      presentedViewController.view.layer.shadowColor = shadowColor.CGColor
      presentedViewController.view.layer.masksToBounds = false
    }
  }

}

// MARK: - Notifications

extension AnimatablePresentationController {

  private func setupObservers() {
    guard presentationConfiguration.keyboardTranslation != .None else {
      return
    }

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(AnimatablePresentationController.keyboardWasShown(_:)), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(AnimatablePresentationController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
  } 

  func keyboardWasShown (notification: NSNotification) {
    if let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey]?.CGRectValue() {
      let presentedFrame = frameOfPresentedViewInContainerView()
      let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue ?? 0.5
      let translatedFrame = presentationConfiguration.keyboardTranslation.translationFrame(keyboardFrame, presentedFrame: presentedFrame)

      let curve = UIViewAnimationOptions(rawValue: UInt(duration))
      UIView.animateWithDuration(duration, delay: 0, options: curve, animations: {
        self.presentedView()?.frame = translatedFrame
      }, completion: nil)
    }
  }

  func keyboardWillHide (notification: NSNotification) {    
    let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue ?? 0.5
    let curve = UIViewAnimationOptions(rawValue: UInt(duration))
    UIView.animateWithDuration(duration, delay: 0, options: curve, animations: {
      self.presentedView()!.frame = self.frameOfPresentedViewInContainerView()
    }, completion: nil)
  }

}

// MARK: - Size & origin helpers

private extension AnimatablePresentationController {

  func modalSize() -> CGSize {
    guard let containerSize = containerView?.bounds.size else {
      return CGSize.zero
    }

    let width = CGFloat(presentationConfiguration.modalSize.0.width(containerSize))
    let height = CGFloat(presentationConfiguration.modalSize.1.height(containerSize))
    return CGSize(width: width, height: height)
  }

  func modalCenter() -> CGPoint? {
    guard let containerBounds = containerView?.bounds else {
      return nil
    }

    return presentationConfiguration.modalPosition.calculateCenter(containerBounds, modalSize: modalSize())
{'fraction_non_alphanumeric': 0.07901519864900898, 'fraction_numerical': 0.003555239534263621, 'mean_word_length': 4.749616760347471, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 17, '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': '7314955', 'n_tokens_mistral': 2920, 'n_tokens_neox': 2790, 'n_words': 542}