Explorar o código

Platform separation (#4178)

* Added system dark mode support for primary label colors in the framework

Moved Color to its own Platform file

* Relocated color file

* Reverted demo change

* Separated `Platform` into multiple files for better organization

* Updated from master
Jacob Christie %!s(int64=5) %!d(string=hai) anos
pai
achega
b630e8885e

+ 16 - 0
Charts.xcodeproj/project.pbxproj

@@ -124,6 +124,10 @@
 		C33E1AF5471A60BA42DAF52E /* RadarHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F368CF209744D8F3B85B1028 /* RadarHighlighter.swift */; };
 		C3F0DDB7F0A922F0BB7EDB8A /* IBarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A53A9E42FC07FFDACA937C1 /* IBarChartDataSet.swift */; };
 		C7B150D740255670DEB9F455 /* Charts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65AD9E95D9ED4DC0BD73A743 /* Charts.framework */; };
+		C9AA360A2355F01F00C97D93 /* Platform+Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9AA36092355F01F00C97D93 /* Platform+Color.swift */; };
+		C9F3DC262355F791000C3215 /* Platform+Graphics.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9F3DC242355F791000C3215 /* Platform+Graphics.swift */; };
+		C9F3DC272355F791000C3215 /* Platform+Gestures.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9F3DC252355F791000C3215 /* Platform+Gestures.swift */; };
+		C9F3DC292355FA2F000C3215 /* Platform+Touch Handling.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9F3DC282355FA2F000C3215 /* Platform+Touch Handling.swift */; };
 		CB785FE9B6B312408D17BC3B /* ChartUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FDA09EF973925A110506799 /* ChartUtils.swift */; };
 		CC7F8198A13249B5DEBBF25E /* AnimatedViewPortJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 710D7C9B2F1DB4A331EE405A /* AnimatedViewPortJob.swift */; };
 		CEF68F42A5390A73113F3663 /* Renderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F66B32AD8A878CBD6DB6ED2 /* Renderer.swift */; };
@@ -289,6 +293,10 @@
 		C75935E899183DDFA181E2CC /* AxisRendererBase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AxisRendererBase.swift; path = Source/Charts/Renderers/AxisRendererBase.swift; sourceTree = "<group>"; };
 		C8C9A105A7DB64F39DDA648B /* ComponentBase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ComponentBase.swift; path = Source/Charts/Components/ComponentBase.swift; sourceTree = "<group>"; };
 		C8FB6219B143F8F7DA762950 /* TriangleShapeRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TriangleShapeRenderer.swift; path = Source/Charts/Renderers/Scatter/TriangleShapeRenderer.swift; sourceTree = "<group>"; };
+		C9AA36092355F01F00C97D93 /* Platform+Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Platform+Color.swift"; path = "Source/Charts/Utils/Platform+Color.swift"; sourceTree = "<group>"; };
+		C9F3DC242355F791000C3215 /* Platform+Graphics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Platform+Graphics.swift"; path = "Source/Charts/Utils/Platform+Graphics.swift"; sourceTree = "<group>"; };
+		C9F3DC252355F791000C3215 /* Platform+Gestures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Platform+Gestures.swift"; path = "Source/Charts/Utils/Platform+Gestures.swift"; sourceTree = "<group>"; };
+		C9F3DC282355FA2F000C3215 /* Platform+Touch Handling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Platform+Touch Handling.swift"; path = "Source/Charts/Utils/Platform+Touch Handling.swift"; sourceTree = "<group>"; };
 		C9FE42E868A225C116537368 /* ChartBaseDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartBaseDataSet.swift; path = Source/Charts/Data/Implementations/ChartBaseDataSet.swift; sourceTree = "<group>"; };
 		CB1DD1A0F64266A10EE94194 /* ScatterChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ScatterChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/ScatterChartDataSet.swift; sourceTree = "<group>"; };
 		D2E1819D72CD7B6C4A4E8048 /* LineChartTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LineChartTests.swift; path = Tests/Charts/LineChartTests.swift; sourceTree = "<group>"; };
@@ -590,6 +598,10 @@
 				5A4CFFFB65819121595F06F1 /* Fill.swift */,
 				3ED23C354AFE81818D78E645 /* Platform.swift */,
 				97AD2D4520AF917100F9C24A /* Platform+Accessibility.swift */,
+				C9AA36092355F01F00C97D93 /* Platform+Color.swift */,
+				C9F3DC252355F791000C3215 /* Platform+Gestures.swift */,
+				C9F3DC242355F791000C3215 /* Platform+Graphics.swift */,
+				C9F3DC282355FA2F000C3215 /* Platform+Touch Handling.swift */,
 				FF475B9593B9898853814340 /* Transformer.swift */,
 				324C9127B53A8D39C8B49277 /* TransformerHorizontalBarChart.swift */,
 				72EAEBB7CF73E33565FC2896 /* ViewPortHandler.swift */,
@@ -839,6 +851,7 @@
 				DBC9DB402CC9BB84B76968C4 /* Description.swift in Sources */,
 				03960E8148C6AEDACE4B77CC /* IMarker.swift in Sources */,
 				ECE7EAE7179A7F57CE9BBD8F /* Legend.swift in Sources */,
+				C9F3DC272355F791000C3215 /* Platform+Gestures.swift in Sources */,
 				C20A62D8CB9120523D5FB650 /* LegendEntry.swift in Sources */,
 				369DEB23452CB436A3A1A644 /* MarkerImage.swift in Sources */,
 				9360348A04723E653FBC8B18 /* MarkerView.swift in Sources */,
@@ -848,6 +861,7 @@
 				3395682A1E27756651FF6F4D /* BarChartData.swift in Sources */,
 				45C459FA25DFCBE62FA6A06C /* BarChartDataEntry.swift in Sources */,
 				17E994DA88777AA1D8CCFC58 /* BarChartDataSet.swift in Sources */,
+				C9AA360A2355F01F00C97D93 /* Platform+Color.swift in Sources */,
 				7C9CE6718D18859A35146098 /* BarLineScatterCandleBubbleChartData.swift in Sources */,
 				53A91F6F86740E26FE733639 /* BarLineScatterCandleBubbleChartDataSet.swift in Sources */,
 				E68CA3DC66EB638C956E09B8 /* BubbleChartData.swift in Sources */,
@@ -893,6 +907,7 @@
 				B6C9F450D937B87224D29D5C /* IFillFormatter.swift in Sources */,
 				967EE2EDDE3337C5C4337C59 /* IndexAxisValueFormatter.swift in Sources */,
 				A40ACF0CCE96EEE104B0463D /* IValueFormatter.swift in Sources */,
+				C9F3DC262355F791000C3215 /* Platform+Graphics.swift in Sources */,
 				3CBE95F1E9394FA08CDCF31E /* BarHighlighter.swift in Sources */,
 				D326491E8BCDE54A0921E137 /* ChartHighlighter.swift in Sources */,
 				64FA1EDB4DC1F65727D52D10 /* CombinedHighlighter.swift in Sources */,
@@ -908,6 +923,7 @@
 				4272DA5D44AF7DA05A5A8287 /* BubbleChartDataProvider.swift in Sources */,
 				30DCC4BAA5601B154ABADA13 /* CandleChartDataProvider.swift in Sources */,
 				FD37AAC0270F390FFC470A65 /* ChartDataProvider.swift in Sources */,
+				C9F3DC292355FA2F000C3215 /* Platform+Touch Handling.swift in Sources */,
 				65EA404AE098EBCE8D5DE04B /* CombinedChartDataProvider.swift in Sources */,
 				2BA03CEC36BADCF682F1328B /* LineChartDataProvider.swift in Sources */,
 				0511E43EF3FD2CDE7F7F15DB /* ScatterChartDataProvider.swift in Sources */,

+ 1 - 3
ChartsDemo-iOS/Swift/Demos/PiePolylineChartViewController.swift

@@ -6,9 +6,7 @@
 //  Copyright © 2017 jc. All rights reserved.
 //
 
-#if canImport(UIKit)
-    import UIKit
-#endif
+import UIKit
 import Charts
 
 class PiePolylineChartViewController: DemoBaseViewController {

+ 1 - 1
Source/Charts/Charts/ChartViewBase.swift

@@ -98,7 +98,7 @@ open class ChartViewBase: NSUIView, ChartDataProvider, AnimatorDelegate
     @objc open var noDataFont = NSUIFont.systemFont(ofSize: 12)
     
     /// color of the no data text
-    @objc open var noDataTextColor: NSUIColor = NSUIColor.labelOrBlack
+    @objc open var noDataTextColor: NSUIColor = .labelOrBlack
 
     /// alignment of the no data text
     @objc open var noDataTextAlignment: NSTextAlignment = .left

+ 2 - 2
Source/Charts/Data/Implementations/ChartBaseDataSet.swift

@@ -21,7 +21,7 @@ open class ChartBaseDataSet: NSObject, IChartDataSet, NSCopying
         
         // default color
         colors.append(NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0))
-        valueColors.append(NSUIColor.labelOrBlack)
+        valueColors.append(.labelOrBlack)
     }
     
     @objc public init(label: String?)
@@ -30,7 +30,7 @@ open class ChartBaseDataSet: NSObject, IChartDataSet, NSCopying
         
         // default color
         colors.append(NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0))
-        valueColors.append(NSUIColor.labelOrBlack)
+        valueColors.append(.labelOrBlack)
         
         self.label = label
     }

+ 53 - 0
Source/Charts/Utils/Platform+Color.swift

@@ -0,0 +1,53 @@
+//
+//  Platform+Color.swift
+//  Charts
+//
+//  Created by Jacob Christie on 2019-10-15.
+//
+
+#if canImport(UIKit)
+import UIKit
+
+public typealias NSUIColor = UIColor
+private func fetchLabelColor() -> UIColor
+{
+    if #available(iOS 13, tvOS 13, *)
+    {
+        return .label
+    }
+    else
+    {
+        return .black
+    }
+}
+private let labelColor: UIColor = fetchLabelColor()
+
+extension UIColor
+{
+    static var labelOrBlack: UIColor { labelColor }
+}
+#endif
+
+#if canImport(AppKit)
+
+import AppKit
+
+public typealias NSUIColor = NSColor
+private func fetchLabelColor() -> NSColor
+{
+    if #available(macOS 10.14, *)
+    {
+        return .labelColor
+    }
+    else
+    {
+        return .black
+    }
+}
+private let labelColor: NSColor = fetchLabelColor()
+
+extension NSColor
+{
+    static var labelOrBlack: NSColor { labelColor }
+}
+#endif

+ 168 - 0
Source/Charts/Utils/Platform+Gestures.swift

@@ -0,0 +1,168 @@
+//
+//  Platform+Gestures.swift
+//  
+//
+//  Created by Jacob Christie on 2019-10-15.
+//
+
+// MARK: - UIKit
+#if canImport(UIKit)
+import UIKit
+
+public typealias NSUIGestureRecognizer = UIGestureRecognizer
+public typealias NSUIGestureRecognizerState = UIGestureRecognizer.State
+public typealias NSUIGestureRecognizerDelegate = UIGestureRecognizerDelegate
+public typealias NSUITapGestureRecognizer = UITapGestureRecognizer
+public typealias NSUIPanGestureRecognizer = UIPanGestureRecognizer
+
+extension NSUITapGestureRecognizer
+{
+    @objc final func nsuiNumberOfTouches() -> Int
+    {
+        return numberOfTouches
+    }
+
+    @objc final var nsuiNumberOfTapsRequired: Int
+        {
+        get
+        {
+            return self.numberOfTapsRequired
+        }
+        set
+        {
+            self.numberOfTapsRequired = newValue
+        }
+    }
+}
+
+extension NSUIPanGestureRecognizer
+{
+    @objc final func nsuiNumberOfTouches() -> Int
+    {
+        return numberOfTouches
+    }
+
+    @objc final func nsuiLocationOfTouch(_ touch: Int, inView: UIView?) -> CGPoint
+    {
+        return super.location(ofTouch: touch, in: inView)
+    }
+}
+
+#if !os(tvOS)
+public typealias NSUIPinchGestureRecognizer = UIPinchGestureRecognizer
+public typealias NSUIRotationGestureRecognizer = UIRotationGestureRecognizer
+
+extension NSUIRotationGestureRecognizer
+{
+    @objc final var nsuiRotation: CGFloat
+        {
+        get { return rotation }
+        set { rotation = newValue }
+    }
+}
+
+extension NSUIPinchGestureRecognizer
+{
+    @objc final var nsuiScale: CGFloat
+        {
+        get
+        {
+            return scale
+        }
+        set
+        {
+            scale = newValue
+        }
+    }
+
+    @objc final func nsuiLocationOfTouch(_ touch: Int, inView: UIView?) -> CGPoint
+    {
+        return super.location(ofTouch: touch, in: inView)
+    }
+}
+#endif
+#endif
+
+// MARK: - AppKit
+#if canImport(AppKit)
+import AppKit
+
+public typealias NSUIGestureRecognizer = NSGestureRecognizer
+public typealias NSUIGestureRecognizerState = NSGestureRecognizer.State
+public typealias NSUIGestureRecognizerDelegate = NSGestureRecognizerDelegate
+public typealias NSUITapGestureRecognizer = NSClickGestureRecognizer
+public typealias NSUIPanGestureRecognizer = NSPanGestureRecognizer
+public typealias NSUIPinchGestureRecognizer = NSMagnificationGestureRecognizer
+public typealias NSUIRotationGestureRecognizer = NSRotationGestureRecognizer
+
+/** The 'tap' gesture is mapped to clicks. */
+extension NSUITapGestureRecognizer
+{
+    final func nsuiNumberOfTouches() -> Int
+    {
+        return 1
+    }
+
+    final var nsuiNumberOfTapsRequired: Int
+        {
+        get
+        {
+            return self.numberOfClicksRequired
+        }
+        set
+        {
+            self.numberOfClicksRequired = newValue
+        }
+    }
+}
+
+extension NSUIPanGestureRecognizer
+{
+    final func nsuiNumberOfTouches() -> Int
+    {
+        return 1
+    }
+
+    /// FIXME: Currently there are no more than 1 touch in OSX gestures, and not way to create custom touch gestures.
+    final func nsuiLocationOfTouch(_ touch: Int, inView: NSView?) -> NSPoint
+    {
+        return super.location(in: inView)
+    }
+}
+
+extension NSUIRotationGestureRecognizer
+{
+    /// FIXME: Currently there are no velocities in OSX gestures, and not way to create custom touch gestures.
+    final var velocity: CGFloat
+    {
+        return 0.1
+    }
+
+    final var nsuiRotation: CGFloat
+        {
+        get { return -rotation }
+        set { rotation = -newValue }
+    }
+}
+
+extension NSUIPinchGestureRecognizer
+{
+    final var nsuiScale: CGFloat
+        {
+        get
+        {
+            return magnification + 1.0
+        }
+        set
+        {
+            magnification = newValue - 1.0
+        }
+    }
+
+    /// FIXME: Currently there are no more than 1 touch in OSX gestures, and not way to create custom touch gestures.
+    final func nsuiLocationOfTouch(_ touch: Int, inView view: NSView?) -> NSPoint
+    {
+        return super.location(in: view)
+    }
+}
+#endif

+ 144 - 0
Source/Charts/Utils/Platform+Graphics.swift

@@ -0,0 +1,144 @@
+//
+//  Platform+Graphics.swift
+//  
+//
+//  Created by Jacob Christie on 2019-10-15.
+//
+
+// MARK: - UIKit
+#if canImport(UIKit)
+import UIKit
+
+func NSUIGraphicsGetCurrentContext() -> CGContext?
+{
+    return UIGraphicsGetCurrentContext()
+}
+
+func NSUIGraphicsGetImageFromCurrentImageContext() -> NSUIImage!
+{
+    return UIGraphicsGetImageFromCurrentImageContext()
+}
+
+func NSUIGraphicsPushContext(_ context: CGContext)
+{
+    UIGraphicsPushContext(context)
+}
+
+func NSUIGraphicsPopContext()
+{
+    UIGraphicsPopContext()
+}
+
+func NSUIGraphicsEndImageContext()
+{
+    UIGraphicsEndImageContext()
+}
+
+func NSUIImagePNGRepresentation(_ image: NSUIImage) -> Data?
+{
+    return image.pngData()
+}
+
+func NSUIImageJPEGRepresentation(_ image: NSUIImage, _ quality: CGFloat = 0.8) -> Data?
+{
+    return image.jpegData(compressionQuality: quality)
+}
+
+func NSUIGraphicsBeginImageContextWithOptions(_ size: CGSize, _ opaque: Bool, _ scale: CGFloat)
+{
+    UIGraphicsBeginImageContextWithOptions(size, opaque, scale)
+}
+#endif
+
+// MARK: - AppKit
+#if canImport(AppKit)
+import AppKit
+
+func NSUIGraphicsGetCurrentContext() -> CGContext?
+{
+    return NSGraphicsContext.current?.cgContext
+}
+
+func NSUIGraphicsPushContext(_ context: CGContext)
+{
+    let cx = NSGraphicsContext(cgContext: context, flipped: true)
+    NSGraphicsContext.saveGraphicsState()
+    NSGraphicsContext.current = cx
+}
+
+func NSUIGraphicsPopContext()
+{
+    NSGraphicsContext.restoreGraphicsState()
+}
+
+func NSUIImagePNGRepresentation(_ image: NSUIImage) -> Data?
+{
+    image.lockFocus()
+    let rep = NSBitmapImageRep(focusedViewRect: NSMakeRect(0, 0, image.size.width, image.size.height))
+    image.unlockFocus()
+    return rep?.representation(using: .png, properties: [:])
+}
+
+func NSUIImageJPEGRepresentation(_ image: NSUIImage, _ quality: CGFloat = 0.9) -> Data?
+{
+    image.lockFocus()
+    let rep = NSBitmapImageRep(focusedViewRect: NSMakeRect(0, 0, image.size.width, image.size.height))
+    image.unlockFocus()
+    return rep?.representation(using: .jpeg, properties: [NSBitmapImageRep.PropertyKey.compressionFactor: quality])
+}
+
+private var imageContextStack: [CGFloat] = []
+
+func NSUIGraphicsBeginImageContextWithOptions(_ size: CGSize, _ opaque: Bool, _ scale: CGFloat)
+{
+    var scale = scale
+    if scale == 0.0
+    {
+        scale = NSScreen.main?.backingScaleFactor ?? 1.0
+    }
+
+    let width = Int(size.width * scale)
+    let height = Int(size.height * scale)
+
+    if width > 0 && height > 0
+    {
+        imageContextStack.append(scale)
+
+        let colorSpace = CGColorSpaceCreateDeviceRGB()
+
+        guard let ctx = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: 4*width, space: colorSpace, bitmapInfo: (opaque ?  CGImageAlphaInfo.noneSkipFirst.rawValue : CGImageAlphaInfo.premultipliedFirst.rawValue))
+            else { return }
+
+        ctx.concatenate(CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: CGFloat(height)))
+        ctx.scaleBy(x: scale, y: scale)
+        NSUIGraphicsPushContext(ctx)
+    }
+}
+
+func NSUIGraphicsGetImageFromCurrentImageContext() -> NSUIImage?
+{
+    if !imageContextStack.isEmpty
+    {
+        guard let ctx = NSUIGraphicsGetCurrentContext()
+            else { return nil }
+
+        let scale = imageContextStack.last!
+        if let theCGImage = ctx.makeImage()
+        {
+            let size = CGSize(width: CGFloat(ctx.width) / scale, height: CGFloat(ctx.height) / scale)
+            let image = NSImage(cgImage: theCGImage, size: size)
+            return image
+        }
+    }
+    return nil
+}
+
+func NSUIGraphicsEndImageContext()
+{
+    if imageContextStack.last != nil
+    {
+        imageContextStack.removeLast()
+        NSUIGraphicsPopContext()
+    }
+}
+#endif

+ 130 - 0
Source/Charts/Utils/Platform+Touch Handling.swift

@@ -0,0 +1,130 @@
+//
+//  Platform+Touch Handling.swift
+//  Charts
+//
+//  Created by Jacob Christie on 2019-10-15.
+//
+
+#if canImport(UIKit)
+import UIKit
+
+public typealias NSUIEvent = UIEvent
+public typealias NSUITouch = UITouch
+
+@objc
+extension NSUIView {
+    public final override func touchesBegan(_ touches: Set<NSUITouch>, with event: NSUIEvent?)
+    {
+        self.nsuiTouchesBegan(touches, withEvent: event)
+    }
+
+    public final override func touchesMoved(_ touches: Set<NSUITouch>, with event: NSUIEvent?)
+    {
+        self.nsuiTouchesMoved(touches, withEvent: event)
+    }
+
+    public final override func touchesEnded(_ touches: Set<NSUITouch>, with event: NSUIEvent?)
+    {
+        self.nsuiTouchesEnded(touches, withEvent: event)
+    }
+
+    public final override func touchesCancelled(_ touches: Set<NSUITouch>, with event: NSUIEvent?)
+    {
+        self.nsuiTouchesCancelled(touches, withEvent: event)
+    }
+
+    open func nsuiTouchesBegan(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
+    {
+        super.touchesBegan(touches, with: event!)
+    }
+
+    open func nsuiTouchesMoved(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
+    {
+        super.touchesMoved(touches, with: event!)
+    }
+
+    open func nsuiTouchesEnded(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
+    {
+        super.touchesEnded(touches, with: event!)
+    }
+
+    open func nsuiTouchesCancelled(_ touches: Set<NSUITouch>?, withEvent event: NSUIEvent?)
+    {
+        super.touchesCancelled(touches!, with: event!)
+    }
+}
+
+extension UIView
+{
+    @objc final var nsuiGestureRecognizers: [NSUIGestureRecognizer]?
+    {
+        return self.gestureRecognizers
+    }
+}
+#endif
+
+
+#if canImport(AppKit)
+import AppKit
+
+public typealias NSUIEvent = NSEvent
+public typealias NSUITouch = NSTouch
+
+@objc
+extension NSUIView
+{
+    public final override func touchesBegan(with event: NSEvent)
+    {
+        self.nsuiTouchesBegan(event.touches(matching: .any, in: self), withEvent: event)
+    }
+
+    public final override func touchesEnded(with event: NSEvent)
+    {
+        self.nsuiTouchesEnded(event.touches(matching: .any, in: self), withEvent: event)
+    }
+
+    public final override func touchesMoved(with event: NSEvent)
+    {
+        self.nsuiTouchesMoved(event.touches(matching: .any, in: self), withEvent: event)
+    }
+
+    open override func touchesCancelled(with event: NSEvent)
+    {
+        self.nsuiTouchesCancelled(event.touches(matching: .any, in: self), withEvent: event)
+    }
+
+    open func nsuiTouchesBegan(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
+    {
+        super.touchesBegan(with: event!)
+    }
+
+    open func nsuiTouchesMoved(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
+    {
+        super.touchesMoved(with: event!)
+    }
+
+    open func nsuiTouchesEnded(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
+    {
+        super.touchesEnded(with: event!)
+    }
+
+    open func nsuiTouchesCancelled(_ touches: Set<NSUITouch>?, withEvent event: NSUIEvent?)
+    {
+        super.touchesCancelled(with: event!)
+    }
+}
+
+extension NSTouch
+{
+    /** Touch locations on OS X are relative to the trackpad, whereas on iOS they are actually *on* the view. */
+    func locationInView(view: NSView) -> NSPoint
+    {
+        let n = self.normalizedPosition
+        let b = view.bounds
+        return NSPoint(
+            x: b.origin.x + b.size.width * n.x,
+            y: b.origin.y + b.size.height * n.y
+        )
+    }
+}
+#endif

+ 1 - 423
Source/Charts/Utils/Platform.swift

@@ -9,164 +9,19 @@ import Foundation
 #endif
 
 public typealias NSUIFont = UIFont
-public typealias NSUIColor = UIColor
-public typealias NSUIEvent = UIEvent
-public typealias NSUITouch = UITouch
 public typealias NSUIImage = UIImage
 public typealias NSUIScrollView = UIScrollView
-public typealias NSUIGestureRecognizer = UIGestureRecognizer
-public typealias NSUIGestureRecognizerState = UIGestureRecognizer.State
-public typealias NSUIGestureRecognizerDelegate = UIGestureRecognizerDelegate
-public typealias NSUITapGestureRecognizer = UITapGestureRecognizer
-public typealias NSUIPanGestureRecognizer = UIPanGestureRecognizer
-#if !os(tvOS)
-public typealias NSUIPinchGestureRecognizer = UIPinchGestureRecognizer
-public typealias NSUIRotationGestureRecognizer = UIRotationGestureRecognizer
-#endif
 public typealias NSUIScreen = UIScreen
-
 public typealias NSUIDisplayLink = CADisplayLink
 
-private func fetchLabelColor() -> UIColor
-{
-    if #available(iOS 13, tvOS 13, *)
-    {
-        return .label
-    }
-    else
-    {
-        return .black
-    }
-}
-private let labelColor: UIColor = fetchLabelColor()
-
-extension UIColor
-{
-    static var labelOrBlack: UIColor { labelColor }
-}
-
-extension NSUITapGestureRecognizer
-{
-    @objc final func nsuiNumberOfTouches() -> Int
-    {
-        return numberOfTouches
-    }
-
-    @objc final var nsuiNumberOfTapsRequired: Int
-        {
-        get
-        {
-            return self.numberOfTapsRequired
-        }
-        set
-        {
-            self.numberOfTapsRequired = newValue
-        }
-    }
-}
-
-extension NSUIPanGestureRecognizer
-{
-    @objc final func nsuiNumberOfTouches() -> Int
-    {
-        return numberOfTouches
-    }
-
-    @objc final func nsuiLocationOfTouch(_ touch: Int, inView: UIView?) -> CGPoint
-    {
-        return super.location(ofTouch: touch, in: inView)
-    }
-}
-
-#if !os(tvOS)
-extension NSUIRotationGestureRecognizer
-{
-    @objc final var nsuiRotation: CGFloat
-        {
-        get { return rotation }
-        set { rotation = newValue }
-    }
-}
-#endif
-
-#if !os(tvOS)
-extension NSUIPinchGestureRecognizer
-{
-    @objc final var nsuiScale: CGFloat
-        {
-        get
-        {
-            return scale
-        }
-        set
-        {
-            scale = newValue
-        }
-    }
-
-    @objc final func nsuiLocationOfTouch(_ touch: Int, inView: UIView?) -> CGPoint
-    {
-        return super.location(ofTouch: touch, in: inView)
-    }
-}
-#endif
-
 open class NSUIView: UIView
 {
-    public final override func touchesBegan(_ touches: Set<NSUITouch>, with event: NSUIEvent?)
-    {
-        self.nsuiTouchesBegan(touches, withEvent: event)
-    }
-
-    public final override func touchesMoved(_ touches: Set<NSUITouch>, with event: NSUIEvent?)
-    {
-        self.nsuiTouchesMoved(touches, withEvent: event)
-    }
-
-    public final override func touchesEnded(_ touches: Set<NSUITouch>, with event: NSUIEvent?)
-    {
-        self.nsuiTouchesEnded(touches, withEvent: event)
-    }
-
-    public final override func touchesCancelled(_ touches: Set<NSUITouch>, with event: NSUIEvent?)
-    {
-        self.nsuiTouchesCancelled(touches, withEvent: event)
-    }
-
-    @objc open func nsuiTouchesBegan(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
-    {
-        super.touchesBegan(touches, with: event!)
-    }
-
-    @objc open func nsuiTouchesMoved(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
-    {
-        super.touchesMoved(touches, with: event!)
-    }
-
-    @objc open func nsuiTouchesEnded(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
-    {
-        super.touchesEnded(touches, with: event!)
-    }
-
-    @objc open func nsuiTouchesCancelled(_ touches: Set<NSUITouch>?, withEvent event: NSUIEvent?)
-    {
-        super.touchesCancelled(touches!, with: event!)
-    }
-
     @objc var nsuiLayer: CALayer?
     {
         return self.layer
     }
 }
 
-extension UIView
-{
-    @objc final var nsuiGestureRecognizers: [NSUIGestureRecognizer]?
-    {
-        return self.gestureRecognizers
-    }
-}
-
 extension UIScrollView
 {
     @objc var nsuiIsScrollEnabled: Bool
@@ -184,51 +39,11 @@ extension UIScreen
     }
 }
 
-func NSUIGraphicsGetCurrentContext() -> CGContext?
-{
-    return UIGraphicsGetCurrentContext()
-}
-
-func NSUIGraphicsGetImageFromCurrentImageContext() -> NSUIImage!
-{
-    return UIGraphicsGetImageFromCurrentImageContext()
-}
-
-func NSUIGraphicsPushContext(_ context: CGContext)
-{
-    UIGraphicsPushContext(context)
-}
-
-func NSUIGraphicsPopContext()
-{
-    UIGraphicsPopContext()
-}
-
-func NSUIGraphicsEndImageContext()
-{
-    UIGraphicsEndImageContext()
-}
-
-func NSUIImagePNGRepresentation(_ image: NSUIImage) -> Data?
-{
-    return image.pngData()
-}
-
-func NSUIImageJPEGRepresentation(_ image: NSUIImage, _ quality: CGFloat = 0.8) -> Data?
-{
-    return image.jpegData(compressionQuality: quality)
-}
-
 func NSUIMainScreen() -> NSUIScreen?
 {
     return NSUIScreen.main
 }
 
-func NSUIGraphicsBeginImageContextWithOptions(_ size: CGSize, _ opaque: Bool, _ scale: CGFloat)
-{
-    UIGraphicsBeginImageContextWithOptions(size, opaque, scale)
-}
-
 #endif
 
 #if os(OSX)
@@ -236,18 +51,8 @@ import Cocoa
 import Quartz
 
 public typealias NSUIFont = NSFont
-public typealias NSUIColor = NSColor
-public typealias NSUIEvent = NSEvent
-public typealias NSUITouch = NSTouch
 public typealias NSUIImage = NSImage
 public typealias NSUIScrollView = NSScrollView
-public typealias NSUIGestureRecognizer = NSGestureRecognizer
-public typealias NSUIGestureRecognizerState = NSGestureRecognizer.State
-public typealias NSUIGestureRecognizerDelegate = NSGestureRecognizerDelegate
-public typealias NSUITapGestureRecognizer = NSClickGestureRecognizer
-public typealias NSUIPanGestureRecognizer = NSPanGestureRecognizer
-public typealias NSUIPinchGestureRecognizer = NSMagnificationGestureRecognizer
-public typealias NSUIRotationGestureRecognizer = NSRotationGestureRecognizer
 public typealias NSUIScreen = NSScreen
 
 /** On OS X there is no CADisplayLink. Use a 60 fps timer to render the animations. */
@@ -324,77 +129,6 @@ public class NSUIDisplayLink
     }
 }
 
-/** The 'tap' gesture is mapped to clicks. */
-extension NSUITapGestureRecognizer
-{
-    final func nsuiNumberOfTouches() -> Int
-    {
-        return 1
-    }
-
-    final var nsuiNumberOfTapsRequired: Int
-        {
-        get
-        {
-            return self.numberOfClicksRequired
-        }
-        set
-        {
-            self.numberOfClicksRequired = newValue
-        }
-    }
-}
-
-extension NSUIPanGestureRecognizer
-{
-    final func nsuiNumberOfTouches() -> Int
-    {
-        return 1
-    }
-
-    /// FIXME: Currently there are no more than 1 touch in OSX gestures, and not way to create custom touch gestures.
-    final func nsuiLocationOfTouch(_ touch: Int, inView: NSView?) -> NSPoint
-    {
-        return super.location(in: inView)
-    }
-}
-
-extension NSUIRotationGestureRecognizer
-{
-    /// FIXME: Currently there are no velocities in OSX gestures, and not way to create custom touch gestures.
-    final var velocity: CGFloat
-    {
-        return 0.1
-    }
-
-    final var nsuiRotation: CGFloat
-        {
-        get { return -rotation }
-        set { rotation = -newValue }
-    }
-}
-
-extension NSUIPinchGestureRecognizer
-{
-    final var nsuiScale: CGFloat
-        {
-        get
-        {
-            return magnification + 1.0
-        }
-        set
-        {
-            magnification = newValue - 1.0
-        }
-    }
-
-    /// FIXME: Currently there are no more than 1 touch in OSX gestures, and not way to create custom touch gestures.
-    final func nsuiLocationOfTouch(_ touch: Int, inView view: NSView?) -> NSPoint
-    {
-        return super.location(in: view)
-    }
-}
-
 extension NSView
 {
     final var nsuiGestureRecognizers: [NSGestureRecognizer]?
@@ -441,45 +175,6 @@ open class NSUIView: NSView
         self.setNeedsDisplay(self.bounds)
     }
 
-    public final override func touchesBegan(with event: NSEvent)
-    {
-        self.nsuiTouchesBegan(event.touches(matching: .any, in: self), withEvent: event)
-    }
-
-    public final override func touchesEnded(with event: NSEvent)
-    {
-        self.nsuiTouchesEnded(event.touches(matching: .any, in: self), withEvent: event)
-    }
-
-    public final override func touchesMoved(with event: NSEvent)
-    {
-        self.nsuiTouchesMoved(event.touches(matching: .any, in: self), withEvent: event)
-    }
-
-    open override func touchesCancelled(with event: NSEvent)
-    {
-        self.nsuiTouchesCancelled(event.touches(matching: .any, in: self), withEvent: event)
-    }
-
-    open func nsuiTouchesBegan(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
-    {
-        super.touchesBegan(with: event!)
-    }
-
-    open func nsuiTouchesMoved(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
-    {
-        super.touchesMoved(with: event!)
-    }
-
-    open func nsuiTouchesEnded(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
-    {
-        super.touchesEnded(with: event!)
-    }
-
-    open func nsuiTouchesCancelled(_ touches: Set<NSUITouch>?, withEvent event: NSUIEvent?)
-    {
-        super.touchesCancelled(with: event!)
-    }
 
     open var backgroundColor: NSUIColor?
         {
@@ -527,37 +222,9 @@ extension NSImage
     }
 }
 
-extension NSTouch
-{
-    /** Touch locations on OS X are relative to the trackpad, whereas on iOS they are actually *on* the view. */
-    func locationInView(view: NSView) -> NSPoint
-    {
-        let n = self.normalizedPosition
-        let b = view.bounds
-        return NSPoint(x: b.origin.x + b.size.width * n.x, y: b.origin.y + b.size.height * n.y)
-    }
-}
-
-private func fetchLabelColor() -> NSColor
-{
-    if #available(macOS 10.14, *)
-    {
-        return .labelColor
-    }
-    else
-    {
-        return .black
-    }
-}
-private let labelColor: NSColor = fetchLabelColor()
-
-extension NSColor
-{
-    static var labelOrBlack: NSColor { labelColor }
-}
-
 extension NSScrollView
 {
+    /// NOTE: Unable to disable scrolling in macOS
     var scrollEnabled: Bool
     {
         get
@@ -566,97 +233,8 @@ extension NSScrollView
         }
         set
         {
-            // FIXME: We can't disable  scrolling it on OSX
-        }
-    }
-}
-
-func NSUIGraphicsGetCurrentContext() -> CGContext?
-{
-    return NSGraphicsContext.current?.cgContext
-}
-
-func NSUIGraphicsPushContext(_ context: CGContext)
-{
-    let cx = NSGraphicsContext(cgContext: context, flipped: true)
-    NSGraphicsContext.saveGraphicsState()
-    NSGraphicsContext.current = cx
-}
-
-func NSUIGraphicsPopContext()
-{
-    NSGraphicsContext.restoreGraphicsState()
-}
-
-func NSUIImagePNGRepresentation(_ image: NSUIImage) -> Data?
-{
-    image.lockFocus()
-    let rep = NSBitmapImageRep(focusedViewRect: NSMakeRect(0, 0, image.size.width, image.size.height))
-    image.unlockFocus()
-    return rep?.representation(using: .png, properties: [:])
-}
-
-func NSUIImageJPEGRepresentation(_ image: NSUIImage, _ quality: CGFloat = 0.9) -> Data?
-{
-    image.lockFocus()
-    let rep = NSBitmapImageRep(focusedViewRect: NSMakeRect(0, 0, image.size.width, image.size.height))
-    image.unlockFocus()
-    return rep?.representation(using: .jpeg, properties: [NSBitmapImageRep.PropertyKey.compressionFactor: quality])
-}
-
-private var imageContextStack: [CGFloat] = []
-
-func NSUIGraphicsBeginImageContextWithOptions(_ size: CGSize, _ opaque: Bool, _ scale: CGFloat)
-{
-    var scale = scale
-    if scale == 0.0
-    {
-        scale = NSScreen.main?.backingScaleFactor ?? 1.0
-    }
-
-    let width = Int(size.width * scale)
-    let height = Int(size.height * scale)
-
-    if width > 0 && height > 0
-    {
-        imageContextStack.append(scale)
-
-        let colorSpace = CGColorSpaceCreateDeviceRGB()
-
-        guard let ctx = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: 4*width, space: colorSpace, bitmapInfo: (opaque ?  CGImageAlphaInfo.noneSkipFirst.rawValue : CGImageAlphaInfo.premultipliedFirst.rawValue))
-            else { return }
-
-        ctx.concatenate(CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: CGFloat(height)))
-        ctx.scaleBy(x: scale, y: scale)
-        NSUIGraphicsPushContext(ctx)
-    }
-}
-
-func NSUIGraphicsGetImageFromCurrentImageContext() -> NSUIImage?
-{
-    if !imageContextStack.isEmpty
-    {
-        guard let ctx = NSUIGraphicsGetCurrentContext()
-            else { return nil }
-
-        let scale = imageContextStack.last!
-        if let theCGImage = ctx.makeImage()
-        {
-            let size = CGSize(width: CGFloat(ctx.width) / scale, height: CGFloat(ctx.height) / scale)
-            let image = NSImage(cgImage: theCGImage, size: size)
-            return image
         }
     }
-    return nil
-}
-
-func NSUIGraphicsEndImageContext()
-{
-    if imageContextStack.last != nil
-    {
-        imageContextStack.removeLast()
-        NSUIGraphicsPopContext()
-    }
 }
 
 func NSUIMainScreen() -> NSUIScreen?