diff --git a/Diagrams.playground/Pages/OffsetTriangleRing.xcplaygroundpage/Contents.swift b/Diagrams.playground/Pages/OffsetTriangleRing.xcplaygroundpage/Contents.swift index 1dae623..73a8054 100644 --- a/Diagrams.playground/Pages/OffsetTriangleRing.xcplaygroundpage/Contents.swift +++ b/Diagrams.playground/Pages/OffsetTriangleRing.xcplaygroundpage/Contents.swift @@ -4,15 +4,15 @@ import CoreGraphics extension Diagram { - func ring(radius radius: CGFloat, number: Int) -> Diagram { - let angles = 0.0.stride(to: 360.0, by: 360.0/Double(number)) + func ring(radius: CGFloat, number: Int) -> Diagram { + let angles = stride(from: 0.0, to: 360.0, by: 360.0/Double(number)) return diagrams(angles.map { - self.translate(x: 0, y: radius).rotate(CGFloat($0)) + translate(x: 0, y: radius).rotate(CGFloat($0)) } ) } - func iterateScale(s: CGFloat, offset: Point = (0,0), iterate: Int) -> Diagram { + func iterateScale(_ s: CGFloat, offset: Point = (0,0), iterate: Int) -> Diagram { if iterate == 0 { return self } return self + scale(s) .translate(x: offset.x, y: offset.y) @@ -26,7 +26,7 @@ let triangleRing = triangle.ring(radius: 220, number: 27) let diagram = triangleRing.iterateScale(0.618, offset: (15, 30), iterate: 7) showCoreGraphicsDiagram(size: CGSize(width: 600, height: 500)) { - drawDiagram(diagram)(context: $0) + drawDiagram(diagram, context: $0) } /*: To see the result, View>Assistant Editor>Show Assistant Editor (opt-cmd-Return). diff --git a/Diagrams.playground/Pages/StarRing.xcplaygroundpage/Contents.swift b/Diagrams.playground/Pages/StarRing.xcplaygroundpage/Contents.swift index 3daed63..fca2936 100644 --- a/Diagrams.playground/Pages/StarRing.xcplaygroundpage/Contents.swift +++ b/Diagrams.playground/Pages/StarRing.xcplaygroundpage/Contents.swift @@ -3,15 +3,15 @@ import CoreGraphics extension Diagram { - func ring(radius radius: CGFloat, number: Int) -> Diagram { - let angles = 0.0.stride(to: 360.0, by: 360.0/Double(number)) + func ring(radius: CGFloat, number: Int) -> Diagram { + let angles = stride(from: 0.0, to: 360.0, by: 360.0/Double(number)) return diagrams(angles.map { translate(x: 0, y: radius).rotate(CGFloat($0)) } ) } - func iterateScale(s: CGFloat, iterate: Int) -> Diagram { + func iterateScale(_ s: CGFloat, iterate: Int) -> Diagram { if iterate == 0 { return self } return self + scale(s).iterateScale(s, iterate: iterate - 1) } @@ -26,7 +26,7 @@ let starRing = star.ring(radius: 185, number: 16) let diagram = starRing.iterateScale(0.74, iterate: 6) showCoreGraphicsDiagram(size: CGSize(width: 600, height: 500)) { - drawDiagram(diagram)(context: $0) + drawDiagram(diagram, context: $0) } /*: To see the result, View>Assistant Editor>Show Assistant Editor (opt-cmd-Return). diff --git a/Diagrams.playground/Pages/Tree - The Larch.xcplaygroundpage/Contents.swift b/Diagrams.playground/Pages/Tree - The Larch.xcplaygroundpage/Contents.swift index e4ace97..9cdb17f 100644 --- a/Diagrams.playground/Pages/Tree - The Larch.xcplaygroundpage/Contents.swift +++ b/Diagrams.playground/Pages/Tree - The Larch.xcplaygroundpage/Contents.swift @@ -3,16 +3,8 @@ ## The Larch */ -import CoreGraphics - -func displayDiagram(diagram: Diagram) { - showCoreGraphicsDiagram(size: CGSize(width: 600, height: 600)) { - drawDiagram(diagram)(context: $0) - } -} - extension Diagram { - func tree(n: Int) -> Diagram { + func tree(_ n: Int) -> Diagram { if n == 0 { return self } let smallTree = tree(n - 1).scale(x: 0.33, y: 0.45) diff --git a/Diagrams.playground/Pages/Tree.xcplaygroundpage/Contents.swift b/Diagrams.playground/Pages/Tree.xcplaygroundpage/Contents.swift index 3b06a19..bdfff62 100644 --- a/Diagrams.playground/Pages/Tree.xcplaygroundpage/Contents.swift +++ b/Diagrams.playground/Pages/Tree.xcplaygroundpage/Contents.swift @@ -3,16 +3,8 @@ ## I want to be a tree */ -import CoreGraphics - -func displayDiagram(diagram: Diagram) { - showCoreGraphicsDiagram(size: CGSize(width: 600, height: 600)) { - drawDiagram(diagram)(context: $0) - } -} - extension Diagram { - func tree(n: Int) -> Diagram { + func tree(_ n: Int) -> Diagram { if n == 0 { return self } let smallTree = tree(n - 1).scale(x: 0.6, y: 0.67) diff --git a/Diagrams.playground/Sources/CGContextExtension.swift b/Diagrams.playground/Sources/CGContextExtension.swift index 8408c4d..8d9eba8 100644 --- a/Diagrams.playground/Sources/CGContextExtension.swift +++ b/Diagrams.playground/Sources/CGContextExtension.swift @@ -1,49 +1,47 @@ import CoreGraphics public extension CGContext { - func moveTo(position: CGPoint) { - CGContextMoveToPoint(self, position.x, position.y) - } - func lineTo(position: CGPoint) { - CGContextAddLineToPoint(self, position.x, position.y) - } - func drawPath(points: [CGPoint]) { - if let p = points.first { moveTo(p) } - points.forEach(lineTo) + func drawPath(_ points: [CGPoint]) { + if let p = points.first { + move(to: p) + points.forEach { addLine(to: $0) } + } } - func drawPolygon(points: [CGPoint]) { - if let p = points.last { moveTo(p) } - points.forEach(lineTo) + func drawPolygon(_ points: [CGPoint]) { + if let p = points.last { + move(to: p) + points.forEach { addLine(to: $0) } + } } func arc(radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) { - let arc = CGPathCreateMutable() - CGPathAddArc(arc, nil, 0, 0, radius, startAngle, endAngle, false) - CGContextAddPath(self, arc) + let arc = CGMutablePath() + arc.addArc(center: .zero, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true) + addPath(arc) } func circle(radius: CGFloat) { - arc(radius, startAngle: 0.0, endAngle: twoPi) + arc(radius: radius, startAngle: 0.0, endAngle: twoPi) } func saveContext(operation: () -> ()) { - CGContextSaveGState(self) + saveGState() operation() - CGContextRestoreGState(self) + restoreGState() } - func scale(x: CGFloat, _ y: CGFloat, operation: CGContext -> ()) { + func scale(x: CGFloat, y: CGFloat, operation: (CGContext) -> ()) { saveContext { - CGContextScaleCTM(self, x, y) + scaleBy(x: x, y: y) operation(self) } } - func translate(x: CGFloat, _ y: CGFloat, operation: CGContext -> ()) { + func translate(x: CGFloat, y: CGFloat, operation: (CGContext) -> ()) { saveContext { - CGContextTranslateCTM(self, x, y) + translateBy(x: x, y: y) operation(self) } } - func rotate(angle: CGFloat, operation: CGContext -> ()) { + func rotate(angle: CGFloat, operation: (CGContext) -> ()) { saveContext { - CGContextRotateCTM(self, angle) + rotate(by: angle) operation(self) } } -} \ No newline at end of file +} diff --git a/Diagrams.playground/Sources/CoreGraphicsDiagramView.swift b/Diagrams.playground/Sources/CoreGraphicsDiagramView.swift index a1e4e42..3fa7f16 100644 --- a/Diagrams.playground/Sources/CoreGraphicsDiagramView.swift +++ b/Diagrams.playground/Sources/CoreGraphicsDiagramView.swift @@ -1,24 +1,24 @@ import UIKit -import XCPlayground +import PlaygroundSupport /// `CoreGraphicsDiagramView` is a `UIView` that draws itself by calling a /// user-supplied function to generate paths in a `CGContext`, then strokes /// the context's current path, creating lines in a pleasing shade of blue. class CoreGraphicsDiagramView : UIView { - override func drawRect(rect: CGRect) { + override func draw(_ rect: CGRect) { if let context = UIGraphicsGetCurrentContext() { - CGContextSaveGState(context) - let flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, frame.height) - CGContextConcatCTM(context, flipVertical); - CGContextTranslateCTM(context, frame.width/2, frame.height/2) + context.saveGState() + let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: frame.height) + context.concatenate(flipVertical) + context.translateBy(x: frame.width/2, y: frame.height/2) draw(context) - let lightBlue = UIColor(red: 0.222, green: 0.617, blue: 0.976, alpha: 1.0).CGColor - CGContextSetStrokeColorWithColor(context, lightBlue) - CGContextSetLineWidth(context, 2) - CGContextStrokePath(context) - CGContextRestoreGState(context) + let lightBlue = UIColor(red: 0.222, green: 0.617, blue: 0.976, alpha: 1.0).cgColor + context.setStrokeColor(lightBlue) + context.setLineWidth(2) + context.strokePath() + context.restoreGState() } } @@ -28,9 +28,15 @@ class CoreGraphicsDiagramView : UIView { /// Shows a `UIView` in the current playground that draws itself by invoking /// `draw` on a `CGContext`, then stroking the context's current path in a /// pleasing light blue. -public func showCoreGraphicsDiagram(size size: CGSize, draw: (CGContext)->()) { - let diagramView = CoreGraphicsDiagramView(frame: CGRect(origin: CGPointZero, size: size)) +public func showCoreGraphicsDiagram(size: CGSize, draw: @escaping (CGContext)->()) { + let diagramView = CoreGraphicsDiagramView(frame: CGRect(origin: .zero, size: size)) diagramView.draw = draw diagramView.setNeedsDisplay() - XCPlaygroundPage.currentPage.liveView = diagramView + PlaygroundPage.current.liveView = diagramView +} + +public func displayDiagram(_ diagram: Diagram) { + showCoreGraphicsDiagram(size: CGSize(width: 600, height: 600)) { + drawDiagram(diagram, context: $0) + } } diff --git a/Diagrams.playground/Sources/Diagram.swift b/Diagrams.playground/Sources/Diagram.swift index 622e255..36b2e13 100644 --- a/Diagrams.playground/Sources/Diagram.swift +++ b/Diagrams.playground/Sources/Diagram.swift @@ -5,32 +5,32 @@ let toRadians = { $0 * CGFloat(M_PI / 180) } public typealias Point = (x: CGFloat, y: CGFloat) //: A `Diagram` as a recursive enum -public indirect enum Diagram { - case Polygon(corners: [CGPoint]) - case Line(points: [CGPoint]) +public enum Diagram { + case Polygon([CGPoint]) + case Line([CGPoint]) case Arc(radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) case Circle(radius: CGFloat) - case Scale(x: CGFloat, y: CGFloat, diagram: Diagram) - case Translate(x: CGFloat, y: CGFloat, diagram: Diagram) - case Rotate(angle: CGFloat, diagram: Diagram) + indirect case Scale(x: CGFloat, y: CGFloat, diagram: Diagram) + indirect case Translate(x: CGFloat, y: CGFloat, diagram: Diagram) + indirect case Rotate(angle: CGFloat, diagram: Diagram) case Diagrams([Diagram]) } // convenience methods to allow chaining of transformations public extension Diagram { - func scale(s: CGFloat) -> Diagram { + func scale(_ s: CGFloat) -> Diagram { return .Scale(x: s, y: s, diagram: self) } - func scale(x x: CGFloat, y: CGFloat) -> Diagram { + func scale(x: CGFloat, y: CGFloat) -> Diagram { return .Scale(x: x, y: y, diagram: self) } - func translate(x x: CGFloat, y: CGFloat) -> Diagram { + func translate(x: CGFloat, y: CGFloat) -> Diagram { return .Translate(x: x, y: y, diagram: self) } - func rotate(x: CGFloat) -> Diagram { + func rotate(_ x: CGFloat) -> Diagram { return .Rotate(angle: x, diagram: self) } } @@ -38,28 +38,28 @@ public extension Diagram { // convenience functions to handle conversion from `Point` to `CGPoint` // (defining an Array of `CGpoint`s is really verbose – hence the use of the `tuple` typealias `Point`) public func line(ps: [Point]) -> Diagram { - return .Line(points: ps.map { x, y in CGPoint(x: x, y: y) }) + return .Line(ps.map { x, y in CGPoint(x: x, y: y) }) } -public func polygon(ps: [Point]) -> Diagram { - return .Polygon(corners: ps.map { x, y in CGPoint(x: x, y: y) }) +public func polygon(_ ps: [Point]) -> Diagram { + return .Polygon(ps.map { x, y in CGPoint(x: x, y: y) }) } -public func rectanglePath(width: CGFloat, _ height: CGFloat) -> [Point] { +public func rectanglePath(width: CGFloat, height: CGFloat) -> [Point] { let sx = width / 2 let sy = height / 2 return [(-sx, -sy), (-sx, sy), (sx, sy), (sx, -sy)] } public func rectangle(x: CGFloat, _ y: CGFloat) -> Diagram { - return polygon(rectanglePath(x, y)) + return polygon(rectanglePath(width: x, height: y)) } -public func circle(radius: CGFloat) -> Diagram { +public func circle(_ radius: CGFloat) -> Diagram { return .Circle(radius: radius) } -public func diagrams(diagrams: [Diagram]) -> Diagram { +public func diagrams(_ diagrams: [Diagram]) -> Diagram { return .Diagrams(diagrams) } @@ -97,14 +97,14 @@ public func == (lhs: Diagram, rhs: Diagram) -> Bool { } //: Infix operator for combining Diagrams -public func + (d1:Diagram, d2:Diagram) -> Diagram { +public func + (d1: Diagram, d2: Diagram) -> Diagram { return diagrams([d1, d2]) } //: ## Do some drawing! //: //: A recursive function responsible for drawing a diagram into a CGContext -public func drawDiagram(diagram: Diagram)(context: CGContext) -> () { +public func drawDiagram(_ diagram: Diagram, context: CGContext) -> () { switch diagram { case let .Polygon(corners): context.drawPolygon(corners) @@ -113,28 +113,27 @@ public func drawDiagram(diagram: Diagram)(context: CGContext) -> () { context.drawPath(points) case let .Arc(r, a1, a2): - context.arc(r, startAngle: toRadians(a1), endAngle: toRadians(a2)) + context.arc(radius: r, startAngle: toRadians(a1), endAngle: toRadians(a2)) case let .Circle(radius): - context.circle(radius) - + context.circle(radius: radius) + case let .Scale(x, y, diagram): - context.scale(x, y) { - drawDiagram(diagram)(context: $0) + context.scale(x: x, y: y) { + drawDiagram(diagram, context: $0) } case let .Translate(x, y, diagram): - context.translate(x, y) { - drawDiagram(diagram)(context: $0) + context.translate(x: x, y: y) { + drawDiagram(diagram, context: $0) } case let .Rotate(angle, diagram): - context.rotate(toRadians(angle)) { - drawDiagram(diagram)(context: $0) + context.rotate(angle: toRadians(angle)) { + drawDiagram(diagram, context: $0) } case let .Diagrams(diagrams): - diagrams.forEach { d in drawDiagram(d)(context: context) } + diagrams.forEach { d in drawDiagram(d, context: context) } } } -