<commit_before>//
//  TouchDrawView.swift
//  TouchDraw
//
//  Created by <NAME> on 10/4/15.
//

public protocol TouchDrawViewDelegate {
    func undoEnabled()
    func undoDisabled()
    func redoEnabled()
    func redoDisabled()
}

public class TouchDrawView: UIView {

    public var delegate: TouchDrawViewDelegate!
    
    // Used for undo/redo
    private var stack: NSMutableArray!
    private var pointsArray: NSMutableArray!
    
    private var lastPoint = CGPoint.zero
    
    private var brushColor = CIColor(color: UIColor.blackColor())
    private var brushWidth = CGFloat(10.0)
    
    private var touchesMoved = false
    
    private var mainImageView = UIImageView()
    private var tempImageView = UIImageView()
    
    private var undoEnabled = false
    private var redoEnabled = false
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        initTouchDrawView()
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initTouchDrawView()
    }

    private func initTouchDrawView() {
        addSubview(mainImageView)
        addSubview(tempImageView)
        stack = []
    }
    
    override public func drawRect(rect: CGRect) {
        mainImageView.frame = rect
        tempImageView.frame = rect
    }
    
    // MARK: - Actions
    override public func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        touchesMoved = false
        if let touch = touches.first {
            lastPoint = touch.locationInView(self)
            pointsArray = []
            pointsArray.addObject(NSStringFromCGPoint(lastPoint))
        }
    }
    
    override public func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        touchesMoved = true
        if let touch = touches.first {
            let currentPoint = touch.locationInView(self)
            drawLineFrom(lastPoint, toPoint: currentPoint)
            
            lastPoint = currentPoint
            pointsArray.addObject(NSStringFromCGPoint(lastPoint))
        }
    }
    
    override public func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if !touchesMoved {
            // draw a single point
            drawLineFrom(lastPoint, toPoint: lastPoint)
        }
        
        mergeViews()
        
        stack.addObject(pointsArray)
        undoManager?.registerUndoWithTarget(self, selector: "popDrawing", object: nil)
        
        if !undoEnabled {
            delegate.undoEnabled()
            undoEnabled = true
        }
        if redoEnabled {
            delegate.redoDisabled()
            redoEnabled = false
        }
    }
    
    private func mergeViews() {
        // Merge tempImageView into mainImageView
        UIGraphicsBeginImageContext(mainImageView.frame.size)
        mainImageView.image?.drawInRect(mainImageView.frame, blendMode: CGBlendMode.Normal, alpha: 1.0)
        tempImageView.image?.drawInRect(tempImageView.frame, blendMode: CGBlendMode.Normal, alpha: brushColor.alpha)
        mainImageView.image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        tempImageView.image = nil
    }
    
    func popDrawing() {
        let array = stack.lastObject as! NSArray
        stack.removeLastObject()
        redrawLinePathsInStack()
        undoManager?.registerUndoWithTarget(self, selector: "pushDrawing:", object: array)
    }
    
    func pushDrawing(array: NSArray) {
        stack.addObject(array)
        drawLine(array)
        undoManager?.registerUndoWithTarget(self, selector: "popDrawing", object: nil)
    }
    
    private func redrawLinePathsInStack() {
        internalClear()
        for object in stack {
            let array = object as! NSArray
            drawLine(array)
        }
    }
    
    private func drawLine(array: NSArray) {
        if array.count == 1 {
            // Draw the one point
            let pointStr = array[0] as! String
            let point = CGPointFromString(pointStr)
            drawLineFrom(point, toPoint: point)
        }
        
        for i in 0 ..< array.count - 1 {
            let pointStr0 = array[i] as! String
            let pointStr1 = array[i+1] as! String
            
            let point0 = CGPointFromString(pointStr0)
            let point1 = CGPointFromString(pointStr1)
            drawLineFrom(point0, toPoint: point1)
        }
        mergeViews()
    }
    
    private func drawLineFrom(fromPoint: CGPoint, toPoint: CGPoint) {
        
        UIGraphicsBeginImageContext(self.frame.size)
        let context = UIGraphicsGetCurrentContext()
        
        CGContextMoveToPoint(context, fromPoint.x, fromPoint.y)
        CGContextAddLineToPoint(context, toPoint.x, toPoint.y)
        
        CGContextSetLineCap(context, CGLineCap.Round)
        CGContextSetLineWidth(context, brushWidth)
        CGContextSetRGBStrokeColor(context, brushColor.red, brushColor.green, brushColor.blue, 1.0)
        CGContextSetBlendMode(context, CGBlendMode.Normal)
        
        CGContextStrokePath(context)
        
        tempImageView.image?.drawInRect(tempImageView.frame)
        tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
        tempImageView.alpha = brushColor.alpha
        UIGraphicsEndImageContext()
    }
    
    public func exportDrawing() -> UIImage {
        UIGraphicsBeginImageContext(mainImageView.bounds.size)
        mainImageView.image?.drawInRect(mainImageView.frame)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    private func internalClear() {
        mainImageView.image = nil
        tempImageView.image = nil
    }
    
    public func clearDrawing() {
        internalClear()
        undoManager?.registerUndoWithTarget(self, selector: "pushAll:", object: stack)
        stack = []
    }
    
    private func pushAll(array: NSArray) {
        for mark in array {
            let markArray = mark as! NSArray
            drawLine(markArray)
            stack.addObject(markArray)
        }
        undoManager?.registerUndoWithTarget(self, selector: "clearDrawing", object: nil)
    }
    
    public func setColor(color: UIColor) {
        brushColor = CIColor(color: color)<commit_msg>Bug fix for undoManager (accidentally broke it in last commit)<commit_after>//
//  TouchDrawView.swift
//  TouchDraw
//
//  Created by <NAME> on 10/4/15.
//

public protocol TouchDrawViewDelegate {
    func undoEnabled()
    func undoDisabled()
    func redoEnabled()
    func redoDisabled()
}

public class TouchDrawView: UIView {

    public var delegate: TouchDrawViewDelegate!
    
    // Used for undo/redo
    private var stack: NSMutableArray!
    private var pointsArray: NSMutableArray!
    
    private var lastPoint = CGPoint.zero
    
    private var brushColor = CIColor(color: UIColor.blackColor())
    private var brushWidth = CGFloat(10.0)
    
    private var touchesMoved = false
    
    private var mainImageView = UIImageView()
    private var tempImageView = UIImageView()
    
    private var undoEnabled = false
    private var redoEnabled = false
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        initTouchDrawView()
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initTouchDrawView()
    }

    private func initTouchDrawView() {
        addSubview(mainImageView)
        addSubview(tempImageView)
        stack = []
    }
    
    override public func drawRect(rect: CGRect) {
        mainImageView.frame = rect
        tempImageView.frame = rect
    }
    
    // MARK: - Actions
    override public func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        touchesMoved = false
        if let touch = touches.first {
            lastPoint = touch.locationInView(self)
            pointsArray = []
            pointsArray.addObject(NSStringFromCGPoint(lastPoint))
        }
    }
    
    override public func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        touchesMoved = true
        if let touch = touches.first {
            let currentPoint = touch.locationInView(self)
            drawLineFrom(lastPoint, toPoint: currentPoint)
            
            lastPoint = currentPoint
            pointsArray.addObject(NSStringFromCGPoint(lastPoint))
        }
    }
    
    override public func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if !touchesMoved {
            // draw a single point
            drawLineFrom(lastPoint, toPoint: lastPoint)
        }
        
        mergeViews()
        
        stack.addObject(pointsArray)
        undoManager?.registerUndoWithTarget(self, selector: "popDrawing", object: nil)
        
        if !undoEnabled {
            delegate.undoEnabled()
            undoEnabled = true
        }
        if redoEnabled {
            delegate.redoDisabled()
            redoEnabled = false
        }
    }
    
    private func mergeViews() {
        // Merge tempImageView into mainImageView
        UIGraphicsBeginImageContext(mainImageView.frame.size)
        mainImageView.image?.drawInRect(mainImageView.frame, blendMode: CGBlendMode.Normal, alpha: 1.0)
        tempImageView.image?.drawInRect(tempImageView.frame, blendMode: CGBlendMode.Normal, alpha: brushColor.alpha)
        mainImageView.image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        tempImageView.image = nil
    }
    
    // Needs to be public for undoManager
    public func popDrawing() {
        let array = stack.lastObject as! NSArray
        stack.removeLastObject()
        redrawLinePathsInStack()
        undoManager?.registerUndoWithTarget(self, selector: "pushDrawing:", object: array)
    }
    
    // Needs to be public for undoManager
    public func pushDrawing(array: NSArray) {
        stack.addObject(array)
        drawLine(array)
        undoManager?.registerUndoWithTarget(self, selector: "popDrawing", object: nil)
    }
    
    private func redrawLinePathsInStack() {
        internalClear()
        for object in stack {
            let array = object as! NSArray
            drawLine(array)
        }
    }
    
    private func drawLine(array: NSArray) {
        if array.count == 1 {
            // Draw the one point
            let pointStr = array[0] as! String
            let point = CGPointFromString(pointStr)
            drawLineFrom(point, toPoint: point)
        }
        
        for i in 0 ..< array.count - 1 {
            let pointStr0 = array[i] as! String
            let pointStr1 = array[i+1] as! String
            
            let point0 = CGPointFromString(pointStr0)
            let point1 = CGPointFromString(pointStr1)
            drawLineFrom(point0, toPoint: point1)
        }
        mergeViews()
    }
    
    private func drawLineFrom(fromPoint: CGPoint, toPoint: CGPoint) {
        
        UIGraphicsBeginImageContext(self.frame.size)
        let context = UIGraphicsGetCurrentContext()
        
        CGContextMoveToPoint(context, fromPoint.x, fromPoint.y)
        CGContextAddLineToPoint(context, toPoint.x, toPoint.y)
        
        CGContextSetLineCap(context, CGLineCap.Round)
        CGContextSetLineWidth(context, brushWidth)
        CGContextSetRGBStrokeColor(context, brushColor.red, brushColor.green, brushColor.blue, 1.0)
        CGContextSetBlendMode(context, CGBlendMode.Normal)
        
        CGContextStrokePath(context)
        
        tempImageView.image?.drawInRect(tempImageView.frame)
        tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
        tempImageView.alpha = brushColor.alpha
        UIGraphicsEndImageContext()
    }
    
    public func exportDrawing() -> UIImage {
        UIGraphicsBeginImageContext(mainImageView.bounds.size)
        mainImageView.image?.drawInRect(mainImageView.frame)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    private func internalClear() {
        mainImageView.image = nil
        tempImageView.image = nil
    }
    
    public func clearDrawing() {
        internalClear()
        undoManager?.registerUndoWithTarget(self, selector: "pushAll:", object: stack)
        stack = []
    }
    
    // Needs to be public for undoManager
    public func pushAll(array: NSArray) {
        for mark in array {
            let markArray = mark as! NSArray
            drawLine(markArray)
            stack.addObject(markArray)
        }
        undoManager?.registerUndoWithTarget(self, selector: "clearDrawing", object: nil)
    }
    
    public func setColor(color: UIColor) {
        brushColor = CIColor(color: color)
{'fraction_non_alphanumeric': 0.07974406991260924, 'fraction_numerical': 0.0039013732833957553, 'mean_word_length': 2.2654777070063696, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, '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': '4012981', 'n_tokens_mistral': 3679, 'n_tokens_neox': 3524, 'n_words': 780}