<commit_before>//
//  ForwardingView.swift
//  TransliteratingKeyboard
//
//  Created by <NAME> on 7/19/14.
//  Copyright (c) 2014 Apple. All rights reserved.
//

import UIKit

class ForwardingView: UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.contentMode = UIViewContentMode.Redraw
        self.multipleTouchEnabled = false
        self.userInteractionEnabled = true
        self.opaque = false
    }
    
    required init(coder: NSCoder) {
        fatalError("NSCoding not supported")
    }
    
    // Why have this useless drawRect? Well, if we just set the backgroundColor to clearColor,
    // then some weird optimization happens on UIKit's side where tapping down on a transparent pixel will
    // not actually recognize the touch. Having a manual drawRect fixes this behavior, even though it doesn't
    // actually do anything.
    override func drawRect(rect: CGRect) {}
    
    override func hitTest(point: CGPoint, withEvent event: UIEvent!) -> UIView? {
        return self
    }
    
    var myView: UIView?
    
    // TODO: drag up control centre from bottom == stuck
    func handleControl(view: UIView?, controlEvent: UIControlEvents) {
        if view == nil {
            return
        }
        
        if !(view is UIControl) {
            return
        }
        
        let control = view! as UIControl
        
        switch controlEvent {
        case
        UIControlEvents.TouchDown,
        UIControlEvents.TouchDragEnter:
            control.highlighted = true
        case
        UIControlEvents.TouchDragExit,
        UIControlEvents.TouchUpInside,
        UIControlEvents.TouchUpOutside,
        UIControlEvents.TouchCancel:
            control.highlighted = false
        default:
            break
        }
        
        let targets = control.allTargets()
        for target in targets.allObjects { // TODO: Xcode crashes
            var actions = control.actionsForTarget(target, forControlEvent: controlEvent)
            if (actions != nil) {
                for action in actions! {
                    let selector = Selector(action as String)
                    control.sendAction(selector, to: target, forEvent: nil)
                }
            }
        }
    }
    
    // TODO: there's a bit of "stickiness" to Apple's implementation
    func findNearestView(position: CGPoint) -> UIView? {
        var closest: (UIView, CGFloat)? = nil
        
        for anyView in self.subviews {
            let view = anyView as UIView
            
            if view.hidden {
                continue
            }
            
            view.alpha = 1
            
            let distance = distanceBetween(view.frame, point: position)
            
            if closest != nil {
                if distance < closest!.1 {
                    closest = (view, distance)
                }
            }
            else {
                closest = (view, distance)
            }
        }
        
        if closest != nil {
            return closest!.0
        }
        else {
            return nil
        }
    }
    
    // http://stackoverflow.com/questions/3552108/finding-closest-object-to-cgpoint b/c I'm lazy
    func distanceBetween(rect: CGRect, point: CGPoint) -> CGFloat {
        if CGRectContainsPoint(rect, point) {
            return 0
        }

        var closest = rect.origin
        
        if (rect.origin.x + rect.size.width < point.x) {
            closest.x += rect.size.width
        }
        else if (point.x > rect.origin.x) {
            closest.x = point.x
        }
        if (rect.origin.y + rect.size.height < point.y) {
            closest.y += rect.size.height
        }
        else if (point.y > rect.origin.y) {
            closest.y = point.y
        }
        
        let a = pow(Double(closest.y - point.y), 2)
        let b = pow(Double(closest.x - point.x), 2)
        return CGFloat(sqrt(a + b));
    }
    
    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        let touch = touches.anyObject() as UITouch
        let position = touch.locationInView(self)
        var view = findNearestView(position)
        
        self.myView = view
        
        self.handleControl(self.myView, controlEvent: .TouchDown)
    }
    
    override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
        let touch = touches.anyObject() as UITouch
        let position = touch.locationInView(self)
        var view = findNearestView(position)
        
        if view != self.myView {
            self.handleControl(self.myView, controlEvent: .TouchUpOutside)
            
            self.myView = view
            
            self.handleControl(self.myView, controlEvent: .TouchDown)
        }
        else {
            self.handleControl(self.myView, controlEvent: .TouchDragInside)
        }
    }
    
    override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
        let touch = touches.anyObject() as UITouch
        let pos = touch.locationInView(self)
        var view = findNearestView(pos)
        
        self.handleControl(view, controlEvent: .TouchUpInside)
    }

    override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {
        self.handleControl(self.myView, controlEvent: .TouchCancel)
    }
}<commit_msg>Starting multitouch.<commit_after>//
//  ForwardingView.swift
//  TransliteratingKeyboard
//
//  Created by <NAME> on 7/19/14.
//  Copyright (c) 2014 Apple. All rights reserved.
//

import UIKit

class ForwardingView: UIView {
    
    var activeTouches: [Int]
    var multiTapTimers: [Int: NSTimer]
    var touchToView: [UITouch:UIView]
    
    override init(frame: CGRect) {
        self.activeTouches = []
        self.multiTapTimers = [:]
        self.touchToView = [:]
        
        super.init(frame: frame)
        
        self.contentMode = UIViewContentMode.Redraw
        self.multipleTouchEnabled = true
        self.userInteractionEnabled = true
        self.opaque = false
    }
    
    required init(coder: NSCoder) {
        fatalError("NSCoding not supported")
    }
    
    // Why have this useless drawRect? Well, if we just set the backgroundColor to clearColor,
    // then some weird optimization happens on UIKit's side where tapping down on a transparent pixel will
    // not actually recognize the touch. Having a manual drawRect fixes this behavior, even though it doesn't
    // actually do anything.
    override func drawRect(rect: CGRect) {}
    
    override func hitTest(point: CGPoint, withEvent event: UIEvent!) -> UIView? {
        return self
    }
    
    // TODO: drag up control centre from bottom == stuck
    func handleControl(view: UIView?, controlEvent: UIControlEvents) {
        if view == nil {
            return
        }
        
        if !(view is UIControl) {
            return
        }
        
        let control = view! as UIControl
        
        switch controlEvent {
        case
        UIControlEvents.TouchDown,
        UIControlEvents.TouchDragEnter:
            control.highlighted = true
        case
        UIControlEvents.TouchDragExit,
        UIControlEvents.TouchUpInside,
        UIControlEvents.TouchUpOutside,
        UIControlEvents.TouchCancel:
            control.highlighted = false
        default:
            break
        }
        
        let targets = control.allTargets()
        for target in targets.allObjects { // TODO: Xcode crashes
            var actions = control.actionsForTarget(target, forControlEvent: controlEvent)
            if (actions != nil) {
                for action in actions! {
                    let selector = Selector(action as String)
                    control.sendAction(selector, to: target, forEvent: nil)
                }
            }
        }
    }
    
    // TODO: there's a bit of "stickiness" to Apple's implementation
    func findNearestView(position: CGPoint) -> UIView? {
        var closest: (UIView, CGFloat)? = nil
        
        for anyView in self.subviews {
            let view = anyView as UIView
            
            if view.hidden {
                continue
            }
            
            view.alpha = 1
            
            let distance = distanceBetween(view.frame, point: position)
            
            if closest != nil {
                if distance < closest!.1 {
                    closest = (view, distance)
                }
            }
            else {
                closest = (view, distance)
            }
        }
        
        if closest != nil {
            return closest!.0
        }
        else {
            return nil
        }
    }
    
    // http://stackoverflow.com/questions/3552108/finding-closest-object-to-cgpoint b/c I'm lazy
    func distanceBetween(rect: CGRect, point: CGPoint) -> CGFloat {
        if CGRectContainsPoint(rect, point) {
            return 0
        }

        var closest = rect.origin
        
        if (rect.origin.x + rect.size.width < point.x) {
            closest.x += rect.size.width
        }
        else if (point.x > rect.origin.x) {
            closest.x = point.x
        }
        if (rect.origin.y + rect.size.height < point.y) {
            closest.y += rect.size.height
        }
        else if (point.y > rect.origin.y) {
            closest.y = point.y
        }
        
        let a = pow(Double(closest.y - point.y), 2)
        let b = pow(Double(closest.x - point.x), 2)
        return CGFloat(sqrt(a + b));
    }
    
    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        for obj in touches {
            let touch = obj as UITouch
            let position = touch.locationInView(self)
            var view = findNearestView(position)
            
            self.touchToView[touch] = view
            
            self.handleControl(view, controlEvent: .TouchDown)
        }
    }
    
    override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
        for obj in touches {
            let touch = obj as UITouch
            let position = touch.locationInView(self)
            
            var view = self.touchToView[touch]
            var newView = findNearestView(position)
            
            if view != newView {
                self.handleControl(view, controlEvent: .TouchUpOutside)
                self.touchToView[touch] = newView
                self.handleControl(newView, controlEvent: .TouchDown)
            }
            else {
                self.handleControl(view, controlEvent: .TouchDragInside)
            }
        }
    }
    
    override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
        for obj in touches {
            let touch = obj as UITouch
            
            var view = self.touchToView[touch]
            
            self.handleControl(view, controlEvent: .TouchUpInside)
        }
    }

    override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {
        for obj in touches {
            let touch = obj as UITouch
            
            var view = self.touchToView[touch]
            
            self.handleControl(view, controlEvent: .TouchCancel)
        }
    }
}
{'fraction_non_alphanumeric': 0.08350377945753669, 'fraction_numerical': 0.003912850155624722, 'mean_word_length': 1.5864765409383625, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, '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': '749298', 'n_tokens_mistral': 3154, 'n_tokens_neox': 3041, 'n_words': 795}