ソースを参照

Initial Commit

Jon Fawcett 6 年 前
コミット
250a7e196c
100 ファイル変更14859 行追加0 行削除
  1. 16 0
      LoopFollow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
  2. 6 0
      LoopFollow.xcodeproj/xcuserdata/jon.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  3. 10 0
      LoopFollow.xcworkspace/contents.xcworkspacedata
  4. 8 0
      LoopFollow.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  5. 6 0
      LoopFollow.xcworkspace/xcuserdata/jon.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  6. 7 0
      Podfile
  7. 22 0
      Podfile.lock
  8. 202 0
      Pods/Charts/LICENSE
  9. 221 0
      Pods/Charts/README.md
  10. 281 0
      Pods/Charts/Source/Charts/Animation/Animator.swift
  11. 394 0
      Pods/Charts/Source/Charts/Animation/ChartAnimationEasing.swift
  12. 186 0
      Pods/Charts/Source/Charts/Charts/BarChartView.swift
  13. 1969 0
      Pods/Charts/Source/Charts/Charts/BarLineChartViewBase.swift
  14. 27 0
      Pods/Charts/Source/Charts/Charts/BubbleChartView.swift
  15. 34 0
      Pods/Charts/Source/Charts/Charts/CandleStickChartView.swift
  16. 1042 0
      Pods/Charts/Source/Charts/Charts/ChartViewBase.swift
  17. 246 0
      Pods/Charts/Source/Charts/Charts/CombinedChartView.swift
  18. 270 0
      Pods/Charts/Source/Charts/Charts/HorizontalBarChartView.swift
  19. 28 0
      Pods/Charts/Source/Charts/Charts/LineChartView.swift
  20. 690 0
      Pods/Charts/Source/Charts/Charts/PieChartView.swift
  21. 855 0
      Pods/Charts/Source/Charts/Charts/PieRadarChartViewBase.swift
  22. 221 0
      Pods/Charts/Source/Charts/Charts/RadarChartView.swift
  23. 31 0
      Pods/Charts/Source/Charts/Charts/ScatterChartView.swift
  24. 369 0
      Pods/Charts/Source/Charts/Components/AxisBase.swift
  25. 74 0
      Pods/Charts/Source/Charts/Components/ChartLimitLine.swift
  26. 37 0
      Pods/Charts/Source/Charts/Components/ComponentBase.swift
  27. 54 0
      Pods/Charts/Source/Charts/Components/Description.swift
  28. 39 0
      Pods/Charts/Source/Charts/Components/IMarker.swift
  29. 420 0
      Pods/Charts/Source/Charts/Components/Legend.swift
  30. 88 0
      Pods/Charts/Source/Charts/Components/LegendEntry.swift
  31. 106 0
      Pods/Charts/Source/Charts/Components/MarkerImage.swift
  32. 100 0
      Pods/Charts/Source/Charts/Components/MarkerView.swift
  33. 75 0
      Pods/Charts/Source/Charts/Components/XAxis.swift
  34. 206 0
      Pods/Charts/Source/Charts/Components/YAxis.swift
  35. 435 0
      Pods/Charts/Source/Charts/Data/Implementations/ChartBaseDataSet.swift
  36. 107 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartData.swift
  37. 230 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataEntry.swift
  38. 167 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift
  39. 25 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartData.swift
  40. 38 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartDataSet.swift
  41. 32 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartData.swift
  42. 79 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataEntry.swift
  43. 58 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataSet.swift
  44. 25 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartData.swift
  45. 98 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataEntry.swift
  46. 136 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataSet.swift
  47. 610 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartData.swift
  48. 110 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntry.swift
  49. 96 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntryBase.swift
  50. 574 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataSet.swift
  51. 301 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/CombinedChartData.swift
  52. 26 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartData.swift
  53. 173 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartDataSet.swift
  54. 85 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/LineRadarChartDataSet.swift
  55. 51 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/LineScatterCandleRadarChartDataSet.swift
  56. 124 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartData.swift
  57. 119 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartDataEntry.swift
  58. 135 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartDataSet.swift
  59. 46 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartData.swift
  60. 54 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataEntry.swift
  61. 59 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataSet.swift
  62. 34 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartData.swift
  63. 78 0
      Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartDataSet.swift
  64. 42 0
      Pods/Charts/Source/Charts/Data/Interfaces/IBarChartDataSet.swift
  65. 26 0
      Pods/Charts/Source/Charts/Data/Interfaces/IBarLineScatterCandleBubbleChartDataSet.swift
  66. 27 0
      Pods/Charts/Source/Charts/Data/Interfaces/IBubbleChartDataSet.swift
  67. 66 0
      Pods/Charts/Source/Charts/Data/Interfaces/ICandleChartDataSet.swift
  68. 270 0
      Pods/Charts/Source/Charts/Data/Interfaces/IChartDataSet.swift
  69. 80 0
      Pods/Charts/Source/Charts/Data/Interfaces/ILineChartDataSet.swift
  70. 45 0
      Pods/Charts/Source/Charts/Data/Interfaces/ILineRadarChartDataSet.swift
  71. 36 0
      Pods/Charts/Source/Charts/Data/Interfaces/ILineScatterCandleRadarChartDataSet.swift
  72. 64 0
      Pods/Charts/Source/Charts/Data/Interfaces/IPieChartDataSet.swift
  73. 40 0
      Pods/Charts/Source/Charts/Data/Interfaces/IRadarChartDataSet.swift
  74. 36 0
      Pods/Charts/Source/Charts/Data/Interfaces/IScatterChartDataSet.swift
  75. 153 0
      Pods/Charts/Source/Charts/Filters/DataApproximator+N.swift
  76. 115 0
      Pods/Charts/Source/Charts/Filters/DataApproximator.swift
  77. 100 0
      Pods/Charts/Source/Charts/Formatters/DefaultAxisValueFormatter.swift
  78. 58 0
      Pods/Charts/Source/Charts/Formatters/DefaultFillFormatter.swift
  79. 103 0
      Pods/Charts/Source/Charts/Formatters/DefaultValueFormatter.swift
  80. 30 0
      Pods/Charts/Source/Charts/Formatters/IAxisValueFormatter.swift
  81. 21 0
      Pods/Charts/Source/Charts/Formatters/IFillFormatter.swift
  82. 36 0
      Pods/Charts/Source/Charts/Formatters/IValueFormatter.swift
  83. 59 0
      Pods/Charts/Source/Charts/Formatters/IndexAxisValueFormatter.swift
  84. 108 0
      Pods/Charts/Source/Charts/Highlight/BarHighlighter.swift
  85. 180 0
      Pods/Charts/Source/Charts/Highlight/ChartHighlighter.swift
  86. 70 0
      Pods/Charts/Source/Charts/Highlight/CombinedHighlighter.swift
  87. 203 0
      Pods/Charts/Source/Charts/Highlight/Highlight.swift
  88. 63 0
      Pods/Charts/Source/Charts/Highlight/HorizontalBarHighlighter.swift
  89. 23 0
      Pods/Charts/Source/Charts/Highlight/IHighlighter.swift
  90. 27 0
      Pods/Charts/Source/Charts/Highlight/PieHighlighter.swift
  91. 61 0
      Pods/Charts/Source/Charts/Highlight/PieRadarHighlighter.swift
  92. 78 0
      Pods/Charts/Source/Charts/Highlight/RadarHighlighter.swift
  93. 52 0
      Pods/Charts/Source/Charts/Highlight/Range.swift
  94. 23 0
      Pods/Charts/Source/Charts/Interfaces/BarChartDataProvider.swift
  95. 23 0
      Pods/Charts/Source/Charts/Interfaces/BarLineScatterCandleBubbleChartDataProvider.swift
  96. 19 0
      Pods/Charts/Source/Charts/Interfaces/BubbleChartDataProvider.swift
  97. 19 0
      Pods/Charts/Source/Charts/Interfaces/CandleChartDataProvider.swift
  98. 39 0
      Pods/Charts/Source/Charts/Interfaces/ChartDataProvider.swift
  99. 19 0
      Pods/Charts/Source/Charts/Interfaces/CombinedChartDataProvider.swift
  100. 0 0
      Pods/Charts/Source/Charts/Interfaces/LineChartDataProvider.swift

+ 16 - 0
LoopFollow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -0,0 +1,16 @@
+{
+  "object": {
+    "pins": [
+      {
+        "package": "Oxygen",
+        "repositoryURL": "https://github.com/mpangburn/Oxygen.git",
+        "state": {
+          "branch": "master",
+          "revision": "b3c7a6ead1400e4799b16755d23c9905040d4acc",
+          "version": null
+        }
+      }
+    ]
+  },
+  "version": 1
+}

+ 6 - 0
LoopFollow.xcodeproj/xcuserdata/jon.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Bucket
+   uuid = "C0EEF0AD-617A-4043-BA1F-15E64D6E9119"
+   type = "1"
+   version = "2.0">
+</Bucket>

+ 10 - 0
LoopFollow.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:LoopFollow.xcodeproj">
+   </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
+</Workspace>

+ 8 - 0
LoopFollow.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>

+ 6 - 0
LoopFollow.xcworkspace/xcuserdata/jon.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Bucket
+   uuid = "35B1BDC7-1374-42B0-9D79-1E7D694F0434"
+   type = "0"
+   version = "2.0">
+</Bucket>

+ 7 - 0
Podfile

@@ -0,0 +1,7 @@
+target 'LoopFollow' do
+  use_frameworks!
+
+  pod 'Charts'
+  pod 'Eureka'
+
+  end

+ 22 - 0
Podfile.lock

@@ -0,0 +1,22 @@
+PODS:
+  - Charts (3.5.0):
+    - Charts/Core (= 3.5.0)
+  - Charts/Core (3.5.0)
+  - Eureka (5.2.1)
+
+DEPENDENCIES:
+  - Charts
+  - Eureka
+
+SPEC REPOS:
+  trunk:
+    - Charts
+    - Eureka
+
+SPEC CHECKSUMS:
+  Charts: 40a08591df1f8ad5c223ddedfb1a06da92f24f7c
+  Eureka: c883105488e05bc65539f583246ecf9657cabbfe
+
+PODFILE CHECKSUM: 7665842405edac4f27ad84d4b66d6d57d5a4e5aa
+
+COCOAPODS: 1.9.3

+ 202 - 0
Pods/Charts/LICENSE

@@ -0,0 +1,202 @@
+Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2016-2019 Daniel Cohen Gindi & Philipp Jahoda
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+

ファイルの差分が大きいため隠しています
+ 221 - 0
Pods/Charts/README.md


+ 281 - 0
Pods/Charts/Source/Charts/Animation/Animator.swift

@@ -0,0 +1,281 @@
+//
+//  Animator.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+import QuartzCore
+
+@objc(ChartAnimatorDelegate)
+public protocol AnimatorDelegate
+{
+    /// Called when the Animator has stepped.
+    func animatorUpdated(_ animator: Animator)
+    
+    /// Called when the Animator has stopped.
+    func animatorStopped(_ animator: Animator)
+}
+
+@objc(ChartAnimator)
+open class Animator: NSObject
+{
+    @objc open weak var delegate: AnimatorDelegate?
+    @objc open var updateBlock: (() -> Void)?
+    @objc open var stopBlock: (() -> Void)?
+    
+    /// the phase that is animated and influences the drawn values on the x-axis
+    @objc open var phaseX: Double = 1.0
+    
+    /// the phase that is animated and influences the drawn values on the y-axis
+    @objc open var phaseY: Double = 1.0
+    
+    private var _startTimeX: TimeInterval = 0.0
+    private var _startTimeY: TimeInterval = 0.0
+    private var _displayLink: NSUIDisplayLink?
+    
+    private var _durationX: TimeInterval = 0.0
+    private var _durationY: TimeInterval = 0.0
+    
+    private var _endTimeX: TimeInterval = 0.0
+    private var _endTimeY: TimeInterval = 0.0
+    private var _endTime: TimeInterval = 0.0
+    
+    private var _enabledX: Bool = false
+    private var _enabledY: Bool = false
+    
+    private var _easingX: ChartEasingFunctionBlock?
+    private var _easingY: ChartEasingFunctionBlock?
+
+    public override init()
+    {
+        super.init()
+    }
+    
+    deinit
+    {
+        stop()
+    }
+    
+    @objc open func stop()
+    {
+        guard _displayLink != nil else { return }
+
+        _displayLink?.remove(from: .main, forMode: RunLoop.Mode.common)
+        _displayLink = nil
+
+        _enabledX = false
+        _enabledY = false
+
+        // If we stopped an animation in the middle, we do not want to leave it like this
+        if phaseX != 1.0 || phaseY != 1.0
+        {
+            phaseX = 1.0
+            phaseY = 1.0
+
+            delegate?.animatorUpdated(self)
+            updateBlock?()
+        }
+
+        delegate?.animatorStopped(self)
+        stopBlock?()
+    }
+    
+    private func updateAnimationPhases(_ currentTime: TimeInterval)
+    {
+        if _enabledX
+        {
+            let elapsedTime: TimeInterval = currentTime - _startTimeX
+            let duration: TimeInterval = _durationX
+            var elapsed: TimeInterval = elapsedTime
+            if elapsed > duration
+            {
+                elapsed = duration
+            }
+           
+            phaseX = _easingX?(elapsed, duration) ?? elapsed / duration
+        }
+        
+        if _enabledY
+        {
+            let elapsedTime: TimeInterval = currentTime - _startTimeY
+            let duration: TimeInterval = _durationY
+            var elapsed: TimeInterval = elapsedTime
+            if elapsed > duration
+            {
+                elapsed = duration
+            }
+
+            phaseY = _easingY?(elapsed, duration) ?? elapsed / duration
+        }
+    }
+    
+    @objc private func animationLoop()
+    {
+        let currentTime: TimeInterval = CACurrentMediaTime()
+        
+        updateAnimationPhases(currentTime)
+
+        delegate?.animatorUpdated(self)
+        updateBlock?()
+        
+        if currentTime >= _endTime
+        {
+            stop()
+        }
+    }
+    
+    /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time.
+    /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart.
+    ///
+    /// - Parameters:
+    ///   - xAxisDuration: duration for animating the x axis
+    ///   - yAxisDuration: duration for animating the y axis
+    ///   - easingX: an easing function for the animation on the x axis
+    ///   - easingY: an easing function for the animation on the y axis
+    @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easingX: ChartEasingFunctionBlock?, easingY: ChartEasingFunctionBlock?)
+    {
+        stop()
+        
+        _startTimeX = CACurrentMediaTime()
+        _startTimeY = _startTimeX
+        _durationX = xAxisDuration
+        _durationY = yAxisDuration
+        _endTimeX = _startTimeX + xAxisDuration
+        _endTimeY = _startTimeY + yAxisDuration
+        _endTime = _endTimeX > _endTimeY ? _endTimeX : _endTimeY
+        _enabledX = xAxisDuration > 0.0
+        _enabledY = yAxisDuration > 0.0
+        
+        _easingX = easingX
+        _easingY = easingY
+        
+        // Take care of the first frame if rendering is already scheduled...
+        updateAnimationPhases(_startTimeX)
+        
+        if _enabledX || _enabledY
+        {
+            _displayLink = NSUIDisplayLink(target: self, selector: #selector(animationLoop))
+            _displayLink?.add(to: RunLoop.main, forMode: RunLoop.Mode.common)
+        }
+    }
+    
+    /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time.
+    /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart.
+    ///
+    /// - Parameters:
+    ///   - xAxisDuration: duration for animating the x axis
+    ///   - yAxisDuration: duration for animating the y axis
+    ///   - easingOptionX: the easing function for the animation on the x axis
+    ///   - easingOptionY: the easing function for the animation on the y axis
+    @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easingOptionX: ChartEasingOption, easingOptionY: ChartEasingOption)
+    {
+        animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easingX: easingFunctionFromOption(easingOptionX), easingY: easingFunctionFromOption(easingOptionY))
+    }
+    
+    /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time.
+    /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart.
+    ///
+    /// - Parameters:
+    ///   - xAxisDuration: duration for animating the x axis
+    ///   - yAxisDuration: duration for animating the y axis
+    ///   - easing: an easing function for the animation
+    @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easing: ChartEasingFunctionBlock?)
+    {
+        animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easingX: easing, easingY: easing)
+    }
+    
+    /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time.
+    /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart.
+    ///
+    /// - Parameters:
+    ///   - xAxisDuration: duration for animating the x axis
+    ///   - yAxisDuration: duration for animating the y axis
+    ///   - easingOption: the easing function for the animation
+    @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easingOption: ChartEasingOption = .easeInOutSine)
+    {
+        animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easing: easingFunctionFromOption(easingOption))
+    }
+
+    /// Animates the drawing / rendering of the chart the x-axis with the specified animation time.
+    /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart.
+    ///
+    /// - Parameters:
+    ///   - xAxisDuration: duration for animating the x axis
+    ///   - easing: an easing function for the animation
+    @objc open func animate(xAxisDuration: TimeInterval, easing: ChartEasingFunctionBlock?)
+    {
+        _startTimeX = CACurrentMediaTime()
+        _durationX = xAxisDuration
+        _endTimeX = _startTimeX + xAxisDuration
+        _endTime = _endTimeX > _endTimeY ? _endTimeX : _endTimeY
+        _enabledX = xAxisDuration > 0.0
+        
+        _easingX = easing
+        
+        // Take care of the first frame if rendering is already scheduled...
+        updateAnimationPhases(_startTimeX)
+        
+        if _enabledX || _enabledY,
+            _displayLink == nil
+        {
+            _displayLink = NSUIDisplayLink(target: self, selector: #selector(animationLoop))
+            _displayLink?.add(to: .main, forMode: RunLoop.Mode.common)
+        }
+    }
+    
+    /// Animates the drawing / rendering of the chart the x-axis with the specified animation time.
+    /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart.
+    ///
+    /// - Parameters:
+    ///   - xAxisDuration: duration for animating the x axis
+    ///   - easingOption: the easing function for the animation
+    @objc open func animate(xAxisDuration: TimeInterval, easingOption: ChartEasingOption = .easeInOutSine)
+    {
+        animate(xAxisDuration: xAxisDuration, easing: easingFunctionFromOption(easingOption))
+    }
+
+    /// Animates the drawing / rendering of the chart the y-axis with the specified animation time.
+    /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart.
+    ///
+    /// - Parameters:
+    ///   - yAxisDuration: duration for animating the y axis
+    ///   - easing: an easing function for the animation
+    @objc open func animate(yAxisDuration: TimeInterval, easing: ChartEasingFunctionBlock?)
+    {
+        _startTimeY = CACurrentMediaTime()
+        _durationY = yAxisDuration
+        _endTimeY = _startTimeY + yAxisDuration
+        _endTime = _endTimeX > _endTimeY ? _endTimeX : _endTimeY
+        _enabledY = yAxisDuration > 0.0
+        
+        _easingY = easing
+        
+        // Take care of the first frame if rendering is already scheduled...
+        updateAnimationPhases(_startTimeY)
+        
+        if _enabledX || _enabledY,
+            _displayLink == nil
+        {
+            _displayLink = NSUIDisplayLink(target: self, selector: #selector(animationLoop))
+            _displayLink?.add(to: .main, forMode: RunLoop.Mode.common)
+        }
+    }
+    
+    /// Animates the drawing / rendering of the chart the y-axis with the specified animation time.
+    /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart.
+    ///
+    /// - Parameters:
+    ///   - yAxisDuration: duration for animating the y axis
+    ///   - easingOption: the easing function for the animation
+    @objc open func animate(yAxisDuration: TimeInterval, easingOption: ChartEasingOption = .easeInOutSine)
+    {
+        animate(yAxisDuration: yAxisDuration, easing: easingFunctionFromOption(easingOption))
+    }
+}

+ 394 - 0
Pods/Charts/Source/Charts/Animation/ChartAnimationEasing.swift

@@ -0,0 +1,394 @@
+//
+//  ChartAnimationUtils.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public enum ChartEasingOption: Int
+{
+    case linear
+    case easeInQuad
+    case easeOutQuad
+    case easeInOutQuad
+    case easeInCubic
+    case easeOutCubic
+    case easeInOutCubic
+    case easeInQuart
+    case easeOutQuart
+    case easeInOutQuart
+    case easeInQuint
+    case easeOutQuint
+    case easeInOutQuint
+    case easeInSine
+    case easeOutSine
+    case easeInOutSine
+    case easeInExpo
+    case easeOutExpo
+    case easeInOutExpo
+    case easeInCirc
+    case easeOutCirc
+    case easeInOutCirc
+    case easeInElastic
+    case easeOutElastic
+    case easeInOutElastic
+    case easeInBack
+    case easeOutBack
+    case easeInOutBack
+    case easeInBounce
+    case easeOutBounce
+    case easeInOutBounce
+}
+
+public typealias ChartEasingFunctionBlock = ((_ elapsed: TimeInterval, _ duration: TimeInterval) -> Double)
+
+internal func easingFunctionFromOption(_ easing: ChartEasingOption) -> ChartEasingFunctionBlock
+{
+    switch easing
+    {
+    case .linear:
+        return EasingFunctions.Linear
+    case .easeInQuad:
+        return EasingFunctions.EaseInQuad
+    case .easeOutQuad:
+        return EasingFunctions.EaseOutQuad
+    case .easeInOutQuad:
+        return EasingFunctions.EaseInOutQuad
+    case .easeInCubic:
+        return EasingFunctions.EaseInCubic
+    case .easeOutCubic:
+        return EasingFunctions.EaseOutCubic
+    case .easeInOutCubic:
+        return EasingFunctions.EaseInOutCubic
+    case .easeInQuart:
+        return EasingFunctions.EaseInQuart
+    case .easeOutQuart:
+        return EasingFunctions.EaseOutQuart
+    case .easeInOutQuart:
+        return EasingFunctions.EaseInOutQuart
+    case .easeInQuint:
+        return EasingFunctions.EaseInQuint
+    case .easeOutQuint:
+        return EasingFunctions.EaseOutQuint
+    case .easeInOutQuint:
+        return EasingFunctions.EaseInOutQuint
+    case .easeInSine:
+        return EasingFunctions.EaseInSine
+    case .easeOutSine:
+        return EasingFunctions.EaseOutSine
+    case .easeInOutSine:
+        return EasingFunctions.EaseInOutSine
+    case .easeInExpo:
+        return EasingFunctions.EaseInExpo
+    case .easeOutExpo:
+        return EasingFunctions.EaseOutExpo
+    case .easeInOutExpo:
+        return EasingFunctions.EaseInOutExpo
+    case .easeInCirc:
+        return EasingFunctions.EaseInCirc
+    case .easeOutCirc:
+        return EasingFunctions.EaseOutCirc
+    case .easeInOutCirc:
+        return EasingFunctions.EaseInOutCirc
+    case .easeInElastic:
+        return EasingFunctions.EaseInElastic
+    case .easeOutElastic:
+        return EasingFunctions.EaseOutElastic
+    case .easeInOutElastic:
+        return EasingFunctions.EaseInOutElastic
+    case .easeInBack:
+        return EasingFunctions.EaseInBack
+    case .easeOutBack:
+        return EasingFunctions.EaseOutBack
+    case .easeInOutBack:
+        return EasingFunctions.EaseInOutBack
+    case .easeInBounce:
+        return EasingFunctions.EaseInBounce
+    case .easeOutBounce:
+        return EasingFunctions.EaseOutBounce
+    case .easeInOutBounce:
+        return EasingFunctions.EaseInOutBounce
+    }
+}
+
+internal struct EasingFunctions
+{
+    internal static let Linear = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in return Double(elapsed / duration) }
+    
+    internal static let EaseInQuad = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / duration)
+        return position * position
+    }
+    
+    internal static let EaseOutQuad = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / duration)
+        return -position * (position - 2.0)
+    }
+    
+    internal static let EaseInOutQuad = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / (duration / 2.0))
+        if position < 1.0
+        {
+            return 0.5 * position * position
+        }
+        
+        return -0.5 * ((position - 1.0) * (position - 3.0) - 1.0)
+    }
+    
+    internal static let EaseInCubic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / duration)
+        return position * position * position
+    }
+    
+    internal static let EaseOutCubic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / duration)
+        position -= 1.0
+        return (position * position * position + 1.0)
+    }
+    
+    internal static let EaseInOutCubic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / (duration / 2.0))
+        if position < 1.0
+        {
+            return 0.5 * position * position * position
+        }
+        position -= 2.0
+        return 0.5 * (position * position * position + 2.0)
+    }
+    
+    internal static let EaseInQuart = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / duration)
+        return position * position * position * position
+    }
+    
+    internal static let EaseOutQuart = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / duration)
+        position -= 1.0
+        return -(position * position * position * position - 1.0)
+    }
+    
+    internal static let EaseInOutQuart = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / (duration / 2.0))
+        if position < 1.0
+        {
+            return 0.5 * position * position * position * position
+        }
+        position -= 2.0
+        return -0.5 * (position * position * position * position - 2.0)
+    }
+    
+    internal static let EaseInQuint = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / duration)
+        return position * position * position * position * position
+    }
+    
+    internal static let EaseOutQuint = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / duration)
+        position -= 1.0
+        return (position * position * position * position * position + 1.0)
+    }
+    
+    internal static let EaseInOutQuint = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / (duration / 2.0))
+        if position < 1.0
+        {
+            return 0.5 * position * position * position * position * position
+        }
+        else
+        {
+            position -= 2.0
+            return 0.5 * (position * position * position * position * position + 2.0)
+        }
+    }
+    
+    internal static let EaseInSine = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position: TimeInterval = elapsed / duration
+        return Double( -cos(position * Double.pi / 2) + 1.0 )
+    }
+    
+    internal static let EaseOutSine = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position: TimeInterval = elapsed / duration
+        return Double( sin(position * Double.pi / 2) )
+    }
+    
+    internal static let EaseInOutSine = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position: TimeInterval = elapsed / duration
+        return Double( -0.5 * (cos(Double.pi * position) - 1.0) )
+    }
+    
+    internal static let EaseInExpo = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        return (elapsed == 0) ? 0.0 : Double(pow(2.0, 10.0 * (elapsed / duration - 1.0)))
+    }
+    
+    internal static let EaseOutExpo = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        return (elapsed == duration) ? 1.0 : (-Double(pow(2.0, -10.0 * elapsed / duration)) + 1.0)
+    }
+    
+    internal static let EaseInOutExpo = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        if elapsed == 0
+        {
+            return 0.0
+        }
+        if elapsed == duration
+        {
+            return 1.0
+        }
+        
+        var position: TimeInterval = elapsed / (duration / 2.0)
+        if position < 1.0
+        {
+            return Double( 0.5 * pow(2.0, 10.0 * (position - 1.0)) )
+        }
+        
+        position = position - 1.0
+        return Double( 0.5 * (-pow(2.0, -10.0 * position) + 2.0) )
+    }
+    
+    internal static let EaseInCirc = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / duration)
+        return -(Double(sqrt(1.0 - position * position)) - 1.0)
+    }
+    
+    internal static let EaseOutCirc = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position = Double(elapsed / duration)
+        position -= 1.0
+        return Double( sqrt(1 - position * position) )
+    }
+    
+    internal static let EaseInOutCirc = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position: TimeInterval = elapsed / (duration / 2.0)
+        if position < 1.0
+        {
+            return Double( -0.5 * (sqrt(1.0 - position * position) - 1.0) )
+        }
+        position -= 2.0
+        return Double( 0.5 * (sqrt(1.0 - position * position) + 1.0) )
+    }
+    
+    internal static let EaseInElastic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        if elapsed == 0.0
+        {
+            return 0.0
+        }
+        
+        var position: TimeInterval = elapsed / duration
+        if position == 1.0
+        {
+            return 1.0
+        }
+        
+        var p = duration * 0.3
+        var s = p / (2.0 * Double.pi) * asin(1.0)
+        position -= 1.0
+        return Double( -(pow(2.0, 10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p)) )
+    }
+    
+    internal static let EaseOutElastic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        if elapsed == 0.0
+        {
+            return 0.0
+        }
+        
+        var position: TimeInterval = elapsed / duration
+        if position == 1.0
+        {
+            return 1.0
+        }
+        
+        var p = duration * 0.3
+        var s = p / (2.0 * Double.pi) * asin(1.0)
+        return Double( pow(2.0, -10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p) + 1.0 )
+    }
+    
+    internal static let EaseInOutElastic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        if elapsed == 0.0
+        {
+            return 0.0
+        }
+        
+        var position: TimeInterval = elapsed / (duration / 2.0)
+        if position == 2.0
+        {
+            return 1.0
+        }
+        
+        var p = duration * (0.3 * 1.5)
+        var s = p / (2.0 * Double.pi) * asin(1.0)
+        if position < 1.0
+        {
+            position -= 1.0
+            return Double( -0.5 * (pow(2.0, 10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p)) )
+        }
+        position -= 1.0
+        return Double( pow(2.0, -10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p) * 0.5 + 1.0 )
+    }
+    
+    internal static let EaseInBack = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        let s: TimeInterval = 1.70158
+        var position: TimeInterval = elapsed / duration
+        return Double( position * position * ((s + 1.0) * position - s) )
+    }
+    
+    internal static let EaseOutBack = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        let s: TimeInterval = 1.70158
+        var position: TimeInterval = elapsed / duration
+        position -= 1.0
+        return Double( position * position * ((s + 1.0) * position + s) + 1.0 )
+    }
+    
+    internal static let EaseInOutBack = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var s: TimeInterval = 1.70158
+        var position: TimeInterval = elapsed / (duration / 2.0)
+        if position < 1.0
+        {
+            s *= 1.525
+            return Double( 0.5 * (position * position * ((s + 1.0) * position - s)) )
+        }
+        s *= 1.525
+        position -= 2.0
+        return Double( 0.5 * (position * position * ((s + 1.0) * position + s) + 2.0) )
+    }
+    
+    internal static let EaseInBounce = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        return 1.0 - EaseOutBounce(duration - elapsed, duration)
+    }
+    
+    internal static let EaseOutBounce = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        var position: TimeInterval = elapsed / duration
+        if position < (1.0 / 2.75)
+        {
+            return Double( 7.5625 * position * position )
+        }
+        else if position < (2.0 / 2.75)
+        {
+            position -= (1.5 / 2.75)
+            return Double( 7.5625 * position * position + 0.75 )
+        }
+        else if position < (2.5 / 2.75)
+        {
+            position -= (2.25 / 2.75)
+            return Double( 7.5625 * position * position + 0.9375 )
+        }
+        else
+        {
+            position -= (2.625 / 2.75)
+            return Double( 7.5625 * position * position + 0.984375 )
+        }
+    }
+    
+    internal static let EaseInOutBounce = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in
+        if elapsed < (duration / 2.0)
+        {
+            return EaseInBounce(elapsed * 2.0, duration) * 0.5
+        }
+        return EaseOutBounce(elapsed * 2.0 - duration, duration) * 0.5 + 0.5
+    }
+}

+ 186 - 0
Pods/Charts/Source/Charts/Charts/BarChartView.swift

@@ -0,0 +1,186 @@
+//
+//  BarChartView.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+/// Chart that draws bars.
+open class BarChartView: BarLineChartViewBase, BarChartDataProvider
+{
+    /// if set to true, all values are drawn above their bars, instead of below their top
+    private var _drawValueAboveBarEnabled = true
+
+    /// if set to true, a grey area is drawn behind each bar that indicates the maximum value
+    private var _drawBarShadowEnabled = false
+    
+    internal override func initialize()
+    {
+        super.initialize()
+        
+        renderer = BarChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
+        
+        self.highlighter = BarHighlighter(chart: self)
+        
+        self.xAxis.spaceMin = 0.5
+        self.xAxis.spaceMax = 0.5
+    }
+    
+    internal override func calcMinMax()
+    {
+        guard let data = self.data as? BarChartData
+            else { return }
+        
+        if fitBars
+        {
+            _xAxis.calculate(
+                min: data.xMin - data.barWidth / 2.0,
+                max: data.xMax + data.barWidth / 2.0)
+        }
+        else
+        {
+            _xAxis.calculate(min: data.xMin, max: data.xMax)
+        }
+        
+        // calculate axis range (min / max) according to provided data
+        leftAxis.calculate(
+            min: data.getYMin(axis: .left),
+            max: data.getYMax(axis: .left))
+        rightAxis.calculate(
+            min: data.getYMin(axis: .right),
+            max: data.getYMax(axis: .right))
+    }
+    
+    /// - Returns: The Highlight object (contains x-index and DataSet index) of the selected value at the given touch point inside the BarChart.
+    open override func getHighlightByTouchPoint(_ pt: CGPoint) -> Highlight?
+    {
+        if _data === nil
+        {
+            Swift.print("Can't select by touch. No data set.")
+            return nil
+        }
+        
+        guard let h = self.highlighter?.getHighlight(x: pt.x, y: pt.y)
+            else { return nil }
+        
+        if !isHighlightFullBarEnabled { return h }
+        
+        // For isHighlightFullBarEnabled, remove stackIndex
+        return Highlight(
+            x: h.x, y: h.y,
+            xPx: h.xPx, yPx: h.yPx,
+            dataIndex: h.dataIndex,
+            dataSetIndex: h.dataSetIndex,
+            stackIndex: -1,
+            axis: h.axis)
+    }
+        
+    /// - Returns: The bounding box of the specified Entry in the specified DataSet. Returns null if the Entry could not be found in the charts data.
+    @objc open func getBarBounds(entry e: BarChartDataEntry) -> CGRect
+    {
+        guard let
+            data = _data as? BarChartData,
+            let set = data.getDataSetForEntry(e) as? IBarChartDataSet
+            else { return CGRect.null }
+        
+        let y = e.y
+        let x = e.x
+        
+        let barWidth = data.barWidth
+        
+        let left = x - barWidth / 2.0
+        let right = x + barWidth / 2.0
+        let top = y >= 0.0 ? y : 0.0
+        let bottom = y <= 0.0 ? y : 0.0
+        
+        var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top)
+        
+        getTransformer(forAxis: set.axisDependency).rectValueToPixel(&bounds)
+        
+        return bounds
+    }
+    
+    /// Groups all BarDataSet objects this data object holds together by modifying the x-value of their entries.
+    /// Previously set x-values of entries will be overwritten. Leaves space between bars and groups as specified by the parameters.
+    /// Calls `notifyDataSetChanged()` afterwards.
+    ///
+    /// - Parameters:
+    ///   - fromX: the starting point on the x-axis where the grouping should begin
+    ///   - groupSpace: the space between groups of bars in values (not pixels) e.g. 0.8f for bar width 1f
+    ///   - barSpace: the space between individual bars in values (not pixels) e.g. 0.1f for bar width 1f
+    @objc open func groupBars(fromX: Double, groupSpace: Double, barSpace: Double)
+    {
+        guard let barData = self.barData
+            else
+        {
+            Swift.print("You need to set data for the chart before grouping bars.", terminator: "\n")
+            return
+        }
+        
+        barData.groupBars(fromX: fromX, groupSpace: groupSpace, barSpace: barSpace)
+        notifyDataSetChanged()
+    }
+    
+    /// Highlights the value at the given x-value in the given DataSet. Provide -1 as the dataSetIndex to undo all highlighting.
+    ///
+    /// - Parameters:
+    ///   - x:
+    ///   - dataSetIndex:
+    ///   - stackIndex: the index inside the stack - only relevant for stacked entries
+    @objc open func highlightValue(x: Double, dataSetIndex: Int, stackIndex: Int)
+    {
+        highlightValue(Highlight(x: x, dataSetIndex: dataSetIndex, stackIndex: stackIndex))
+    }
+
+    // MARK: Accessors
+    
+    /// if set to true, all values are drawn above their bars, instead of below their top
+    @objc open var drawValueAboveBarEnabled: Bool
+    {
+        get { return _drawValueAboveBarEnabled }
+        set
+        {
+            _drawValueAboveBarEnabled = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// if set to true, a grey area is drawn behind each bar that indicates the maximum value
+    @objc open var drawBarShadowEnabled: Bool
+    {
+        get { return _drawBarShadowEnabled }
+        set
+        {
+            _drawBarShadowEnabled = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// Adds half of the bar width to each side of the x-axis range in order to allow the bars of the barchart to be fully displayed.
+    /// **default**: false
+    @objc open var fitBars = false
+    
+    /// Set this to `true` to make the highlight operation full-bar oriented, `false` to make it highlight single values (relevant only for stacked).
+    /// If enabled, highlighting operations will highlight the whole bar, even if only a single stack entry was tapped.
+    @objc open var highlightFullBarEnabled: Bool = false
+    
+    /// `true` the highlight is be full-bar oriented, `false` ifsingle-value
+    open var isHighlightFullBarEnabled: Bool { return highlightFullBarEnabled }
+    
+    // MARK: - BarChartDataProvider
+    
+    open var barData: BarChartData? { return _data as? BarChartData }
+    
+    /// `true` if drawing values above bars is enabled, `false` ifnot
+    open var isDrawValueAboveBarEnabled: Bool { return drawValueAboveBarEnabled }
+    
+    /// `true` if drawing shadows (maxvalue) for each bar is enabled, `false` ifnot
+    open var isDrawBarShadowEnabled: Bool { return drawBarShadowEnabled }
+}

ファイルの差分が大きいため隠しています
+ 1969 - 0
Pods/Charts/Source/Charts/Charts/BarLineChartViewBase.swift


+ 27 - 0
Pods/Charts/Source/Charts/Charts/BubbleChartView.swift

@@ -0,0 +1,27 @@
+//
+//  BubbleChartView.swift
+//  Charts
+//
+//  Bubble chart implementation:
+//    Copyright 2015 Pierre-Marc Airoldi
+//    Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+open class BubbleChartView: BarLineChartViewBase, BubbleChartDataProvider
+{
+    open override func initialize()
+    {
+        super.initialize()
+        
+        renderer = BubbleChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
+    }
+    
+    // MARK: - BubbleChartDataProvider
+    
+    open var bubbleData: BubbleChartData? { return _data as? BubbleChartData }
+}

+ 34 - 0
Pods/Charts/Source/Charts/Charts/CandleStickChartView.swift

@@ -0,0 +1,34 @@
+//
+//  CandleStickChartView.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+/// Financial chart type that draws candle-sticks.
+open class CandleStickChartView: BarLineChartViewBase, CandleChartDataProvider
+{
+    internal override func initialize()
+    {
+        super.initialize()
+        
+        renderer = CandleStickChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
+        
+        self.xAxis.spaceMin = 0.5
+        self.xAxis.spaceMax = 0.5
+    }
+    
+    // MARK: - CandleChartDataProvider
+    
+    open var candleData: CandleChartData?
+    {
+        return _data as? CandleChartData
+    }
+}

ファイルの差分が大きいため隠しています
+ 1042 - 0
Pods/Charts/Source/Charts/Charts/ChartViewBase.swift


+ 246 - 0
Pods/Charts/Source/Charts/Charts/CombinedChartView.swift

@@ -0,0 +1,246 @@
+//
+//  CombinedChartView.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+/// This chart class allows the combination of lines, bars, scatter and candle data all displayed in one chart area.
+open class CombinedChartView: BarLineChartViewBase, CombinedChartDataProvider
+{
+    /// the fill-formatter used for determining the position of the fill-line
+    internal var _fillFormatter: IFillFormatter!
+    
+    /// enum that allows to specify the order in which the different data objects for the combined-chart are drawn
+    @objc(CombinedChartDrawOrder)
+    public enum DrawOrder: Int
+    {
+        case bar
+        case bubble
+        case line
+        case candle
+        case scatter
+    }
+    
+    open override func initialize()
+    {
+        super.initialize()
+        
+        self.highlighter = CombinedHighlighter(chart: self, barDataProvider: self)
+        
+        // Old default behaviour
+        self.highlightFullBarEnabled = true
+        
+        _fillFormatter = DefaultFillFormatter()
+        
+        renderer = CombinedChartRenderer(chart: self, animator: _animator, viewPortHandler: _viewPortHandler)
+    }
+    
+    open override var data: ChartData?
+    {
+        get
+        {
+            return super.data
+        }
+        set
+        {
+            super.data = newValue
+            
+            self.highlighter = CombinedHighlighter(chart: self, barDataProvider: self)
+            
+            (renderer as? CombinedChartRenderer)?.createRenderers()
+            renderer?.initBuffers()
+        }
+    }
+    
+    @objc open var fillFormatter: IFillFormatter
+    {
+        get
+        {
+            return _fillFormatter
+        }
+        set
+        {
+            _fillFormatter = newValue
+            if _fillFormatter == nil
+            {
+                _fillFormatter = DefaultFillFormatter()
+            }
+        }
+    }
+    
+    /// - Returns: The Highlight object (contains x-index and DataSet index) of the selected value at the given touch point inside the CombinedChart.
+    open override func getHighlightByTouchPoint(_ pt: CGPoint) -> Highlight?
+    {
+        if _data === nil
+        {
+            Swift.print("Can't select by touch. No data set.")
+            return nil
+        }
+        
+        guard let h = self.highlighter?.getHighlight(x: pt.x, y: pt.y)
+            else { return nil }
+        
+        if !isHighlightFullBarEnabled { return h }
+        
+        // For isHighlightFullBarEnabled, remove stackIndex
+        return Highlight(
+            x: h.x, y: h.y,
+            xPx: h.xPx, yPx: h.yPx,
+            dataIndex: h.dataIndex,
+            dataSetIndex: h.dataSetIndex,
+            stackIndex: -1,
+            axis: h.axis)
+    }
+    
+    // MARK: - CombinedChartDataProvider
+    
+    open var combinedData: CombinedChartData?
+    {
+        get
+        {
+            return _data as? CombinedChartData
+        }
+    }
+    
+    // MARK: - LineChartDataProvider
+    
+    open var lineData: LineChartData?
+    {
+        get
+        {
+            return combinedData?.lineData
+        }
+    }
+    
+    // MARK: - BarChartDataProvider
+    
+    open var barData: BarChartData?
+    {
+        get
+        {
+            return combinedData?.barData
+        }
+    }
+    
+    // MARK: - ScatterChartDataProvider
+    
+    open var scatterData: ScatterChartData?
+    {
+        get
+        {
+            return combinedData?.scatterData
+        }
+    }
+    
+    // MARK: - CandleChartDataProvider
+    
+    open var candleData: CandleChartData?
+    {
+        get
+        {
+            return combinedData?.candleData
+        }
+    }
+    
+    // MARK: - BubbleChartDataProvider
+    
+    open var bubbleData: BubbleChartData?
+    {
+        get
+        {
+            return combinedData?.bubbleData
+        }
+    }
+    
+    // MARK: - Accessors
+    
+    /// if set to true, all values are drawn above their bars, instead of below their top
+    @objc open var drawValueAboveBarEnabled: Bool
+        {
+        get { return (renderer as! CombinedChartRenderer).drawValueAboveBarEnabled }
+        set { (renderer as! CombinedChartRenderer).drawValueAboveBarEnabled = newValue }
+    }
+    
+    /// if set to true, a grey area is drawn behind each bar that indicates the maximum value
+    @objc open var drawBarShadowEnabled: Bool
+    {
+        get { return (renderer as! CombinedChartRenderer).drawBarShadowEnabled }
+        set { (renderer as! CombinedChartRenderer).drawBarShadowEnabled = newValue }
+    }
+    
+    /// `true` if drawing values above bars is enabled, `false` ifnot
+    open var isDrawValueAboveBarEnabled: Bool { return (renderer as! CombinedChartRenderer).drawValueAboveBarEnabled }
+    
+    /// `true` if drawing shadows (maxvalue) for each bar is enabled, `false` ifnot
+    open var isDrawBarShadowEnabled: Bool { return (renderer as! CombinedChartRenderer).drawBarShadowEnabled }
+    
+    /// the order in which the provided data objects should be drawn.
+    /// The earlier you place them in the provided array, the further they will be in the background. 
+    /// e.g. if you provide [DrawOrder.Bar, DrawOrder.Line], the bars will be drawn behind the lines.
+    @objc open var drawOrder: [Int]
+    {
+        get
+        {
+            return (renderer as! CombinedChartRenderer).drawOrder.map { $0.rawValue }
+        }
+        set
+        {
+            (renderer as! CombinedChartRenderer).drawOrder = newValue.map { DrawOrder(rawValue: $0)! }
+        }
+    }
+    
+    /// Set this to `true` to make the highlight operation full-bar oriented, `false` to make it highlight single values
+    @objc open var highlightFullBarEnabled: Bool = false
+    
+    /// `true` the highlight is be full-bar oriented, `false` ifsingle-value
+    open var isHighlightFullBarEnabled: Bool { return highlightFullBarEnabled }
+    
+    // MARK: - ChartViewBase
+    
+    /// draws all MarkerViews on the highlighted positions
+    override func drawMarkers(context: CGContext)
+    {
+        guard
+            let marker = marker, 
+            isDrawMarkersEnabled && valuesToHighlight()
+            else { return }
+        
+        for i in 0 ..< _indicesToHighlight.count
+        {
+            let highlight = _indicesToHighlight[i]
+            
+            guard 
+                let set = combinedData?.getDataSetByHighlight(highlight),
+                let e = _data?.entryForHighlight(highlight)
+                else { continue }
+            
+            let entryIndex = set.entryIndex(entry: e)
+            if entryIndex > Int(Double(set.entryCount) * _animator.phaseX)
+            {
+                continue
+            }
+            
+            let pos = getMarkerPosition(highlight: highlight)
+            
+            // check bounds
+            if !_viewPortHandler.isInBounds(x: pos.x, y: pos.y)
+            {
+                continue
+            }
+            
+            // callbacks to update the content
+            marker.refreshContent(entry: e, highlight: highlight)
+            
+            // draw the marker
+            marker.draw(context: context, point: pos)
+        }
+    }
+}

+ 270 - 0
Pods/Charts/Source/Charts/Charts/HorizontalBarChartView.swift

@@ -0,0 +1,270 @@
+//
+//  HorizontalBarChartView.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+/// BarChart with horizontal bar orientation. In this implementation, x- and y-axis are switched.
+open class HorizontalBarChartView: BarChartView
+{
+    internal override func initialize()
+    {
+        super.initialize()
+        
+        _leftAxisTransformer = TransformerHorizontalBarChart(viewPortHandler: _viewPortHandler)
+        _rightAxisTransformer = TransformerHorizontalBarChart(viewPortHandler: _viewPortHandler)
+        
+        renderer = HorizontalBarChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
+        leftYAxisRenderer = YAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, yAxis: leftAxis, transformer: _leftAxisTransformer)
+        rightYAxisRenderer = YAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, yAxis: rightAxis, transformer: _rightAxisTransformer)
+        xAxisRenderer = XAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, xAxis: _xAxis, transformer: _leftAxisTransformer, chart: self)
+        
+        self.highlighter = HorizontalBarHighlighter(chart: self)
+    }
+    
+    internal override func calculateLegendOffsets(offsetLeft: inout CGFloat, offsetTop: inout CGFloat, offsetRight: inout CGFloat, offsetBottom: inout CGFloat)
+    {
+        guard
+            let legend = _legend,
+            legend.isEnabled,
+            !legend.drawInside
+        else { return }
+        
+        // setup offsets for legend
+        switch legend.orientation
+        {
+        case .vertical:
+            switch legend.horizontalAlignment
+            {
+            case .left:
+                offsetLeft += min(legend.neededWidth, _viewPortHandler.chartWidth * legend.maxSizePercent) + legend.xOffset
+                
+            case .right:
+                offsetRight += min(legend.neededWidth, _viewPortHandler.chartWidth * legend.maxSizePercent) + legend.xOffset
+                
+            case .center:
+                
+                switch legend.verticalAlignment
+                {
+                case .top:
+                    offsetTop += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset
+                    
+                case .bottom:
+                    offsetBottom += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset
+                    
+                default:
+                    break
+                }
+            }
+            
+        case .horizontal:
+            switch legend.verticalAlignment
+            {
+            case .top:
+                offsetTop += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset
+                
+                // left axis equals the top x-axis in a horizontal chart
+                if leftAxis.isEnabled && leftAxis.isDrawLabelsEnabled
+                {
+                    offsetTop += leftAxis.getRequiredHeightSpace()
+                }
+                
+            case .bottom:
+                offsetBottom += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset
+
+                // right axis equals the bottom x-axis in a horizontal chart
+                if rightAxis.isEnabled && rightAxis.isDrawLabelsEnabled
+                {
+                    offsetBottom += rightAxis.getRequiredHeightSpace()
+                }
+            default:
+                break
+            }
+        }
+    }
+    
+    internal override func calculateOffsets()
+    {
+        var offsetLeft: CGFloat = 0.0,
+        offsetRight: CGFloat = 0.0,
+        offsetTop: CGFloat = 0.0,
+        offsetBottom: CGFloat = 0.0
+        
+        calculateLegendOffsets(offsetLeft: &offsetLeft,
+                               offsetTop: &offsetTop,
+                               offsetRight: &offsetRight,
+                               offsetBottom: &offsetBottom)
+        
+        // offsets for y-labels
+        if leftAxis.needsOffset
+        {
+            offsetTop += leftAxis.getRequiredHeightSpace()
+        }
+        
+        if rightAxis.needsOffset
+        {
+            offsetBottom += rightAxis.getRequiredHeightSpace()
+        }
+        
+        let xlabelwidth = _xAxis.labelRotatedWidth
+        
+        if _xAxis.isEnabled
+        {
+            // offsets for x-labels
+            if _xAxis.labelPosition == .bottom
+            {
+                offsetLeft += xlabelwidth
+            }
+            else if _xAxis.labelPosition == .top
+            {
+                offsetRight += xlabelwidth
+            }
+            else if _xAxis.labelPosition == .bothSided
+            {
+                offsetLeft += xlabelwidth
+                offsetRight += xlabelwidth
+            }
+        }
+        
+        offsetTop += self.extraTopOffset
+        offsetRight += self.extraRightOffset
+        offsetBottom += self.extraBottomOffset
+        offsetLeft += self.extraLeftOffset
+
+        _viewPortHandler.restrainViewPort(
+            offsetLeft: max(self.minOffset, offsetLeft),
+            offsetTop: max(self.minOffset, offsetTop),
+            offsetRight: max(self.minOffset, offsetRight),
+            offsetBottom: max(self.minOffset, offsetBottom))
+        
+        prepareOffsetMatrix()
+        prepareValuePxMatrix()
+    }
+    
+    internal override func prepareValuePxMatrix()
+    {
+        _rightAxisTransformer.prepareMatrixValuePx(chartXMin: rightAxis._axisMinimum, deltaX: CGFloat(rightAxis.axisRange), deltaY: CGFloat(_xAxis.axisRange), chartYMin: _xAxis._axisMinimum)
+        _leftAxisTransformer.prepareMatrixValuePx(chartXMin: leftAxis._axisMinimum, deltaX: CGFloat(leftAxis.axisRange), deltaY: CGFloat(_xAxis.axisRange), chartYMin: _xAxis._axisMinimum)
+    }
+    
+    open override func getMarkerPosition(highlight: Highlight) -> CGPoint
+    {
+        return CGPoint(x: highlight.drawY, y: highlight.drawX)
+    }
+    
+    open override func getBarBounds(entry e: BarChartDataEntry) -> CGRect
+    {
+        guard
+            let data = _data as? BarChartData,
+            let set = data.getDataSetForEntry(e) as? IBarChartDataSet
+            else { return CGRect.null }
+        
+        let y = e.y
+        let x = e.x
+        
+        let barWidth = data.barWidth
+        
+        let top = x - 0.5 + barWidth / 2.0
+        let bottom = x + 0.5 - barWidth / 2.0
+        let left = y >= 0.0 ? y : 0.0
+        let right = y <= 0.0 ? y : 0.0
+        
+        var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top)
+        
+        getTransformer(forAxis: set.axisDependency).rectValueToPixel(&bounds)
+        
+        return bounds
+    }
+    
+    open override func getPosition(entry e: ChartDataEntry, axis: YAxis.AxisDependency) -> CGPoint
+    {
+        var vals = CGPoint(x: CGFloat(e.y), y: CGFloat(e.x))
+        
+        getTransformer(forAxis: axis).pointValueToPixel(&vals)
+        
+        return vals
+    }
+
+    open override func getHighlightByTouchPoint(_ pt: CGPoint) -> Highlight?
+    {
+        if _data === nil
+        {
+            Swift.print("Can't select by touch. No data set.", terminator: "\n")
+            return nil
+        }
+        
+        return self.highlighter?.getHighlight(x: pt.y, y: pt.x)
+    }
+    
+    /// The lowest x-index (value on the x-axis) that is still visible on he chart.
+    open override var lowestVisibleX: Double
+    {
+        var pt = CGPoint(
+            x: viewPortHandler.contentLeft,
+            y: viewPortHandler.contentBottom)
+        
+        getTransformer(forAxis: .left).pixelToValues(&pt)
+        
+        return max(xAxis._axisMinimum, Double(pt.y))
+    }
+    
+    /// The highest x-index (value on the x-axis) that is still visible on the chart.
+    open override var highestVisibleX: Double
+    {
+        var pt = CGPoint(
+            x: viewPortHandler.contentLeft,
+            y: viewPortHandler.contentTop)
+        
+        getTransformer(forAxis: .left).pixelToValues(&pt)
+        
+        return min(xAxis._axisMaximum, Double(pt.y))
+    }
+    
+    // MARK: - Viewport
+    
+    open override func setVisibleXRangeMaximum(_ maxXRange: Double)
+    {
+        let xScale = xAxis.axisRange / maxXRange
+        viewPortHandler.setMinimumScaleY(CGFloat(xScale))
+    }
+    
+    open override func setVisibleXRangeMinimum(_ minXRange: Double)
+    {
+        let xScale = xAxis.axisRange / minXRange
+        viewPortHandler.setMaximumScaleY(CGFloat(xScale))
+    }
+    
+    open override func setVisibleXRange(minXRange: Double, maxXRange: Double)
+    {
+        let minScale = xAxis.axisRange / minXRange
+        let maxScale = xAxis.axisRange / maxXRange
+        viewPortHandler.setMinMaxScaleY(minScaleY: CGFloat(minScale), maxScaleY: CGFloat(maxScale))
+    }
+    
+    open override func setVisibleYRangeMaximum(_ maxYRange: Double, axis: YAxis.AxisDependency)
+    {
+        let yScale = getAxisRange(axis: axis) / maxYRange
+        viewPortHandler.setMinimumScaleX(CGFloat(yScale))
+    }
+    
+    open override func setVisibleYRangeMinimum(_ minYRange: Double, axis: YAxis.AxisDependency)
+    {
+        let yScale = getAxisRange(axis: axis) / minYRange
+        viewPortHandler.setMaximumScaleX(CGFloat(yScale))
+    }
+    
+    open override func setVisibleYRange(minYRange: Double, maxYRange: Double, axis: YAxis.AxisDependency)
+    {
+        let minScale = getAxisRange(axis: axis) / minYRange
+        let maxScale = getAxisRange(axis: axis) / maxYRange
+        viewPortHandler.setMinMaxScaleX(minScaleX: CGFloat(minScale), maxScaleX: CGFloat(maxScale))
+    }
+}

+ 28 - 0
Pods/Charts/Source/Charts/Charts/LineChartView.swift

@@ -0,0 +1,28 @@
+//
+//  LineChartView.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+/// Chart that draws lines, surfaces, circles, ...
+open class LineChartView: BarLineChartViewBase, LineChartDataProvider
+{
+    internal override func initialize()
+    {
+        super.initialize()
+        
+        renderer = LineChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
+    }
+    
+    // MARK: - LineChartDataProvider
+    
+    open var lineData: LineChartData? { return _data as? LineChartData }
+}

+ 690 - 0
Pods/Charts/Source/Charts/Charts/PieChartView.swift

@@ -0,0 +1,690 @@
+//
+//  PieChartView.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+#if canImport(UIKit)
+    import UIKit
+#endif
+
+#if canImport(Cocoa)
+import Cocoa
+#endif
+
+/// View that represents a pie chart. Draws cake like slices.
+open class PieChartView: PieRadarChartViewBase
+{
+    /// rect object that represents the bounds of the piechart, needed for drawing the circle
+    private var _circleBox = CGRect()
+    
+    /// flag indicating if entry labels should be drawn or not
+    private var _drawEntryLabelsEnabled = true
+    
+    /// array that holds the width of each pie-slice in degrees
+    private var _drawAngles = [CGFloat]()
+    
+    /// array that holds the absolute angle in degrees of each slice
+    private var _absoluteAngles = [CGFloat]()
+    
+    /// if true, the hole inside the chart will be drawn
+    private var _drawHoleEnabled = true
+    
+    private var _holeColor: NSUIColor? = NSUIColor.white
+    
+    /// Sets the color the entry labels are drawn with.
+    private var _entryLabelColor: NSUIColor? = NSUIColor.white
+    
+    /// Sets the font the entry labels are drawn with.
+    private var _entryLabelFont: NSUIFont? = NSUIFont(name: "HelveticaNeue", size: 13.0)
+    
+    /// if true, the hole will see-through to the inner tips of the slices
+    private var _drawSlicesUnderHoleEnabled = false
+    
+    /// if true, the values inside the piechart are drawn as percent values
+    private var _usePercentValuesEnabled = false
+    
+    /// variable for the text that is drawn in the center of the pie-chart
+    private var _centerAttributedText: NSAttributedString?
+    
+    /// the offset on the x- and y-axis the center text has in dp.
+    private var _centerTextOffset: CGPoint = CGPoint()
+    
+    /// indicates the size of the hole in the center of the piechart
+    ///
+    /// **default**: `0.5`
+    private var _holeRadiusPercent = CGFloat(0.5)
+    
+    private var _transparentCircleColor: NSUIColor? = NSUIColor(white: 1.0, alpha: 105.0/255.0)
+    
+    /// the radius of the transparent circle next to the chart-hole in the center
+    private var _transparentCircleRadiusPercent = CGFloat(0.55)
+    
+    /// if enabled, centertext is drawn
+    private var _drawCenterTextEnabled = true
+    
+    private var _centerTextRadiusPercent: CGFloat = 1.0
+    
+    /// maximum angle for this pie
+    private var _maxAngle: CGFloat = 360.0
+
+    public override init(frame: CGRect)
+    {
+        super.init(frame: frame)
+    }
+    
+    public required init?(coder aDecoder: NSCoder)
+    {
+        super.init(coder: aDecoder)
+    }
+    
+    internal override func initialize()
+    {
+        super.initialize()
+        
+        renderer = PieChartRenderer(chart: self, animator: _animator, viewPortHandler: _viewPortHandler)
+        _xAxis = nil
+        
+        self.highlighter = PieHighlighter(chart: self)
+    }
+    
+    open override func draw(_ rect: CGRect)
+    {
+        super.draw(rect)
+        
+        if _data === nil
+        {
+            return
+        }
+        
+        let optionalContext = NSUIGraphicsGetCurrentContext()
+        guard let context = optionalContext, let renderer = renderer else
+        {
+            return
+        }
+        
+        renderer.drawData(context: context)
+        
+        if (valuesToHighlight())
+        {
+            renderer.drawHighlighted(context: context, indices: _indicesToHighlight)
+        }
+        
+        renderer.drawExtras(context: context)
+        
+        renderer.drawValues(context: context)
+        
+        legendRenderer.renderLegend(context: context)
+        
+        drawDescription(context: context)
+        
+        drawMarkers(context: context)
+    }
+
+    /// if width is larger than height
+    private var widthLarger: Bool
+    {
+        return _viewPortHandler.contentRect.orientation == .landscape
+    }
+
+    /// adjusted radius. Use diameter when it's half pie and width is larger
+    private var adjustedRadius: CGFloat
+    {
+        return maxAngle <= 180 && widthLarger ? diameter : diameter / 2.0
+    }
+
+    /// true centerOffsets considering half pie & width is larger
+    private func adjustedCenterOffsets() -> CGPoint
+    {
+        var c = self.centerOffsets
+        c.y = maxAngle <= 180 && widthLarger ? c.y + adjustedRadius / 2 : c.y
+        return c
+    }
+    
+    internal override func calculateOffsets()
+    {
+        super.calculateOffsets()
+        
+        // prevent nullpointer when no data set
+        if _data === nil
+        {
+            return
+        }
+
+        let radius = adjustedRadius
+        
+        let c = adjustedCenterOffsets()
+        
+        let shift = (data as? PieChartData)?.dataSet?.selectionShift ?? 0.0
+        
+        // create the circle box that will contain the pie-chart (the bounds of the pie-chart)
+        _circleBox.origin.x = (c.x - radius) + shift
+        _circleBox.origin.y = (c.y - radius) + shift
+        _circleBox.size.width = radius * 2 - shift * 2.0
+        _circleBox.size.height = radius * 2 - shift * 2.0
+
+    }
+
+    internal override func calcMinMax()
+    {
+        calcAngles()
+    }
+
+    @objc open override func angleForPoint(x: CGFloat, y: CGFloat) -> CGFloat
+    {
+        let c = adjustedCenterOffsets()
+
+        let tx = Double(x - c.x)
+        let ty = Double(y - c.y)
+        let length = sqrt(tx * tx + ty * ty)
+        let r = acos(ty / length)
+
+        var angle = r.RAD2DEG
+
+        if x > c.x
+        {
+            angle = 360.0 - angle
+        }
+
+        // add 90° because chart starts EAST
+        angle = angle + 90.0
+
+        // neutralize overflow
+        if angle > 360.0
+        {
+            angle = angle - 360.0
+        }
+
+        return CGFloat(angle)
+    }
+
+    /// - Returns: The distance of a certain point on the chart to the center of the chart.
+    @objc open override func distanceToCenter(x: CGFloat, y: CGFloat) -> CGFloat
+    {
+        let c = adjustedCenterOffsets()
+
+        var dist = CGFloat(0.0)
+
+        var xDist = CGFloat(0.0)
+        var yDist = CGFloat(0.0)
+
+        if x > c.x
+        {
+            xDist = x - c.x
+        }
+        else
+        {
+            xDist = c.x - x
+        }
+
+        if y > c.y
+        {
+            yDist = y - c.y
+        }
+        else
+        {
+            yDist = c.y - y
+        }
+
+        // pythagoras
+        dist = sqrt(pow(xDist, 2.0) + pow(yDist, 2.0))
+
+        return dist
+    }
+
+    open override func getMarkerPosition(highlight: Highlight) -> CGPoint
+    {
+        let center = self.centerCircleBox
+        var r = self.radius
+        
+        var off = r / 10.0 * 3.6
+        
+        if self.isDrawHoleEnabled
+        {
+            off = (r - (r * self.holeRadiusPercent)) / 2.0
+        }
+        
+        r -= off // offset to keep things inside the chart
+        
+        let rotationAngle = self.rotationAngle
+        
+        let entryIndex = Int(highlight.x)
+        
+        // offset needed to center the drawn text in the slice
+        let offset = drawAngles[entryIndex] / 2.0
+        
+        // calculate the text position
+        let x: CGFloat = (r * cos(((rotationAngle + absoluteAngles[entryIndex] - offset) * CGFloat(_animator.phaseY)).DEG2RAD) + center.x)
+        let y: CGFloat = (r * sin(((rotationAngle + absoluteAngles[entryIndex] - offset) * CGFloat(_animator.phaseY)).DEG2RAD) + center.y)
+        
+        return CGPoint(x: x, y: y)
+    }
+    
+    /// calculates the needed angles for the chart slices
+    private func calcAngles()
+    {
+        _drawAngles = [CGFloat]()
+        _absoluteAngles = [CGFloat]()
+        
+        guard let data = _data else { return }
+
+        let entryCount = data.entryCount
+        
+        _drawAngles.reserveCapacity(entryCount)
+        _absoluteAngles.reserveCapacity(entryCount)
+        
+        let yValueSum = (_data as! PieChartData).yValueSum
+
+        var cnt = 0
+
+        for set in data.dataSets
+        {
+            for j in 0 ..< set.entryCount
+            {
+                guard let e = set.entryForIndex(j) else { continue }
+                
+                _drawAngles.append(calcAngle(value: abs(e.y), yValueSum: yValueSum))
+
+                if cnt == 0
+                {
+                    _absoluteAngles.append(_drawAngles[cnt])
+                }
+                else
+                {
+                    _absoluteAngles.append(_absoluteAngles[cnt - 1] + _drawAngles[cnt])
+                }
+
+                cnt += 1
+            }
+        }
+    }
+    
+    /// Checks if the given index is set to be highlighted.
+    @objc open func needsHighlight(index: Int) -> Bool
+    {
+        return _indicesToHighlight.contains { Int($0.x) == index }
+    }
+    
+    /// calculates the needed angle for a given value
+    private func calcAngle(_ value: Double) -> CGFloat
+    {
+        return calcAngle(value: value, yValueSum: (_data as! PieChartData).yValueSum)
+    }
+    
+    /// calculates the needed angle for a given value
+    private func calcAngle(value: Double, yValueSum: Double) -> CGFloat
+    {
+        return CGFloat(value) / CGFloat(yValueSum) * _maxAngle
+    }
+    
+    /// This will throw an exception, PieChart has no XAxis object.
+    open override var xAxis: XAxis
+    {
+        fatalError("PieChart has no XAxis")
+    }
+
+    open override func indexForAngle(_ angle: CGFloat) -> Int
+    {
+        // TODO: Return nil instead of -1
+        // take the current angle of the chart into consideration
+        let a = (angle - self.rotationAngle).normalizedAngle
+        return _absoluteAngles.firstIndex { $0 > a } ?? -1
+    }
+    
+    /// - Returns: The index of the DataSet this x-index belongs to.
+    @objc open func dataSetIndexForIndex(_ xValue: Double) -> Int
+    {
+        // TODO: Return nil instead of -1
+        return _data?.dataSets.firstIndex {
+            $0.entryForXValue(xValue, closestToY: .nan) != nil
+        } ?? -1
+    }
+    
+    /// - Returns: An integer array of all the different angles the chart slices
+    /// have the angles in the returned array determine how much space (of 360°)
+    /// each slice takes
+    @objc open var drawAngles: [CGFloat]
+    {
+        return _drawAngles
+    }
+
+    /// - Returns: The absolute angles of the different chart slices (where the
+    /// slices end)
+    @objc open var absoluteAngles: [CGFloat]
+    {
+        return _absoluteAngles
+    }
+    
+    /// The color for the hole that is drawn in the center of the PieChart (if enabled).
+    /// 
+    /// - Note: Use holeTransparent with holeColor = nil to make the hole transparent.*
+    @objc open var holeColor: NSUIColor?
+    {
+        get
+        {
+            return _holeColor
+        }
+        set
+        {
+            _holeColor = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// if true, the hole will see-through to the inner tips of the slices
+    ///
+    /// **default**: `false`
+    @objc open var drawSlicesUnderHoleEnabled: Bool
+    {
+        get
+        {
+            return _drawSlicesUnderHoleEnabled
+        }
+        set
+        {
+            _drawSlicesUnderHoleEnabled = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// `true` if the inner tips of the slices are visible behind the hole, `false` if not.
+    @objc open var isDrawSlicesUnderHoleEnabled: Bool
+    {
+        return drawSlicesUnderHoleEnabled
+    }
+    
+    /// `true` if the hole in the center of the pie-chart is set to be visible, `false` ifnot
+    @objc open var drawHoleEnabled: Bool
+    {
+        get
+        {
+            return _drawHoleEnabled
+        }
+        set
+        {
+            _drawHoleEnabled = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// `true` if the hole in the center of the pie-chart is set to be visible, `false` ifnot
+    @objc open var isDrawHoleEnabled: Bool
+    {
+        get
+        {
+            return drawHoleEnabled
+        }
+    }
+    
+    /// the text that is displayed in the center of the pie-chart
+    @objc open var centerText: String?
+    {
+        get
+        {
+            return self.centerAttributedText?.string
+        }
+        set
+        {
+            var attrString: NSMutableAttributedString?
+            if newValue == nil
+            {
+                attrString = nil
+            }
+            else
+            {
+                let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
+                paragraphStyle.lineBreakMode = .byTruncatingTail
+                paragraphStyle.alignment = .center
+                
+                attrString = NSMutableAttributedString(string: newValue!)
+                attrString?.setAttributes([
+                    .foregroundColor: NSUIColor.labelOrBlack,
+                    .font: NSUIFont.systemFont(ofSize: 12.0),
+                    .paragraphStyle: paragraphStyle
+                    ], range: NSMakeRange(0, attrString!.length))
+            }
+            self.centerAttributedText = attrString
+        }
+    }
+    
+    /// the text that is displayed in the center of the pie-chart
+    @objc open var centerAttributedText: NSAttributedString?
+    {
+        get
+        {
+            return _centerAttributedText
+        }
+        set
+        {
+            _centerAttributedText = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// Sets the offset the center text should have from it's original position in dp. Default x = 0, y = 0
+    @objc open var centerTextOffset: CGPoint
+    {
+        get
+        {
+            return _centerTextOffset
+        }
+        set
+        {
+            _centerTextOffset = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// `true` if drawing the center text is enabled
+    @objc open var drawCenterTextEnabled: Bool
+    {
+        get
+        {
+            return _drawCenterTextEnabled
+        }
+        set
+        {
+            _drawCenterTextEnabled = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// `true` if drawing the center text is enabled
+    @objc open var isDrawCenterTextEnabled: Bool
+    {
+        get
+        {
+            return drawCenterTextEnabled
+        }
+    }
+    
+    internal override var requiredLegendOffset: CGFloat
+    {
+        return _legend.font.pointSize * 2.0
+    }
+    
+    internal override var requiredBaseOffset: CGFloat
+    {
+        return 0.0
+    }
+    
+    open override var radius: CGFloat
+    {
+        return _circleBox.width / 2.0
+    }
+    
+    /// The circlebox, the boundingbox of the pie-chart slices
+    @objc open var circleBox: CGRect
+    {
+        return _circleBox
+    }
+    
+    /// The center of the circlebox
+    @objc open var centerCircleBox: CGPoint
+    {
+        return CGPoint(x: _circleBox.midX, y: _circleBox.midY)
+    }
+    
+    /// the radius of the hole in the center of the piechart in percent of the maximum radius (max = the radius of the whole chart)
+    /// 
+    /// **default**: 0.5 (50%) (half the pie)
+    @objc open var holeRadiusPercent: CGFloat
+    {
+        get
+        {
+            return _holeRadiusPercent
+        }
+        set
+        {
+            _holeRadiusPercent = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// The color that the transparent-circle should have.
+    ///
+    /// **default**: `nil`
+    @objc open var transparentCircleColor: NSUIColor?
+    {
+        get
+        {
+            return _transparentCircleColor
+        }
+        set
+        {
+            _transparentCircleColor = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// the radius of the transparent circle that is drawn next to the hole in the piechart in percent of the maximum radius (max = the radius of the whole chart)
+    /// 
+    /// **default**: 0.55 (55%) -> means 5% larger than the center-hole by default
+    @objc open var transparentCircleRadiusPercent: CGFloat
+    {
+        get
+        {
+            return _transparentCircleRadiusPercent
+        }
+        set
+        {
+            _transparentCircleRadiusPercent = newValue
+            setNeedsDisplay()
+        }
+    }
+        
+    /// The color the entry labels are drawn with.
+    @objc open var entryLabelColor: NSUIColor?
+    {
+        get { return _entryLabelColor }
+        set
+        {
+            _entryLabelColor = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// The font the entry labels are drawn with.
+    @objc open var entryLabelFont: NSUIFont?
+    {
+        get { return _entryLabelFont }
+        set
+        {
+            _entryLabelFont = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// Set this to true to draw the enrty labels into the pie slices
+    @objc open var drawEntryLabelsEnabled: Bool
+    {
+        get
+        {
+            return _drawEntryLabelsEnabled
+        }
+        set
+        {
+            _drawEntryLabelsEnabled = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// `true` if drawing entry labels is enabled, `false` ifnot
+    @objc open var isDrawEntryLabelsEnabled: Bool
+    {
+        get
+        {
+            return drawEntryLabelsEnabled
+        }
+    }
+    
+    /// If this is enabled, values inside the PieChart are drawn in percent and not with their original value. Values provided for the ValueFormatter to format are then provided in percent.
+    @objc open var usePercentValuesEnabled: Bool
+    {
+        get
+        {
+            return _usePercentValuesEnabled
+        }
+        set
+        {
+            _usePercentValuesEnabled = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// `true` if drawing x-values is enabled, `false` ifnot
+    @objc open var isUsePercentValuesEnabled: Bool
+    {
+        get
+        {
+            return usePercentValuesEnabled
+        }
+    }
+    
+    /// the rectangular radius of the bounding box for the center text, as a percentage of the pie hole
+    @objc open var centerTextRadiusPercent: CGFloat
+    {
+        get
+        {
+            return _centerTextRadiusPercent
+        }
+        set
+        {
+            _centerTextRadiusPercent = newValue
+            setNeedsDisplay()
+        }
+    }
+    
+    /// The max angle that is used for calculating the pie-circle.
+    /// 360 means it's a full pie-chart, 180 results in a half-pie-chart.
+    /// **default**: 360.0
+    @objc open var maxAngle: CGFloat
+    {
+        get
+        {
+            return _maxAngle
+        }
+        set
+        {
+            _maxAngle = newValue
+            
+            if _maxAngle > 360.0
+            {
+                _maxAngle = 360.0
+            }
+            
+            if _maxAngle < 90.0
+            {
+                _maxAngle = 90.0
+            }
+        }
+    }
+}

+ 855 - 0
Pods/Charts/Source/Charts/Charts/PieRadarChartViewBase.swift

@@ -0,0 +1,855 @@
+//
+//  PieRadarChartViewBase.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+import QuartzCore
+
+#if canImport(AppKit)
+import AppKit
+#endif
+
+
+/// Base class of PieChartView and RadarChartView.
+open class PieRadarChartViewBase: ChartViewBase
+{
+    /// holds the normalized version of the current rotation angle of the chart
+    private var _rotationAngle = CGFloat(270.0)
+    
+    /// holds the raw version of the current rotation angle of the chart
+    private var _rawRotationAngle = CGFloat(270.0)
+    
+    /// flag that indicates if rotation is enabled or not
+    @objc open var rotationEnabled = true
+    
+    /// Sets the minimum offset (padding) around the chart, defaults to 0.0
+    @objc open var minOffset = CGFloat(0.0)
+
+    /// iOS && OSX only: Enabled multi-touch rotation using two fingers.
+    private var _rotationWithTwoFingers = false
+    
+    private var _tapGestureRecognizer: NSUITapGestureRecognizer!
+    #if !os(tvOS)
+    private var _rotationGestureRecognizer: NSUIRotationGestureRecognizer!
+    #endif
+    
+    public override init(frame: CGRect)
+    {
+        super.init(frame: frame)
+    }
+    
+    public required init?(coder aDecoder: NSCoder)
+    {
+        super.init(coder: aDecoder)
+    }
+    
+    deinit
+    {
+        stopDeceleration()
+    }
+    
+    internal override func initialize()
+    {
+        super.initialize()
+        
+        _tapGestureRecognizer = NSUITapGestureRecognizer(target: self, action: #selector(tapGestureRecognized(_:)))
+        
+        self.addGestureRecognizer(_tapGestureRecognizer)
+
+        #if !os(tvOS)
+        _rotationGestureRecognizer = NSUIRotationGestureRecognizer(target: self, action: #selector(rotationGestureRecognized(_:)))
+        self.addGestureRecognizer(_rotationGestureRecognizer)
+        _rotationGestureRecognizer.isEnabled = rotationWithTwoFingers
+        #endif
+    }
+    
+    internal override func calcMinMax()
+    {
+        /*_xAxis.axisRange = Double((_data?.xVals.count ?? 0) - 1)*/
+    }
+    
+    open override var maxVisibleCount: Int
+    {
+        get
+        {
+            return data?.entryCount ?? 0
+        }
+    }
+    
+    open override func notifyDataSetChanged()
+    {
+        calcMinMax()
+        
+        if let data = _data , _legend !== nil
+        {
+            legendRenderer.computeLegend(data: data)
+        }
+        
+        calculateOffsets()
+        
+        setNeedsDisplay()
+    }
+  
+    internal override func calculateOffsets()
+    {
+        var legendLeft = CGFloat(0.0)
+        var legendRight = CGFloat(0.0)
+        var legendBottom = CGFloat(0.0)
+        var legendTop = CGFloat(0.0)
+
+        if _legend != nil && _legend.enabled && !_legend.drawInside
+        {
+            let fullLegendWidth = min(_legend.neededWidth, _viewPortHandler.chartWidth * _legend.maxSizePercent)
+            
+            switch _legend.orientation
+            {
+            case .vertical:
+                
+                var xLegendOffset: CGFloat = 0.0
+                
+                if _legend.horizontalAlignment == .left
+                    || _legend.horizontalAlignment == .right
+                {
+                    if _legend.verticalAlignment == .center
+                    {
+                        // this is the space between the legend and the chart
+                        let spacing = CGFloat(13.0)
+                        
+                        xLegendOffset = fullLegendWidth + spacing
+                    }
+                    else
+                    {
+                        // this is the space between the legend and the chart
+                        let spacing = CGFloat(8.0)
+                        
+                        let legendWidth = fullLegendWidth + spacing
+                        let legendHeight = _legend.neededHeight + _legend.textHeightMax
+                        
+                        let c = self.midPoint
+                        
+                        let bottomX = _legend.horizontalAlignment == .right
+                            ? self.bounds.width - legendWidth + 15.0
+                            : legendWidth - 15.0
+                        let bottomY = legendHeight + 15
+                        let distLegend = distanceToCenter(x: bottomX, y: bottomY)
+                        
+                        let reference = getPosition(center: c, dist: self.radius,
+                                                    angle: angleForPoint(x: bottomX, y: bottomY))
+                        
+                        let distReference = distanceToCenter(x: reference.x, y: reference.y)
+                        let minOffset = CGFloat(5.0)
+                        
+                        if bottomY >= c.y
+                            && self.bounds.height - legendWidth > self.bounds.width
+                        {
+                            xLegendOffset = legendWidth
+                        }
+                        else if distLegend < distReference
+                        {
+                            let diff = distReference - distLegend
+                            xLegendOffset = minOffset + diff
+                        }
+                    }
+                }
+                
+                switch _legend.horizontalAlignment
+                {
+                case .left:
+                    legendLeft = xLegendOffset
+                    
+                case .right:
+                    legendRight = xLegendOffset
+                    
+                case .center:
+                    
+                    switch _legend.verticalAlignment
+                    {
+                    case .top:
+                        legendTop = min(_legend.neededHeight, _viewPortHandler.chartHeight * _legend.maxSizePercent)
+                        
+                    case .bottom:
+                        legendBottom = min(_legend.neededHeight, _viewPortHandler.chartHeight * _legend.maxSizePercent)
+                        
+                    default:
+                        break
+                    }
+                }
+            
+            case .horizontal:
+                
+                var yLegendOffset: CGFloat = 0.0
+                
+                if _legend.verticalAlignment == .top
+                    || _legend.verticalAlignment == .bottom
+                {
+                    // It's possible that we do not need this offset anymore as it
+                    //   is available through the extraOffsets, but changing it can mean
+                    //   changing default visibility for existing apps.
+                    let yOffset = self.requiredLegendOffset
+                    
+                    yLegendOffset = min(
+                        _legend.neededHeight + yOffset,
+                        _viewPortHandler.chartHeight * _legend.maxSizePercent)
+                }
+                
+                switch _legend.verticalAlignment
+                {
+                case .top:
+                    
+                    legendTop = yLegendOffset
+                    
+                case .bottom:
+                    
+                    legendBottom = yLegendOffset
+                    
+                default:
+                    break
+                }
+            }
+
+            legendLeft += self.requiredBaseOffset
+            legendRight += self.requiredBaseOffset
+            legendTop += self.requiredBaseOffset
+            legendBottom += self.requiredBaseOffset
+        }
+        
+        legendTop += self.extraTopOffset
+        legendRight += self.extraRightOffset
+        legendBottom += self.extraBottomOffset
+        legendLeft += self.extraLeftOffset
+        
+        var minOffset = self.minOffset
+        
+        if self is RadarChartView
+        {
+            let x = self.xAxis
+            
+            if x.isEnabled && x.drawLabelsEnabled
+            {
+                minOffset = max(minOffset, x.labelRotatedWidth)
+            }
+        }
+
+        let offsetLeft = max(minOffset, legendLeft)
+        let offsetTop = max(minOffset, legendTop)
+        let offsetRight = max(minOffset, legendRight)
+        let offsetBottom = max(minOffset, max(self.requiredBaseOffset, legendBottom))
+
+        _viewPortHandler.restrainViewPort(offsetLeft: offsetLeft, offsetTop: offsetTop, offsetRight: offsetRight, offsetBottom: offsetBottom)
+    }
+
+    /// - Returns: The angle relative to the chart center for the given point on the chart in degrees.
+    /// The angle is always between 0 and 360°, 0° is NORTH, 90° is EAST, ...
+    @objc open func angleForPoint(x: CGFloat, y: CGFloat) -> CGFloat
+    {
+        let c = centerOffsets
+        
+        let tx = Double(x - c.x)
+        let ty = Double(y - c.y)
+        let length = sqrt(tx * tx + ty * ty)
+        let r = acos(ty / length)
+
+        var angle = r.RAD2DEG
+
+        if x > c.x
+        {
+            angle = 360.0 - angle
+        }
+
+        // add 90° because chart starts EAST
+        angle = angle + 90.0
+
+        // neutralize overflow
+        if angle > 360.0
+        {
+            angle = angle - 360.0
+        }
+
+        return CGFloat(angle)
+    }
+    
+    /// Calculates the position around a center point, depending on the distance
+    /// from the center, and the angle of the position around the center.
+    @objc open func getPosition(center: CGPoint, dist: CGFloat, angle: CGFloat) -> CGPoint
+    {
+        return CGPoint(x: center.x + dist * cos(angle.DEG2RAD),
+                y: center.y + dist * sin(angle.DEG2RAD))
+    }
+
+    /// - Returns: The distance of a certain point on the chart to the center of the chart.
+    @objc open func distanceToCenter(x: CGFloat, y: CGFloat) -> CGFloat
+    {
+        let c = self.centerOffsets
+
+        var dist = CGFloat(0.0)
+
+        var xDist = CGFloat(0.0)
+        var yDist = CGFloat(0.0)
+
+        if x > c.x
+        {
+            xDist = x - c.x
+        }
+        else
+        {
+            xDist = c.x - x
+        }
+
+        if y > c.y
+        {
+            yDist = y - c.y
+        }
+        else
+        {
+            yDist = c.y - y
+        }
+
+        // pythagoras
+        dist = sqrt(pow(xDist, 2.0) + pow(yDist, 2.0))
+
+        return dist
+    }
+
+    /// - Returns: The xIndex for the given angle around the center of the chart.
+    /// -1 if not found / outofbounds.
+    @objc open func indexForAngle(_ angle: CGFloat) -> Int
+    {
+        fatalError("indexForAngle() cannot be called on PieRadarChartViewBase")
+    }
+
+    /// current rotation angle of the pie chart
+    ///
+    /// **default**: 270 --> top (NORTH)
+    /// Will always return a normalized value, which will be between 0.0 < 360.0
+    @objc open var rotationAngle: CGFloat
+    {
+        get
+        {
+            return _rotationAngle
+        }
+        set
+        {
+            _rawRotationAngle = newValue
+            _rotationAngle = newValue.normalizedAngle
+            setNeedsDisplay()
+        }
+    }
+    
+    /// gets the raw version of the current rotation angle of the pie chart the returned value could be any value, negative or positive, outside of the 360 degrees. 
+    /// this is used when working with rotation direction, mainly by gestures and animations.
+    @objc open var rawRotationAngle: CGFloat
+    {
+        return _rawRotationAngle
+    }
+
+    /// The diameter of the pie- or radar-chart
+    @objc open var diameter: CGFloat
+    {
+        var content = _viewPortHandler.contentRect
+        content.origin.x += extraLeftOffset
+        content.origin.y += extraTopOffset
+        content.size.width -= extraLeftOffset + extraRightOffset
+        content.size.height -= extraTopOffset + extraBottomOffset
+        return min(content.width, content.height)
+    }
+
+    /// The radius of the chart in pixels.
+    @objc open var radius: CGFloat
+    {
+        fatalError("radius cannot be called on PieRadarChartViewBase")
+    }
+
+    /// The required offset for the chart legend.
+    internal var requiredLegendOffset: CGFloat
+    {
+        fatalError("requiredLegendOffset cannot be called on PieRadarChartViewBase")
+    }
+
+    /// - Returns: The base offset needed for the chart without calculating the
+    /// legend size.
+    internal var requiredBaseOffset: CGFloat
+    {
+        fatalError("requiredBaseOffset cannot be called on PieRadarChartViewBase")
+    }
+    
+    open override var chartYMax: Double
+    {
+        return 0.0
+    }
+    
+    open override var chartYMin: Double
+    {
+        return 0.0
+    }
+    
+    @objc open var isRotationEnabled: Bool { return rotationEnabled }
+    
+    /// flag that indicates if rotation is done with two fingers or one.
+    /// when the chart is inside a scrollview, you need a two-finger rotation because a one-finger rotation eats up all touch events.
+    ///
+    /// On iOS this will disable one-finger rotation.
+    /// On OSX this will keep two-finger multitouch rotation, and one-pointer mouse rotation.
+    /// 
+    /// **default**: false
+    @objc open var rotationWithTwoFingers: Bool
+    {
+        get
+        {
+            return _rotationWithTwoFingers
+        }
+        set
+        {
+            _rotationWithTwoFingers = newValue
+            #if !os(tvOS)
+            _rotationGestureRecognizer.isEnabled = _rotationWithTwoFingers
+            #endif
+        }
+    }
+    
+    /// flag that indicates if rotation is done with two fingers or one.
+    /// when the chart is inside a scrollview, you need a two-finger rotation because a one-finger rotation eats up all touch events.
+    ///
+    /// On iOS this will disable one-finger rotation.
+    /// On OSX this will keep two-finger multitouch rotation, and one-pointer mouse rotation.
+    ///
+    /// **default**: false
+    @objc open var isRotationWithTwoFingers: Bool
+    {
+        return _rotationWithTwoFingers
+    }
+    
+    // MARK: - Animation
+    
+    private var _spinAnimator: Animator!
+    
+    /// Applys a spin animation to the Chart.
+    @objc open func spin(duration: TimeInterval, fromAngle: CGFloat, toAngle: CGFloat, easing: ChartEasingFunctionBlock?)
+    {
+        if _spinAnimator != nil
+        {
+            _spinAnimator.stop()
+        }
+        
+        _spinAnimator = Animator()
+        _spinAnimator.updateBlock = {
+            self.rotationAngle = (toAngle - fromAngle) * CGFloat(self._spinAnimator.phaseX) + fromAngle
+        }
+        _spinAnimator.stopBlock = { self._spinAnimator = nil }
+        
+        _spinAnimator.animate(xAxisDuration: duration, easing: easing)
+    }
+    
+    @objc open func spin(duration: TimeInterval, fromAngle: CGFloat, toAngle: CGFloat, easingOption: ChartEasingOption)
+    {
+        spin(duration: duration, fromAngle: fromAngle, toAngle: toAngle, easing: easingFunctionFromOption(easingOption))
+    }
+    
+    @objc open func spin(duration: TimeInterval, fromAngle: CGFloat, toAngle: CGFloat)
+    {
+        spin(duration: duration, fromAngle: fromAngle, toAngle: toAngle, easing: nil)
+    }
+    
+    @objc open func stopSpinAnimation()
+    {
+        if _spinAnimator != nil
+        {
+            _spinAnimator.stop()
+        }
+    }
+    
+    // MARK: - Gestures
+    
+    private var _rotationGestureStartPoint: CGPoint!
+    private var _isRotating = false
+    private var _startAngle = CGFloat(0.0)
+    
+    private struct AngularVelocitySample
+    {
+        var time: TimeInterval
+        var angle: CGFloat
+    }
+    
+    private var velocitySamples = [AngularVelocitySample]()
+    
+    private var _decelerationLastTime: TimeInterval = 0.0
+    private var _decelerationDisplayLink: NSUIDisplayLink!
+    private var _decelerationAngularVelocity: CGFloat = 0.0
+    
+    internal final func processRotationGestureBegan(location: CGPoint)
+    {
+        self.resetVelocity()
+        
+        if rotationEnabled
+        {
+            self.sampleVelocity(touchLocation: location)
+        }
+        
+        self.setGestureStartAngle(x: location.x, y: location.y)
+        
+        _rotationGestureStartPoint = location
+    }
+    
+    internal final func processRotationGestureMoved(location: CGPoint)
+    {
+        if isDragDecelerationEnabled
+        {
+            sampleVelocity(touchLocation: location)
+        }
+        
+        if !_isRotating &&
+            distance(
+                eventX: location.x,
+                startX: _rotationGestureStartPoint.x,
+                eventY: location.y,
+                startY: _rotationGestureStartPoint.y) > CGFloat(8.0)
+        {
+            _isRotating = true
+        }
+        else
+        {
+            self.updateGestureRotation(x: location.x, y: location.y)
+            setNeedsDisplay()
+        }
+    }
+    
+    internal final func processRotationGestureEnded(location: CGPoint)
+    {
+        if isDragDecelerationEnabled
+        {
+            stopDeceleration()
+            
+            sampleVelocity(touchLocation: location)
+            
+            _decelerationAngularVelocity = calculateVelocity()
+            
+            if _decelerationAngularVelocity != 0.0
+            {
+                _decelerationLastTime = CACurrentMediaTime()
+                _decelerationDisplayLink = NSUIDisplayLink(target: self, selector: #selector(PieRadarChartViewBase.decelerationLoop))
+                _decelerationDisplayLink.add(to: RunLoop.main, forMode: RunLoop.Mode.common)
+            }
+        }
+    }
+    
+    internal final func processRotationGestureCancelled()
+    {
+        if _isRotating
+        {
+            _isRotating = false
+        }
+    }
+    
+    #if !os(OSX)
+    open override func nsuiTouchesBegan(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
+    {
+        // if rotation by touch is enabled
+        if rotationEnabled
+        {
+            stopDeceleration()
+            
+            if !rotationWithTwoFingers, let touchLocation = touches.first?.location(in: self)
+            {
+                processRotationGestureBegan(location: touchLocation)
+            }
+        }
+        
+        if !_isRotating
+        {
+            super.nsuiTouchesBegan(touches, withEvent: event)
+        }
+    }
+    
+    open override func nsuiTouchesMoved(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
+    {
+        if rotationEnabled && !rotationWithTwoFingers, let touch = touches.first
+        {
+            let touchLocation = touch.location(in: self)
+            processRotationGestureMoved(location: touchLocation)
+        }
+        
+        if !_isRotating
+        {
+            super.nsuiTouchesMoved(touches, withEvent: event)
+        }
+    }
+    
+    open override func nsuiTouchesEnded(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?)
+    {
+        if !_isRotating
+        {
+            super.nsuiTouchesEnded(touches, withEvent: event)
+        }
+        
+        if rotationEnabled && !rotationWithTwoFingers, let touch = touches.first
+        {
+            let touchLocation = touch.location(in: self)
+            processRotationGestureEnded(location: touchLocation)
+        }
+        
+        if _isRotating
+        {
+            _isRotating = false
+        }
+    }
+    
+    open override func nsuiTouchesCancelled(_ touches: Set<NSUITouch>?, withEvent event: NSUIEvent?)
+    {
+        super.nsuiTouchesCancelled(touches, withEvent: event)
+        
+        processRotationGestureCancelled()
+    }
+    #endif
+    
+    #if os(OSX)
+    open override func mouseDown(with theEvent: NSEvent)
+    {
+        // if rotation by touch is enabled
+        if rotationEnabled
+        {
+            stopDeceleration()
+        
+            let location = self.convert(theEvent.locationInWindow, from: nil)
+            
+            processRotationGestureBegan(location: location)
+        }
+        
+        if !_isRotating
+        {
+            super.mouseDown(with: theEvent)
+        }
+    }
+    
+    open override func mouseDragged(with theEvent: NSEvent)
+    {
+        if rotationEnabled
+        {
+            let location = self.convert(theEvent.locationInWindow, from: nil)
+            
+            processRotationGestureMoved(location: location)
+        }
+        
+        if !_isRotating
+        {
+            super.mouseDragged(with: theEvent)
+        }
+    }
+    
+    open override func mouseUp(with theEvent: NSEvent)
+    {
+        if !_isRotating
+        {
+            super.mouseUp(with: theEvent)
+        }
+        
+        if rotationEnabled
+        {
+            let location = self.convert(theEvent.locationInWindow, from: nil)
+            
+            processRotationGestureEnded(location: location)
+        }
+        
+        if _isRotating
+        {
+            _isRotating = false
+        }
+    }
+    #endif
+    
+    private func resetVelocity()
+    {
+        velocitySamples.removeAll(keepingCapacity: false)
+    }
+    
+    private func sampleVelocity(touchLocation: CGPoint)
+    {
+        let currentSample: AngularVelocitySample = {
+            let time = CACurrentMediaTime()
+            let angle = angleForPoint(x: touchLocation.x, y: touchLocation.y)
+            return AngularVelocitySample(time: time, angle: angle)
+        }()
+
+        // Remove samples older than our sample time - 1 seconds
+        // while keeping at least one sample
+        
+        var i = 0, count = velocitySamples.count
+        while (i < count - 2)
+        {
+            if currentSample.time - velocitySamples[i].time > 1.0
+            {
+                velocitySamples.remove(at: 0)
+                i -= 1
+                count -= 1
+            }
+            else
+            {
+                break
+            }
+
+            i += 1
+        }
+
+        velocitySamples.append(currentSample)
+    }
+
+    private func calculateVelocity() -> CGFloat
+    {
+        guard var firstSample = velocitySamples.first,
+            var lastSample = velocitySamples.last
+            else { return 0 }
+
+        // Look for a sample that's closest to the latest sample, but not the same, so we can deduce the direction
+        let beforeLastSample = velocitySamples.last { $0.angle != lastSample.angle }
+            ?? firstSample
+
+        // Calculate the sampling time
+        let timeDelta: CGFloat = {
+            let delta = CGFloat(lastSample.time - firstSample.time)
+            return delta == 0 ? 0.1 : delta
+        }()
+
+        // Calculate clockwise/ccw by choosing two values that should be closest to each other,
+        // so if the angles are two far from each other we know they are inverted "for sure"
+        let isClockwise: Bool = {
+            let isClockwise = lastSample.angle >= beforeLastSample.angle
+            let isInverted = abs(lastSample.angle - beforeLastSample.angle) > 270.0
+            return isInverted ? !isClockwise : isClockwise
+        }()
+
+        // Now if the "gesture" is over a too big of an angle - then we know the angles are inverted, and we need to move them closer to each other from both sides of the 360.0 wrapping point
+        if lastSample.angle - firstSample.angle > 180.0
+        {
+            firstSample.angle += 360.0
+        }
+        else if firstSample.angle - lastSample.angle > 180.0
+        {
+            lastSample.angle += 360.0
+        }
+
+        // The velocity
+        let velocity = abs((lastSample.angle - firstSample.angle) / timeDelta)
+        return isClockwise ? velocity : -velocity
+    }
+
+    /// sets the starting angle of the rotation, this is only used by the touch listener, x and y is the touch position
+    private func setGestureStartAngle(x: CGFloat, y: CGFloat)
+    {
+        _startAngle = angleForPoint(x: x, y: y)
+        
+        // take the current angle into consideration when starting a new drag
+        _startAngle -= _rotationAngle
+    }
+    
+    /// updates the view rotation depending on the given touch position, also takes the starting angle into consideration
+    private func updateGestureRotation(x: CGFloat, y: CGFloat)
+    {
+        self.rotationAngle = angleForPoint(x: x, y: y) - _startAngle
+    }
+    
+    @objc open func stopDeceleration()
+    {
+        if _decelerationDisplayLink !== nil
+        {
+            _decelerationDisplayLink.remove(from: RunLoop.main, forMode: RunLoop.Mode.common)
+            _decelerationDisplayLink = nil
+        }
+    }
+    
+    @objc private func decelerationLoop()
+    {
+        let currentTime = CACurrentMediaTime()
+        
+        _decelerationAngularVelocity *= self.dragDecelerationFrictionCoef
+        
+        let timeInterval = CGFloat(currentTime - _decelerationLastTime)
+        
+        self.rotationAngle += _decelerationAngularVelocity * timeInterval
+        
+        _decelerationLastTime = currentTime
+        
+        if(abs(_decelerationAngularVelocity) < 0.001)
+        {
+            stopDeceleration()
+        }
+    }
+    
+    /// - Returns: The distance between two points
+    private func distance(eventX: CGFloat, startX: CGFloat, eventY: CGFloat, startY: CGFloat) -> CGFloat
+    {
+        let dx = eventX - startX
+        let dy = eventY - startY
+        return sqrt(dx * dx + dy * dy)
+    }
+    
+    /// - Returns: The distance between two points
+    private func distance(from: CGPoint, to: CGPoint) -> CGFloat
+    {
+        let dx = from.x - to.x
+        let dy = from.y - to.y
+        return sqrt(dx * dx + dy * dy)
+    }
+    
+    /// reference to the last highlighted object
+    private var _lastHighlight: Highlight!
+    
+    @objc private func tapGestureRecognized(_ recognizer: NSUITapGestureRecognizer)
+    {
+        if recognizer.state == NSUIGestureRecognizerState.ended
+        {
+            if !self.isHighLightPerTapEnabled { return }
+            
+            let location = recognizer.location(in: self)
+            
+            let high = self.getHighlightByTouchPoint(location)
+            self.highlightValue(high, callDelegate: true)
+        }
+    }
+    
+    #if !os(tvOS)
+    @objc private func rotationGestureRecognized(_ recognizer: NSUIRotationGestureRecognizer)
+    {
+        if recognizer.state == NSUIGestureRecognizerState.began
+        {
+            stopDeceleration()
+            
+            _startAngle = self.rawRotationAngle
+        }
+        
+        if recognizer.state == NSUIGestureRecognizerState.began || recognizer.state == NSUIGestureRecognizerState.changed
+        {
+            let angle = recognizer.nsuiRotation.RAD2DEG
+            
+            self.rotationAngle = _startAngle + angle
+            setNeedsDisplay()
+        }
+        else if recognizer.state == NSUIGestureRecognizerState.ended
+        {
+            let angle = recognizer.nsuiRotation.RAD2DEG
+            
+            self.rotationAngle = _startAngle + angle
+            setNeedsDisplay()
+            
+            if isDragDecelerationEnabled
+            {
+                stopDeceleration()
+                
+                _decelerationAngularVelocity = recognizer.velocity.RAD2DEG
+                
+                if _decelerationAngularVelocity != 0.0
+                {
+                    _decelerationLastTime = CACurrentMediaTime()
+                    _decelerationDisplayLink = NSUIDisplayLink(target: self, selector: #selector(PieRadarChartViewBase.decelerationLoop))
+                    _decelerationDisplayLink.add(to: RunLoop.main, forMode: RunLoop.Mode.common)
+                }
+            }
+        }
+    }
+    #endif
+}

+ 221 - 0
Pods/Charts/Source/Charts/Charts/RadarChartView.swift

@@ -0,0 +1,221 @@
+//
+//  RadarChartView.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+/// Implementation of the RadarChart, a "spidernet"-like chart. It works best
+/// when displaying 5-10 entries per DataSet.
+open class RadarChartView: PieRadarChartViewBase
+{
+    /// width of the web lines that come from the center.
+    @objc open var webLineWidth = CGFloat(1.5)
+    
+    /// width of the web lines that are in between the lines coming from the center
+    @objc open var innerWebLineWidth = CGFloat(0.75)
+    
+    /// color for the web lines that come from the center
+    @objc open var webColor = NSUIColor(red: 122/255.0, green: 122/255.0, blue: 122.0/255.0, alpha: 1.0)
+    
+    /// color for the web lines in between the lines that come from the center.
+    @objc open var innerWebColor = NSUIColor(red: 122/255.0, green: 122/255.0, blue: 122.0/255.0, alpha: 1.0)
+    
+    /// transparency the grid is drawn with (0.0 - 1.0)
+    @objc open var webAlpha: CGFloat = 150.0 / 255.0
+    
+    /// flag indicating if the web lines should be drawn or not
+    @objc open var drawWeb = true
+    
+    /// modulus that determines how many labels and web-lines are skipped before the next is drawn
+    private var _skipWebLineCount = 0
+    
+    /// the object reprsenting the y-axis labels
+    private var _yAxis: YAxis!
+    
+    internal var _yAxisRenderer: YAxisRendererRadarChart!
+    internal var _xAxisRenderer: XAxisRendererRadarChart!
+    
+    public override init(frame: CGRect)
+    {
+        super.init(frame: frame)
+    }
+    
+    public required init?(coder aDecoder: NSCoder)
+    {
+        super.init(coder: aDecoder)
+    }
+    
+    internal override func initialize()
+    {
+        super.initialize()
+        
+        _yAxis = YAxis(position: .left)
+        _yAxis.labelXOffset = 10.0
+        
+        renderer = RadarChartRenderer(chart: self, animator: _animator, viewPortHandler: _viewPortHandler)
+        
+        _yAxisRenderer = YAxisRendererRadarChart(viewPortHandler: _viewPortHandler, yAxis: _yAxis, chart: self)
+        _xAxisRenderer = XAxisRendererRadarChart(viewPortHandler: _viewPortHandler, xAxis: _xAxis, chart: self)
+        
+        self.highlighter = RadarHighlighter(chart: self)
+    }
+
+    internal override func calcMinMax()
+    {
+        super.calcMinMax()
+        
+        guard let data = _data else { return }
+        
+        _yAxis.calculate(min: data.getYMin(axis: .left), max: data.getYMax(axis: .left))
+        _xAxis.calculate(min: 0.0, max: Double(data.maxEntryCountSet?.entryCount ?? 0))
+    }
+    
+    open override func notifyDataSetChanged()
+    {
+        calcMinMax()
+
+        _yAxisRenderer?.computeAxis(min: _yAxis._axisMinimum, max: _yAxis._axisMaximum, inverted: _yAxis.isInverted)
+        _xAxisRenderer?.computeAxis(min: _xAxis._axisMinimum, max: _xAxis._axisMaximum, inverted: false)
+        
+        if let data = _data,
+            let legend = _legend,
+            !legend.isLegendCustom
+        {
+            legendRenderer?.computeLegend(data: data)
+        }
+        
+        calculateOffsets()
+        
+        setNeedsDisplay()
+    }
+    
+    open override func draw(_ rect: CGRect)
+    {
+        super.draw(rect)
+
+        guard data != nil, let renderer = renderer else { return }
+        
+        let optionalContext = NSUIGraphicsGetCurrentContext()
+        guard let context = optionalContext else { return }
+        
+        if _xAxis.isEnabled
+        {
+            _xAxisRenderer.computeAxis(min: _xAxis._axisMinimum, max: _xAxis._axisMaximum, inverted: false)
+        }
+        
+        _xAxisRenderer?.renderAxisLabels(context: context)
+        
+        if drawWeb
+        {
+            renderer.drawExtras(context: context)
+        }
+        
+        if _yAxis.isEnabled && _yAxis.isDrawLimitLinesBehindDataEnabled
+        {
+            _yAxisRenderer.renderLimitLines(context: context)
+        }
+
+        renderer.drawData(context: context)
+
+        if valuesToHighlight()
+        {
+            renderer.drawHighlighted(context: context, indices: _indicesToHighlight)
+        }
+        
+        if _yAxis.isEnabled && !_yAxis.isDrawLimitLinesBehindDataEnabled
+        {
+            _yAxisRenderer.renderLimitLines(context: context)
+        }
+        
+        _yAxisRenderer.renderAxisLabels(context: context)
+
+        renderer.drawValues(context: context)
+
+        legendRenderer.renderLegend(context: context)
+
+        drawDescription(context: context)
+
+        drawMarkers(context: context)
+    }
+
+    /// The factor that is needed to transform values into pixels.
+    @objc open var factor: CGFloat
+    {
+        let content = _viewPortHandler.contentRect
+        return min(content.width / 2.0, content.height / 2.0)
+                / CGFloat(_yAxis.axisRange)
+    }
+
+    /// The angle that each slice in the radar chart occupies.
+    @objc open var sliceAngle: CGFloat
+    {
+        return 360.0 / CGFloat(_data?.maxEntryCountSet?.entryCount ?? 0)
+    }
+
+    open override func indexForAngle(_ angle: CGFloat) -> Int
+    {
+        // take the current angle of the chart into consideration
+        let a = (angle - self.rotationAngle).normalizedAngle
+        
+        let sliceAngle = self.sliceAngle
+        
+        let max = _data?.maxEntryCountSet?.entryCount ?? 0
+        return (0..<max).firstIndex {
+            sliceAngle * CGFloat($0 + 1) - sliceAngle / 2.0 > a
+        } ?? max
+    }
+
+    /// The object that represents all y-labels of the RadarChart.
+    @objc open var yAxis: YAxis
+    {
+        return _yAxis
+    }
+
+    /// Sets the number of web-lines that should be skipped on chart web before the next one is drawn. This targets the lines that come from the center of the RadarChart.
+    /// if count = 1 -> 1 line is skipped in between
+    @objc open var skipWebLineCount: Int
+    {
+        get
+        {
+            return _skipWebLineCount
+        }
+        set
+        {
+            _skipWebLineCount = max(0, newValue)
+        }
+    }
+    
+    internal override var requiredLegendOffset: CGFloat
+    {
+        return _legend.font.pointSize * 4.0
+    }
+
+    internal override var requiredBaseOffset: CGFloat
+    {
+        return _xAxis.isEnabled && _xAxis.isDrawLabelsEnabled ? _xAxis.labelRotatedWidth : 10.0
+    }
+
+    open override var radius: CGFloat
+    {
+        let content = _viewPortHandler.contentRect
+        return min(content.width / 2.0, content.height / 2.0)
+    }
+
+    /// The maximum value this chart can display on it's y-axis.
+    open override var chartYMax: Double { return _yAxis._axisMaximum }
+    
+    /// The minimum value this chart can display on it's y-axis.
+    open override var chartYMin: Double { return _yAxis._axisMinimum }
+    
+    /// The range of y-values this chart can display.
+    @objc open var yRange: Double { return _yAxis.axisRange }
+}

+ 31 - 0
Pods/Charts/Source/Charts/Charts/ScatterChartView.swift

@@ -0,0 +1,31 @@
+//
+//  ScatterChartView.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+/// The ScatterChart. Draws dots, triangles, squares and custom shapes into the chartview.
+open class ScatterChartView: BarLineChartViewBase, ScatterChartDataProvider
+{
+    open override func initialize()
+    {
+        super.initialize()
+        
+        renderer = ScatterChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
+
+        xAxis.spaceMin = 0.5
+        xAxis.spaceMax = 0.5
+    }
+    
+    // MARK: - ScatterChartDataProvider
+    
+    open var scatterData: ScatterChartData? { return _data as? ScatterChartData }
+}

+ 369 - 0
Pods/Charts/Source/Charts/Components/AxisBase.swift

@@ -0,0 +1,369 @@
+//
+//  AxisBase.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+/// Base class for all axes
+@objc(ChartAxisBase)
+open class AxisBase: ComponentBase
+{
+    public override init()
+    {
+        super.init()
+    }
+    
+    /// Custom formatter that is used instead of the auto-formatter if set
+    private var _axisValueFormatter: IAxisValueFormatter?
+    
+    @objc open var labelFont = NSUIFont.systemFont(ofSize: 10.0)
+    @objc open var labelTextColor = NSUIColor.labelOrBlack
+    
+    @objc open var axisLineColor = NSUIColor.gray
+    @objc open var axisLineWidth = CGFloat(0.5)
+    @objc open var axisLineDashPhase = CGFloat(0.0)
+    @objc open var axisLineDashLengths: [CGFloat]!
+    
+    @objc open var gridColor = NSUIColor.gray.withAlphaComponent(0.9)
+    @objc open var gridLineWidth = CGFloat(0.5)
+    @objc open var gridLineDashPhase = CGFloat(0.0)
+    @objc open var gridLineDashLengths: [CGFloat]!
+    @objc open var gridLineCap = CGLineCap.butt
+    
+    @objc open var drawGridLinesEnabled = true
+    @objc open var drawAxisLineEnabled = true
+    
+    /// flag that indicates of the labels of this axis should be drawn or not
+    @objc open var drawLabelsEnabled = true
+    
+    private var _centerAxisLabelsEnabled = false
+
+    /// Centers the axis labels instead of drawing them at their original position.
+    /// This is useful especially for grouped BarChart.
+    @objc open var centerAxisLabelsEnabled: Bool
+    {
+        get { return _centerAxisLabelsEnabled && entryCount > 0 }
+        set { _centerAxisLabelsEnabled = newValue }
+    }
+    
+    @objc open var isCenterAxisLabelsEnabled: Bool
+    {
+        get { return centerAxisLabelsEnabled }
+    }
+
+    /// array of limitlines that can be set for the axis
+    private var _limitLines = [ChartLimitLine]()
+    
+    /// Are the LimitLines drawn behind the data or in front of the data?
+    ///
+    /// **default**: false
+    @objc open var drawLimitLinesBehindDataEnabled = false
+    
+    /// Are the grid lines drawn behind the data or in front of the data?
+    ///
+    /// **default**: true
+    @objc open var drawGridLinesBehindDataEnabled = true
+
+    /// the flag can be used to turn off the antialias for grid lines
+    @objc open var gridAntialiasEnabled = true
+    
+    /// the actual array of entries
+    @objc open var entries = [Double]()
+    
+    /// axis label entries only used for centered labels
+    @objc open var centeredEntries = [Double]()
+    
+    /// the number of entries the legend contains
+    @objc open var entryCount: Int { return entries.count }
+    
+    /// the number of label entries the axis should have
+    ///
+    /// **default**: 6
+    private var _labelCount = Int(6)
+    
+    /// the number of decimal digits to use (for the default formatter
+    @objc open var decimals: Int = 0
+    
+    /// When true, axis labels are controlled by the `granularity` property.
+    /// When false, axis values could possibly be repeated.
+    /// This could happen if two adjacent axis values are rounded to same value.
+    /// If using granularity this could be avoided by having fewer axis values visible.
+    @objc open var granularityEnabled = false
+    
+    private var _granularity = Double(1.0)
+    
+    /// The minimum interval between axis values.
+    /// This can be used to avoid label duplicating when zooming in.
+    ///
+    /// **default**: 1.0
+    @objc open var granularity: Double
+    {
+        get
+        {
+            return _granularity
+        }
+        set
+        {
+            _granularity = newValue
+            
+            // set this to `true` if it was disabled, as it makes no sense to set this property with granularity disabled
+            granularityEnabled = true
+        }
+    }
+    
+    /// The minimum interval between axis values.
+    @objc open var isGranularityEnabled: Bool
+    {
+        get
+        {
+            return granularityEnabled
+        }
+    }
+    
+    /// if true, the set number of y-labels will be forced
+    @objc open var forceLabelsEnabled = false
+    
+    @objc open func getLongestLabel() -> String
+    {
+        var longest = ""
+        
+        for i in 0 ..< entries.count
+        {
+            let text = getFormattedLabel(i)
+            
+            if longest.count < text.count
+            {
+                longest = text
+            }
+        }
+        
+        return longest
+    }
+    
+    /// - Returns: The formatted label at the specified index. This will either use the auto-formatter or the custom formatter (if one is set).
+    @objc open func getFormattedLabel(_ index: Int) -> String
+    {
+        if index < 0 || index >= entries.count
+        {
+            return ""
+        }
+        
+        return valueFormatter?.stringForValue(entries[index], axis: self) ?? ""
+    }
+    
+    /// Sets the formatter to be used for formatting the axis labels.
+    /// If no formatter is set, the chart will automatically determine a reasonable formatting (concerning decimals) for all the values that are drawn inside the chart.
+    /// Use `nil` to use the formatter calculated by the chart.
+    @objc open var valueFormatter: IAxisValueFormatter?
+    {
+        get
+        {
+            if _axisValueFormatter == nil ||
+                (_axisValueFormatter is DefaultAxisValueFormatter &&
+                    (_axisValueFormatter as! DefaultAxisValueFormatter).hasAutoDecimals &&
+                    (_axisValueFormatter as! DefaultAxisValueFormatter).decimals != decimals)
+            {
+                _axisValueFormatter = DefaultAxisValueFormatter(decimals: decimals)
+            }
+            
+            return _axisValueFormatter
+        }
+        set
+        {
+            _axisValueFormatter = newValue ?? DefaultAxisValueFormatter(decimals: decimals)
+        }
+    }
+    
+    @objc open var isDrawGridLinesEnabled: Bool { return drawGridLinesEnabled }
+    
+    @objc open var isDrawAxisLineEnabled: Bool { return drawAxisLineEnabled }
+    
+    @objc open var isDrawLabelsEnabled: Bool { return drawLabelsEnabled }
+    
+    /// Are the LimitLines drawn behind the data or in front of the data?
+    /// 
+    /// **default**: false
+    @objc open var isDrawLimitLinesBehindDataEnabled: Bool { return drawLimitLinesBehindDataEnabled }
+    
+    /// Are the grid lines drawn behind the data or in front of the data?
+    ///
+    /// **default**: true
+    @objc open var isDrawGridLinesBehindDataEnabled: Bool { return drawGridLinesBehindDataEnabled }
+    
+    /// Extra spacing for `axisMinimum` to be added to automatically calculated `axisMinimum`
+    @objc open var spaceMin: Double = 0.0
+    
+    /// Extra spacing for `axisMaximum` to be added to automatically calculated `axisMaximum`
+    @objc open var spaceMax: Double = 0.0
+    
+    /// Flag indicating that the axis-min value has been customized
+    internal var _customAxisMin: Bool = false
+    
+    /// Flag indicating that the axis-max value has been customized
+    internal var _customAxisMax: Bool = false
+    
+    /// Do not touch this directly, instead, use axisMinimum.
+    /// This is automatically calculated to represent the real min value,
+    /// and is used when calculating the effective minimum.
+    internal var _axisMinimum = Double(0)
+    
+    /// Do not touch this directly, instead, use axisMaximum.
+    /// This is automatically calculated to represent the real max value,
+    /// and is used when calculating the effective maximum.
+    internal var _axisMaximum = Double(0)
+    
+    /// the total range of values this axis covers
+    @objc open var axisRange = Double(0)
+    
+    /// The minumum number of labels on the axis
+    @objc open var axisMinLabels = Int(2) {
+        didSet { axisMinLabels = axisMinLabels > 0 ? axisMinLabels : oldValue }
+    }
+    
+    /// The maximum number of labels on the axis
+    @objc open var axisMaxLabels = Int(25) {
+        didSet { axisMaxLabels = axisMaxLabels > 0 ? axisMaxLabels : oldValue }
+    }
+    
+    /// the number of label entries the axis should have
+    /// max = 25,
+    /// min = 2,
+    /// default = 6,
+    /// be aware that this number is not fixed and can only be approximated
+    @objc open var labelCount: Int
+    {
+        get
+        {
+            return _labelCount
+        }
+        set
+        {
+            let range = axisMinLabels...axisMaxLabels as ClosedRange
+            _labelCount = newValue.clamped(to: range)
+                        
+            forceLabelsEnabled = false
+        }
+    }
+    
+    @objc open func setLabelCount(_ count: Int, force: Bool)
+    {
+        self.labelCount = count
+        forceLabelsEnabled = force
+    }
+    
+    /// `true` if focing the y-label count is enabled. Default: false
+    @objc open var isForceLabelsEnabled: Bool { return forceLabelsEnabled }
+    
+    /// Adds a new ChartLimitLine to this axis.
+    @objc open func addLimitLine(_ line: ChartLimitLine)
+    {
+        _limitLines.append(line)
+    }
+    
+    /// Removes the specified ChartLimitLine from the axis.
+    @objc open func removeLimitLine(_ line: ChartLimitLine)
+    {
+        guard let i = _limitLines.firstIndex(of: line) else { return }
+        _limitLines.remove(at: i)
+    }
+    
+    /// Removes all LimitLines from the axis.
+    @objc open func removeAllLimitLines()
+    {
+        _limitLines.removeAll(keepingCapacity: false)
+    }
+    
+    /// The LimitLines of this axis.
+    @objc open var limitLines : [ChartLimitLine]
+    {
+        return _limitLines
+    }
+    
+    // MARK: Custom axis ranges
+    
+    /// By calling this method, any custom minimum value that has been previously set is reseted, and the calculation is done automatically.
+    @objc open func resetCustomAxisMin()
+    {
+        _customAxisMin = false
+    }
+    
+    @objc open var isAxisMinCustom: Bool { return _customAxisMin }
+    
+    /// By calling this method, any custom maximum value that has been previously set is reseted, and the calculation is done automatically.
+    @objc open func resetCustomAxisMax()
+    {
+        _customAxisMax = false
+    }
+    
+    @objc open var isAxisMaxCustom: Bool { return _customAxisMax }
+        
+    /// The minimum value for this axis.
+    /// If set, this value will not be calculated automatically depending on the provided data.
+    /// Use `resetCustomAxisMin()` to undo this.
+    @objc open var axisMinimum: Double
+    {
+        get
+        {
+            return _axisMinimum
+        }
+        set
+        {
+            _customAxisMin = true
+            _axisMinimum = newValue
+            axisRange = abs(_axisMaximum - newValue)
+        }
+    }
+    
+    /// The maximum value for this axis.
+    /// If set, this value will not be calculated automatically depending on the provided data.
+    /// Use `resetCustomAxisMax()` to undo this.
+    @objc open var axisMaximum: Double
+    {
+        get
+        {
+            return _axisMaximum
+        }
+        set
+        {
+            _customAxisMax = true
+            _axisMaximum = newValue
+            axisRange = abs(newValue - _axisMinimum)
+        }
+    }
+    
+    /// Calculates the minimum, maximum and range values of the YAxis with the given minimum and maximum values from the chart data.
+    ///
+    /// - Parameters:
+    ///   - dataMin: the y-min value according to chart data
+    ///   - dataMax: the y-max value according to chart
+    @objc open func calculate(min dataMin: Double, max dataMax: Double)
+    {
+        // if custom, use value as is, else use data value
+        var min = _customAxisMin ? _axisMinimum : (dataMin - spaceMin)
+        var max = _customAxisMax ? _axisMaximum : (dataMax + spaceMax)
+        
+        // temporary range (before calculations)
+        let range = abs(max - min)
+        
+        // in case all values are equal
+        if range == 0.0
+        {
+            max = max + 1.0
+            min = min - 1.0
+        }
+        
+        _axisMinimum = min
+        _axisMaximum = max
+        
+        // actual range
+        axisRange = abs(max - min)
+    }
+}

+ 74 - 0
Pods/Charts/Source/Charts/Components/ChartLimitLine.swift

@@ -0,0 +1,74 @@
+//
+//  ChartLimitLine.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+/// The limit line is an additional feature for all Line, Bar and ScatterCharts.
+/// It allows the displaying of an additional line in the chart that marks a certain maximum / limit on the specified axis (x- or y-axis).
+open class ChartLimitLine: ComponentBase
+{
+    @objc(ChartLimitLabelPosition)
+    public enum LabelPosition: Int
+    {
+        case topLeft
+        case topRight
+        case bottomLeft
+        case bottomRight
+    }
+    
+    /// limit / maximum (the y-value or xIndex)
+    @objc open var limit = Double(0.0)
+    
+    private var _lineWidth = CGFloat(2.0)
+    @objc open var lineColor = NSUIColor(red: 237.0/255.0, green: 91.0/255.0, blue: 91.0/255.0, alpha: 1.0)
+    @objc open var lineDashPhase = CGFloat(0.0)
+    @objc open var lineDashLengths: [CGFloat]?
+    
+    @objc open var valueTextColor = NSUIColor.labelOrBlack
+    @objc open var valueFont = NSUIFont.systemFont(ofSize: 13.0)
+    
+    @objc open var drawLabelEnabled = true
+    @objc open var label = ""
+    @objc open var labelPosition = LabelPosition.topRight
+    
+    public override init()
+    {
+        super.init()
+    }
+    
+    @objc public init(limit: Double)
+    {
+        super.init()
+        self.limit = limit
+    }
+    
+    @objc public init(limit: Double, label: String)
+    {
+        super.init()
+        self.limit = limit
+        self.label = label
+    }
+    
+    /// set the line width of the chart (min = 0.2, max = 12); default 2
+    @objc open var lineWidth: CGFloat
+    {
+        get
+        {
+            return _lineWidth
+        }
+        set
+        {
+            _lineWidth = newValue.clamped(to: 0.2...12)
+        }
+    }
+}

+ 37 - 0
Pods/Charts/Source/Charts/Components/ComponentBase.swift

@@ -0,0 +1,37 @@
+//
+//  ComponentBase.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+/// This class encapsulates everything both Axis, Legend and LimitLines have in common
+@objc(ChartComponentBase)
+open class ComponentBase: NSObject
+{
+    /// flag that indicates if this component is enabled or not
+    @objc open var enabled = true
+    
+    /// The offset this component has on the x-axis
+    /// **default**: 5.0
+    @objc open var xOffset = CGFloat(5.0)
+    
+    /// The offset this component has on the x-axis
+    /// **default**: 5.0 (or 0.0 on ChartYAxis)
+    @objc open var yOffset = CGFloat(5.0)
+    
+    public override init()
+    {
+        super.init()
+    }
+
+    @objc open var isEnabled: Bool { return enabled }
+}

+ 54 - 0
Pods/Charts/Source/Charts/Components/Description.swift

@@ -0,0 +1,54 @@
+//
+//  Description.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+#if canImport(UIKit)
+    import UIKit
+#endif
+
+#if canImport(Cocoa)
+import Cocoa
+#endif
+
+@objc(ChartDescription)
+open class Description: ComponentBase
+{
+    public override init()
+    {
+        #if os(tvOS)
+        // 23 is the smallest recommended font size on the TV
+        font = .systemFont(ofSize: 23)
+        #elseif os(OSX)
+        font = .systemFont(ofSize: NSUIFont.systemFontSize)
+        #else
+        font = .systemFont(ofSize: 8.0)
+        #endif
+        
+        super.init()
+    }
+    
+    /// The text to be shown as the description.
+    @objc open var text: String?
+    
+    /// Custom position for the description text in pixels on the screen.
+    open var position: CGPoint? = nil
+    
+    /// The text alignment of the description text. Default RIGHT.
+    @objc open var textAlign: NSTextAlignment = NSTextAlignment.right
+    
+    /// Font object used for drawing the description text.
+    @objc open var font: NSUIFont
+    
+    /// Text color used for drawing the description text
+    @objc open var textColor = NSUIColor.labelOrBlack
+}

+ 39 - 0
Pods/Charts/Source/Charts/Components/IMarker.swift

@@ -0,0 +1,39 @@
+//
+//  ChartMarker.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(IChartMarker)
+public protocol IMarker: class
+{
+    /// - Returns: The desired (general) offset you wish the IMarker to have on the x-axis.
+    /// By returning x: -(width / 2) you will center the IMarker horizontally.
+    /// By returning y: -(height / 2) you will center the IMarker vertically.
+    var offset: CGPoint { get }
+    
+    /// - Parameters:
+    ///   - point: This is the point at which the marker wants to be drawn. You can adjust the offset conditionally based on this argument.
+    /// - Returns: The offset for drawing at the specific `point`.
+    ///            This allows conditional adjusting of the Marker position.
+    ///            If you have no adjustments to make, return self.offset().
+    func offsetForDrawing(atPoint: CGPoint) -> CGPoint
+    
+    /// This method enables a custom IMarker to update it's content every time the IMarker is redrawn according to the data entry it points to.
+    ///
+    /// - Parameters:
+    ///   - entry: The Entry the IMarker belongs to. This can also be any subclass of Entry, like BarEntry or CandleEntry, simply cast it at runtime.
+    ///   - highlight: The highlight object contains information about the highlighted value such as it's dataset-index, the selected range or stack-index (only stacked bar entries).
+    func refreshContent(entry: ChartDataEntry, highlight: Highlight)
+    
+    /// Draws the IMarker on the given position on the given context
+    func draw(context: CGContext, point: CGPoint)
+}

+ 420 - 0
Pods/Charts/Source/Charts/Components/Legend.swift

@@ -0,0 +1,420 @@
+//
+//  Legend.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(ChartLegend)
+open class Legend: ComponentBase
+{
+    @objc(ChartLegendForm)
+    public enum Form: Int
+    {
+        /// Avoid drawing a form
+        case none
+        
+        /// Do not draw the a form, but leave space for it
+        case empty
+        
+        /// Use default (default dataset's form to the legend's form)
+        case `default`
+        
+        /// Draw a square
+        case square
+        
+        /// Draw a circle
+        case circle
+        
+        /// Draw a horizontal line
+        case line
+    }
+    
+    @objc(ChartLegendHorizontalAlignment)
+    public enum HorizontalAlignment: Int
+    {
+        case left
+        case center
+        case right
+    }
+    
+    @objc(ChartLegendVerticalAlignment)
+    public enum VerticalAlignment: Int
+    {
+        case top
+        case center
+        case bottom
+    }
+    
+    @objc(ChartLegendOrientation)
+    public enum Orientation: Int
+    {
+        case horizontal
+        case vertical
+    }
+    
+    @objc(ChartLegendDirection)
+    public enum Direction: Int
+    {
+        case leftToRight
+        case rightToLeft
+    }
+    
+    /// The legend entries array
+    @objc open var entries = [LegendEntry]()
+    
+    /// Entries that will be appended to the end of the auto calculated entries after calculating the legend.
+    /// (if the legend has already been calculated, you will need to call notifyDataSetChanged() to let the changes take effect)
+    @objc open var extraEntries = [LegendEntry]()
+    
+    /// Are the legend labels/colors a custom value or auto calculated? If false, then it's auto, if true, then custom.
+    /// 
+    /// **default**: false (automatic legend)
+    private var _isLegendCustom = false
+
+    /// The horizontal alignment of the legend
+    @objc open var horizontalAlignment: HorizontalAlignment = HorizontalAlignment.left
+    
+    /// The vertical alignment of the legend
+    @objc open var verticalAlignment: VerticalAlignment = VerticalAlignment.bottom
+    
+    /// The orientation of the legend
+    @objc open var orientation: Orientation = Orientation.horizontal
+    
+    /// Flag indicating whether the legend will draw inside the chart or outside
+    @objc open var drawInside: Bool = false
+    
+    /// Flag indicating whether the legend will draw inside the chart or outside
+    @objc open var isDrawInsideEnabled: Bool { return drawInside }
+    
+    /// The text direction of the legend
+    @objc open var direction: Direction = Direction.leftToRight
+
+    @objc open var font: NSUIFont = NSUIFont.systemFont(ofSize: 10.0)
+    @objc open var textColor = NSUIColor.labelOrBlack
+
+    /// The form/shape of the legend forms
+    @objc open var form = Form.square
+    
+    /// The size of the legend forms
+    @objc open var formSize = CGFloat(8.0)
+    
+    /// The line width for forms that consist of lines
+    @objc open var formLineWidth = CGFloat(3.0)
+    
+    /// Line dash configuration for shapes that consist of lines.
+    ///
+    /// This is how much (in pixels) into the dash pattern are we starting from.
+    @objc open var formLineDashPhase: CGFloat = 0.0
+    
+    /// Line dash configuration for shapes that consist of lines.
+    ///
+    /// This is the actual dash pattern.
+    /// I.e. [2, 3] will paint [--   --   ]
+    /// [1, 3, 4, 2] will paint [-   ----  -   ----  ]
+    @objc open var formLineDashLengths: [CGFloat]?
+    
+    @objc open var xEntrySpace = CGFloat(6.0)
+    @objc open var yEntrySpace = CGFloat(0.0)
+    @objc open var formToTextSpace = CGFloat(5.0)
+    @objc open var stackSpace = CGFloat(3.0)
+    
+    @objc open var calculatedLabelSizes = [CGSize]()
+    @objc open var calculatedLabelBreakPoints = [Bool]()
+    @objc open var calculatedLineSizes = [CGSize]()
+    
+    public override init()
+    {
+        super.init()
+        
+        self.xOffset = 5.0
+        self.yOffset = 3.0
+    }
+    
+    @objc public init(entries: [LegendEntry])
+    {
+        super.init()
+        
+        self.entries = entries
+    }
+    
+    @objc open func getMaximumEntrySize(withFont font: NSUIFont) -> CGSize
+    {
+        var maxW = CGFloat(0.0)
+        var maxH = CGFloat(0.0)
+        
+        var maxFormSize: CGFloat = 0.0
+
+        for entry in entries
+        {
+            let formSize = entry.formSize.isNaN ? self.formSize : entry.formSize
+            if formSize > maxFormSize
+            {
+                maxFormSize = formSize
+            }
+            
+            guard let label = entry.label
+                else { continue }
+            
+            let size = (label as NSString).size(withAttributes: [.font: font])
+            
+            if size.width > maxW
+            {
+                maxW = size.width
+            }
+            if size.height > maxH
+            {
+                maxH = size.height
+            }
+        }
+        
+        return CGSize(
+            width: maxW + maxFormSize + formToTextSpace,
+            height: maxH
+        )
+    }
+
+    @objc open var neededWidth = CGFloat(0.0)
+    @objc open var neededHeight = CGFloat(0.0)
+    @objc open var textWidthMax = CGFloat(0.0)
+    @objc open var textHeightMax = CGFloat(0.0)
+    
+    /// flag that indicates if word wrapping is enabled
+    /// this is currently supported only for `orientation == Horizontal`.
+    /// you may want to set maxSizePercent when word wrapping, to set the point where the text wraps.
+    /// 
+    /// **default**: true
+    @objc open var wordWrapEnabled = true
+    
+    /// if this is set, then word wrapping the legend is enabled.
+    @objc open var isWordWrapEnabled: Bool { return wordWrapEnabled }
+
+    /// The maximum relative size out of the whole chart view in percent.
+    /// If the legend is to the right/left of the chart, then this affects the width of the legend.
+    /// If the legend is to the top/bottom of the chart, then this affects the height of the legend.
+    /// 
+    /// **default**: 0.95 (95%)
+    @objc open var maxSizePercent: CGFloat = 0.95
+    
+    @objc open func calculateDimensions(labelFont: NSUIFont, viewPortHandler: ViewPortHandler)
+    {
+        let maxEntrySize = getMaximumEntrySize(withFont: labelFont)
+        let defaultFormSize = self.formSize
+        let stackSpace = self.stackSpace
+        let formToTextSpace = self.formToTextSpace
+        let xEntrySpace = self.xEntrySpace
+        let yEntrySpace = self.yEntrySpace
+        let wordWrapEnabled = self.wordWrapEnabled
+        let entries = self.entries
+        let entryCount = entries.count
+        
+        textWidthMax = maxEntrySize.width
+        textHeightMax = maxEntrySize.height
+        
+        switch orientation
+        {
+        case .vertical:
+            
+            var maxWidth = CGFloat(0.0)
+            var width = CGFloat(0.0)
+            var maxHeight = CGFloat(0.0)
+            let labelLineHeight = labelFont.lineHeight
+            
+            var wasStacked = false
+            
+            for i in 0 ..< entryCount
+            {
+                let e = entries[i]
+                let drawingForm = e.form != .none
+                let formSize = e.formSize.isNaN ? defaultFormSize : e.formSize
+                let label = e.label
+                
+                if !wasStacked
+                {
+                    width = 0.0
+                }
+                
+                if drawingForm
+                {
+                    if wasStacked
+                    {
+                        width += stackSpace
+                    }
+                    width += formSize
+                }
+                
+                if label != nil
+                {
+                    let size = (label! as NSString).size(withAttributes: [.font: labelFont])
+                    
+                    if drawingForm && !wasStacked
+                    {
+                        width += formToTextSpace
+                    }
+                    else if wasStacked
+                    {
+                        maxWidth = max(maxWidth, width)
+                        maxHeight += labelLineHeight + yEntrySpace
+                        width = 0.0
+                        wasStacked = false
+                    }
+                    
+                    width += size.width
+                    maxHeight += labelLineHeight + yEntrySpace
+                }
+                else
+                {
+                    wasStacked = true
+                    width += formSize
+                    
+                    if i < entryCount - 1
+                    {
+                        width += stackSpace
+                    }
+                }
+                
+                maxWidth = max(maxWidth, width)
+            }
+            
+            neededWidth = maxWidth
+            neededHeight = maxHeight
+            
+        case .horizontal:
+            
+            let labelLineHeight = labelFont.lineHeight
+            
+            let contentWidth: CGFloat = viewPortHandler.contentWidth * maxSizePercent
+            
+            // Prepare arrays for calculated layout
+            if calculatedLabelSizes.count != entryCount
+            {
+                calculatedLabelSizes = [CGSize](repeating: CGSize(), count: entryCount)
+            }
+            
+            if calculatedLabelBreakPoints.count != entryCount
+            {
+                calculatedLabelBreakPoints = [Bool](repeating: false, count: entryCount)
+            }
+            
+            calculatedLineSizes.removeAll(keepingCapacity: true)
+            
+            // Start calculating layout
+            
+            let labelAttrs = [NSAttributedString.Key.font: labelFont]
+            var maxLineWidth: CGFloat = 0.0
+            var currentLineWidth: CGFloat = 0.0
+            var requiredWidth: CGFloat = 0.0
+            var stackedStartIndex: Int = -1
+            
+            for i in 0 ..< entryCount
+            {
+                let e = entries[i]
+                let drawingForm = e.form != .none
+                let label = e.label
+                
+                calculatedLabelBreakPoints[i] = false
+                
+                if stackedStartIndex == -1
+                {
+                    // we are not stacking, so required width is for this label only
+                    requiredWidth = 0.0
+                }
+                else
+                {
+                    // add the spacing appropriate for stacked labels/forms
+                    requiredWidth += stackSpace
+                }
+                
+                // grouped forms have null labels
+                if label != nil
+                {
+                    calculatedLabelSizes[i] = (label! as NSString).size(withAttributes: labelAttrs)
+                    requiredWidth += drawingForm ? formToTextSpace + formSize : 0.0
+                    requiredWidth += calculatedLabelSizes[i].width
+                }
+                else
+                {
+                    calculatedLabelSizes[i] = CGSize()
+                    requiredWidth += drawingForm ? formSize : 0.0
+                    
+                    if stackedStartIndex == -1
+                    {
+                        // mark this index as we might want to break here later
+                        stackedStartIndex = i
+                    }
+                }
+                
+                if label != nil || i == entryCount - 1
+                {
+                    let requiredSpacing = currentLineWidth == 0.0 ? 0.0 : xEntrySpace
+                    
+                    if (!wordWrapEnabled || // No word wrapping, it must fit.
+                        currentLineWidth == 0.0 || // The line is empty, it must fit.
+                        (contentWidth - currentLineWidth >= requiredSpacing + requiredWidth)) // It simply fits
+                    {
+                        // Expand current line
+                        currentLineWidth += requiredSpacing + requiredWidth
+                    }
+                    else
+                    { // It doesn't fit, we need to wrap a line
+                        
+                        // Add current line size to array
+                        calculatedLineSizes.append(CGSize(width: currentLineWidth, height: labelLineHeight))
+                        maxLineWidth = max(maxLineWidth, currentLineWidth)
+                        
+                        // Start a new line
+                        calculatedLabelBreakPoints[stackedStartIndex > -1 ? stackedStartIndex : i] = true
+                        currentLineWidth = requiredWidth
+                    }
+                    
+                    if i == entryCount - 1
+                    { // Add last line size to array
+                        calculatedLineSizes.append(CGSize(width: currentLineWidth, height: labelLineHeight))
+                        maxLineWidth = max(maxLineWidth, currentLineWidth)
+                    }
+                }
+                
+                stackedStartIndex = label != nil ? -1 : stackedStartIndex
+            }
+            
+            neededWidth = maxLineWidth
+            neededHeight = labelLineHeight * CGFloat(calculatedLineSizes.count) +
+                yEntrySpace * CGFloat(calculatedLineSizes.count == 0 ? 0 : (calculatedLineSizes.count - 1))
+        }
+        
+        neededWidth += xOffset
+        neededHeight += yOffset
+    }
+    
+    /// MARK: - Custom legend
+    
+    /// Sets a custom legend's entries array.
+    /// * A nil label will start a group.
+    /// This will disable the feature that automatically calculates the legend entries from the datasets.
+    /// Call `resetCustom(...)` to re-enable automatic calculation (and then `notifyDataSetChanged()` is needed).
+    @objc open func setCustom(entries: [LegendEntry])
+    {
+        self.entries = entries
+        _isLegendCustom = true
+    }
+    
+    /// Calling this will disable the custom legend entries (set by `setLegend(...)`). Instead, the entries will again be calculated automatically (after `notifyDataSetChanged()` is called).
+    @objc open func resetCustom()
+    {
+        _isLegendCustom = false
+    }
+    
+    /// **default**: false (automatic legend)
+    /// `true` if a custom legend entries has been set
+    @objc open var isLegendCustom: Bool
+    {
+        return _isLegendCustom
+    }
+}

+ 88 - 0
Pods/Charts/Source/Charts/Components/LegendEntry.swift

@@ -0,0 +1,88 @@
+//
+//  LegendEntry.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(ChartLegendEntry)
+open class LegendEntry: NSObject
+{
+    public override init()
+    {
+        super.init()
+    }
+    
+    /// - Parameters:
+    ///   - label:                  The legend entry text.
+    ///                                     A `nil` label will start a group.
+    ///   - form:                   The form to draw for this entry.
+    ///   - formSize:               Set to NaN to use the legend's default.
+    ///   - formLineWidth:          Set to NaN to use the legend's default.
+    ///   - formLineDashPhase:      Line dash configuration.
+    ///   - formLineDashLengths:    Line dash configurationas NaN to use the legend's default.
+    ///   - formColor:              The color for drawing the form.
+    @objc public init(label: String?,
+                form: Legend.Form,
+                formSize: CGFloat,
+                formLineWidth: CGFloat,
+                formLineDashPhase: CGFloat,
+                formLineDashLengths: [CGFloat]?,
+                formColor: NSUIColor?)
+    {
+        self.label = label
+        self.form = form
+        self.formSize = formSize
+        self.formLineWidth = formLineWidth
+        self.formLineDashPhase = formLineDashPhase
+        self.formLineDashLengths = formLineDashLengths
+        self.formColor = formColor
+    }
+    
+    /// The legend entry text.
+    /// A `nil` label will start a group.
+    @objc open var label: String?
+    
+    /// The form to draw for this entry.
+    ///
+    /// `None` will avoid drawing a form, and any related space.
+    /// `Empty` will avoid drawing a form, but keep its space.
+    /// `Default` will use the Legend's default.
+    @objc open var form: Legend.Form = .default
+    
+    /// Form size will be considered except for when .None is used
+    ///
+    /// Set as NaN to use the legend's default
+    @objc open var formSize: CGFloat = CGFloat.nan
+    
+    /// Line width used for shapes that consist of lines.
+    ///
+    /// Set to NaN to use the legend's default.
+    @objc open var formLineWidth: CGFloat = CGFloat.nan
+    
+    /// Line dash configuration for shapes that consist of lines.
+    ///
+    /// This is how much (in pixels) into the dash pattern are we starting from.
+    ///
+    /// Set to NaN to use the legend's default.
+    @objc open var formLineDashPhase: CGFloat = 0.0
+    
+    /// Line dash configuration for shapes that consist of lines.
+    ///
+    /// This is the actual dash pattern.
+    /// I.e. [2, 3] will paint [--   --   ]
+    /// [1, 3, 4, 2] will paint [-   ----  -   ----  ]
+    ///
+    /// Set to nil to use the legend's default.
+    @objc open var formLineDashLengths: [CGFloat]?
+    
+    /// The color for drawing the form
+    @objc open var formColor: NSUIColor?
+}

+ 106 - 0
Pods/Charts/Source/Charts/Components/MarkerImage.swift

@@ -0,0 +1,106 @@
+//
+//  ChartMarkerImage.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(ChartMarkerImage)
+open class MarkerImage: NSObject, IMarker
+{
+    /// The marker image to render
+    @objc open var image: NSUIImage?
+    
+    open var offset: CGPoint = CGPoint()
+    
+    @objc open weak var chartView: ChartViewBase?
+    
+    /// As long as size is 0.0/0.0 - it will default to the image's size
+    @objc open var size: CGSize = CGSize()
+    
+    public override init()
+    {
+        super.init()
+    }
+    
+    open func offsetForDrawing(atPoint point: CGPoint) -> CGPoint
+    {
+        var offset = self.offset
+        
+        let chart = self.chartView
+        
+        var size = self.size
+        
+        if size.width == 0.0 && image != nil
+        {
+            size.width = image?.size.width ?? 0.0
+        }
+        if size.height == 0.0 && image != nil
+        {
+            size.height = image?.size.height ?? 0.0
+        }
+        
+        let width = size.width
+        let height = size.height
+        
+        if point.x + offset.x < 0.0
+        {
+            offset.x = -point.x
+        }
+        else if chart != nil && point.x + width + offset.x > chart!.bounds.size.width
+        {
+            offset.x = chart!.bounds.size.width - point.x - width
+        }
+        
+        if point.y + offset.y < 0
+        {
+            offset.y = -point.y
+        }
+        else if chart != nil && point.y + height + offset.y > chart!.bounds.size.height
+        {
+            offset.y = chart!.bounds.size.height - point.y - height
+        }
+        
+        return offset
+    }
+    
+    open func refreshContent(entry: ChartDataEntry, highlight: Highlight)
+    {
+        // Do nothing here...
+    }
+    
+    open func draw(context: CGContext, point: CGPoint)
+    {
+        guard let image = image else { return }
+
+        let offset = offsetForDrawing(atPoint: point)
+        
+        var size = self.size
+        
+        if size.width == 0.0
+        {
+            size.width = image.size.width
+        }
+        if size.height == 0.0
+        {
+            size.height = image.size.height
+        }
+        
+        let rect = CGRect(
+            x: point.x + offset.x,
+            y: point.y + offset.y,
+            width: size.width,
+            height: size.height)
+        
+        NSUIGraphicsPushContext(context)
+        image.draw(in: rect)
+        NSUIGraphicsPopContext()
+    }
+}

+ 100 - 0
Pods/Charts/Source/Charts/Components/MarkerView.swift

@@ -0,0 +1,100 @@
+//
+//  ChartMarkerView.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+#if canImport(AppKit)
+import AppKit
+#endif
+
+@objc(ChartMarkerView)
+open class MarkerView: NSUIView, IMarker
+{
+    open var offset: CGPoint = CGPoint()
+    
+    @objc open weak var chartView: ChartViewBase?
+    
+    open func offsetForDrawing(atPoint point: CGPoint) -> CGPoint
+    {
+        guard let chart = chartView else { return self.offset }
+        
+        var offset = self.offset
+        
+        let width = self.bounds.size.width
+        let height = self.bounds.size.height
+        
+        if point.x + offset.x < 0.0
+        {
+            offset.x = -point.x
+        }
+        else if point.x + width + offset.x > chart.bounds.size.width
+        {
+            offset.x = chart.bounds.size.width - point.x - width
+        }
+        
+        if point.y + offset.y < 0
+        {
+            offset.y = -point.y
+        }
+        else if point.y + height + offset.y > chart.bounds.size.height
+        {
+            offset.y = chart.bounds.size.height - point.y - height
+        }
+        
+        return offset
+    }
+    
+    open func refreshContent(entry: ChartDataEntry, highlight: Highlight)
+    {
+        // Do nothing here...
+    }
+    
+    open func draw(context: CGContext, point: CGPoint)
+    {
+        let offset = self.offsetForDrawing(atPoint: point)
+        
+        context.saveGState()
+        context.translateBy(x: point.x + offset.x,
+                              y: point.y + offset.y)
+        NSUIGraphicsPushContext(context)
+        self.nsuiLayer?.render(in: context)
+        NSUIGraphicsPopContext()
+        context.restoreGState()
+    }
+    
+    @objc
+    open class func viewFromXib(in bundle: Bundle = .main) -> MarkerView?
+    {
+        #if !os(OSX)
+        
+        return bundle.loadNibNamed(
+            String(describing: self),
+            owner: nil,
+            options: nil)?[0] as? MarkerView
+        #else
+        
+        var loadedObjects = NSArray()
+        let loadedObjectsPointer = AutoreleasingUnsafeMutablePointer<NSArray?>(&loadedObjects)
+        
+        if bundle.loadNibNamed(
+            NSNib.Name(String(describing: self)),
+            owner: nil,
+            topLevelObjects: loadedObjectsPointer)
+        {
+            return loadedObjects[0] as? MarkerView
+        }
+        
+        return nil
+        #endif
+    }
+    
+}

+ 75 - 0
Pods/Charts/Source/Charts/Components/XAxis.swift

@@ -0,0 +1,75 @@
+//
+//  XAxis.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(ChartXAxis)
+open class XAxis: AxisBase
+{
+    @objc(XAxisLabelPosition)
+    public enum LabelPosition: Int
+    {
+        case top
+        case bottom
+        case bothSided
+        case topInside
+        case bottomInside
+    }
+    
+    /// width of the x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers
+    @objc open var labelWidth = CGFloat(1.0)
+    
+    /// height of the x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers
+    @objc open var labelHeight = CGFloat(1.0)
+    
+    /// width of the (rotated) x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers
+    @objc open var labelRotatedWidth = CGFloat(1.0)
+    
+    /// height of the (rotated) x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers
+    @objc open var labelRotatedHeight = CGFloat(1.0)
+    
+    /// This is the angle for drawing the X axis labels (in degrees)
+    @objc open var labelRotationAngle = CGFloat(0.0)
+
+    /// if set to true, the chart will avoid that the first and last label entry in the chart "clip" off the edge of the chart
+    @objc open var avoidFirstLastClippingEnabled = false
+    
+    /// the position of the x-labels relative to the chart
+    @objc open var labelPosition = LabelPosition.top
+    
+    /// if set to true, word wrapping the labels will be enabled.
+    /// word wrapping is done using `(value width * labelRotatedWidth)`
+    ///
+    /// - Note: currently supports all charts except pie/radar/horizontal-bar*
+    @objc open var wordWrapEnabled = false
+    
+    /// `true` if word wrapping the labels is enabled
+    @objc open var isWordWrapEnabled: Bool { return wordWrapEnabled }
+    
+    /// the width for wrapping the labels, as percentage out of one value width.
+    /// used only when isWordWrapEnabled = true.
+    /// 
+    /// **default**: 1.0
+    @objc open var wordWrapWidthPercent: CGFloat = 1.0
+    
+    public override init()
+    {
+        super.init()
+        
+        self.yOffset = 4.0
+    }
+    
+    @objc open var isAvoidFirstLastClippingEnabled: Bool
+    {
+        return avoidFirstLastClippingEnabled
+    }
+}

+ 206 - 0
Pods/Charts/Source/Charts/Components/YAxis.swift

@@ -0,0 +1,206 @@
+//
+//  YAxis.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+#if canImport(UIKit)
+    import UIKit
+#endif
+
+#if canImport(Cocoa)
+import Cocoa
+#endif
+
+
+/// Class representing the y-axis labels settings and its entries.
+/// Be aware that not all features the YLabels class provides are suitable for the RadarChart.
+/// Customizations that affect the value range of the axis need to be applied before setting data for the chart.
+@objc(ChartYAxis)
+open class YAxis: AxisBase
+{
+    @objc(YAxisLabelPosition)
+    public enum LabelPosition: Int
+    {
+        case outsideChart
+        case insideChart
+    }
+    
+    ///  Enum that specifies the axis a DataSet should be plotted against, either Left or Right.
+    @objc
+    public enum AxisDependency: Int
+    {
+        case left
+        case right
+    }
+    
+    /// indicates if the bottom y-label entry is drawn or not
+    @objc open var drawBottomYLabelEntryEnabled = true
+    
+    /// indicates if the top y-label entry is drawn or not
+    @objc open var drawTopYLabelEntryEnabled = true
+    
+    /// flag that indicates if the axis is inverted or not
+    @objc open var inverted = false
+    
+    /// flag that indicates if the zero-line should be drawn regardless of other grid lines
+    @objc open var drawZeroLineEnabled = false
+    
+    /// Color of the zero line
+    @objc open var zeroLineColor: NSUIColor? = NSUIColor.gray
+    
+    /// Width of the zero line
+    @objc open var zeroLineWidth: CGFloat = 1.0
+    
+    /// This is how much (in pixels) into the dash pattern are we starting from.
+    @objc open var zeroLineDashPhase = CGFloat(0.0)
+    
+    /// This is the actual dash pattern.
+    /// I.e. [2, 3] will paint [--   --   ]
+    /// [1, 3, 4, 2] will paint [-   ----  -   ----  ]
+    @objc open var zeroLineDashLengths: [CGFloat]?
+
+    /// axis space from the largest value to the top in percent of the total axis range
+    @objc open var spaceTop = CGFloat(0.1)
+
+    /// axis space from the smallest value to the bottom in percent of the total axis range
+    @objc open var spaceBottom = CGFloat(0.1)
+    
+    /// the position of the y-labels relative to the chart
+    @objc open var labelPosition = LabelPosition.outsideChart
+
+    /// the alignment of the text in the y-label
+    @objc open var labelAlignment: NSTextAlignment = .left
+
+    /// the horizontal offset of the y-label
+    @objc open var labelXOffset: CGFloat = 0.0
+    
+    /// the side this axis object represents
+    private var _axisDependency = AxisDependency.left
+    
+    /// the minimum width that the axis should take
+    /// 
+    /// **default**: 0.0
+    @objc open var minWidth = CGFloat(0)
+    
+    /// the maximum width that the axis can take.
+    /// use Infinity for disabling the maximum.
+    /// 
+    /// **default**: CGFloat.infinity
+    @objc open var maxWidth = CGFloat(CGFloat.infinity)
+    
+    public override init()
+    {
+        super.init()
+        
+        self.yOffset = 0.0
+    }
+    
+    @objc public init(position: AxisDependency)
+    {
+        super.init()
+        
+        _axisDependency = position
+        
+        self.yOffset = 0.0
+    }
+    
+    @objc open var axisDependency: AxisDependency
+    {
+        return _axisDependency
+    }
+    
+    @objc open func requiredSize() -> CGSize
+    {
+        let label = getLongestLabel() as NSString
+        var size = label.size(withAttributes: [NSAttributedString.Key.font: labelFont])
+        size.width += xOffset * 2.0
+        size.height += yOffset * 2.0
+        size.width = max(minWidth, min(size.width, maxWidth > 0.0 ? maxWidth : size.width))
+        return size
+    }
+    
+    @objc open func getRequiredHeightSpace() -> CGFloat
+    {
+        return requiredSize().height
+    }
+    
+    /// `true` if this axis needs horizontal offset, `false` ifno offset is needed.
+    @objc open var needsOffset: Bool
+    {
+        if isEnabled && isDrawLabelsEnabled && labelPosition == .outsideChart
+        {
+            return true
+        }
+        else
+        {
+            return false
+        }
+    }
+    
+    @objc open var isInverted: Bool { return inverted }
+    
+    open override func calculate(min dataMin: Double, max dataMax: Double)
+    {
+        // if custom, use value as is, else use data value
+        var min = _customAxisMin ? _axisMinimum : dataMin
+        var max = _customAxisMax ? _axisMaximum : dataMax
+        
+        // Make sure max is greater than min
+        // Discussion: https://github.com/danielgindi/Charts/pull/3650#discussion_r221409991
+        if min > max
+        {
+            switch(_customAxisMax, _customAxisMin)
+            {
+            case(true, true):
+                (min, max) = (max, min)
+            case(true, false):
+                min = max < 0 ? max * 1.5 : max * 0.5
+            case(false, true):
+                max = min < 0 ? min * 0.5 : min * 1.5
+            case(false, false):
+                break
+            }
+        }
+        
+        // temporary range (before calculations)
+        let range = abs(max - min)
+        
+        // in case all values are equal
+        if range == 0.0
+        {
+            max = max + 1.0
+            min = min - 1.0
+        }
+        
+        // bottom-space only effects non-custom min
+        if !_customAxisMin
+        {
+            let bottomSpace = range * Double(spaceBottom)
+            _axisMinimum = (min - bottomSpace)
+        }
+        
+        // top-space only effects non-custom max
+        if !_customAxisMax
+        {
+            let topSpace = range * Double(spaceTop)
+            _axisMaximum = (max + topSpace)
+        }
+        
+        // calc actual range
+        axisRange = abs(_axisMaximum - _axisMinimum)
+    }
+    
+    @objc open var isDrawBottomYLabelEntryEnabled: Bool { return drawBottomYLabelEntryEnabled }
+    
+    @objc open var isDrawTopYLabelEntryEnabled: Bool { return drawTopYLabelEntryEnabled }
+
+}

+ 435 - 0
Pods/Charts/Source/Charts/Data/Implementations/ChartBaseDataSet.swift

@@ -0,0 +1,435 @@
+//
+//  BaseDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+open class ChartBaseDataSet: NSObject, IChartDataSet, NSCopying
+{
+    public required override init()
+    {
+        super.init()
+        
+        // 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(.labelOrBlack)
+    }
+    
+    @objc public init(label: String?)
+    {
+        super.init()
+        
+        // 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(.labelOrBlack)
+        
+        self.label = label
+    }
+    
+    // MARK: - Data functions and accessors
+    
+    /// Use this method to tell the data set that the underlying data has changed
+    open func notifyDataSetChanged()
+    {
+        calcMinMax()
+    }
+    
+    open func calcMinMax()
+    {
+        fatalError("calcMinMax is not implemented in ChartBaseDataSet")
+    }
+    
+    open func calcMinMaxY(fromX: Double, toX: Double)
+    {
+        fatalError("calcMinMaxY(fromX:, toX:) is not implemented in ChartBaseDataSet")
+    }
+    
+    open var yMin: Double
+    {
+        fatalError("yMin is not implemented in ChartBaseDataSet")
+    }
+    
+    open var yMax: Double
+    {
+        fatalError("yMax is not implemented in ChartBaseDataSet")
+    }
+    
+    open var xMin: Double
+    {
+        fatalError("xMin is not implemented in ChartBaseDataSet")
+    }
+    
+    open var xMax: Double
+    {
+        fatalError("xMax is not implemented in ChartBaseDataSet")
+    }
+    
+    open var entryCount: Int
+    {
+        fatalError("entryCount is not implemented in ChartBaseDataSet")
+    }
+        
+    open func entryForIndex(_ i: Int) -> ChartDataEntry?
+    {
+        fatalError("entryForIndex is not implemented in ChartBaseDataSet")
+    }
+    
+    open func entryForXValue(
+        _ x: Double,
+        closestToY y: Double,
+        rounding: ChartDataSetRounding) -> ChartDataEntry?
+    {
+        fatalError("entryForXValue(x, closestToY, rounding) is not implemented in ChartBaseDataSet")
+    }
+    
+    open func entryForXValue(
+        _ x: Double,
+        closestToY y: Double) -> ChartDataEntry?
+    {
+        fatalError("entryForXValue(x, closestToY) is not implemented in ChartBaseDataSet")
+    }
+    
+    open func entriesForXValue(_ x: Double) -> [ChartDataEntry]
+    {
+        fatalError("entriesForXValue is not implemented in ChartBaseDataSet")
+    }
+    
+    open func entryIndex(
+        x xValue: Double,
+        closestToY y: Double,
+        rounding: ChartDataSetRounding) -> Int
+    {
+        fatalError("entryIndex(x, closestToY, rounding) is not implemented in ChartBaseDataSet")
+    }
+    
+    open func entryIndex(entry e: ChartDataEntry) -> Int
+    {
+        fatalError("entryIndex(entry) is not implemented in ChartBaseDataSet")
+    }
+    
+    open func addEntry(_ e: ChartDataEntry) -> Bool
+    {
+        fatalError("addEntry is not implemented in ChartBaseDataSet")
+    }
+    
+    open func addEntryOrdered(_ e: ChartDataEntry) -> Bool
+    {
+        fatalError("addEntryOrdered is not implemented in ChartBaseDataSet")
+    }
+    
+    @discardableResult open func removeEntry(_ entry: ChartDataEntry) -> Bool
+    {
+        fatalError("removeEntry is not implemented in ChartBaseDataSet")
+    }
+    
+    @discardableResult open func removeEntry(index: Int) -> Bool
+    {
+        if let entry = entryForIndex(index)
+        {
+            return removeEntry(entry)
+        }
+        return false
+    }
+    
+    @discardableResult open func removeEntry(x: Double) -> Bool
+    {
+        if let entry = entryForXValue(x, closestToY: Double.nan)
+        {
+            return removeEntry(entry)
+        }
+        return false
+    }
+    
+    @discardableResult open func removeFirst() -> Bool
+    {
+        if entryCount > 0
+        {
+            if let entry = entryForIndex(0)
+            {
+                return removeEntry(entry)
+            }
+        }
+        return false
+    }
+    
+    @discardableResult open func removeLast() -> Bool
+    {
+        if entryCount > 0
+        {
+            if let entry = entryForIndex(entryCount - 1)
+            {
+                return removeEntry(entry)
+            }
+        }
+        return false
+    }
+    
+    open func contains(_ e: ChartDataEntry) -> Bool
+    {
+        fatalError("removeEntry is not implemented in ChartBaseDataSet")
+    }
+    
+    open func clear()
+    {
+        fatalError("clear is not implemented in ChartBaseDataSet")
+    }
+    
+    // MARK: - Styling functions and accessors
+    
+    /// All the colors that are used for this DataSet.
+    /// Colors are reused as soon as the number of Entries the DataSet represents is higher than the size of the colors array.
+    open var colors = [NSUIColor]()
+    
+    /// List representing all colors that are used for drawing the actual values for this DataSet
+    open var valueColors = [NSUIColor]()
+
+    /// The label string that describes the DataSet.
+    open var label: String? = "DataSet"
+    
+    /// The axis this DataSet should be plotted against.
+    open var axisDependency = YAxis.AxisDependency.left
+    
+    /// - Returns: The color at the given index of the DataSet's color array.
+    /// This prevents out-of-bounds by performing a modulus on the color index, so colours will repeat themselves.
+    open func color(atIndex index: Int) -> NSUIColor
+    {
+        var index = index
+        if index < 0
+        {
+            index = 0
+        }
+        return colors[index % colors.count]
+    }
+    
+    /// Resets all colors of this DataSet and recreates the colors array.
+    open func resetColors()
+    {
+        colors.removeAll(keepingCapacity: false)
+    }
+    
+    /// Adds a new color to the colors array of the DataSet.
+    ///
+    /// - Parameters:
+    ///   - color: the color to add
+    open func addColor(_ color: NSUIColor)
+    {
+        colors.append(color)
+    }
+    
+    /// Sets the one and **only** color that should be used for this DataSet.
+    /// Internally, this recreates the colors array and adds the specified color.
+    ///
+    /// - Parameters:
+    ///   - color: the color to set
+    open func setColor(_ color: NSUIColor)
+    {
+        colors.removeAll(keepingCapacity: false)
+        colors.append(color)
+    }
+    
+    /// Sets colors to a single color a specific alpha value.
+    ///
+    /// - Parameters:
+    ///   - color: the color to set
+    ///   - alpha: alpha to apply to the set `color`
+    @objc open func setColor(_ color: NSUIColor, alpha: CGFloat)
+    {
+        setColor(color.withAlphaComponent(alpha))
+    }
+    
+    /// Sets colors with a specific alpha value.
+    ///
+    /// - Parameters:
+    ///   - colors: the colors to set
+    ///   - alpha: alpha to apply to the set `colors`
+    @objc open func setColors(_ colors: [NSUIColor], alpha: CGFloat)
+    {
+        self.colors = colors.map { $0.withAlphaComponent(alpha) }
+    }
+    
+    /// Sets colors with a specific alpha value.
+    ///
+    /// - Parameters:
+    ///   - colors: the colors to set
+    ///   - alpha: alpha to apply to the set `colors`
+    open func setColors(_ colors: NSUIColor...)
+    {
+        self.colors = colors
+    }
+    
+    /// if true, value highlighting is enabled
+    open var highlightEnabled = true
+    
+    /// `true` if value highlighting is enabled for this dataset
+    open var isHighlightEnabled: Bool { return highlightEnabled }
+    
+    /// Custom formatter that is used instead of the auto-formatter if set
+    internal var _valueFormatter: IValueFormatter?
+    
+    /// Custom formatter that is used instead of the auto-formatter if set
+    open var valueFormatter: IValueFormatter?
+    {
+        get
+        {
+            if needsFormatter
+            {
+                return ChartUtils.defaultValueFormatter()
+            }
+            
+            return _valueFormatter
+        }
+        set
+        {
+            if newValue == nil { return }
+            
+            _valueFormatter = newValue
+        }
+    }
+    
+    open var needsFormatter: Bool
+    {
+        return _valueFormatter == nil
+    }
+    
+    /// Sets/get a single color for value text.
+    /// Setting the color clears the colors array and adds a single color.
+    /// Getting will return the first color in the array.
+    open var valueTextColor: NSUIColor
+    {
+        get
+        {
+            return valueColors[0]
+        }
+        set
+        {
+            valueColors.removeAll(keepingCapacity: false)
+            valueColors.append(newValue)
+        }
+    }
+    
+    /// - Returns: The color at the specified index that is used for drawing the values inside the chart. Uses modulus internally.
+    open func valueTextColorAt(_ index: Int) -> NSUIColor
+    {
+        var index = index
+        if index < 0
+        {
+            index = 0
+        }
+        return valueColors[index % valueColors.count]
+    }
+    
+    /// the font for the value-text labels
+    open var valueFont: NSUIFont = NSUIFont.systemFont(ofSize: 7.0)
+    
+    /// The form to draw for this dataset in the legend.
+    open var form = Legend.Form.default
+    
+    /// The form size to draw for this dataset in the legend.
+    ///
+    /// Return `NaN` to use the default legend form size.
+    open var formSize: CGFloat = CGFloat.nan
+    
+    /// The line width for drawing the form of this dataset in the legend
+    ///
+    /// Return `NaN` to use the default legend form line width.
+    open var formLineWidth: CGFloat = CGFloat.nan
+    
+    /// Line dash configuration for legend shapes that consist of lines.
+    ///
+    /// This is how much (in pixels) into the dash pattern are we starting from.
+    open var formLineDashPhase: CGFloat = 0.0
+    
+    /// Line dash configuration for legend shapes that consist of lines.
+    ///
+    /// This is the actual dash pattern.
+    /// I.e. [2, 3] will paint [--   --   ]
+    /// [1, 3, 4, 2] will paint [-   ----  -   ----  ]
+    open var formLineDashLengths: [CGFloat]? = nil
+    
+    /// Set this to true to draw y-values on the chart.
+    ///
+    /// - Note: For bar and line charts: if `maxVisibleCount` is reached, no values will be drawn even if this is enabled.
+    open var drawValuesEnabled = true
+    
+    /// `true` if y-value drawing is enabled, `false` ifnot
+    open var isDrawValuesEnabled: Bool
+    {
+        return drawValuesEnabled
+    }
+
+    /// Set this to true to draw y-icons on the chart.
+    ///
+    /// - Note: For bar and line charts: if `maxVisibleCount` is reached, no icons will be drawn even if this is enabled.
+    open var drawIconsEnabled = true
+    
+    /// Returns true if y-icon drawing is enabled, false if not
+    open var isDrawIconsEnabled: Bool
+    {
+        return drawIconsEnabled
+    }
+    
+    /// Offset of icons drawn on the chart.  
+    ///
+    /// For all charts except Pie and Radar it will be ordinary (x offset, y offset).
+    ///
+    /// For Pie and Radar chart it will be (y offset, distance from center offset); so if you want icon to be rendered under value, you should increase X component of CGPoint, and if you want icon to be rendered closet to center, you should decrease height component of CGPoint.
+    open var iconsOffset = CGPoint(x: 0, y: 0)
+    
+    /// Set the visibility of this DataSet. If not visible, the DataSet will not be drawn to the chart upon refreshing it.
+    open var visible = true
+    
+    /// `true` if this DataSet is visible inside the chart, or `false` ifit is currently hidden.
+    open var isVisible: Bool
+    {
+        return visible
+    }
+    
+    // MARK: - NSObject
+    
+    open override var description: String
+    {
+        return String(format: "%@, label: %@, %i entries", arguments: [NSStringFromClass(type(of: self)), self.label ?? "", self.entryCount])
+    }
+    
+    open override var debugDescription: String
+    {
+        return (0..<entryCount).reduce(description + ":") {
+            "\($0)\n\(self.entryForIndex($1)?.description ?? "")"
+        }
+    }
+    
+    // MARK: - NSCopying
+    
+    open func copy(with zone: NSZone? = nil) -> Any 
+    {
+        let copy = type(of: self).init()
+        
+        copy.colors = colors
+        copy.valueColors = valueColors
+        copy.label = label
+        copy.axisDependency = axisDependency
+        copy.highlightEnabled = highlightEnabled
+        copy._valueFormatter = _valueFormatter
+        copy.valueFont = valueFont
+        copy.form = form
+        copy.formSize = formSize
+        copy.formLineWidth = formLineWidth
+        copy.formLineDashPhase = formLineDashPhase
+        copy.formLineDashLengths = formLineDashLengths
+        copy.drawValuesEnabled = drawValuesEnabled
+        copy.drawValuesEnabled = drawValuesEnabled
+        copy.iconsOffset = iconsOffset
+        copy.visible = visible
+        
+        return copy
+    }
+}

+ 107 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartData.swift

@@ -0,0 +1,107 @@
+//
+//  BarChartData.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+open class BarChartData: BarLineScatterCandleBubbleChartData
+{
+    public override init()
+    {
+        super.init()
+    }
+    
+    public override init(dataSets: [IChartDataSet]?)
+    {
+        super.init(dataSets: dataSets)
+    }
+    
+    /// The width of the bars on the x-axis, in values (not pixels)
+    ///
+    /// **default**: 0.85
+    @objc open var barWidth = Double(0.85)
+    
+    /// Groups all BarDataSet objects this data object holds together by modifying the x-value of their entries.
+    /// Previously set x-values of entries will be overwritten. Leaves space between bars and groups as specified by the parameters.
+    /// Do not forget to call notifyDataSetChanged() on your BarChart object after calling this method.
+    ///
+    /// - Parameters:
+    ///   - fromX: the starting point on the x-axis where the grouping should begin
+    ///   - groupSpace: The space between groups of bars in values (not pixels) e.g. 0.8f for bar width 1f
+    ///   - barSpace: The space between individual bars in values (not pixels) e.g. 0.1f for bar width 1f
+    @objc open func groupBars(fromX: Double, groupSpace: Double, barSpace: Double)
+    {
+        let setCount = _dataSets.count
+        if setCount <= 1
+        {
+            print("BarData needs to hold at least 2 BarDataSets to allow grouping.", terminator: "\n")
+            return
+        }
+        
+        let max = maxEntryCountSet
+        let maxEntryCount = max?.entryCount ?? 0
+        
+        let groupSpaceWidthHalf = groupSpace / 2.0
+        let barSpaceHalf = barSpace / 2.0
+        let barWidthHalf = self.barWidth / 2.0
+        
+        var fromX = fromX
+        
+        let interval = groupWidth(groupSpace: groupSpace, barSpace: barSpace)
+
+        for i in stride(from: 0, to: maxEntryCount, by: 1)
+        {
+            let start = fromX
+            fromX += groupSpaceWidthHalf
+            
+            (_dataSets as? [IBarChartDataSet])?.forEach { set in
+                fromX += barSpaceHalf
+                fromX += barWidthHalf
+                
+                if i < set.entryCount
+                {
+                    if let entry = set.entryForIndex(i)
+                    {
+                        entry.x = fromX
+                    }
+                }
+                
+                fromX += barWidthHalf
+                fromX += barSpaceHalf
+            }
+            
+            fromX += groupSpaceWidthHalf
+            let end = fromX
+            let innerInterval = end - start
+            let diff = interval - innerInterval
+            
+            // correct rounding errors
+            if diff > 0 || diff < 0
+            {
+                fromX += diff
+            }
+
+        }
+        
+        notifyDataChanged()
+    }
+    
+    /// In case of grouped bars, this method returns the space an individual group of bar needs on the x-axis.
+    ///
+    /// - Parameters:
+    ///   - groupSpace:
+    ///   - barSpace:
+    @objc open func groupWidth(groupSpace: Double, barSpace: Double) -> Double
+    {
+        return Double(_dataSets.count) * (self.barWidth + barSpace) + groupSpace
+    }
+    
+}

+ 230 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataEntry.swift

@@ -0,0 +1,230 @@
+//
+//  BarChartDataEntry.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+open class BarChartDataEntry: ChartDataEntry
+{
+    /// the values the stacked barchart holds
+    private var _yVals: [Double]?
+    
+    /// the ranges for the individual stack values - automatically calculated
+    private var _ranges: [Range]?
+    
+    /// the sum of all negative values this entry (if stacked) contains
+    private var _negativeSum: Double = 0.0
+    
+    /// the sum of all positive values this entry (if stacked) contains
+    private var _positiveSum: Double = 0.0
+    
+    public required init()
+    {
+        super.init()
+    }
+    
+    /// Constructor for normal bars (not stacked).
+    public override init(x: Double, y: Double)
+    {
+        super.init(x: x, y: y)
+    }
+    
+    /// Constructor for normal bars (not stacked).
+    public convenience init(x: Double, y: Double, data: Any?)
+    {
+        self.init(x: x, y: y)
+        self.data = data
+    }
+    
+    /// Constructor for normal bars (not stacked).
+    public convenience init(x: Double, y: Double, icon: NSUIImage?)
+    {
+        self.init(x: x, y: y)
+        self.icon = icon
+    }
+    
+    /// Constructor for normal bars (not stacked).
+    public convenience init(x: Double, y: Double, icon: NSUIImage?, data: Any?)
+    {
+        self.init(x: x, y: y)
+        self.icon = icon
+        self.data = data
+    }
+    
+    /// Constructor for stacked bar entries.
+    @objc public init(x: Double, yValues: [Double])
+    {
+        super.init(x: x, y: BarChartDataEntry.calcSum(values: yValues))
+        self._yVals = yValues
+        calcPosNegSum()
+        calcRanges()
+    }
+
+    /// Constructor for stacked bar entries. One data object for whole stack
+    @objc public convenience init(x: Double, yValues: [Double], icon: NSUIImage?)
+    {
+        self.init(x: x, yValues: yValues)
+        self.icon = icon
+    }
+
+    /// Constructor for stacked bar entries. One data object for whole stack
+    @objc public convenience init(x: Double, yValues: [Double], data: Any?)
+    {
+        self.init(x: x, yValues: yValues)
+        self.data = data
+    }
+
+    /// Constructor for stacked bar entries. One data object for whole stack
+    @objc public convenience init(x: Double, yValues: [Double], icon: NSUIImage?, data: Any?)
+    {
+        self.init(x: x, yValues: yValues)
+        self.icon = icon
+        self.data = data
+    }
+    
+    @objc open func sumBelow(stackIndex :Int) -> Double
+    {
+        guard let yVals = _yVals else
+        {
+            return 0
+        }
+        
+        var remainder: Double = 0.0
+        var index = yVals.count - 1
+        
+        while (index > stackIndex && index >= 0)
+        {
+            remainder += yVals[index]
+            index -= 1
+        }
+        
+        return remainder
+    }
+    
+    /// The sum of all negative values this entry (if stacked) contains. (this is a positive number)
+    @objc open var negativeSum: Double
+    {
+        return _negativeSum
+    }
+    
+    /// The sum of all positive values this entry (if stacked) contains.
+    @objc open var positiveSum: Double
+    {
+        return _positiveSum
+    }
+
+    @objc open func calcPosNegSum()
+    {
+        (_negativeSum, _positiveSum) = _yVals?.reduce(into: (0,0)) { (result, y) in
+            if y < 0
+            {
+                result.0 += -y
+            }
+            else
+            {
+                result.1 += y
+            }
+        } ?? (0,0)
+    }
+    
+    /// Splits up the stack-values of the given bar-entry into Range objects.
+    ///
+    /// - Parameters:
+    ///   - entry:
+    /// - Returns:
+    @objc open func calcRanges()
+    {
+        guard let values = yValues, !values.isEmpty else { return }
+
+        if _ranges == nil
+        {
+            _ranges = [Range]()
+        }
+        else
+        {
+            _ranges!.removeAll()
+        }
+        
+        _ranges!.reserveCapacity(values.count)
+        
+        var negRemain = -negativeSum
+        var posRemain: Double = 0.0
+        
+        for value in values
+        {
+            if value < 0
+            {
+                _ranges!.append(Range(from: negRemain, to: negRemain - value))
+                negRemain -= value
+            }
+            else
+            {
+                _ranges!.append(Range(from: posRemain, to: posRemain + value))
+                posRemain += value
+            }
+        }
+    }
+    
+    // MARK: Accessors
+    
+    /// the values the stacked barchart holds
+    @objc open var isStacked: Bool { return _yVals != nil }
+    
+    /// the values the stacked barchart holds
+    @objc open var yValues: [Double]?
+    {
+        get { return self._yVals }
+        set
+        {
+            self.y = BarChartDataEntry.calcSum(values: newValue)
+            self._yVals = newValue
+            calcPosNegSum()
+            calcRanges()
+        }
+    }
+    
+    /// The ranges of the individual stack-entries. Will return null if this entry is not stacked.
+    @objc open var ranges: [Range]?
+    {
+        return _ranges
+    }
+    
+    // MARK: NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! BarChartDataEntry
+        copy._yVals = _yVals
+        copy.y = y
+        copy._negativeSum = _negativeSum
+        copy._positiveSum = _positiveSum
+        return copy
+    }
+    
+    /// Calculates the sum across all values of the given stack.
+    ///
+    /// - Parameters:
+    ///   - vals:
+    /// - Returns:
+    private static func calcSum(values: [Double]?) -> Double
+    {
+        guard let values = values
+            else { return 0.0 }
+        
+        var sum = 0.0
+        
+        for f in values
+        {
+            sum += f
+        }
+        
+        return sum
+    }
+}

+ 167 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift

@@ -0,0 +1,167 @@
+//
+//  BarChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+open class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet, IBarChartDataSet
+{
+    private func initialize()
+    {
+        self.highlightColor = NSUIColor.black
+        
+        self.calcStackSize(entries: entries as! [BarChartDataEntry])
+        self.calcEntryCountIncludingStacks(entries: entries as! [BarChartDataEntry])
+    }
+    
+    public required init()
+    {
+        super.init()
+        initialize()
+    }
+    
+    public override init(entries: [ChartDataEntry]?, label: String?)
+    {
+        super.init(entries: entries, label: label)
+        initialize()
+    }
+
+    // MARK: - Data functions and accessors
+    
+    /// the maximum number of bars that are stacked upon each other, this value
+    /// is calculated from the Entries that are added to the DataSet
+    private var _stackSize = 1
+    
+    /// the overall entry count, including counting each stack-value individually
+    private var _entryCountStacks = 0
+    
+    /// Calculates the total number of entries this DataSet represents, including
+    /// stacks. All values belonging to a stack are calculated separately.
+    private func calcEntryCountIncludingStacks(entries: [BarChartDataEntry])
+    {
+        _entryCountStacks = 0
+        
+        for i in 0 ..< entries.count
+        {
+            if let vals = entries[i].yValues
+            {
+                _entryCountStacks += vals.count
+            }
+            else
+            {
+                _entryCountStacks += 1
+            }
+        }
+    }
+    
+    /// calculates the maximum stacksize that occurs in the Entries array of this DataSet
+    private func calcStackSize(entries: [BarChartDataEntry])
+    {
+        for i in 0 ..< entries.count
+        {
+            if let vals = entries[i].yValues
+            {
+                if vals.count > _stackSize
+                {
+                    _stackSize = vals.count
+                }
+            }
+        }
+    }
+    
+    open override func calcMinMax(entry e: ChartDataEntry)
+    {
+        guard let e = e as? BarChartDataEntry
+            else { return }
+        
+        if !e.y.isNaN
+        {
+            if e.yValues == nil
+            {
+                if e.y < _yMin
+                {
+                    _yMin = e.y
+                }
+                
+                if e.y > _yMax
+                {
+                    _yMax = e.y
+                }
+            }
+            else
+            {
+                if -e.negativeSum < _yMin
+                {
+                    _yMin = -e.negativeSum
+                }
+                
+                if e.positiveSum > _yMax
+                {
+                    _yMax = e.positiveSum
+                }
+            }
+            
+            calcMinMaxX(entry: e)
+        }
+    }
+    
+    /// The maximum number of bars that can be stacked upon another in this DataSet.
+    open var stackSize: Int
+    {
+        return _stackSize
+    }
+    
+    /// `true` if this DataSet is stacked (stacksize > 1) or not.
+    open var isStacked: Bool
+    {
+        return _stackSize > 1 ? true : false
+    }
+    
+    /// The overall entry count, including counting each stack-value individually
+    @objc open var entryCountStacks: Int
+    {
+        return _entryCountStacks
+    }
+    
+    /// array of labels used to describe the different values of the stacked bars
+    open var stackLabels: [String] = []
+    
+    // MARK: - Styling functions and accessors
+    
+    /// the color used for drawing the bar-shadows. The bar shadows is a surface behind the bar that indicates the maximum value
+    open var barShadowColor = NSUIColor(red: 215.0/255.0, green: 215.0/255.0, blue: 215.0/255.0, alpha: 1.0)
+
+    /// the width used for drawing borders around the bars. If borderWidth == 0, no border will be drawn.
+    open var barBorderWidth : CGFloat = 0.0
+
+    /// the color drawing borders around the bars.
+    open var barBorderColor = NSUIColor.black
+
+    /// the alpha value (transparency) that is used for drawing the highlight indicator bar. min = 0.0 (fully transparent), max = 1.0 (fully opaque)
+    open var highlightAlpha = CGFloat(120.0 / 255.0)
+    
+    // MARK: - NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! BarChartDataSet
+        copy._stackSize = _stackSize
+        copy._entryCountStacks = _entryCountStacks
+        copy.stackLabels = stackLabels
+
+        copy.barShadowColor = barShadowColor
+        copy.barBorderWidth = barBorderWidth
+        copy.barBorderColor = barBorderColor
+        copy.highlightAlpha = highlightAlpha
+        return copy
+    }
+}

+ 25 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartData.swift

@@ -0,0 +1,25 @@
+//
+//  BarLineScatterCandleBubbleChartData.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+open class BarLineScatterCandleBubbleChartData: ChartData
+{
+    public override init()
+    {
+        super.init()
+    }
+    
+    public override init(dataSets: [IChartDataSet]?)
+    {
+        super.init(dataSets: dataSets)
+    }
+}

+ 38 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartDataSet.swift

@@ -0,0 +1,38 @@
+//
+//  BarLineScatterCandleBubbleChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+open class BarLineScatterCandleBubbleChartDataSet: ChartDataSet, IBarLineScatterCandleBubbleChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    open var highlightColor = NSUIColor(red: 255.0/255.0, green: 187.0/255.0, blue: 115.0/255.0, alpha: 1.0)
+    open var highlightLineWidth = CGFloat(0.5)
+    open var highlightLineDashPhase = CGFloat(0.0)
+    open var highlightLineDashLengths: [CGFloat]?
+    
+    // MARK: - NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! BarLineScatterCandleBubbleChartDataSet
+        copy.highlightColor = highlightColor
+        copy.highlightLineWidth = highlightLineWidth
+        copy.highlightLineDashPhase = highlightLineDashPhase
+        copy.highlightLineDashLengths = highlightLineDashLengths
+        return copy
+    }
+}

+ 32 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartData.swift

@@ -0,0 +1,32 @@
+//
+//  BubbleChartData.swift
+//  Charts
+//
+//  Bubble chart implementation:
+//    Copyright 2015 Pierre-Marc Airoldi
+//    Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+open class BubbleChartData: BarLineScatterCandleBubbleChartData
+{
+    public override init()
+    {
+        super.init()
+    }
+    
+    public override init(dataSets: [IChartDataSet]?)
+    {
+        super.init(dataSets: dataSets)
+    }
+    
+    /// Sets the width of the circle that surrounds the bubble when highlighted for all DataSet objects this data object contains
+    @objc open func setHighlightCircleWidth(_ width: CGFloat)
+    {
+        (_dataSets as? [IBubbleChartDataSet])?.forEach { $0.highlightCircleWidth = width }
+    }
+}

+ 79 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataEntry.swift

@@ -0,0 +1,79 @@
+//
+//  BubbleDataEntry.swift
+//  Charts
+//
+//  Bubble chart implementation: 
+//    Copyright 2015 Pierre-Marc Airoldi
+//    Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+open class BubbleChartDataEntry: ChartDataEntry
+{
+    /// The size of the bubble.
+    @objc open var size = CGFloat(0.0)
+    
+    public required init()
+    {
+        super.init()
+    }
+    
+    /// - Parameters:
+    ///   - x: The index on the x-axis.
+    ///   - y: The value on the y-axis.
+    ///   - size: The size of the bubble.
+    @objc public init(x: Double, y: Double, size: CGFloat)
+    {
+        super.init(x: x, y: y)
+        
+        self.size = size
+    }
+    
+    /// - Parameters:
+    ///   - x: The index on the x-axis.
+    ///   - y: The value on the y-axis.
+    ///   - size: The size of the bubble.
+    ///   - data: Spot for additional data this Entry represents.
+    @objc public convenience init(x: Double, y: Double, size: CGFloat, data: Any?)
+    {
+        self.init(x: x, y: y, size: size)
+        self.data = data
+    }
+    
+    /// - Parameters:
+    ///   - x: The index on the x-axis.
+    ///   - y: The value on the y-axis.
+    ///   - size: The size of the bubble.
+    ///   - icon: icon image
+    @objc public convenience init(x: Double, y: Double, size: CGFloat, icon: NSUIImage?)
+    {
+        self.init(x: x, y: y, size: size)
+        self.icon = icon
+    }
+    
+    /// - Parameters:
+    ///   - x: The index on the x-axis.
+    ///   - y: The value on the y-axis.
+    ///   - size: The size of the bubble.
+    ///   - icon: icon image
+    ///   - data: Spot for additional data this Entry represents.
+    @objc public convenience init(x: Double, y: Double, size: CGFloat, icon: NSUIImage?, data: Any?)
+    {
+        self.init(x: x, y: y, size: size)
+        self.icon = icon
+        self.data = data
+    }
+    
+    // MARK: NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! BubbleChartDataEntry
+        copy.size = size
+        return copy
+    }
+}

+ 58 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataSet.swift

@@ -0,0 +1,58 @@
+//
+//  BubbleChartDataSet.swift
+//  Charts
+//
+//  Bubble chart implementation:
+//    Copyright 2015 Pierre-Marc Airoldi
+//    Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+open class BubbleChartDataSet: BarLineScatterCandleBubbleChartDataSet, IBubbleChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    internal var _maxSize = CGFloat(0.0)
+    
+    open var maxSize: CGFloat { return _maxSize }
+    @objc open var normalizeSizeEnabled: Bool = true
+    open var isNormalizeSizeEnabled: Bool { return normalizeSizeEnabled }
+    
+    open override func calcMinMax(entry e: ChartDataEntry)
+    {
+        guard let e = e as? BubbleChartDataEntry
+            else { return }
+        
+        super.calcMinMax(entry: e)
+        
+        let size = e.size
+        
+        if size > _maxSize
+        {
+            _maxSize = size
+        }
+    }
+    
+    // MARK: - Styling functions and accessors
+    
+    /// Sets/gets the width of the circle that surrounds the bubble when highlighted
+    open var highlightCircleWidth: CGFloat = 2.5
+    
+    // MARK: - NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! BubbleChartDataSet
+        copy._xMin = _xMin
+        copy._xMax = _xMax
+        copy._maxSize = _maxSize
+        copy.normalizeSizeEnabled = normalizeSizeEnabled
+        copy.highlightCircleWidth = highlightCircleWidth
+        return copy
+    }
+}

+ 25 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartData.swift

@@ -0,0 +1,25 @@
+//
+//  CandleChartData.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+open class CandleChartData: BarLineScatterCandleBubbleChartData
+{
+    public override init()
+    {
+        super.init()
+    }
+    
+    public override init(dataSets: [IChartDataSet]?)
+    {
+        super.init(dataSets: dataSets)
+    }
+}

+ 98 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataEntry.swift

@@ -0,0 +1,98 @@
+//
+//  CandleChartDataEntry.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+open class CandleChartDataEntry: ChartDataEntry
+{
+    /// shadow-high value
+    @objc open var high = Double(0.0)
+    
+    /// shadow-low value
+    @objc open var low = Double(0.0)
+    
+    /// close value
+    @objc open var close = Double(0.0)
+    
+    /// open value
+    @objc open var open = Double(0.0)
+    
+    public required init()
+    {
+        super.init()
+    }
+    
+    @objc public init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double)
+    {
+        super.init(x: x, y: (shadowH + shadowL) / 2.0)
+        
+        self.high = shadowH
+        self.low = shadowL
+        self.open = open
+        self.close = close
+    }
+
+    @objc public convenience init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double, icon: NSUIImage?)
+    {
+        self.init(x: x, shadowH: shadowH, shadowL: shadowL, open: open, close: close)
+        self.icon = icon
+    }
+
+    @objc public convenience init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double, data: Any?)
+    {
+        self.init(x: x, shadowH: shadowH, shadowL: shadowL, open: open, close: close)
+        self.data = data
+    }
+
+    @objc public convenience init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double, icon: NSUIImage?, data: Any?)
+    {
+        self.init(x: x, shadowH: shadowH, shadowL: shadowL, open: open, close: close)
+        self.icon = icon
+        self.data = data
+    }
+    
+    /// The overall range (difference) between shadow-high and shadow-low.
+    @objc open var shadowRange: Double
+    {
+        return abs(high - low)
+    }
+    
+    /// The body size (difference between open and close).
+    @objc open var bodyRange: Double
+    {
+        return abs(open - close)
+    }
+    
+    /// the center value of the candle. (Middle value between high and low)
+    open override var y: Double
+    {
+        get
+        {
+            return super.y
+        }
+        set
+        {
+            super.y = (high + low) / 2.0
+        }
+    }
+    
+    // MARK: NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! CandleChartDataEntry
+        copy.high = high
+        copy.low = low
+        copy.open = open
+        copy.close = close
+        return copy
+    }
+}

+ 136 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataSet.swift

@@ -0,0 +1,136 @@
+//
+//  CandleChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+open class CandleChartDataSet: LineScatterCandleRadarChartDataSet, ICandleChartDataSet
+{
+    
+    public required init()
+    {
+        super.init()
+    }
+    
+    public override init(entries: [ChartDataEntry]?, label: String?)
+    {
+        super.init(entries: entries, label: label)
+    }
+    
+    // MARK: - Data functions and accessors
+    
+    open override func calcMinMax(entry e: ChartDataEntry)
+    {
+        guard let e = e as? CandleChartDataEntry
+            else { return }
+        
+        if e.low < _yMin
+        {
+            _yMin = e.low
+        }
+        
+        if e.high > _yMax
+        {
+            _yMax = e.high
+        }
+        
+        calcMinMaxX(entry: e)
+    }
+    
+    open override func calcMinMaxY(entry e: ChartDataEntry)
+    {
+        guard let e = e as? CandleChartDataEntry
+            else { return }
+        
+        if e.high < _yMin
+        {
+            _yMin = e.high
+        }
+        if e.high > _yMax
+        {
+            _yMax = e.high
+        }
+        
+        if e.low < _yMin
+        {
+            _yMin = e.low
+        }
+        if e.low > _yMax
+        {
+            _yMax = e.low
+        }
+    }
+    
+    // MARK: - Styling functions and accessors
+    
+    /// the space between the candle entries
+    ///
+    /// **default**: 0.1 (10%)
+    private var _barSpace = CGFloat(0.1)
+    
+    /// the space that is left out on the left and right side of each candle,
+    /// **default**: 0.1 (10%), max 0.45, min 0.0
+    open var barSpace: CGFloat
+    {
+        get
+        {
+            return _barSpace
+        }
+        set
+        {
+            _barSpace = newValue.clamped(to: 0...0.45)
+        }
+    }
+    
+    /// should the candle bars show?
+    /// when false, only "ticks" will show
+    ///
+    /// **default**: true
+    open var showCandleBar: Bool = true
+    
+    /// the width of the candle-shadow-line in pixels.
+    ///
+    /// **default**: 1.5
+    open var shadowWidth = CGFloat(1.5)
+    
+    /// the color of the shadow line
+    open var shadowColor: NSUIColor?
+    
+    /// use candle color for the shadow
+    open var shadowColorSameAsCandle = false
+    
+    /// Is the shadow color same as the candle color?
+    open var isShadowColorSameAsCandle: Bool { return shadowColorSameAsCandle }
+    
+    /// color for open == close
+    open var neutralColor: NSUIColor?
+    
+    /// color for open > close
+    open var increasingColor: NSUIColor?
+    
+    /// color for open < close
+    open var decreasingColor: NSUIColor?
+    
+    /// Are increasing values drawn as filled?
+    /// increasing candlesticks are traditionally hollow
+    open var increasingFilled = false
+    
+    /// Are increasing values drawn as filled?
+    open var isIncreasingFilled: Bool { return increasingFilled }
+    
+    /// Are decreasing values drawn as filled?
+    /// descreasing candlesticks are traditionally filled
+    open var decreasingFilled = true
+    
+    /// Are decreasing values drawn as filled?
+    open var isDecreasingFilled: Bool { return decreasingFilled }
+}

+ 610 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartData.swift

@@ -0,0 +1,610 @@
+//
+//  ChartData.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+open class ChartData: NSObject
+{
+    internal var _yMax: Double = -Double.greatestFiniteMagnitude
+    internal var _yMin: Double = Double.greatestFiniteMagnitude
+    internal var _xMax: Double = -Double.greatestFiniteMagnitude
+    internal var _xMin: Double = Double.greatestFiniteMagnitude
+    internal var _leftAxisMax: Double = -Double.greatestFiniteMagnitude
+    internal var _leftAxisMin: Double = Double.greatestFiniteMagnitude
+    internal var _rightAxisMax: Double = -Double.greatestFiniteMagnitude
+    internal var _rightAxisMin: Double = Double.greatestFiniteMagnitude
+    
+    internal var _dataSets = [IChartDataSet]()
+    
+    public override init()
+    {
+        super.init()
+        
+        _dataSets = [IChartDataSet]()
+    }
+    
+    @objc public init(dataSets: [IChartDataSet]?)
+    {
+        super.init()
+        
+        _dataSets = dataSets ?? [IChartDataSet]()
+        
+        self.initialize(dataSets: _dataSets)
+    }
+    
+    @objc public convenience init(dataSet: IChartDataSet?)
+    {
+        self.init(dataSets: dataSet === nil ? nil : [dataSet!])
+    }
+    
+    internal func initialize(dataSets: [IChartDataSet])
+    {
+        notifyDataChanged()
+    }
+    
+    /// Call this method to let the ChartData know that the underlying data has changed.
+    /// Calling this performs all necessary recalculations needed when the contained data has changed.
+    @objc open func notifyDataChanged()
+    {
+        calcMinMax()
+    }
+    
+    @objc open func calcMinMaxY(fromX: Double, toX: Double)
+    {
+        _dataSets.forEach { $0.calcMinMaxY(fromX: fromX, toX: toX) }
+        // apply the new data
+        calcMinMax()
+    }
+    
+    /// calc minimum and maximum y value over all datasets
+    @objc open func calcMinMax()
+    {
+        _yMax = -Double.greatestFiniteMagnitude
+        _yMin = Double.greatestFiniteMagnitude
+        _xMax = -Double.greatestFiniteMagnitude
+        _xMin = Double.greatestFiniteMagnitude
+        
+        _dataSets.forEach { calcMinMax(dataSet: $0) }
+        
+        _leftAxisMax = -Double.greatestFiniteMagnitude
+        _leftAxisMin = Double.greatestFiniteMagnitude
+        _rightAxisMax = -Double.greatestFiniteMagnitude
+        _rightAxisMin = Double.greatestFiniteMagnitude
+        
+        // left axis
+        let firstLeft = getFirstLeft(dataSets: dataSets)
+        
+        if firstLeft !== nil
+        {
+            _leftAxisMax = firstLeft!.yMax
+            _leftAxisMin = firstLeft!.yMin
+            
+            for dataSet in _dataSets
+            {
+                if dataSet.axisDependency == .left
+                {
+                    if dataSet.yMin < _leftAxisMin
+                    {
+                        _leftAxisMin = dataSet.yMin
+                    }
+                    
+                    if dataSet.yMax > _leftAxisMax
+                    {
+                        _leftAxisMax = dataSet.yMax
+                    }
+                }
+            }
+        }
+        
+        // right axis
+        let firstRight = getFirstRight(dataSets: dataSets)
+        
+        if firstRight !== nil
+        {
+            _rightAxisMax = firstRight!.yMax
+            _rightAxisMin = firstRight!.yMin
+            
+            for dataSet in _dataSets
+            {
+                if dataSet.axisDependency == .right
+                {
+                    if dataSet.yMin < _rightAxisMin
+                    {
+                        _rightAxisMin = dataSet.yMin
+                    }
+                    
+                    if dataSet.yMax > _rightAxisMax
+                    {
+                        _rightAxisMax = dataSet.yMax
+                    }
+                }
+            }
+        }
+    }
+    
+    /// Adjusts the current minimum and maximum values based on the provided Entry object.
+    @objc open func calcMinMax(entry e: ChartDataEntry, axis: YAxis.AxisDependency)
+    {
+        if _yMax < e.y
+        {
+            _yMax = e.y
+        }
+        
+        if _yMin > e.y
+        {
+            _yMin = e.y
+        }
+        
+        if _xMax < e.x
+        {
+            _xMax = e.x
+        }
+        
+        if _xMin > e.x
+        {
+            _xMin = e.x
+        }
+        
+        if axis == .left
+        {
+            if _leftAxisMax < e.y
+            {
+                _leftAxisMax = e.y
+            }
+            
+            if _leftAxisMin > e.y
+            {
+                _leftAxisMin = e.y
+            }
+        }
+        else
+        {
+            if _rightAxisMax < e.y
+            {
+                _rightAxisMax = e.y
+            }
+            
+            if _rightAxisMin > e.y
+            {
+                _rightAxisMin = e.y
+            }
+        }
+    }
+    
+    /// Adjusts the minimum and maximum values based on the given DataSet.
+    @objc open func calcMinMax(dataSet d: IChartDataSet)
+    {
+        if _yMax < d.yMax
+        {
+            _yMax = d.yMax
+        }
+        
+        if _yMin > d.yMin
+        {
+            _yMin = d.yMin
+        }
+        
+        if _xMax < d.xMax
+        {
+            _xMax = d.xMax
+        }
+        
+        if _xMin > d.xMin
+        {
+            _xMin = d.xMin
+        }
+        
+        if d.axisDependency == .left
+        {
+            if _leftAxisMax < d.yMax
+            {
+                _leftAxisMax = d.yMax
+            }
+            
+            if _leftAxisMin > d.yMin
+            {
+                _leftAxisMin = d.yMin
+            }
+        }
+        else
+        {
+            if _rightAxisMax < d.yMax
+            {
+                _rightAxisMax = d.yMax
+            }
+            
+            if _rightAxisMin > d.yMin
+            {
+                _rightAxisMin = d.yMin
+            }
+        }
+    }
+    
+    /// The number of LineDataSets this object contains
+    @objc open var dataSetCount: Int
+    {
+        return _dataSets.count
+    }
+    
+    /// The smallest y-value the data object contains.
+    @objc open var yMin: Double
+    {
+        return _yMin
+    }
+    
+    @nonobjc
+    open func getYMin() -> Double
+    {
+        return _yMin
+    }
+    
+    @objc open func getYMin(axis: YAxis.AxisDependency) -> Double
+    {
+        if axis == .left
+        {
+            if _leftAxisMin == Double.greatestFiniteMagnitude
+            {
+                return _rightAxisMin
+            }
+            else
+            {
+                return _leftAxisMin
+            }
+        }
+        else
+        {
+            if _rightAxisMin == Double.greatestFiniteMagnitude
+            {
+                return _leftAxisMin
+            }
+            else
+            {
+                return _rightAxisMin
+            }
+        }
+    }
+    
+    /// The greatest y-value the data object contains.
+    @objc open var yMax: Double
+    {
+        return _yMax
+    }
+    
+    @nonobjc
+    open func getYMax() -> Double
+    {
+        return _yMax
+    }
+    
+    @objc open func getYMax(axis: YAxis.AxisDependency) -> Double
+    {
+        if axis == .left
+        {
+            if _leftAxisMax == -Double.greatestFiniteMagnitude
+            {
+                return _rightAxisMax
+            }
+            else
+            {
+                return _leftAxisMax
+            }
+        }
+        else
+        {
+            if _rightAxisMax == -Double.greatestFiniteMagnitude
+            {
+                return _leftAxisMax
+            }
+            else
+            {
+                return _rightAxisMax
+            }
+        }
+    }
+    
+    /// The minimum x-value the data object contains.
+    @objc open var xMin: Double
+    {
+        return _xMin
+    }
+    /// The maximum x-value the data object contains.
+    @objc open var xMax: Double
+    {
+        return _xMax
+    }
+    
+    /// All DataSet objects this ChartData object holds.
+    @objc open var dataSets: [IChartDataSet]
+    {
+        get
+        {
+            return _dataSets
+        }
+        set
+        {
+            _dataSets = newValue
+            notifyDataChanged()
+        }
+    }
+    
+    /// Retrieve the index of a ChartDataSet with a specific label from the ChartData. Search can be case sensitive or not.
+    /// 
+    /// **IMPORTANT: This method does calculations at runtime, do not over-use in performance critical situations.**
+    ///
+    /// - Parameters:
+    ///   - dataSets: the DataSet array to search
+    ///   - type:
+    ///   - ignorecase: if true, the search is not case-sensitive
+    /// - Returns: The index of the DataSet Object with the given label. Sensitive or not.
+    internal func getDataSetIndexByLabel(_ label: String, ignorecase: Bool) -> Int
+    {
+        // TODO: Return nil instead of -1
+        if ignorecase
+        {
+            return dataSets.firstIndex { $0.label?.caseInsensitiveCompare(label) == .orderedSame }
+                ?? -1
+        }
+        else
+        {
+            return dataSets.firstIndex { $0.label == label }
+                ?? -1
+        }
+    }
+
+    /// Get the Entry for a corresponding highlight object
+    ///
+    /// - Parameters:
+    ///   - highlight:
+    /// - Returns: The entry that is highlighted
+    @objc open func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry?
+    {
+        if highlight.dataSetIndex >= dataSets.count
+        {
+            return nil
+        }
+        else
+        {
+            return dataSets[highlight.dataSetIndex].entryForXValue(highlight.x, closestToY: highlight.y)
+        }
+    }
+    
+    /// **IMPORTANT: This method does calculations at runtime. Use with care in performance critical situations.**
+    ///
+    /// - Parameters:
+    ///   - label:
+    ///   - ignorecase:
+    /// - Returns: The DataSet Object with the given label. Sensitive or not.
+    @objc open func getDataSetByLabel(_ label: String, ignorecase: Bool) -> IChartDataSet?
+    {
+        let index = getDataSetIndexByLabel(label, ignorecase: ignorecase)
+        
+        if index < 0 || index >= _dataSets.count
+        {
+            return nil
+        }
+        else
+        {
+            return _dataSets[index]
+        }
+    }
+    
+    @objc open func getDataSetByIndex(_ index: Int) -> IChartDataSet!
+    {
+        if index < 0 || index >= _dataSets.count
+        {
+            return nil
+        }
+        
+        return _dataSets[index]
+    }
+    
+    @objc open func addDataSet(_ dataSet: IChartDataSet!)
+    {
+        calcMinMax(dataSet: dataSet)
+        
+        _dataSets.append(dataSet)
+    }
+    
+    /// Removes the given DataSet from this data object.
+    /// Also recalculates all minimum and maximum values.
+    ///
+    /// - Returns: `true` if a DataSet was removed, `false` ifno DataSet could be removed.
+    @objc @discardableResult open func removeDataSet(_ dataSet: IChartDataSet) -> Bool
+    {
+        guard let i = _dataSets.firstIndex(where: { $0 === dataSet }) else { return false }
+        return removeDataSetByIndex(i)
+    }
+    
+    /// Removes the DataSet at the given index in the DataSet array from the data object. 
+    /// Also recalculates all minimum and maximum values. 
+    ///
+    /// - Returns: `true` if a DataSet was removed, `false` ifno DataSet could be removed.
+    @objc @discardableResult open func removeDataSetByIndex(_ index: Int) -> Bool
+    {
+        if index >= _dataSets.count || index < 0
+        {
+            return false
+        }
+        
+        _dataSets.remove(at: index)
+        
+        calcMinMax()
+        
+        return true
+    }
+    
+    /// Adds an Entry to the DataSet at the specified index. Entries are added to the end of the list.
+    @objc open func addEntry(_ e: ChartDataEntry, dataSetIndex: Int)
+    {
+        if _dataSets.count > dataSetIndex && dataSetIndex >= 0
+        {
+            let set = _dataSets[dataSetIndex]
+            
+            if !set.addEntry(e) { return }
+            
+            calcMinMax(entry: e, axis: set.axisDependency)
+        }
+        else
+        {
+            print("ChartData.addEntry() - Cannot add Entry because dataSetIndex too high or too low.", terminator: "\n")
+        }
+    }
+    
+    /// Removes the given Entry object from the DataSet at the specified index.
+    @objc @discardableResult open func removeEntry(_ entry: ChartDataEntry, dataSetIndex: Int) -> Bool
+    {
+        // entry outofbounds
+        if dataSetIndex >= _dataSets.count
+        {
+            return false
+        }
+        
+        // remove the entry from the dataset
+        let removed = _dataSets[dataSetIndex].removeEntry(entry)
+        
+        if removed
+        {
+            calcMinMax()
+        }
+        
+        return removed
+    }
+    
+    /// Removes the Entry object closest to the given xIndex from the ChartDataSet at the
+    /// specified index. 
+    ///
+    /// - Returns: `true` if an entry was removed, `false` ifno Entry was found that meets the specified requirements.
+    @objc @discardableResult open func removeEntry(xValue: Double, dataSetIndex: Int) -> Bool
+    {
+        if dataSetIndex >= _dataSets.count
+        {
+            return false
+        }
+        
+        if let entry = _dataSets[dataSetIndex].entryForXValue(xValue, closestToY: Double.nan)
+        {
+            return removeEntry(entry, dataSetIndex: dataSetIndex)
+        }
+        
+        return false
+    }
+    
+    /// - Returns: The DataSet that contains the provided Entry, or null, if no DataSet contains this entry.
+    @objc open func getDataSetForEntry(_ e: ChartDataEntry) -> IChartDataSet?
+    {
+        return _dataSets.first { $0.entryForXValue(e.x, closestToY: e.y) === e }
+    }
+
+    /// - Returns: The index of the provided DataSet in the DataSet array of this data object, or -1 if it does not exist.
+    @objc open func indexOfDataSet(_ dataSet: IChartDataSet) -> Int
+    {
+        // TODO: Return nil instead of -1
+        return _dataSets.firstIndex { $0 === dataSet } ?? -1
+    }
+    
+    /// - Returns: The first DataSet from the datasets-array that has it's dependency on the left axis. Returns null if no DataSet with left dependency could be found.
+    @objc open func getFirstLeft(dataSets: [IChartDataSet]) -> IChartDataSet?
+    {
+        return dataSets.first { $0.axisDependency == .left }
+    }
+    
+    /// - Returns: The first DataSet from the datasets-array that has it's dependency on the right axis. Returns null if no DataSet with right dependency could be found.
+    @objc open func getFirstRight(dataSets: [IChartDataSet]) -> IChartDataSet?
+    {
+        return dataSets.first { $0.axisDependency == .right }
+    }
+    
+    /// - Returns: All colors used across all DataSet objects this object represents.
+    @objc open func getColors() -> [NSUIColor]?
+    {
+        // TODO: Don't return nil
+        return _dataSets.flatMap { $0.colors }
+    }
+    
+    /// Sets a custom IValueFormatter for all DataSets this data object contains.
+    @objc open func setValueFormatter(_ formatter: IValueFormatter)
+    {
+        dataSets.forEach { $0.valueFormatter = formatter }
+    }
+    
+    /// Sets the color of the value-text (color in which the value-labels are drawn) for all DataSets this data object contains.
+    @objc open func setValueTextColor(_ color: NSUIColor)
+    {
+        dataSets.forEach { $0.valueTextColor = color }
+    }
+    
+    /// Sets the font for all value-labels for all DataSets this data object contains.
+    @objc open func setValueFont(_ font: NSUIFont)
+    {
+        dataSets.forEach { $0.valueFont = font }
+    }
+
+    /// Enables / disables drawing values (value-text) for all DataSets this data object contains.
+    @objc open func setDrawValues(_ enabled: Bool)
+    {
+        dataSets.forEach { $0.drawValuesEnabled = enabled }
+    }
+    
+    /// Enables / disables highlighting values for all DataSets this data object contains.
+    /// If set to true, this means that values can be highlighted programmatically or by touch gesture.
+    @objc open var highlightEnabled: Bool
+    {
+        get { return dataSets.allSatisfy { $0.highlightEnabled } }
+        set { dataSets.forEach { $0.highlightEnabled = newValue } }
+    }
+    
+    /// if true, value highlightning is enabled
+    @objc open var isHighlightEnabled: Bool { return highlightEnabled }
+    
+    /// Clears this data object from all DataSets and removes all Entries.
+    /// Don't forget to invalidate the chart after this.
+    @objc open func clearValues()
+    {
+        dataSets.removeAll(keepingCapacity: false)
+        notifyDataChanged()
+    }
+    
+    /// Checks if this data object contains the specified DataSet. 
+    ///
+    /// - Returns: `true` if so, `false` ifnot.
+    @objc open func contains(dataSet: IChartDataSet) -> Bool
+    {
+        return dataSets.contains { $0 === dataSet }
+    }
+    
+    /// The total entry count across all DataSet objects this data object contains.
+    @objc open var entryCount: Int
+    {
+        return _dataSets.reduce(0) { $0 + $1.entryCount }
+    }
+
+    /// The DataSet object with the maximum number of entries or null if there are no DataSets.
+    @objc open var maxEntryCountSet: IChartDataSet?
+    {
+        return dataSets.max { $0.entryCount < $1.entryCount }
+    }
+
+    // MARK: - Accessibility
+
+    /// When the data entry labels are generated identifiers, set this property to prepend a string before each identifier
+    ///
+    /// For example, if a label is "#3", settings this property to "Item" allows it to be spoken as "Item #3"
+    @objc open var accessibilityEntryLabelPrefix: String?
+
+    /// When the data entry value requires a unit, use this property to append the string representation of the unit to the value
+    ///
+    /// For example, if a value is "44.1", setting this property to "m" allows it to be spoken as "44.1 m"
+    @objc open var accessibilityEntryLabelSuffix: String?
+
+    /// If the data entry value is a count, set this to true to allow plurals and other grammatical changes
+    /// **default**: false
+    @objc open var accessibilityEntryLabelSuffixIsCount: Bool = false
+}

+ 110 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntry.swift

@@ -0,0 +1,110 @@
+//
+//  ChartDataEntry.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+open class ChartDataEntry: ChartDataEntryBase, NSCopying
+{
+    /// the x value
+    @objc open var x = 0.0
+    
+    public required init()
+    {
+        super.init()
+    }
+    
+    /// An Entry represents one single entry in the chart.
+    ///
+    /// - Parameters:
+    ///   - x: the x value
+    ///   - y: the y value (the actual value of the entry)
+    @objc public init(x: Double, y: Double)
+    {
+        super.init(y: y)
+        self.x = x
+    }
+    
+    /// An Entry represents one single entry in the chart.
+    ///
+    /// - Parameters:
+    ///   - x: the x value
+    ///   - y: the y value (the actual value of the entry)
+    ///   - data: Space for additional data this Entry represents.
+    
+    @objc public convenience init(x: Double, y: Double, data: Any?)
+    {
+        self.init(x: x, y: y)
+        self.data = data
+    }
+    
+    /// An Entry represents one single entry in the chart.
+    ///
+    /// - Parameters:
+    ///   - x: the x value
+    ///   - y: the y value (the actual value of the entry)
+    ///   - icon: icon image
+    
+    @objc public convenience init(x: Double, y: Double, icon: NSUIImage?)
+    {
+        self.init(x: x, y: y)
+        self.icon = icon
+    }
+    
+    /// An Entry represents one single entry in the chart.
+    ///
+    /// - Parameters:
+    ///   - x: the x value
+    ///   - y: the y value (the actual value of the entry)
+    ///   - icon: icon image
+    ///   - data: Space for additional data this Entry represents.
+    
+    @objc public convenience init(x: Double, y: Double, icon: NSUIImage?, data: Any?)
+    {
+        self.init(x: x, y: y)
+        self.icon = icon
+        self.data = data
+    }
+        
+    // MARK: NSObject
+    
+    open override var description: String
+    {
+        return "ChartDataEntry, x: \(x), y \(y)"
+    }
+    
+    // MARK: NSCopying
+    
+    open func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = type(of: self).init()
+        
+        copy.x = x
+        copy.y = y
+        copy.data = data
+        
+        return copy
+    }
+}
+
+// MARK: Equatable
+extension ChartDataEntry/*: Equatable*/ {
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let object = object as? ChartDataEntry else { return false }
+
+        if self === object
+        {
+            return true
+        }
+
+        return y == object.y
+            && x == object.x
+    }
+}

+ 96 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntryBase.swift

@@ -0,0 +1,96 @@
+//
+//  ChartDataEntryBase.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+open class ChartDataEntryBase: NSObject
+{
+    /// the y value
+    @objc open var y = 0.0
+    
+    /// optional spot for additional data this Entry represents
+    @objc open var data: Any?
+    
+    /// optional icon image
+    @objc open var icon: NSUIImage?
+    
+    public override required init()
+    {
+        super.init()
+    }
+    
+    /// An Entry represents one single entry in the chart.
+    ///
+    /// - Parameters:
+    ///   - y: the y value (the actual value of the entry)
+    @objc public init(y: Double)
+    {
+        super.init()
+        
+        self.y = y
+    }
+    
+    /// - Parameters:
+    ///   - y: the y value (the actual value of the entry)
+    ///   - data: Space for additional data this Entry represents.
+    
+    @objc public convenience init(y: Double, data: Any?)
+    {
+        self.init(y: y)
+        
+        self.data = data
+    }
+    
+    /// - Parameters:
+    ///   - y: the y value (the actual value of the entry)
+    ///   - icon: icon image
+    
+    @objc public convenience init(y: Double, icon: NSUIImage?)
+    {
+        self.init(y: y)
+
+        self.icon = icon
+    }
+    
+    /// - Parameters:
+    ///   - y: the y value (the actual value of the entry)
+    ///   - icon: icon image
+    ///   - data: Space for additional data this Entry represents.
+    
+    @objc public convenience init(y: Double, icon: NSUIImage?, data: Any?)
+    {
+        self.init(y: y)
+
+        self.icon = icon
+        self.data = data
+    }
+
+    // MARK: NSObject
+    
+    open override var description: String
+    {
+        return "ChartDataEntryBase, y \(y)"
+    }
+}
+
+// MARK: Equatable
+extension ChartDataEntryBase/*: Equatable*/ {
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let object = object as? ChartDataEntryBase else { return false }
+
+        if self === object
+        {
+            return true
+        }
+
+        return y == object.y
+    }
+}

+ 574 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataSet.swift

@@ -0,0 +1,574 @@
+//
+//  ChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+/// Determines how to round DataSet index values for `ChartDataSet.entryIndex(x, rounding)` when an exact x-value is not found.
+@objc
+public enum ChartDataSetRounding: Int
+{
+    case up = 0
+    case down = 1
+    case closest = 2
+}
+
+/// The DataSet class represents one group or type of entries (Entry) in the Chart that belong together.
+/// It is designed to logically separate different groups of values inside the Chart (e.g. the values for a specific line in the LineChart, or the values of a specific group of bars in the BarChart).
+open class ChartDataSet: ChartBaseDataSet
+{
+    public required init()
+    {
+        entries = []
+
+        super.init()
+    }
+    
+    public override convenience init(label: String?)
+    {
+        self.init(entries: nil, label: label)
+    }
+    
+    @objc public init(entries: [ChartDataEntry]?, label: String?)
+    {
+        self.entries = entries ?? []
+
+        super.init(label: label)
+
+        self.calcMinMax()
+    }
+    
+    @objc public convenience init(entries: [ChartDataEntry]?)
+    {
+        self.init(entries: entries, label: "DataSet")
+    }
+    
+    // MARK: - Data functions and accessors
+
+    /// - Note: Calls `notifyDataSetChanged()` after setting a new value.
+    /// - Returns: The array of y-values that this DataSet represents.
+    /// the entries that this dataset represents / holds together
+    @available(*, unavailable, renamed: "entries")
+    @objc
+    open var values: [ChartDataEntry] { return entries }
+
+    @objc
+    open private(set) var entries: [ChartDataEntry]
+
+    /// Used to replace all entries of a data set while retaining styling properties.
+    /// This is a separate method from a setter on `entries` to encourage usage
+    /// of `Collection` conformances.
+    ///
+    /// - Parameter entries: new entries to replace existing entries in the dataset
+    @objc
+    public func replaceEntries(_ entries: [ChartDataEntry]) {
+        self.entries = entries
+        notifyDataSetChanged()
+    }
+
+    /// maximum y-value in the value array
+    internal var _yMax: Double = -Double.greatestFiniteMagnitude
+    
+    /// minimum y-value in the value array
+    internal var _yMin: Double = Double.greatestFiniteMagnitude
+    
+    /// maximum x-value in the value array
+    internal var _xMax: Double = -Double.greatestFiniteMagnitude
+    
+    /// minimum x-value in the value array
+    internal var _xMin: Double = Double.greatestFiniteMagnitude
+    
+    open override func calcMinMax()
+    {
+        _yMax = -Double.greatestFiniteMagnitude
+        _yMin = Double.greatestFiniteMagnitude
+        _xMax = -Double.greatestFiniteMagnitude
+        _xMin = Double.greatestFiniteMagnitude
+
+        guard !isEmpty else { return }
+
+        forEach(calcMinMax)
+    }
+    
+    open override func calcMinMaxY(fromX: Double, toX: Double)
+    {
+        _yMax = -Double.greatestFiniteMagnitude
+        _yMin = Double.greatestFiniteMagnitude
+
+        guard !isEmpty else { return }
+        
+        let indexFrom = entryIndex(x: fromX, closestToY: Double.nan, rounding: .down)
+        let indexTo = entryIndex(x: toX, closestToY: Double.nan, rounding: .up)
+        
+        guard !(indexTo < indexFrom) else { return }
+        // only recalculate y
+        self[indexFrom...indexTo].forEach(calcMinMaxY)
+    }
+    
+    @objc open func calcMinMaxX(entry e: ChartDataEntry)
+    {
+        if e.x < _xMin
+        {
+            _xMin = e.x
+        }
+        if e.x > _xMax
+        {
+            _xMax = e.x
+        }
+    }
+    
+    @objc open func calcMinMaxY(entry e: ChartDataEntry)
+    {
+        if e.y < _yMin
+        {
+            _yMin = e.y
+        }
+        if e.y > _yMax
+        {
+            _yMax = e.y
+        }
+    }
+    
+    /// Updates the min and max x and y value of this DataSet based on the given Entry.
+    ///
+    /// - Parameters:
+    ///   - e:
+    internal func calcMinMax(entry e: ChartDataEntry)
+    {
+        calcMinMaxX(entry: e)
+        calcMinMaxY(entry: e)
+    }
+    
+    /// The minimum y-value this DataSet holds
+    open override var yMin: Double { return _yMin }
+    
+    /// The maximum y-value this DataSet holds
+    open override var yMax: Double { return _yMax }
+    
+    /// The minimum x-value this DataSet holds
+    open override var xMin: Double { return _xMin }
+    
+    /// The maximum x-value this DataSet holds
+    open override var xMax: Double { return _xMax }
+    
+    /// The number of y-values this DataSet represents
+    @available(*, deprecated, message: "Use `count` instead")
+    open override var entryCount: Int { return count }
+    
+    /// - Throws: out of bounds
+    /// if `i` is out of bounds, it may throw an out-of-bounds exception
+    /// - Returns: The entry object found at the given index (not x-value!)
+    @available(*, deprecated, message: "Use `subscript(index:)` instead.")
+    open override func entryForIndex(_ i: Int) -> ChartDataEntry?
+    {
+        guard i >= startIndex, i < endIndex else {
+            return nil
+        }
+        return self[i]
+    }
+    
+    /// - Parameters:
+    ///   - xValue: the x-value
+    ///   - closestToY: If there are multiple y-values for the specified x-value,
+    ///   - rounding: determine whether to round up/down/closest if there is no Entry matching the provided x-value
+    /// - Returns: The first Entry object found at the given x-value with binary search.
+    /// If the no Entry at the specified x-value is found, this method returns the Entry at the closest x-value according to the rounding.
+    /// nil if no Entry object at that x-value.
+    open override func entryForXValue(
+        _ xValue: Double,
+        closestToY yValue: Double,
+        rounding: ChartDataSetRounding) -> ChartDataEntry?
+    {
+        let index = entryIndex(x: xValue, closestToY: yValue, rounding: rounding)
+        if index > -1
+        {
+            return self[index]
+        }
+        return nil
+    }
+    
+    /// - Parameters:
+    ///   - xValue: the x-value
+    ///   - closestToY: If there are multiple y-values for the specified x-value,
+    /// - Returns: The first Entry object found at the given x-value with binary search.
+    /// If the no Entry at the specified x-value is found, this method returns the Entry at the closest x-value.
+    /// nil if no Entry object at that x-value.
+    open override func entryForXValue(
+        _ xValue: Double,
+        closestToY yValue: Double) -> ChartDataEntry?
+    {
+        return entryForXValue(xValue, closestToY: yValue, rounding: .closest)
+    }
+    
+    /// - Returns: All Entry objects found at the given xIndex with binary search.
+    /// An empty array if no Entry object at that index.
+    open override func entriesForXValue(_ xValue: Double) -> [ChartDataEntry]
+    {
+        var entries = [ChartDataEntry]()
+        
+        var low = startIndex
+        var high = endIndex - 1
+        
+        while low <= high
+        {
+            var m = (high + low) / 2
+            var entry = self[m]
+            
+            // if we have a match
+            if xValue == entry.x
+            {
+                while m > 0 && self[m - 1].x == xValue
+                {
+                    m -= 1
+                }
+                
+                high = endIndex
+                
+                // loop over all "equal" entries
+                while m < high
+                {
+                    entry = self[m]
+                    if entry.x == xValue
+                    {
+                        entries.append(entry)
+                    }
+                    else
+                    {
+                        break
+                    }
+                    
+                    m += 1
+                }
+                
+                break
+            }
+            else
+            {
+                if xValue > entry.x
+                {
+                    low = m + 1
+                }
+                else
+                {
+                    high = m - 1
+                }
+            }
+        }
+        
+        return entries
+    }
+    
+    /// - Parameters:
+    ///   - xValue: x-value of the entry to search for
+    ///   - closestToY: If there are multiple y-values for the specified x-value,
+    ///   - rounding: Rounding method if exact value was not found
+    /// - Returns: The array-index of the specified entry.
+    /// If the no Entry at the specified x-value is found, this method returns the index of the Entry at the closest x-value according to the rounding.
+    open override func entryIndex(
+        x xValue: Double,
+        closestToY yValue: Double,
+        rounding: ChartDataSetRounding) -> Int
+    {
+        var low = startIndex
+        var high = endIndex - 1
+        var closest = high
+        
+        while low < high
+        {
+            let m = (low + high) / 2
+            
+            let d1 = self[m].x - xValue
+            let d2 = self[m + 1].x - xValue
+            let ad1 = abs(d1), ad2 = abs(d2)
+            
+            if ad2 < ad1
+            {
+                // [m + 1] is closer to xValue
+                // Search in an higher place
+                low = m + 1
+            }
+            else if ad1 < ad2
+            {
+                // [m] is closer to xValue
+                // Search in a lower place
+                high = m
+            }
+            else
+            {
+                // We have multiple sequential x-value with same distance
+                
+                if d1 >= 0.0
+                {
+                    // Search in a lower place
+                    high = m
+                }
+                else if d1 < 0.0
+                {
+                    // Search in an higher place
+                    low = m + 1
+                }
+            }
+            
+            closest = high
+        }
+        
+        if closest != -1
+        {
+            let closestXValue = self[closest].x
+            
+            if rounding == .up
+            {
+                // If rounding up, and found x-value is lower than specified x, and we can go upper...
+                if closestXValue < xValue && closest < endIndex - 1
+                {
+                    closest += 1
+                }
+            }
+            else if rounding == .down
+            {
+                // If rounding down, and found x-value is upper than specified x, and we can go lower...
+                if closestXValue > xValue && closest > 0
+                {
+                    closest -= 1
+                }
+            }
+            
+            // Search by closest to y-value
+            if !yValue.isNaN
+            {
+                while closest > 0 && self[closest - 1].x == closestXValue
+                {
+                    closest -= 1
+                }
+                
+                var closestYValue = self[closest].y
+                var closestYIndex = closest
+                
+                while true
+                {
+                    closest += 1
+                    if closest >= endIndex { break }
+                    
+                    let value = self[closest]
+                    
+                    if value.x != closestXValue { break }
+                    if abs(value.y - yValue) <= abs(closestYValue - yValue)
+                    {
+                        closestYValue = yValue
+                        closestYIndex = closest
+                    }
+                }
+                
+                closest = closestYIndex
+            }
+        }
+        
+        return closest
+    }
+    
+    /// - Parameters:
+    ///   - e: the entry to search for
+    /// - Returns: The array-index of the specified entry
+    @available(*, deprecated, message: "Use `firstIndex(of:)` or `lastIndex(of:)`")
+    open override func entryIndex(entry e: ChartDataEntry) -> Int
+    {
+        return firstIndex(of: e) ?? -1
+    }
+    
+    /// Adds an Entry to the DataSet dynamically.
+    /// Entries are added to the end of the list.
+    /// This will also recalculate the current minimum and maximum values of the DataSet and the value-sum.
+    ///
+    /// - Parameters:
+    ///   - e: the entry to add
+    /// - Returns: True
+    @available(*, deprecated, message: "Use `append(_:)` instead")
+    open override func addEntry(_ e: ChartDataEntry) -> Bool
+    {
+        append(e)
+        return true
+    }
+    
+    /// Adds an Entry to the DataSet dynamically.
+    /// Entries are added to their appropriate index respective to it's x-index.
+    /// This will also recalculate the current minimum and maximum values of the DataSet and the value-sum.
+    ///
+    /// - Parameters:
+    ///   - e: the entry to add
+    /// - Returns: True
+    open override func addEntryOrdered(_ e: ChartDataEntry) -> Bool
+    {
+        calcMinMax(entry: e)
+        
+        if let last = last, last.x > e.x
+        {
+            var closestIndex = entryIndex(x: e.x, closestToY: e.y, rounding: .up)
+            while self[closestIndex].x < e.x
+            {
+                closestIndex += 1
+            }
+            entries.insert(e, at: closestIndex)
+        }
+        else
+        {
+            append(e)
+        }
+        
+        return true
+    }
+    
+    @available(*, renamed: "remove(_:)")
+    open override func removeEntry(_ entry: ChartDataEntry) -> Bool
+    {
+        return remove(entry)
+    }
+
+    /// Removes an Entry from the DataSet dynamically.
+    /// This will also recalculate the current minimum and maximum values of the DataSet and the value-sum.
+    ///
+    /// - Parameters:
+    ///   - entry: the entry to remove
+    /// - Returns: `true` if the entry was removed successfully, else if the entry does not exist
+    open func remove(_ entry: ChartDataEntry) -> Bool
+    {
+        guard let index = firstIndex(of: entry) else { return false }
+        _ = remove(at: index)
+        return true
+    }
+
+    /// Removes the first Entry (at index 0) of this DataSet from the entries array.
+    ///
+    /// - Returns: `true` if successful, `false` if not.
+    @available(*, deprecated, message: "Use `func removeFirst() -> ChartDataEntry` instead.")
+    open override func removeFirst() -> Bool
+    {
+        let entry: ChartDataEntry? = isEmpty ? nil : removeFirst()
+        return entry != nil
+    }
+    
+    /// Removes the last Entry (at index size-1) of this DataSet from the entries array.
+    ///
+    /// - Returns: `true` if successful, `false` if not.
+    @available(*, deprecated, message: "Use `func removeLast() -> ChartDataEntry` instead.")
+    open override func removeLast() -> Bool
+    {
+        let entry: ChartDataEntry? = isEmpty ? nil : removeLast()
+        return entry != nil
+    }
+
+    /// Removes all values from this DataSet and recalculates min and max value.
+    @available(*, deprecated, message: "Use `removeAll(keepingCapacity:)` instead.")
+    open override func clear()
+    {
+        removeAll(keepingCapacity: true)
+    }
+    
+    // MARK: - Data functions and accessors
+
+    // MARK: - NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! ChartDataSet
+        
+        copy.entries = entries
+        copy._yMax = _yMax
+        copy._yMin = _yMin
+        copy._xMax = _xMax
+        copy._xMin = _xMin
+
+        return copy
+    }
+}
+
+// MARK: MutableCollection
+extension ChartDataSet: MutableCollection {
+    public typealias Index = Int
+    public typealias Element = ChartDataEntry
+
+    public var startIndex: Index {
+        return entries.startIndex
+    }
+
+    public var endIndex: Index {
+        return entries.endIndex
+    }
+
+    public func index(after: Index) -> Index {
+        return entries.index(after: after)
+    }
+
+    @objc
+    public subscript(position: Index) -> Element {
+        get {
+            // This is intentionally not a safe subscript to mirror
+            // the behaviour of the built in Swift Collection Types
+            return entries[position]
+        }
+        set {
+            calcMinMax(entry: newValue)
+            entries[position] = newValue
+        }
+    }
+}
+
+// MARK: RandomAccessCollection
+extension ChartDataSet: RandomAccessCollection {
+    public func index(before: Index) -> Index {
+        return entries.index(before: before)
+    }
+}
+
+// MARK: RangeReplaceableCollection
+extension ChartDataSet: RangeReplaceableCollection {
+    public func append(_ newElement: Element) {
+        calcMinMax(entry: newElement)
+        entries.append(newElement)
+    }
+
+    public func remove(at position: Index) -> Element {
+        let element = entries.remove(at: position)
+        notifyDataSetChanged()
+        return element
+    }
+
+    public func removeFirst() -> Element {
+        let element = entries.removeFirst()
+        notifyDataSetChanged()
+        return element
+    }
+
+    public func removeFirst(_ n: Int) {
+        entries.removeFirst(n)
+        notifyDataSetChanged()
+    }
+
+    public func removeLast() -> Element {
+        let element = entries.removeLast()
+        notifyDataSetChanged()
+        return element
+    }
+
+    public func removeLast(_ n: Int) {
+        entries.removeLast(n)
+        notifyDataSetChanged()
+    }
+
+    public func removeSubrange<R>(_ bounds: R) where R : RangeExpression, Index == R.Bound {
+        entries.removeSubrange(bounds)
+        notifyDataSetChanged()
+    }
+
+    @objc
+    public func removeAll(keepingCapacity keepCapacity: Bool) {
+        entries.removeAll(keepingCapacity: keepCapacity)
+        notifyDataSetChanged()
+    }
+}

+ 301 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/CombinedChartData.swift

@@ -0,0 +1,301 @@
+//
+//  CombinedChartData.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+open class CombinedChartData: BarLineScatterCandleBubbleChartData
+{
+    private var _lineData: LineChartData!
+    private var _barData: BarChartData!
+    private var _scatterData: ScatterChartData!
+    private var _candleData: CandleChartData!
+    private var _bubbleData: BubbleChartData!
+    
+    public override init()
+    {
+        super.init()
+    }
+    
+    public override init(dataSets: [IChartDataSet]?)
+    {
+        super.init(dataSets: dataSets)
+    }
+    
+    @objc open var lineData: LineChartData!
+    {
+        get
+        {
+            return _lineData
+        }
+        set
+        {
+            _lineData = newValue
+            notifyDataChanged()
+        }
+    }
+    
+    @objc open var barData: BarChartData!
+    {
+        get
+        {
+            return _barData
+        }
+        set
+        {
+            _barData = newValue
+            notifyDataChanged()
+        }
+    }
+    
+    @objc open var scatterData: ScatterChartData!
+    {
+        get
+        {
+            return _scatterData
+        }
+        set
+        {
+            _scatterData = newValue
+            notifyDataChanged()
+        }
+    }
+    
+    @objc open var candleData: CandleChartData!
+    {
+        get
+        {
+            return _candleData
+        }
+        set
+        {
+            _candleData = newValue
+            notifyDataChanged()
+        }
+    }
+    
+    @objc open var bubbleData: BubbleChartData!
+    {
+        get
+        {
+            return _bubbleData
+        }
+        set
+        {
+            _bubbleData = newValue
+            notifyDataChanged()
+        }
+    }
+    
+    open override func calcMinMax()
+    {
+        _dataSets.removeAll()
+        
+        _yMax = -Double.greatestFiniteMagnitude
+        _yMin = Double.greatestFiniteMagnitude
+        _xMax = -Double.greatestFiniteMagnitude
+        _xMin = Double.greatestFiniteMagnitude
+        
+        _leftAxisMax = -Double.greatestFiniteMagnitude
+        _leftAxisMin = Double.greatestFiniteMagnitude
+        _rightAxisMax = -Double.greatestFiniteMagnitude
+        _rightAxisMin = Double.greatestFiniteMagnitude
+        
+        let allData = self.allData
+        
+        for data in allData
+        {
+            data.calcMinMax()
+            
+            let sets = data.dataSets
+            _dataSets.append(contentsOf: sets)
+            
+            if data.yMax > _yMax
+            {
+                _yMax = data.yMax
+            }
+            
+            if data.yMin < _yMin
+            {
+                _yMin = data.yMin
+            }
+            
+            if data.xMax > _xMax
+            {
+                _xMax = data.xMax
+            }
+            
+            if data.xMin < _xMin
+            {
+                _xMin = data.xMin
+            }
+
+            for dataset in sets
+            {
+                if dataset.axisDependency == .left
+                {
+                    if dataset.yMax > _leftAxisMax
+                    {
+                        _leftAxisMax = dataset.yMax
+                    }
+                    if dataset.yMin < _leftAxisMin
+                    {
+                        _leftAxisMin = dataset.yMin
+                    }
+                }
+                else
+                {
+                    if dataset.yMax > _rightAxisMax
+                    {
+                        _rightAxisMax = dataset.yMax
+                    }
+                    if dataset.yMin < _rightAxisMin
+                    {
+                        _rightAxisMin = dataset.yMin
+                    }
+                }
+            }
+        }
+    }
+    
+    /// All data objects in row: line-bar-scatter-candle-bubble if not null.
+    @objc open var allData: [ChartData]
+    {
+        var data = [ChartData]()
+        
+        if lineData !== nil
+        {
+            data.append(lineData)
+        }
+        if barData !== nil
+        {
+            data.append(barData)
+        }
+        if scatterData !== nil
+        {
+            data.append(scatterData)
+        }
+        if candleData !== nil
+        {
+            data.append(candleData)
+        }
+        if bubbleData !== nil
+        {
+            data.append(bubbleData)
+        }
+        
+        return data
+    }
+    
+    @objc open func dataByIndex(_ index: Int) -> ChartData
+    {
+        return allData[index]
+    }
+    
+    open func dataIndex(_ data: ChartData) -> Int?
+    {
+        return allData.firstIndex(of: data)
+    }
+    
+    open override func removeDataSet(_ dataSet: IChartDataSet) -> Bool
+    {
+        return allData.contains { $0.removeDataSet(dataSet) }
+    }
+    
+    open override func removeDataSetByIndex(_ index: Int) -> Bool
+    {
+        print("removeDataSet(index) not supported for CombinedData", terminator: "\n")
+        return false
+    }
+    
+    open override func removeEntry(_ entry: ChartDataEntry, dataSetIndex: Int) -> Bool
+    {
+        print("removeEntry(entry, dataSetIndex) not supported for CombinedData", terminator: "\n")
+        return false
+    }
+    
+    open override func removeEntry(xValue: Double, dataSetIndex: Int) -> Bool
+    {
+        print("removeEntry(xValue, dataSetIndex) not supported for CombinedData", terminator: "\n")
+        return false
+    }
+    
+    open override func notifyDataChanged()
+    {
+        if _lineData !== nil
+        {
+            _lineData.notifyDataChanged()
+        }
+        if _barData !== nil
+        {
+            _barData.notifyDataChanged()
+        }
+        if _scatterData !== nil
+        {
+            _scatterData.notifyDataChanged()
+        }
+        if _candleData !== nil
+        {
+            _candleData.notifyDataChanged()
+        }
+        if _bubbleData !== nil
+        {
+            _bubbleData.notifyDataChanged()
+        }
+        
+        super.notifyDataChanged() // recalculate everything
+    }
+    
+    /// Get the Entry for a corresponding highlight object
+    ///
+    /// - Parameters:
+    ///   - highlight:
+    /// - Returns: The entry that is highlighted
+    open override func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry?
+    {
+        if highlight.dataIndex >= allData.count
+        {
+            return nil
+        }
+        
+        let data = dataByIndex(highlight.dataIndex)
+        
+        if highlight.dataSetIndex >= data.dataSetCount
+        {
+            return nil
+        }
+        
+        // The value of the highlighted entry could be NaN - if we are not interested in highlighting a specific value.
+        let entries = data.getDataSetByIndex(highlight.dataSetIndex).entriesForXValue(highlight.x)
+        return entries.first { $0.y == highlight.y || highlight.y.isNaN }
+    }
+    
+    /// Get dataset for highlight
+    ///
+    /// - Parameters:
+    ///   - highlight: current highlight
+    /// - Returns: dataset related to highlight
+    @objc open func getDataSetByHighlight(_ highlight: Highlight) -> IChartDataSet!
+    {  
+        if highlight.dataIndex >= allData.count
+        {
+            return nil
+        }
+        
+        let data = dataByIndex(highlight.dataIndex)
+        
+        if highlight.dataSetIndex >= data.dataSetCount
+        {
+            return nil
+        }
+        
+        return data.dataSets[highlight.dataSetIndex]
+    }
+}

+ 26 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartData.swift

@@ -0,0 +1,26 @@
+//
+//  LineChartData.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+/// Data object that encapsulates all data associated with a LineChart.
+open class LineChartData: ChartData
+{
+    public override init()
+    {
+        super.init()
+    }
+    
+    public override init(dataSets: [IChartDataSet]?)
+    {
+        super.init(dataSets: dataSets)
+    }
+}

+ 173 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartDataSet.swift

@@ -0,0 +1,173 @@
+//
+//  LineChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+open class LineChartDataSet: LineRadarChartDataSet, ILineChartDataSet
+{
+    @objc(LineChartMode)
+    public enum Mode: Int
+    {
+        case linear
+        case stepped
+        case cubicBezier
+        case horizontalBezier
+    }
+    
+    private func initialize()
+    {
+        // default color
+        circleColors.append(NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0))
+    }
+    
+    public required init()
+    {
+        super.init()
+        initialize()
+    }
+    
+    public override init(entries: [ChartDataEntry]?, label: String?)
+    {
+        super.init(entries: entries, label: label)
+        initialize()
+    }
+    
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    /// The drawing mode for this line dataset
+    ///
+    /// **default**: Linear
+    open var mode: Mode = Mode.linear
+    
+    private var _cubicIntensity = CGFloat(0.2)
+    
+    /// Intensity for cubic lines (min = 0.05, max = 1)
+    ///
+    /// **default**: 0.2
+    open var cubicIntensity: CGFloat
+    {
+        get
+        {
+            return _cubicIntensity
+        }
+        set
+        {
+            _cubicIntensity = newValue.clamped(to: 0.05...1)
+        }
+    }
+        
+    /// The radius of the drawn circles.
+    open var circleRadius = CGFloat(8.0)
+    
+    /// The hole radius of the drawn circles
+    open var circleHoleRadius = CGFloat(4.0)
+    
+    open var circleColors = [NSUIColor]()
+    
+    /// - Returns: The color at the given index of the DataSet's circle-color array.
+    /// Performs a IndexOutOfBounds check by modulus.
+    open func getCircleColor(atIndex index: Int) -> NSUIColor?
+    {
+        let size = circleColors.count
+        let index = index % size
+        if index >= size
+        {
+            return nil
+        }
+        return circleColors[index]
+    }
+    
+    /// Sets the one and ONLY color that should be used for this DataSet.
+    /// Internally, this recreates the colors array and adds the specified color.
+    open func setCircleColor(_ color: NSUIColor)
+    {
+        circleColors.removeAll(keepingCapacity: false)
+        circleColors.append(color)
+    }
+    
+    open func setCircleColors(_ colors: NSUIColor...)
+    {
+        circleColors.removeAll(keepingCapacity: false)
+        circleColors.append(contentsOf: colors)
+    }
+    
+    /// Resets the circle-colors array and creates a new one
+    open func resetCircleColors(_ index: Int)
+    {
+        circleColors.removeAll(keepingCapacity: false)
+    }
+    
+    /// If true, drawing circles is enabled
+    open var drawCirclesEnabled = true
+    
+    /// `true` if drawing circles for this DataSet is enabled, `false` ifnot
+    open var isDrawCirclesEnabled: Bool { return drawCirclesEnabled }
+    
+    /// The color of the inner circle (the circle-hole).
+    open var circleHoleColor: NSUIColor? = NSUIColor.white
+    
+    /// `true` if drawing circles for this DataSet is enabled, `false` ifnot
+    open var drawCircleHoleEnabled = true
+    
+    /// `true` if drawing the circle-holes is enabled, `false` ifnot.
+    open var isDrawCircleHoleEnabled: Bool { return drawCircleHoleEnabled }
+    
+    /// This is how much (in pixels) into the dash pattern are we starting from.
+    open var lineDashPhase = CGFloat(0.0)
+    
+    /// This is the actual dash pattern.
+    /// I.e. [2, 3] will paint [--   --   ]
+    /// [1, 3, 4, 2] will paint [-   ----  -   ----  ]
+    open var lineDashLengths: [CGFloat]?
+    
+    /// Line cap type, default is CGLineCap.Butt
+    open var lineCapType = CGLineCap.butt
+    
+    /// formatter for customizing the position of the fill-line
+    private var _fillFormatter: IFillFormatter = DefaultFillFormatter()
+    
+    /// Sets a custom IFillFormatter to the chart that handles the position of the filled-line for each DataSet. Set this to null to use the default logic.
+    open var fillFormatter: IFillFormatter?
+    {
+        get
+        {
+            return _fillFormatter
+        }
+        set
+        {
+            _fillFormatter = newValue ?? DefaultFillFormatter()
+        }
+    }
+    
+    // MARK: NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! LineChartDataSet
+        copy.circleColors = circleColors
+        copy.circleHoleColor = circleHoleColor
+        copy.circleRadius = circleRadius
+        copy.circleHoleRadius = circleHoleRadius
+        copy.cubicIntensity = cubicIntensity
+        copy.lineDashPhase = lineDashPhase
+        copy.lineDashLengths = lineDashLengths
+        copy.lineCapType = lineCapType
+        copy.drawCirclesEnabled = drawCirclesEnabled
+        copy.drawCircleHoleEnabled = drawCircleHoleEnabled
+        copy.mode = mode
+        copy._fillFormatter = _fillFormatter
+        return copy
+    }
+}

+ 85 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/LineRadarChartDataSet.swift

@@ -0,0 +1,85 @@
+//
+//  LineRadarChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+open class LineRadarChartDataSet: LineScatterCandleRadarChartDataSet, ILineRadarChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    /// The color that is used for filling the line surface area.
+    private var _fillColor = NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0)
+    
+    /// The color that is used for filling the line surface area.
+    open var fillColor: NSUIColor
+    {
+        get { return _fillColor }
+        set
+        {
+            _fillColor = newValue
+            fill = nil
+        }
+    }
+    
+    /// The object that is used for filling the area below the line.
+    /// **default**: nil
+    open var fill: Fill?
+    
+    /// The alpha value that is used for filling the line surface,
+    /// **default**: 0.33
+    open var fillAlpha = CGFloat(0.33)
+    
+    private var _lineWidth = CGFloat(1.0)
+    
+    /// line width of the chart (min = 0.0, max = 10)
+    ///
+    /// **default**: 1
+    open var lineWidth: CGFloat
+    {
+        get
+        {
+            return _lineWidth
+        }
+        set
+        {
+            _lineWidth = newValue.clamped(to: 0...10)
+        }
+    }
+    
+    /// Set to `true` if the DataSet should be drawn filled (surface), and not just as a line.
+    /// Disabling this will give great performance boost.
+    /// Please note that this method uses the path clipping for drawing the filled area (with images, gradients and layers).
+    open var drawFilledEnabled = false
+    
+    /// `true` if filled drawing is enabled, `false` ifnot
+    open var isDrawFilledEnabled: Bool
+    {
+        return drawFilledEnabled
+    }
+    
+    // MARK: NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! LineRadarChartDataSet
+        copy.fill = fill
+        copy.fillAlpha = fillAlpha
+        copy._fillColor = _fillColor
+        copy._lineWidth = _lineWidth
+        copy.drawFilledEnabled = drawFilledEnabled
+        return copy
+    }
+    
+}

+ 51 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/LineScatterCandleRadarChartDataSet.swift

@@ -0,0 +1,51 @@
+//
+//  LineScatterCandleRadarChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+
+open class LineScatterCandleRadarChartDataSet: BarLineScatterCandleBubbleChartDataSet, ILineScatterCandleRadarChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    /// Enables / disables the horizontal highlight-indicator. If disabled, the indicator is not drawn.
+    open var drawHorizontalHighlightIndicatorEnabled = true
+    
+    /// Enables / disables the vertical highlight-indicator. If disabled, the indicator is not drawn.
+    open var drawVerticalHighlightIndicatorEnabled = true
+    
+    /// `true` if horizontal highlight indicator lines are enabled (drawn)
+    open var isHorizontalHighlightIndicatorEnabled: Bool { return drawHorizontalHighlightIndicatorEnabled }
+    
+    /// `true` if vertical highlight indicator lines are enabled (drawn)
+    open var isVerticalHighlightIndicatorEnabled: Bool { return drawVerticalHighlightIndicatorEnabled }
+    
+    /// Enables / disables both vertical and horizontal highlight-indicators.
+    /// :param: enabled
+    open func setDrawHighlightIndicators(_ enabled: Bool)
+    {
+        drawHorizontalHighlightIndicatorEnabled = enabled
+        drawVerticalHighlightIndicatorEnabled = enabled
+    }
+    
+    // MARK: NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! LineScatterCandleRadarChartDataSet
+        copy.drawHorizontalHighlightIndicatorEnabled = drawHorizontalHighlightIndicatorEnabled
+        copy.drawVerticalHighlightIndicatorEnabled = drawVerticalHighlightIndicatorEnabled
+        return copy
+    }
+    
+}

+ 124 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartData.swift

@@ -0,0 +1,124 @@
+//
+//  PieData.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+open class PieChartData: ChartData
+{
+    public override init()
+    {
+        super.init()
+    }
+    
+    public override init(dataSets: [IChartDataSet]?)
+    {
+        super.init(dataSets: dataSets)
+    }
+
+    /// All DataSet objects this ChartData object holds.
+    @objc open override var dataSets: [IChartDataSet]
+    {
+        get
+        {
+            assert(super.dataSets.count <= 1, "Found multiple data sets while pie chart only allows one")
+            return super.dataSets
+        }
+        set
+        {
+            super.dataSets = newValue
+        }
+    }
+
+    @objc var dataSet: IPieChartDataSet?
+    {
+        get
+        {
+            return dataSets.count > 0 ? dataSets[0] as? IPieChartDataSet : nil
+        }
+        set
+        {
+            if let newValue = newValue
+            {
+                dataSets = [newValue]
+            }
+            else
+            {
+                dataSets = []
+            }
+        }
+    }
+    
+    open override func getDataSetByIndex(_ index: Int) -> IChartDataSet?
+    {
+        if index != 0
+        {
+            return nil
+        }
+        return super.getDataSetByIndex(index)
+    }
+    
+    open override func getDataSetByLabel(_ label: String, ignorecase: Bool) -> IChartDataSet?
+    {
+        if dataSets.count == 0 || dataSets[0].label == nil
+        {
+            return nil
+        }
+        
+        if ignorecase
+        {
+            if let label = dataSets[0].label, label.caseInsensitiveCompare(label) == .orderedSame
+            {
+                return dataSets[0]
+            }
+        }
+        else
+        {
+            if label == dataSets[0].label
+            {
+                return dataSets[0]
+            }
+        }
+        return nil
+    }
+    
+    open override func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry?
+    {
+        return dataSet?.entryForIndex(Int(highlight.x))
+    }
+    
+    open override func addDataSet(_ d: IChartDataSet!)
+    {   
+        super.addDataSet(d)
+    }
+    
+    /// Removes the DataSet at the given index in the DataSet array from the data object.
+    /// Also recalculates all minimum and maximum values.
+    ///
+    /// - Returns: `true` if a DataSet was removed, `false` ifno DataSet could be removed.
+    open override func removeDataSetByIndex(_ index: Int) -> Bool
+    {
+        if index >= _dataSets.count || index < 0
+        {
+            return false
+        }
+        
+        return false
+    }
+    
+    /// The total y-value sum across all DataSet objects the this object represents.
+    @objc open var yValueSum: Double
+    {
+        guard let dataSet = dataSet else { return 0.0 }
+        return (0..<dataSet.entryCount).reduce(into: 0) {
+            $0 += dataSet.entryForIndex($1)?.y ?? 0
+        }
+    }
+}

+ 119 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartDataEntry.swift

@@ -0,0 +1,119 @@
+//
+//  PieChartDataEntry.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+open class PieChartDataEntry: ChartDataEntry
+{
+    public required init()
+    {
+        super.init()
+    }
+    
+
+    /// - Parameters:
+    ///   - value: The value on the y-axis
+    @objc public init(value: Double)
+    {
+        super.init(x: .nan, y: value)
+    }
+
+    /// - Parameters:
+    ///   - value: The value on the y-axis
+    ///   - label: The label for the x-axis
+    @objc public convenience init(value: Double, label: String?)
+    {
+        self.init(value: value)
+        self.label = label
+    }
+    
+    /// - Parameters:
+    ///   - value: The value on the y-axis
+    ///   - label: The label for the x-axis
+    ///   - data: Spot for additional data this Entry represents
+    @objc public convenience init(value: Double, label: String?, data: Any?)
+    {
+        self.init(value: value, label: label, icon: nil, data: data)
+    }
+    
+    /// - Parameters:
+    ///   - value: The value on the y-axis
+    ///   - label: The label for the x-axis
+    ///   - icon: icon image
+    @objc public convenience init(value: Double, label: String?, icon: NSUIImage?)
+    {
+        self.init(value: value)
+        self.label = label
+        self.icon = icon
+    }
+    
+    /// - Parameters:
+    ///   - value: The value on the y-axis
+    ///   - label: The label for the x-axis
+    ///   - icon: icon image
+    ///   - data: Spot for additional data this Entry represents
+    @objc public convenience init(value: Double, label: String?, icon: NSUIImage?, data: Any?)
+    {
+        self.init(value: value)
+        self.label = label
+        self.icon = icon
+        self.data = data
+    }
+
+    /// - Parameters:
+    ///   - value: The value on the y-axis
+    ///   - data: Spot for additional data this Entry represents
+    @objc public convenience init(value: Double, data: Any?)
+    {
+        self.init(value: value)
+        self.data = data
+    }
+    
+    /// - Parameters:
+    ///   - value: The value on the y-axis
+    ///   - icon: icon image
+    @objc public convenience init(value: Double, icon: NSUIImage?)
+    {
+        self.init(value: value)
+        self.icon = icon
+    }
+    
+    /// - Parameters:
+    ///   - value: The value on the y-axis
+    ///   - icon: icon image
+    ///   - data: Spot for additional data this Entry represents
+    @objc public convenience init(value: Double, icon: NSUIImage?, data: Any?)
+    {
+        self.init(value: value)
+        self.icon = icon
+        self.data = data
+    }
+    
+    // MARK: Data property accessors
+    
+    @objc open var label: String?
+    
+    @objc open var value: Double
+    {
+        get { return y }
+        set { y = newValue }
+    }
+        
+    // MARK: NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! PieChartDataEntry
+        copy.label = label
+        return copy
+    }
+}

+ 135 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartDataSet.swift

@@ -0,0 +1,135 @@
+//
+//  PieChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+open class PieChartDataSet: ChartDataSet, IPieChartDataSet
+{
+    @objc(PieChartValuePosition)
+    public enum ValuePosition: Int
+    {
+        case insideSlice
+        case outsideSlice
+    }
+
+    private func initialize()
+    {
+        self.valueTextColor = NSUIColor.white
+        self.valueFont = NSUIFont.systemFont(ofSize: 13.0)
+    }
+
+    public required init()
+    {
+        super.init()
+        initialize()
+    }
+
+    public override init(entries: [ChartDataEntry]?, label: String?)
+    {
+        super.init(entries: entries, label: label)
+        initialize()
+    }
+
+    internal override func calcMinMax(entry e: ChartDataEntry)
+    {
+        calcMinMaxY(entry: e)
+    }
+
+    // MARK: - Styling functions and accessors
+
+    private var _sliceSpace = CGFloat(0.0)
+
+    /// the space in pixels between the pie-slices
+    /// **default**: 0
+    /// **maximum**: 20
+    open var sliceSpace: CGFloat
+    {
+        get
+        {
+            return _sliceSpace
+        }
+        set
+        {
+            var space = newValue
+            if space > 20.0
+            {
+                space = 20.0
+            }
+            if space < 0.0
+            {
+                space = 0.0
+            }
+            _sliceSpace = space
+        }
+    }
+
+    /// When enabled, slice spacing will be 0.0 when the smallest value is going to be smaller than the slice spacing itself.
+    open var automaticallyDisableSliceSpacing: Bool = false
+
+    /// indicates the selection distance of a pie slice
+    open var selectionShift = CGFloat(18.0)
+
+    open var xValuePosition: ValuePosition = .insideSlice
+    open var yValuePosition: ValuePosition = .insideSlice
+
+    /// When valuePosition is OutsideSlice, indicates line color
+    open var valueLineColor: NSUIColor? = NSUIColor.black
+
+    /// When valuePosition is OutsideSlice and enabled, line will have the same color as the slice
+    open var useValueColorForLine: Bool = false
+
+    /// When valuePosition is OutsideSlice, indicates line width
+    open var valueLineWidth: CGFloat = 1.0
+
+    /// When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size
+    open var valueLinePart1OffsetPercentage: CGFloat = 0.75
+
+    /// When valuePosition is OutsideSlice, indicates length of first half of the line
+    open var valueLinePart1Length: CGFloat = 0.3
+
+    /// When valuePosition is OutsideSlice, indicates length of second half of the line
+    open var valueLinePart2Length: CGFloat = 0.4
+
+    /// When valuePosition is OutsideSlice, this allows variable line length
+    open var valueLineVariableLength: Bool = true
+
+    /// the font for the slice-text labels
+    open var entryLabelFont: NSUIFont? = nil
+
+    /// the color for the slice-text labels
+    open var entryLabelColor: NSUIColor? = nil
+
+    /// the color for the highlighted sector
+    open var highlightColor: NSUIColor? = nil
+
+    // MARK: - NSCopying
+
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! PieChartDataSet
+        copy._sliceSpace = _sliceSpace
+        copy.automaticallyDisableSliceSpacing = automaticallyDisableSliceSpacing
+        copy.selectionShift = selectionShift
+        copy.xValuePosition = xValuePosition
+        copy.yValuePosition = yValuePosition
+        copy.valueLineColor = valueLineColor
+        copy.valueLineWidth = valueLineWidth
+        copy.valueLinePart1OffsetPercentage = valueLinePart1OffsetPercentage
+        copy.valueLinePart1Length = valueLinePart1Length
+        copy.valueLinePart2Length = valueLinePart2Length
+        copy.valueLineVariableLength = valueLineVariableLength
+        copy.entryLabelFont = entryLabelFont
+        copy.entryLabelColor = entryLabelColor
+        copy.highlightColor = highlightColor
+        return copy
+    }
+}

+ 46 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartData.swift

@@ -0,0 +1,46 @@
+//
+//  RadarChartData.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+open class RadarChartData: ChartData
+{
+    @objc open var highlightColor = NSUIColor(red: 255.0/255.0, green: 187.0/255.0, blue: 115.0/255.0, alpha: 1.0)
+    @objc open var highlightLineWidth = CGFloat(1.0)
+    @objc open var highlightLineDashPhase = CGFloat(0.0)
+    @objc open var highlightLineDashLengths: [CGFloat]?
+    
+    /// Sets labels that should be drawn around the RadarChart at the end of each web line.
+    @objc open var labels = [String]()
+    
+    /// Sets the labels that should be drawn around the RadarChart at the end of each web line.
+    open func setLabels(_ labels: String...)
+    {
+        self.labels = labels
+    }
+    
+    public override init()
+    {
+        super.init()
+    }
+    
+    public override init(dataSets: [IChartDataSet]?)
+    {
+        super.init(dataSets: dataSets)
+    }
+    
+    open override func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry?
+    {
+        return getDataSetByIndex(highlight.dataSetIndex)?.entryForIndex(Int(highlight.x))
+    }
+}

+ 54 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataEntry.swift

@@ -0,0 +1,54 @@
+//
+//  RadarChartDataEntry.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+open class RadarChartDataEntry: ChartDataEntry
+{
+    public required init()
+    {
+        super.init()
+    }
+
+    /// - Parameters:
+    ///   - value: The value on the y-axis.
+    @objc public init(value: Double)
+    {
+        super.init(x: .nan, y: value)
+    }
+
+    /// - Parameters:
+    ///   - value: The value on the y-axis.
+    ///   - data: Spot for additional data this Entry represents.
+    @objc public convenience init(value: Double, data: Any?)
+    {
+        self.init(value: value)
+        self.data = data
+    }
+    
+    // MARK: Data property accessors
+    
+    @objc open var value: Double
+    {
+        get { return y }
+        set { y = newValue }
+    }
+    
+    // MARK: NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! RadarChartDataEntry
+        
+        return copy
+    }
+}

+ 59 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataSet.swift

@@ -0,0 +1,59 @@
+//
+//  RadarChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+open class RadarChartDataSet: LineRadarChartDataSet, IRadarChartDataSet
+{
+    private func initialize()
+    {
+        self.valueFont = NSUIFont.systemFont(ofSize: 13.0)
+    }
+    
+    public required init()
+    {
+        super.init()
+        initialize()
+    }
+    
+    public required override init(entries: [ChartDataEntry]?, label: String?)
+    {
+        super.init(entries: entries, label: label)
+        initialize()
+    }
+    
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    /// flag indicating whether highlight circle should be drawn or not
+    /// **default**: false
+    open var drawHighlightCircleEnabled: Bool = false
+    
+    /// `true` if highlight circle should be drawn, `false` ifnot
+    open var isDrawHighlightCircleEnabled: Bool { return drawHighlightCircleEnabled }
+    
+    open var highlightCircleFillColor: NSUIColor? = NSUIColor.white
+    
+    /// The stroke color for highlight circle.
+    /// If `nil`, the color of the dataset is taken.
+    open var highlightCircleStrokeColor: NSUIColor?
+    
+    open var highlightCircleStrokeAlpha: CGFloat = 0.3
+    
+    open var highlightCircleInnerRadius: CGFloat = 3.0
+    
+    open var highlightCircleOuterRadius: CGFloat = 4.0
+    
+    open var highlightCircleStrokeWidth: CGFloat = 2.0
+}

+ 34 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartData.swift

@@ -0,0 +1,34 @@
+//
+//  ScatterChartData.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+open class ScatterChartData: BarLineScatterCandleBubbleChartData
+{
+    public override init()
+    {
+        super.init()
+    }
+    
+    public override init(dataSets: [IChartDataSet]?)
+    {
+        super.init(dataSets: dataSets)
+    }
+    
+    /// - Returns: The maximum shape-size across all DataSets.
+    @objc open func getGreatestShapeSize() -> CGFloat
+    {
+        return (_dataSets as? [IScatterChartDataSet])?
+            .max { $0.scatterShapeSize < $1.scatterShapeSize }?
+            .scatterShapeSize ?? 0
+    }
+}

+ 78 - 0
Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartDataSet.swift

@@ -0,0 +1,78 @@
+//
+//  ScatterChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+open class ScatterChartDataSet: LineScatterCandleRadarChartDataSet, IScatterChartDataSet
+{
+    
+    @objc(ScatterShape)
+    public enum Shape: Int
+    {
+        case square
+        case circle
+        case triangle
+        case cross
+        case x
+        case chevronUp
+        case chevronDown
+    }
+    
+    /// The size the scatter shape will have
+    open var scatterShapeSize = CGFloat(10.0)
+    
+    /// The radius of the hole in the shape (applies to Square, Circle and Triangle)
+    /// **default**: 0.0
+    open var scatterShapeHoleRadius: CGFloat = 0.0
+    
+    /// Color for the hole in the shape. Setting to `nil` will behave as transparent.
+    /// **default**: nil
+    open var scatterShapeHoleColor: NSUIColor? = nil
+    
+    /// Sets the ScatterShape this DataSet should be drawn with.
+    /// This will search for an available IShapeRenderer and set this renderer for the DataSet
+    @objc open func setScatterShape(_ shape: Shape)
+    {
+        self.shapeRenderer = ScatterChartDataSet.renderer(forShape: shape)
+    }
+    
+    /// The IShapeRenderer responsible for rendering this DataSet.
+    /// This can also be used to set a custom IShapeRenderer aside from the default ones.
+    /// **default**: `SquareShapeRenderer`
+    open var shapeRenderer: IShapeRenderer? = SquareShapeRenderer()
+    
+    @objc open class func renderer(forShape shape: Shape) -> IShapeRenderer
+    {
+        switch shape
+        {
+        case .square: return SquareShapeRenderer()
+        case .circle: return CircleShapeRenderer()
+        case .triangle: return TriangleShapeRenderer()
+        case .cross: return CrossShapeRenderer()
+        case .x: return XShapeRenderer()
+        case .chevronUp: return ChevronUpShapeRenderer()
+        case .chevronDown: return ChevronDownShapeRenderer()
+        }
+    }
+    
+    // MARK: NSCopying
+    
+    open override func copy(with zone: NSZone? = nil) -> Any
+    {
+        let copy = super.copy(with: zone) as! ScatterChartDataSet
+        copy.scatterShapeSize = scatterShapeSize
+        copy.scatterShapeHoleRadius = scatterShapeHoleRadius
+        copy.scatterShapeHoleColor = scatterShapeHoleColor
+        copy.shapeRenderer = shapeRenderer
+        return copy
+    }
+}

+ 42 - 0
Pods/Charts/Source/Charts/Data/Interfaces/IBarChartDataSet.swift

@@ -0,0 +1,42 @@
+//
+//  IBarChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol IBarChartDataSet: IBarLineScatterCandleBubbleChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    /// `true` if this DataSet is stacked (stacksize > 1) or not.
+    var isStacked: Bool { get }
+    
+    /// The maximum number of bars that can be stacked upon another in this DataSet.
+    var stackSize: Int { get }
+    
+    /// the color used for drawing the bar-shadows. The bar shadows is a surface behind the bar that indicates the maximum value
+    var barShadowColor: NSUIColor { get set }
+    
+    /// the width used for drawing borders around the bars. If borderWidth == 0, no border will be drawn.
+    var barBorderWidth : CGFloat { get set }
+
+    /// the color drawing borders around the bars.
+    var barBorderColor: NSUIColor { get set }
+
+    /// the alpha value (transparency) that is used for drawing the highlight indicator bar. min = 0.0 (fully transparent), max = 1.0 (fully opaque)
+    var highlightAlpha: CGFloat { get set }
+    
+    /// array of labels used to describe the different values of the stacked bars
+    var stackLabels: [String] { get set }
+}

+ 26 - 0
Pods/Charts/Source/Charts/Data/Interfaces/IBarLineScatterCandleBubbleChartDataSet.swift

@@ -0,0 +1,26 @@
+//
+//  IBarLineScatterCandleBubbleChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol IBarLineScatterCandleBubbleChartDataSet: IChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    var highlightColor: NSUIColor { get set }
+    var highlightLineWidth: CGFloat { get set }
+    var highlightLineDashPhase: CGFloat { get set }
+    var highlightLineDashLengths: [CGFloat]? { get set }
+}

+ 27 - 0
Pods/Charts/Source/Charts/Data/Interfaces/IBubbleChartDataSet.swift

@@ -0,0 +1,27 @@
+//
+//  IBubbleChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol IBubbleChartDataSet: IBarLineScatterCandleBubbleChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    var maxSize: CGFloat { get }
+    var isNormalizeSizeEnabled: Bool { get }
+    
+    // MARK: - Styling functions and accessors
+    
+    /// Sets/gets the width of the circle that surrounds the bubble when highlighted
+    var highlightCircleWidth: CGFloat { get set }
+}

+ 66 - 0
Pods/Charts/Source/Charts/Data/Interfaces/ICandleChartDataSet.swift

@@ -0,0 +1,66 @@
+//
+//  ICandleChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol ICandleChartDataSet: ILineScatterCandleRadarChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    /// the space that is left out on the left and right side of each candle,
+    /// **default**: 0.1 (10%), max 0.45, min 0.0
+    var barSpace: CGFloat { get set }
+    
+    /// should the candle bars show?
+    /// when false, only "ticks" will show
+    ///
+    /// **default**: true
+    var showCandleBar: Bool { get set }
+    
+    /// the width of the candle-shadow-line in pixels.
+    ///
+    /// **default**: 3.0
+    var shadowWidth: CGFloat { get set }
+    
+    /// the color of the shadow line
+    var shadowColor: NSUIColor? { get set }
+    
+    /// use candle color for the shadow
+    var shadowColorSameAsCandle: Bool { get set }
+    
+    /// Is the shadow color same as the candle color?
+    var isShadowColorSameAsCandle: Bool { get }
+    
+    /// color for open == close
+    var neutralColor: NSUIColor? { get set }
+    
+    /// color for open > close
+    var increasingColor: NSUIColor? { get set }
+    
+    /// color for open < close
+    var decreasingColor: NSUIColor? { get set }
+    
+    /// Are increasing values drawn as filled?
+    var increasingFilled: Bool { get set }
+    
+    /// Are increasing values drawn as filled?
+    var isIncreasingFilled: Bool { get }
+    
+    /// Are decreasing values drawn as filled?
+    var decreasingFilled: Bool { get set }
+    
+    /// Are decreasing values drawn as filled?
+    var isDecreasingFilled: Bool { get }
+}

+ 270 - 0
Pods/Charts/Source/Charts/Data/Interfaces/IChartDataSet.swift

@@ -0,0 +1,270 @@
+//
+//  IChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol IChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    /// Use this method to tell the data set that the underlying data has changed
+    func notifyDataSetChanged()
+    
+    /// Calculates the minimum and maximum x and y values (_xMin, _xMax, _yMin, _yMax).
+    func calcMinMax()
+    
+    /// Calculates the min and max y-values from the Entry closest to the given fromX to the Entry closest to the given toX value.
+    /// This is only needed for the autoScaleMinMax feature.
+    func calcMinMaxY(fromX: Double, toX: Double)
+    
+    /// The minimum y-value this DataSet holds
+    var yMin: Double { get }
+    
+    /// The maximum y-value this DataSet holds
+    var yMax: Double { get }
+    
+    /// The minimum x-value this DataSet holds
+    var xMin: Double { get }
+    
+    /// The maximum x-value this DataSet holds
+    var xMax: Double { get }
+    
+    /// The number of y-values this DataSet represents
+    var entryCount: Int { get }
+    
+    /// - Throws: out of bounds
+    /// if `i` is out of bounds, it may throw an out-of-bounds exception
+    /// - Returns: The entry object found at the given index (not x-value!)
+    func entryForIndex(_ i: Int) -> ChartDataEntry?
+    
+    /// - Parameters:
+    ///   - xValue: the x-value
+    ///   - closestToY: If there are multiple y-values for the specified x-value,
+    ///   - rounding: determine whether to round up/down/closest if there is no Entry matching the provided x-value
+    /// - Returns: The first Entry object found at the given x-value with binary search.
+    /// If the no Entry at the specified x-value is found, this method returns the Entry at the closest x-value according to the rounding.
+    /// nil if no Entry object at that x-value.
+    func entryForXValue(
+        _ xValue: Double,
+        closestToY yValue: Double,
+        rounding: ChartDataSetRounding) -> ChartDataEntry?
+    
+    /// - Parameters:
+    ///   - xValue: the x-value
+    ///   - closestToY: If there are multiple y-values for the specified x-value,
+    /// - Returns: The first Entry object found at the given x-value with binary search.
+    /// If the no Entry at the specified x-value is found, this method returns the Entry at the closest x-value.
+    /// nil if no Entry object at that x-value.
+    func entryForXValue(
+        _ xValue: Double,
+        closestToY yValue: Double) -> ChartDataEntry?
+    
+    /// - Returns: All Entry objects found at the given x-value with binary search.
+    /// An empty array if no Entry object at that x-value.
+    func entriesForXValue(_ xValue: Double) -> [ChartDataEntry]
+    
+    /// - Parameters:
+    ///   - xValue: x-value of the entry to search for
+    ///   - closestToY: If there are multiple y-values for the specified x-value,
+    ///   - rounding: Rounding method if exact value was not found
+    /// - Returns: The array-index of the specified entry.
+    /// If the no Entry at the specified x-value is found, this method returns the index of the Entry at the closest x-value according to the rounding.
+    func entryIndex(
+        x xValue: Double,
+        closestToY yValue: Double,
+        rounding: ChartDataSetRounding) -> Int
+    
+    /// - Parameters:
+    ///   - e: the entry to search for
+    /// - Returns: The array-index of the specified entry
+    func entryIndex(entry e: ChartDataEntry) -> Int
+    
+    /// Adds an Entry to the DataSet dynamically.
+    ///
+    /// *optional feature, can return `false` ifnot implemented*
+    ///
+    /// Entries are added to the end of the list.
+    ///
+    /// - Parameters:
+    ///   - e: the entry to add
+    /// - Returns: `true` if the entry was added successfully, `false` ifthis feature is not supported
+    func addEntry(_ e: ChartDataEntry) -> Bool
+    
+    /// Adds an Entry to the DataSet dynamically.
+    /// Entries are added to their appropriate index in the values array respective to their x-position.
+    /// This will also recalculate the current minimum and maximum values of the DataSet and the value-sum.
+    ///
+    /// *optional feature, can return `false` ifnot implemented*
+    ///
+    /// Entries are added to the end of the list.
+    ///
+    /// - Parameters:
+    ///   - e: the entry to add
+    /// - Returns: `true` if the entry was added successfully, `false` ifthis feature is not supported
+    func addEntryOrdered(_ e: ChartDataEntry) -> Bool
+    
+    /// Removes an Entry from the DataSet dynamically.
+    ///
+    /// *optional feature, can return `false` ifnot implemented*
+    ///
+    /// - Parameters:
+    ///   - entry: the entry to remove
+    /// - Returns: `true` if the entry was removed successfully, `false` ifthe entry does not exist or if this feature is not supported
+    func removeEntry(_ entry: ChartDataEntry) -> Bool
+    
+    /// Removes the Entry object at the given index in the values array from the DataSet.
+    ///
+    /// *optional feature, can return `false` ifnot implemented*
+    ///
+    /// - Parameters:
+    ///   - index: the index of the entry to remove
+    /// - Returns: `true` if the entry was removed successfully, `false` ifthe entry does not exist or if this feature is not supported
+    func removeEntry(index: Int) -> Bool
+    
+    /// Removes the Entry object closest to the given x-value from the DataSet.
+    ///
+    /// *optional feature, can return `false` ifnot implemented*
+    ///
+    /// - Parameters:
+    ///   - x: the x-value to remove
+    /// - Returns: `true` if the entry was removed successfully, `false` ifthe entry does not exist or if this feature is not supported
+    func removeEntry(x: Double) -> Bool
+    
+    /// Removes the first Entry (at index 0) of this DataSet from the entries array.
+    ///
+    /// *optional feature, can return `false` ifnot implemented*
+    ///
+    /// - Returns: `true` if the entry was removed successfully, `false` ifthe entry does not exist or if this feature is not supported
+    func removeFirst() -> Bool
+    
+    /// Removes the last Entry (at index 0) of this DataSet from the entries array.
+    ///
+    /// *optional feature, can return `false` ifnot implemented*
+    ///
+    /// - Returns: `true` if the entry was removed successfully, `false` ifthe entry does not exist or if this feature is not supported
+    func removeLast() -> Bool
+    
+    /// Checks if this DataSet contains the specified Entry.
+    ///
+    /// - Returns: `true` if contains the entry, `false` ifnot.
+    func contains(_ e: ChartDataEntry) -> Bool
+    
+    /// Removes all values from this DataSet and does all necessary recalculations.
+    ///
+    /// *optional feature, could throw if not implemented*
+    func clear()
+    
+    // MARK: - Styling functions and accessors
+    
+    /// The label string that describes the DataSet.
+    var label: String? { get }
+    
+    /// The axis this DataSet should be plotted against.
+    var axisDependency: YAxis.AxisDependency { get }
+    
+    /// List representing all colors that are used for drawing the actual values for this DataSet
+    var valueColors: [NSUIColor] { get }
+    
+    /// All the colors that are used for this DataSet.
+    /// Colors are reused as soon as the number of Entries the DataSet represents is higher than the size of the colors array.
+    var colors: [NSUIColor] { get }
+    
+    /// - Returns: The color at the given index of the DataSet's color array.
+    /// This prevents out-of-bounds by performing a modulus on the color index, so colours will repeat themselves.
+    func color(atIndex: Int) -> NSUIColor
+    
+    func resetColors()
+    
+    func addColor(_ color: NSUIColor)
+    
+    func setColor(_ color: NSUIColor)
+    
+    /// if true, value highlighting is enabled
+    var highlightEnabled: Bool { get set }
+    
+    /// `true` if value highlighting is enabled for this dataset
+    var isHighlightEnabled: Bool { get }
+    
+    /// Custom formatter that is used instead of the auto-formatter if set
+    var valueFormatter: IValueFormatter? { get set }
+    
+    /// `true` if the valueFormatter object of this DataSet is null.
+    var needsFormatter: Bool { get }
+    
+    /// Sets/get a single color for value text.
+    /// Setting the color clears the colors array and adds a single color.
+    /// Getting will return the first color in the array.
+    var valueTextColor: NSUIColor { get set }
+    
+    /// - Returns: The color at the specified index that is used for drawing the values inside the chart. Uses modulus internally.
+    func valueTextColorAt(_ index: Int) -> NSUIColor
+    
+    /// the font for the value-text labels
+    var valueFont: NSUIFont { get set }
+    
+    /// The form to draw for this dataset in the legend.
+    ///
+    /// Return `.Default` to use the default legend form.
+    var form: Legend.Form { get }
+    
+    /// The form size to draw for this dataset in the legend.
+    ///
+    /// Return `NaN` to use the default legend form size.
+    var formSize: CGFloat { get }
+    
+    /// The line width for drawing the form of this dataset in the legend
+    ///
+    /// Return `NaN` to use the default legend form line width.
+    var formLineWidth: CGFloat { get }
+    
+    /// Line dash configuration for legend shapes that consist of lines.
+    ///
+    /// This is how much (in pixels) into the dash pattern are we starting from.
+    var formLineDashPhase: CGFloat { get }
+    
+    /// Line dash configuration for legend shapes that consist of lines.
+    ///
+    /// This is the actual dash pattern.
+    /// I.e. [2, 3] will paint [--   --   ]
+    /// [1, 3, 4, 2] will paint [-   ----  -   ----  ]
+    var formLineDashLengths: [CGFloat]? { get }
+    
+    /// Set this to true to draw y-values on the chart.
+    ///
+    /// - Note: For bar and line charts: if `maxVisibleCount` is reached, no values will be drawn even if this is enabled.
+    var drawValuesEnabled: Bool { get set }
+    
+    /// `true` if y-value drawing is enabled, `false` ifnot
+    var isDrawValuesEnabled: Bool { get }
+    
+    /// Set this to true to draw y-icons on the chart
+    ///
+    /// - Note: For bar and line charts: if `maxVisibleCount` is reached, no icons will be drawn even if this is enabled.
+    var drawIconsEnabled: Bool { get set }
+    
+    /// Returns true if y-icon drawing is enabled, false if not
+    var isDrawIconsEnabled: Bool { get }
+    
+    /// Offset of icons drawn on the chart.
+    ///
+    /// For all charts except Pie and Radar it will be ordinary (x offset, y offset).
+    ///
+    /// For Pie and Radar chart it will be (y offset, distance from center offset); so if you want icon to be rendered under value, you should increase X component of CGPoint, and if you want icon to be rendered closet to center, you should decrease height component of CGPoint.
+    var iconsOffset: CGPoint { get set }
+    
+    /// Set the visibility of this DataSet. If not visible, the DataSet will not be drawn to the chart upon refreshing it.
+    var visible: Bool { get set }
+    
+    /// `true` if this DataSet is visible inside the chart, or `false` ifit is currently hidden.
+    var isVisible: Bool { get }
+}

+ 80 - 0
Pods/Charts/Source/Charts/Data/Interfaces/ILineChartDataSet.swift

@@ -0,0 +1,80 @@
+//
+//  ILineChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+
+@objc
+public protocol ILineChartDataSet: ILineRadarChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    /// The drawing mode for this line dataset
+    ///
+    /// **default**: Linear
+    var mode: LineChartDataSet.Mode { get set }
+    
+    /// Intensity for cubic lines (min = 0.05, max = 1)
+    ///
+    /// **default**: 0.2
+    var cubicIntensity: CGFloat { get set }
+    
+    /// The radius of the drawn circles.
+    var circleRadius: CGFloat { get set }
+    
+    /// The hole radius of the drawn circles.
+    var circleHoleRadius: CGFloat { get set }
+    
+    var circleColors: [NSUIColor] { get set }
+    
+    /// - Returns: The color at the given index of the DataSet's circle-color array.
+    /// Performs a IndexOutOfBounds check by modulus.
+    func getCircleColor(atIndex: Int) -> NSUIColor?
+    
+    /// Sets the one and ONLY color that should be used for this DataSet.
+    /// Internally, this recreates the colors array and adds the specified color.
+    func setCircleColor(_ color: NSUIColor)
+    
+    /// Resets the circle-colors array and creates a new one
+    func resetCircleColors(_ index: Int)
+    
+    /// If true, drawing circles is enabled
+    var drawCirclesEnabled: Bool { get set }
+    
+    /// `true` if drawing circles for this DataSet is enabled, `false` ifnot
+    var isDrawCirclesEnabled: Bool { get }
+    
+    /// The color of the inner circle (the circle-hole).
+    var circleHoleColor: NSUIColor? { get set }
+    
+    /// `true` if drawing circles for this DataSet is enabled, `false` ifnot
+    var drawCircleHoleEnabled: Bool { get set }
+    
+    /// `true` if drawing the circle-holes is enabled, `false` ifnot.
+    var isDrawCircleHoleEnabled: Bool { get }
+    
+    /// This is how much (in pixels) into the dash pattern are we starting from.
+    var lineDashPhase: CGFloat { get }
+    
+    /// This is the actual dash pattern.
+    /// I.e. [2, 3] will paint [--   --   ]
+    /// [1, 3, 4, 2] will paint [-   ----  -   ----  ]
+    var lineDashLengths: [CGFloat]? { get set }
+    
+    /// Line cap type, default is CGLineCap.Butt
+    var lineCapType: CGLineCap { get set }
+    
+    /// Sets a custom IFillFormatter to the chart that handles the position of the filled-line for each DataSet. Set this to null to use the default logic.
+    var fillFormatter: IFillFormatter? { get set }
+}

+ 45 - 0
Pods/Charts/Source/Charts/Data/Interfaces/ILineRadarChartDataSet.swift

@@ -0,0 +1,45 @@
+//
+//  ILineRadarChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol ILineRadarChartDataSet: ILineScatterCandleRadarChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    /// The color that is used for filling the line surface area.
+    var fillColor: NSUIColor { get set }
+
+    /// - Returns: The object that is used for filling the area below the line.
+    /// **default**: nil
+    var fill: Fill? { get set }
+    
+    /// The alpha value that is used for filling the line surface.
+    /// **default**: 0.33
+    var fillAlpha: CGFloat { get set }
+    
+    /// line width of the chart (min = 0.0, max = 10)
+    ///
+    /// **default**: 1
+    var lineWidth: CGFloat { get set }
+    
+    /// Set to `true` if the DataSet should be drawn filled (surface), and not just as a line.
+    /// Disabling this will give great performance boost.
+    /// Please note that this method uses the path clipping for drawing the filled area (with images, gradients and layers).
+    var drawFilledEnabled: Bool { get set }
+    
+    /// `true` if filled drawing is enabled, `false` if not
+    var isDrawFilledEnabled: Bool { get }
+}

+ 36 - 0
Pods/Charts/Source/Charts/Data/Interfaces/ILineScatterCandleRadarChartDataSet.swift

@@ -0,0 +1,36 @@
+//
+//  ILineScatterCandleRadarChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+@objc
+public protocol ILineScatterCandleRadarChartDataSet: IBarLineScatterCandleBubbleChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    /// Enables / disables the horizontal highlight-indicator. If disabled, the indicator is not drawn.
+    var drawHorizontalHighlightIndicatorEnabled: Bool { get set }
+    
+    /// Enables / disables the vertical highlight-indicator. If disabled, the indicator is not drawn.
+    var drawVerticalHighlightIndicatorEnabled: Bool { get set }
+    
+    /// `true` if horizontal highlight indicator lines are enabled (drawn)
+    var isHorizontalHighlightIndicatorEnabled: Bool { get }
+    
+    /// `true` if vertical highlight indicator lines are enabled (drawn)
+    var isVerticalHighlightIndicatorEnabled: Bool { get }
+    
+    /// Enables / disables both vertical and horizontal highlight-indicators.
+    /// :param: enabled
+    func setDrawHighlightIndicators(_ enabled: Bool)
+}

+ 64 - 0
Pods/Charts/Source/Charts/Data/Interfaces/IPieChartDataSet.swift

@@ -0,0 +1,64 @@
+//
+//  IPieChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol IPieChartDataSet: IChartDataSet
+{
+    // MARK: - Styling functions and accessors
+
+    /// the space in pixels between the pie-slices
+    /// **default**: 0
+    /// **maximum**: 20
+    var sliceSpace: CGFloat { get set }
+
+    /// When enabled, slice spacing will be 0.0 when the smallest value is going to be smaller than the slice spacing itself.
+    var automaticallyDisableSliceSpacing: Bool { get set }
+
+    /// indicates the selection distance of a pie slice
+    var selectionShift: CGFloat { get set }
+
+    var xValuePosition: PieChartDataSet.ValuePosition { get set }
+    var yValuePosition: PieChartDataSet.ValuePosition { get set }
+
+    /// When valuePosition is OutsideSlice, indicates line color
+    var valueLineColor: NSUIColor? { get set }
+
+    /// When valuePosition is OutsideSlice and enabled, line will have the same color as the slice
+    var useValueColorForLine: Bool { get set }
+
+    /// When valuePosition is OutsideSlice, indicates line width
+    var valueLineWidth: CGFloat { get set }
+
+    /// When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size
+    var valueLinePart1OffsetPercentage: CGFloat { get set }
+
+    /// When valuePosition is OutsideSlice, indicates length of first half of the line
+    var valueLinePart1Length: CGFloat { get set }
+
+    /// When valuePosition is OutsideSlice, indicates length of second half of the line
+    var valueLinePart2Length: CGFloat { get set }
+
+    /// When valuePosition is OutsideSlice, this allows variable line length
+    var valueLineVariableLength: Bool { get set }
+
+    /// the font for the slice-text labels
+    var entryLabelFont: NSUIFont? { get set }
+
+    /// the color for the slice-text labels
+    var entryLabelColor: NSUIColor? { get set }
+
+    /// get/sets the color for the highlighted sector
+    var highlightColor: NSUIColor? { get set }
+
+}

+ 40 - 0
Pods/Charts/Source/Charts/Data/Interfaces/IRadarChartDataSet.swift

@@ -0,0 +1,40 @@
+//
+//  IRadarChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol IRadarChartDataSet: ILineRadarChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    /// flag indicating whether highlight circle should be drawn or not
+    var drawHighlightCircleEnabled: Bool { get set }
+    
+    var isDrawHighlightCircleEnabled: Bool { get }
+    
+    var highlightCircleFillColor: NSUIColor? { get set }
+    
+    /// The stroke color for highlight circle.
+    /// If `nil`, the color of the dataset is taken.
+    var highlightCircleStrokeColor: NSUIColor? { get set }
+    
+    var highlightCircleStrokeAlpha: CGFloat { get set }
+    
+    var highlightCircleInnerRadius: CGFloat { get set }
+    
+    var highlightCircleOuterRadius: CGFloat { get set }
+    
+    var highlightCircleStrokeWidth: CGFloat { get set }
+}

+ 36 - 0
Pods/Charts/Source/Charts/Data/Interfaces/IScatterChartDataSet.swift

@@ -0,0 +1,36 @@
+//
+//  IScatterChartDataSet.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol IScatterChartDataSet: ILineScatterCandleRadarChartDataSet
+{
+    // MARK: - Data functions and accessors
+    
+    // MARK: - Styling functions and accessors
+    
+    /// The size the scatter shape will have
+    var scatterShapeSize: CGFloat { get }
+    
+    /// - Returns: The radius of the hole in the shape (applies to Square, Circle and Triangle)
+    /// Set this to <= 0 to remove holes.
+    /// **default**: 0.0
+    var scatterShapeHoleRadius: CGFloat { get }
+    
+    /// - Returns: Color for the hole in the shape. Setting to `nil` will behave as transparent.
+    /// **default**: nil
+    var scatterShapeHoleColor: NSUIColor? { get }
+    
+    /// The IShapeRenderer responsible for rendering this DataSet.
+    var shapeRenderer: IShapeRenderer? { get }
+}

+ 153 - 0
Pods/Charts/Source/Charts/Filters/DataApproximator+N.swift

@@ -0,0 +1,153 @@
+//
+//  DataApproximator+N.swift
+//  Charts
+//
+//  Created by M Ivaniushchenko on 9/6/17.
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+extension CGPoint {
+    fileprivate func distanceToLine(from linePoint1: CGPoint, to linePoint2: CGPoint) -> CGFloat {
+        let dx = linePoint2.x - linePoint1.x
+        let dy = linePoint2.y - linePoint1.y
+        
+        let dividend = abs(dy * self.x - dx * self.y - linePoint1.x * linePoint2.y + linePoint2.x * linePoint1.y)
+        let divisor = sqrt(dx * dx + dy * dy)
+        
+        return dividend / divisor
+    }
+}
+
+private struct LineAlt {
+    let start: Int
+    let end: Int
+    
+    var distance: CGFloat = 0
+    var index: Int = 0
+    
+    init(start: Int, end: Int, points: [CGPoint]) {
+        self.start = start
+        self.end = end
+        
+        let startPoint = points[start]
+        let endPoint = points[end]
+        
+        guard (end > start + 1) else {
+            return
+        }
+        
+        for i in start + 1 ..< end {
+            let currentPoint = points[i]
+            
+            let distance = currentPoint.distanceToLine(from: startPoint, to: endPoint)
+            
+            if distance > self.distance {
+                self.index = i
+                self.distance = distance
+            }
+        }
+    }
+}
+
+extension LineAlt: Comparable {
+    static func ==(lhs: LineAlt, rhs: LineAlt) -> Bool {
+        return (lhs.start == rhs.start) && (lhs.end == rhs.end) && (lhs.index == rhs.index)
+    }
+    
+    static func <(lhs: LineAlt, rhs: LineAlt) -> Bool {
+        return lhs.distance < rhs.distance
+    }
+}
+
+
+extension DataApproximator {
+    /// uses the douglas peuker algorithm to reduce the given arraylist of entries to given number of points
+    /// More algorithm details here - http://psimpl.sourceforge.net/douglas-peucker.html
+    @objc open class func reduceWithDouglasPeukerN(_ points: [CGPoint], resultCount: Int) -> [CGPoint]
+    {
+        // if a shape has 2 or less points it cannot be reduced
+        if resultCount <= 2 || resultCount >= points.count
+        {
+            return points
+        }
+        var keep = [Bool](repeating: false, count: points.count)
+        
+        // first and last always stay
+        keep[0] = true
+        keep[points.count - 1] = true
+        var currentStoredPoints = 2
+        
+        var queue = [LineAlt]()
+        let line = LineAlt(start: 0, end: points.count - 1, points: points)
+        queue.append(line)
+        
+        repeat {
+            let line = queue.popLast()!
+            
+            // store the key
+            keep[line.index] = true
+            
+            // check point count tolerance
+            currentStoredPoints += 1
+            
+            if (currentStoredPoints == resultCount) {
+                break;
+            }
+            
+            // split the polyline at the key and recurse
+            let left = LineAlt(start: line.start, end: line.index, points: points)
+            if (left.index > 0) {
+                self.insertLine(left, into: &queue)
+            }
+            
+            let right = LineAlt(start: line.index, end: line.end, points: points)
+            if (right.index > 0) {
+                self.insertLine(right, into: &queue)
+            }
+            
+        } while !queue.isEmpty
+        
+        // create a new array with series, only take the kept ones
+        let reducedEntries = points.enumerated().compactMap { (index: Int, point: CGPoint) -> CGPoint? in
+            return keep[index] ? point : nil
+        }
+        
+        return reducedEntries
+    }
+    
+    // Keeps array sorted
+    private static func insertLine(_ line: LineAlt, into array: inout [LineAlt]) {
+        let insertionIndex = self.insertionIndex(for: line, into: &array)
+        array.insert(line, at: insertionIndex)
+    }
+    
+    private static func insertionIndex(for line: LineAlt, into array: inout [LineAlt]) -> Int {
+        var indices = array.indices
+        
+        while !indices.isEmpty {
+            let midIndex = indices.lowerBound.advanced(by: indices.count / 2)
+            let midLine = array[midIndex]
+            
+            if midLine == line {
+                return midIndex
+            }
+            else if (line < midLine) {
+                // perform search in left half
+                indices = indices.lowerBound..<midIndex
+            }
+            else {
+                // perform search in right half
+                indices = (midIndex + 1)..<indices.upperBound
+            }
+        }
+        
+        return indices.lowerBound
+    }
+}
+
+

+ 115 - 0
Pods/Charts/Source/Charts/Filters/DataApproximator.swift

@@ -0,0 +1,115 @@
+//
+//  DataApproximator.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(ChartDataApproximator)
+open class DataApproximator: NSObject
+{
+    /// uses the douglas peuker algorithm to reduce the given arraylist of entries
+    @objc open class func reduceWithDouglasPeuker(_ points: [CGPoint], tolerance: CGFloat) -> [CGPoint]
+    {
+        // if a shape has 2 or less points it cannot be reduced
+        if tolerance <= 0 || points.count < 3
+        {
+            return points
+        }
+        
+        var keep = [Bool](repeating: false, count: points.count)
+        
+        // first and last always stay
+        keep[0] = true
+        keep[points.count - 1] = true
+        
+        // first and last entry are entry point to recursion
+        reduceWithDouglasPeuker(points: points,
+                                tolerance: tolerance,
+                                start: 0,
+                                end: points.count - 1,
+                                keep: &keep)
+        
+        // create a new array with series, only take the kept ones
+        return zip(keep, points).compactMap { $0 ? nil : $1 }
+    }
+
+    /// apply the Douglas-Peucker-Reduction to an array of `CGPoint`s with a given tolerance
+    ///
+    /// - Parameters:
+    ///   - points:
+    ///   - tolerance:
+    ///   - start:
+    ///   - end:
+    open class func reduceWithDouglasPeuker(
+        points: [CGPoint],
+        tolerance: CGFloat,
+        start: Int,
+        end: Int,
+        keep: inout [Bool])
+    {
+        if end <= start + 1
+        {
+            // recursion finished
+            return
+        }
+        
+        var greatestIndex = Int(0)
+        var greatestDistance = CGFloat(0.0)
+        
+        let line = Line(pt1: points[start], pt2: points[end])
+        
+        for i in start + 1 ..< end
+        {
+            let distance = line.distance(toPoint: points[i])
+            
+            if distance > greatestDistance
+            {
+                greatestDistance = distance
+                greatestIndex = i
+            }
+        }
+        
+        if greatestDistance > tolerance
+        {
+            // keep max dist point
+            keep[greatestIndex] = true
+            
+            // recursive call
+            reduceWithDouglasPeuker(points: points, tolerance: tolerance, start: start, end: greatestIndex, keep: &keep)
+            reduceWithDouglasPeuker(points: points, tolerance: tolerance, start: greatestIndex, end: end, keep: &keep)
+        } // else don't keep the point...
+    }
+    
+    private class Line
+    {
+        var sxey: CGFloat
+        var exsy: CGFloat
+        
+        var dx: CGFloat
+        var dy: CGFloat
+        
+        var length: CGFloat
+        
+        init(pt1: CGPoint, pt2: CGPoint)
+        {
+            dx = pt1.x - pt2.x
+            dy = pt1.y - pt2.y
+            sxey = pt1.x * pt2.y
+            exsy = pt2.x * pt1.y
+            length = sqrt(dx * dx + dy * dy)
+        }
+        
+        func distance(toPoint pt: CGPoint) -> CGFloat
+        {
+            return abs(dy * pt.x - dx * pt.y + sxey - exsy) / length
+        }
+    }
+}

+ 100 - 0
Pods/Charts/Source/Charts/Formatters/DefaultAxisValueFormatter.swift

@@ -0,0 +1,100 @@
+//
+//  DefaultAxisValueFormatter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+@objc(ChartDefaultAxisValueFormatter)
+open class DefaultAxisValueFormatter: NSObject, IAxisValueFormatter
+{
+    public typealias Block = (
+        _ value: Double,
+        _ axis: AxisBase?) -> String
+    
+    @objc open var block: Block?
+    
+    @objc open var hasAutoDecimals: Bool = false
+    
+    private var _formatter: NumberFormatter?
+    @objc open var formatter: NumberFormatter?
+    {
+        get { return _formatter }
+        set
+        {
+            hasAutoDecimals = false
+            _formatter = newValue
+        }
+    }
+
+    // TODO: Documentation. Especially the nil case
+    private var _decimals: Int?
+    open var decimals: Int?
+    {
+        get { return _decimals }
+        set
+        {
+            _decimals = newValue
+            
+            if let digits = newValue
+            {
+                self.formatter?.minimumFractionDigits = digits
+                self.formatter?.maximumFractionDigits = digits
+                self.formatter?.usesGroupingSeparator = true
+            }
+        }
+    }
+    
+    public override init()
+    {
+        super.init()
+        
+        self.formatter = NumberFormatter()
+        hasAutoDecimals = true
+    }
+    
+    @objc public init(formatter: NumberFormatter)
+    {
+        super.init()
+        
+        self.formatter = formatter
+    }
+    
+    @objc public init(decimals: Int)
+    {
+        super.init()
+        
+        self.formatter = NumberFormatter()
+        self.formatter?.usesGroupingSeparator = true
+        self.decimals = decimals
+        hasAutoDecimals = true
+    }
+    
+    @objc public init(block: @escaping Block)
+    {
+        super.init()
+        
+        self.block = block
+    }
+    
+    @objc public static func with(block: @escaping Block) -> DefaultAxisValueFormatter?
+    {
+        return DefaultAxisValueFormatter(block: block)
+    }
+    
+    open func stringForValue(_ value: Double,
+                               axis: AxisBase?) -> String
+    {
+        if let block = block {
+            return block(value, axis)
+        } else {
+            return formatter?.string(from: NSNumber(floatLiteral: value)) ?? ""
+        }
+    }
+}

+ 58 - 0
Pods/Charts/Source/Charts/Formatters/DefaultFillFormatter.swift

@@ -0,0 +1,58 @@
+//
+//  DefaultFillFormatter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+/// Default formatter that calculates the position of the filled line.
+@objc(ChartDefaultFillFormatter)
+open class DefaultFillFormatter: NSObject, IFillFormatter
+{
+    public typealias Block = (
+        _ dataSet: ILineChartDataSet,
+        _ dataProvider: LineChartDataProvider) -> CGFloat
+    
+    @objc open var block: Block?
+    
+    public override init() { }
+    
+    @objc public init(block: @escaping Block)
+    {
+        self.block = block
+    }
+    
+    @objc public static func with(block: @escaping Block) -> DefaultFillFormatter?
+    {
+        return DefaultFillFormatter(block: block)
+    }
+    
+    open func getFillLinePosition(
+        dataSet: ILineChartDataSet,
+        dataProvider: LineChartDataProvider) -> CGFloat
+    {
+        guard block == nil else { return block!(dataSet, dataProvider) }
+        var fillMin: CGFloat = 0.0
+
+        if dataSet.yMax > 0.0 && dataSet.yMin < 0.0
+        {
+            fillMin = 0.0
+        }
+        else if let data = dataProvider.data
+        {
+            let max = data.yMax > 0.0 ? 0.0 : dataProvider.chartYMax
+            let min = data.yMin < 0.0 ? 0.0 : dataProvider.chartYMin
+
+            fillMin = CGFloat(dataSet.yMin >= 0.0 ? min : max)
+        }
+
+        return fillMin
+    }
+}

+ 103 - 0
Pods/Charts/Source/Charts/Formatters/DefaultValueFormatter.swift

@@ -0,0 +1,103 @@
+//
+//  DefaultValueFormatter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+@objc(ChartDefaultValueFormatter)
+open class DefaultValueFormatter: NSObject, IValueFormatter
+{
+    public typealias Block = (
+        _ value: Double,
+        _ entry: ChartDataEntry,
+        _ dataSetIndex: Int,
+        _ viewPortHandler: ViewPortHandler?) -> String
+    
+    @objc open var block: Block?
+    
+    @objc open var hasAutoDecimals: Bool = false
+    
+    private var _formatter: NumberFormatter?
+    @objc open var formatter: NumberFormatter?
+    {
+        get { return _formatter }
+        set
+        {
+            hasAutoDecimals = false
+            _formatter = newValue
+        }
+    }
+    
+    private var _decimals: Int?
+    open var decimals: Int?
+    {
+        get { return _decimals }
+        set
+        {
+            _decimals = newValue
+            
+            if let digits = newValue
+            {
+                self.formatter?.minimumFractionDigits = digits
+                self.formatter?.maximumFractionDigits = digits
+                self.formatter?.usesGroupingSeparator = true
+            }
+        }
+    }
+    
+    public override init()
+    {
+        super.init()
+        
+        self.formatter = NumberFormatter()
+        hasAutoDecimals = true
+    }
+    
+    @objc public init(formatter: NumberFormatter)
+    {
+        super.init()
+        
+        self.formatter = formatter
+    }
+    
+    @objc public init(decimals: Int)
+    {
+        super.init()
+        
+        self.formatter = NumberFormatter()
+        self.formatter?.usesGroupingSeparator = true
+        self.decimals = decimals
+        hasAutoDecimals = true
+    }
+    
+    @objc public init(block: @escaping Block)
+    {
+        super.init()
+        
+        self.block = block
+    }
+    
+    @objc public static func with(block: @escaping Block) -> DefaultValueFormatter?
+    {
+        return DefaultValueFormatter(block: block)
+    }
+    
+    open func stringForValue(_ value: Double,
+                             entry: ChartDataEntry,
+                             dataSetIndex: Int,
+                             viewPortHandler: ViewPortHandler?) -> String
+    {
+        if let block = block {
+            return block(value, entry, dataSetIndex, viewPortHandler)
+        } else {
+            return formatter?.string(from: NSNumber(floatLiteral: value)) ?? ""
+        }
+    }
+}

+ 30 - 0
Pods/Charts/Source/Charts/Formatters/IAxisValueFormatter.swift

@@ -0,0 +1,30 @@
+//
+//  IAxisValueFormatter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+/// An interface for providing custom axis Strings.
+@objc(IChartAxisValueFormatter)
+public protocol IAxisValueFormatter: class
+{
+    
+    /// Called when a value from an axis is formatted before being drawn.
+    ///
+    /// For performance reasons, avoid excessive calculations and memory allocations inside this method.
+    ///
+    /// - Parameters:
+    ///   - value:           the value that is currently being drawn
+    ///   - axis:            the axis that the value belongs to
+    /// - Returns: The customized label that is drawn on the x-axis.
+    func stringForValue(_ value: Double,
+                        axis: AxisBase?) -> String
+    
+}

+ 21 - 0
Pods/Charts/Source/Charts/Formatters/IFillFormatter.swift

@@ -0,0 +1,21 @@
+//
+//  IFillFormatter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+/// Protocol for providing a custom logic to where the filling line of a LineDataSet should end. This of course only works if setFillEnabled(...) is set to true.
+@objc(IChartFillFormatter)
+public protocol IFillFormatter
+{
+    /// - Returns: The vertical (y-axis) position where the filled-line of the LineDataSet should end.
+    func getFillLinePosition(dataSet: ILineChartDataSet, dataProvider: LineChartDataProvider) -> CGFloat
+}

+ 36 - 0
Pods/Charts/Source/Charts/Formatters/IValueFormatter.swift

@@ -0,0 +1,36 @@
+//
+//  IValueFormatter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+/// Interface that allows custom formatting of all values inside the chart before they are drawn to the screen.
+///
+/// Simply create your own formatting class and let it implement ValueFormatter. Then override the stringForValue()
+/// method and return whatever you want.
+
+@objc(IChartValueFormatter)
+public protocol IValueFormatter: class
+{
+    
+    /// Called when a value (from labels inside the chart) is formatted before being drawn.
+    ///
+    /// For performance reasons, avoid excessive calculations and memory allocations inside this method.
+    ///
+    /// - Parameters:
+    ///   - value:           The value to be formatted
+    ///   - dataSetIndex:    The index of the DataSet the entry in focus belongs to
+    ///   - viewPortHandler: provides information about the current chart state (scale, translation, ...)
+    /// - Returns:                   The formatted label ready to be drawn
+    func stringForValue(_ value: Double,
+                        entry: ChartDataEntry,
+                        dataSetIndex: Int,
+                        viewPortHandler: ViewPortHandler?) -> String
+}

+ 59 - 0
Pods/Charts/Source/Charts/Formatters/IndexAxisValueFormatter.swift

@@ -0,0 +1,59 @@
+//
+//  IndexAxisValueFormatter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+/// This formatter is used for passing an array of x-axis labels, on whole x steps.
+@objc(ChartIndexAxisValueFormatter)
+open class IndexAxisValueFormatter: NSObject, IAxisValueFormatter
+{
+    private var _values: [String] = [String]()
+    private var _valueCount: Int = 0
+    
+    @objc public var values: [String]
+    {
+        get
+        {
+            return _values
+        }
+        set
+        {
+            _values = newValue
+            _valueCount = _values.count
+        }
+    }
+    
+    public override init()
+    {
+        super.init()
+        
+    }
+    
+    @objc public init(values: [String])
+    {
+        super.init()
+        
+        self.values = values
+    }
+    
+    @objc public static func with(values: [String]) -> IndexAxisValueFormatter?
+    {
+        return IndexAxisValueFormatter(values: values)
+    }
+    
+    open func stringForValue(_ value: Double,
+                             axis: AxisBase?) -> String
+    {
+        let index = Int(value.rounded())
+        guard values.indices.contains(index), index == Int(value) else { return "" }
+        return _values[index]
+    }
+}

+ 108 - 0
Pods/Charts/Source/Charts/Highlight/BarHighlighter.swift

@@ -0,0 +1,108 @@
+//
+//  BarHighlighter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(BarChartHighlighter)
+open class BarHighlighter: ChartHighlighter
+{
+    open override func getHighlight(x: CGFloat, y: CGFloat) -> Highlight?
+    {
+        guard
+            let barData = (self.chart as? BarChartDataProvider)?.barData,
+            let high = super.getHighlight(x: x, y: y)
+            else { return nil }
+        
+        let pos = getValsForTouch(x: x, y: y)
+
+        if let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet,
+            set.isStacked
+        {
+            return getStackedHighlight(high: high,
+                                       set: set,
+                                       xValue: Double(pos.x),
+                                       yValue: Double(pos.y))
+        }
+        else
+        {
+            return high
+        }
+    }
+    
+    internal override func getDistance(x1: CGFloat, y1: CGFloat, x2: CGFloat, y2: CGFloat) -> CGFloat
+    {
+        return abs(x1 - x2)
+    }
+    
+    internal override var data: ChartData?
+    {
+        return (chart as? BarChartDataProvider)?.barData
+    }
+    
+    /// This method creates the Highlight object that also indicates which value of a stacked BarEntry has been selected.
+    ///
+    /// - Parameters:
+    ///   - high: the Highlight to work with looking for stacked values
+    ///   - set:
+    ///   - xIndex:
+    ///   - yValue:
+    /// - Returns:
+    @objc open func getStackedHighlight(high: Highlight,
+                                  set: IBarChartDataSet,
+                                  xValue: Double,
+                                  yValue: Double) -> Highlight?
+    {
+        guard
+            let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider,
+            let entry = set.entryForXValue(xValue, closestToY: yValue) as? BarChartDataEntry
+            else { return nil }
+        
+        // Not stacked
+        if entry.yValues == nil
+        {
+            return high
+        }
+        
+        guard
+            let ranges = entry.ranges,
+            ranges.count > 0
+            else { return nil }
+
+        let stackIndex = getClosestStackIndex(ranges: ranges, value: yValue)
+        let pixel = chart
+            .getTransformer(forAxis: set.axisDependency)
+            .pixelForValues(x: high.x, y: ranges[stackIndex].to)
+
+        return Highlight(x: entry.x,
+                         y: entry.y,
+                         xPx: pixel.x,
+                         yPx: pixel.y,
+                         dataSetIndex: high.dataSetIndex,
+                         stackIndex: stackIndex,
+                         axis: high.axis)
+    }
+    
+    /// - Parameters:
+    ///   - entry:
+    ///   - value:
+    /// - Returns: The index of the closest value inside the values array / ranges (stacked barchart) to the value given as a parameter.
+    @objc open func getClosestStackIndex(ranges: [Range]?, value: Double) -> Int
+    {
+        guard let ranges = ranges else { return 0 }
+        if let stackIndex = ranges.firstIndex(where: { $0.contains(value) }) {
+            return stackIndex
+        } else {
+            let length = max(ranges.count - 1, 0)
+            return (value > ranges[length].to) ? length : 0
+        }
+    }
+}

+ 180 - 0
Pods/Charts/Source/Charts/Highlight/ChartHighlighter.swift

@@ -0,0 +1,180 @@
+//
+//  ChartHighlighter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+open class ChartHighlighter : NSObject, IHighlighter
+{
+    /// instance of the data-provider
+    @objc open weak var chart: ChartDataProvider?
+    
+    @objc public init(chart: ChartDataProvider)
+    {
+        self.chart = chart
+    }
+    
+    open func getHighlight(x: CGFloat, y: CGFloat) -> Highlight?
+    {
+        let xVal = Double(getValsForTouch(x: x, y: y).x)
+        return getHighlight(xValue: xVal, x: x, y: y)
+    }
+    
+    /// - Parameters:
+    ///   - x:
+    /// - Returns: The corresponding x-pos for a given touch-position in pixels.
+    @objc open func getValsForTouch(x: CGFloat, y: CGFloat) -> CGPoint
+    {
+        guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider else { return .zero }
+        
+        // take any transformer to determine the values
+        return chart.getTransformer(forAxis: .left).valueForTouchPoint(x: x, y: y)
+    }
+    
+    /// - Parameters:
+    ///   - xValue:
+    ///   - x:
+    ///   - y:
+    /// - Returns: The corresponding ChartHighlight for a given x-value and xy-touch position in pixels.
+    @objc open func getHighlight(xValue xVal: Double, x: CGFloat, y: CGFloat) -> Highlight?
+    {
+        guard let chart = chart else { return nil }
+        
+        let closestValues = getHighlights(xValue: xVal, x: x, y: y)
+        guard !closestValues.isEmpty else { return nil }
+        
+        let leftAxisMinDist = getMinimumDistance(closestValues: closestValues, y: y, axis: .left)
+        let rightAxisMinDist = getMinimumDistance(closestValues: closestValues, y: y, axis: .right)
+        
+        let axis: YAxis.AxisDependency = leftAxisMinDist < rightAxisMinDist ? .left : .right
+        
+        let detail = closestSelectionDetailByPixel(closestValues: closestValues, x: x, y: y, axis: axis, minSelectionDistance: chart.maxHighlightDistance)
+        
+        return detail
+    }
+    
+    /// - Parameters:
+    ///   - xValue: the transformed x-value of the x-touch position
+    ///   - x: touch position
+    ///   - y: touch position
+    /// - Returns: A list of Highlight objects representing the entries closest to the given xVal.
+    /// The returned list contains two objects per DataSet (closest rounding up, closest rounding down).
+    @objc open func getHighlights(xValue: Double, x: CGFloat, y: CGFloat) -> [Highlight]
+    {
+        var vals = [Highlight]()
+        
+        guard let data = self.data else { return vals }
+        
+        for i in 0 ..< data.dataSetCount
+        {
+            guard
+                let dataSet = data.getDataSetByIndex(i),
+                dataSet.isHighlightEnabled      // don't include datasets that cannot be highlighted
+                else { continue }
+            
+
+            // extract all y-values from all DataSets at the given x-value.
+            // some datasets (i.e bubble charts) make sense to have multiple values for an x-value. We'll have to find a way to handle that later on. It's more complicated now when x-indices are floating point.
+            vals.append(contentsOf: buildHighlights(dataSet: dataSet, dataSetIndex: i, xValue: xValue, rounding: .closest))
+        }
+        
+        return vals
+    }
+    
+    /// - Returns: An array of `Highlight` objects corresponding to the selected xValue and dataSetIndex.
+    internal func buildHighlights(
+        dataSet set: IChartDataSet,
+        dataSetIndex: Int,
+        xValue: Double,
+        rounding: ChartDataSetRounding) -> [Highlight]
+    {
+        guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider else { return [] }
+        
+        var entries = set.entriesForXValue(xValue)
+        if entries.count == 0, let closest = set.entryForXValue(xValue, closestToY: .nan, rounding: rounding)
+        {
+            // Try to find closest x-value and take all entries for that x-value
+            entries = set.entriesForXValue(closest.x)
+        }
+
+        return entries.map { e in
+            let px = chart.getTransformer(forAxis: set.axisDependency)
+                .pixelForValues(x: e.x, y: e.y)
+            
+            return Highlight(x: e.x, y: e.y, xPx: px.x, yPx: px.y, dataSetIndex: dataSetIndex, axis: set.axisDependency)
+        }
+    }
+
+    // - MARK: - Utilities
+    
+    /// - Returns: The `ChartHighlight` of the closest value on the x-y cartesian axes
+    internal func closestSelectionDetailByPixel(
+        closestValues: [Highlight],
+        x: CGFloat,
+        y: CGFloat,
+        axis: YAxis.AxisDependency?,
+        minSelectionDistance: CGFloat) -> Highlight?
+    {
+        var distance = minSelectionDistance
+        var closest: Highlight?
+        
+        for high in closestValues
+        {
+            if axis == nil || high.axis == axis
+            {
+                let cDistance = getDistance(x1: x, y1: y, x2: high.xPx, y2: high.yPx)
+
+                if cDistance < distance
+                {
+                    closest = high
+                    distance = cDistance
+                }
+            }
+        }
+        
+        return closest
+    }
+    
+    /// - Returns: The minimum distance from a touch-y-value (in pixels) to the closest y-value (in pixels) that is displayed in the chart.
+    internal func getMinimumDistance(
+        closestValues: [Highlight],
+        y: CGFloat,
+        axis: YAxis.AxisDependency
+    ) -> CGFloat {
+        var distance = CGFloat.greatestFiniteMagnitude
+        
+        for high in closestValues where high.axis == axis
+        {
+            let tempDistance = abs(getHighlightPos(high: high) - y)
+            if tempDistance < distance
+            {
+                distance = tempDistance
+            }
+        }
+        
+        return distance
+    }
+    
+    internal func getHighlightPos(high: Highlight) -> CGFloat
+    {
+        return high.yPx
+    }
+    
+    internal func getDistance(x1: CGFloat, y1: CGFloat, x2: CGFloat, y2: CGFloat) -> CGFloat
+    {
+        return hypot(x1 - x2, y1 - y2)
+    }
+    
+    internal var data: ChartData?
+    {
+        return chart?.data
+    }
+}

+ 70 - 0
Pods/Charts/Source/Charts/Highlight/CombinedHighlighter.swift

@@ -0,0 +1,70 @@
+//
+//  CombinedHighlighter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(CombinedChartHighlighter)
+open class CombinedHighlighter: ChartHighlighter
+{
+    /// bar highlighter for supporting stacked highlighting
+    private var barHighlighter: BarHighlighter?
+    
+    @objc public init(chart: CombinedChartDataProvider, barDataProvider: BarChartDataProvider)
+    {
+        super.init(chart: chart)
+        
+        // if there is BarData, create a BarHighlighter
+        self.barHighlighter = barDataProvider.barData == nil ? nil : BarHighlighter(chart: barDataProvider)
+    }
+    
+    open override func getHighlights(xValue: Double, x: CGFloat, y: CGFloat) -> [Highlight]
+    {
+        var vals = [Highlight]()
+        
+        guard
+            let chart = self.chart as? CombinedChartDataProvider,
+            let dataObjects = chart.combinedData?.allData
+            else { return vals }
+        
+        for i in 0..<dataObjects.count
+        {
+            let dataObject = dataObjects[i]
+
+            // in case of BarData, let the BarHighlighter take over
+            if barHighlighter != nil && dataObject is BarChartData,
+                let high = barHighlighter?.getHighlight(x: x, y: y)
+            {
+                high.dataIndex = i
+                vals.append(high)
+            }
+            else
+            {
+                for j in 0..<dataObject.dataSetCount
+                {
+                    guard let dataSet = dataObject.getDataSetByIndex(j),
+                        dataSet.isHighlightEnabled      // don't include datasets that cannot be highlighted
+                        else { continue }
+
+                    let highs = buildHighlights(dataSet: dataSet, dataSetIndex: j, xValue: xValue, rounding: .closest)
+
+                    for high in highs
+                    {
+                        high.dataIndex = i
+                        vals.append(high)
+                    }
+                }
+            }
+        }
+        
+        return vals
+    }
+}

+ 203 - 0
Pods/Charts/Source/Charts/Highlight/Highlight.swift

@@ -0,0 +1,203 @@
+//
+//  Highlight.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(ChartHighlight)
+open class Highlight: NSObject
+{
+    /// the x-value of the highlighted value
+    fileprivate var _x = Double.nan
+    
+    /// the y-value of the highlighted value
+    fileprivate var _y = Double.nan
+    
+    /// the x-pixel of the highlight
+    private var _xPx = CGFloat.nan
+    
+    /// the y-pixel of the highlight
+    private var _yPx = CGFloat.nan
+    
+    /// the index of the data object - in case it refers to more than one
+    @objc open var dataIndex = Int(-1)
+    
+    /// the index of the dataset the highlighted value is in
+    fileprivate var _dataSetIndex = Int(0)
+    
+    /// index which value of a stacked bar entry is highlighted
+    /// 
+    /// **default**: -1
+    fileprivate var _stackIndex = Int(-1)
+    
+    /// the axis the highlighted value belongs to
+    private var _axis: YAxis.AxisDependency = YAxis.AxisDependency.left
+    
+    /// the x-position (pixels) on which this highlight object was last drawn
+    @objc open var drawX: CGFloat = 0.0
+    
+    /// the y-position (pixels) on which this highlight object was last drawn
+    @objc open var drawY: CGFloat = 0.0
+    
+    public override init()
+    {
+        super.init()
+    }
+    
+    /// - Parameters:
+    ///   - x: the x-value of the highlighted value
+    ///   - y: the y-value of the highlighted value
+    ///   - xPx: the x-pixel of the highlighted value
+    ///   - yPx: the y-pixel of the highlighted value
+    ///   - dataIndex: the index of the Data the highlighted value belongs to
+    ///   - dataSetIndex: the index of the DataSet the highlighted value belongs to
+    ///   - stackIndex: references which value of a stacked-bar entry has been selected
+    ///   - axis: the axis the highlighted value belongs to
+    @objc public init(
+        x: Double, y: Double,
+        xPx: CGFloat, yPx: CGFloat,
+        dataIndex: Int,
+        dataSetIndex: Int,
+        stackIndex: Int,
+        axis: YAxis.AxisDependency)
+    {
+        super.init()
+        
+        _x = x
+        _y = y
+        _xPx = xPx
+        _yPx = yPx
+        self.dataIndex = dataIndex
+        _dataSetIndex = dataSetIndex
+        _stackIndex = stackIndex
+        _axis = axis
+    }
+    
+    /// - Parameters:
+    ///   - x: the x-value of the highlighted value
+    ///   - y: the y-value of the highlighted value
+    ///   - xPx: the x-pixel of the highlighted value
+    ///   - yPx: the y-pixel of the highlighted value
+    ///   - dataSetIndex: the index of the DataSet the highlighted value belongs to
+    ///   - stackIndex: references which value of a stacked-bar entry has been selected
+    ///   - axis: the axis the highlighted value belongs to
+    @objc public convenience init(
+        x: Double, y: Double,
+        xPx: CGFloat, yPx: CGFloat,
+        dataSetIndex: Int,
+        stackIndex: Int,
+        axis: YAxis.AxisDependency)
+    {
+        self.init(x: x, y: y, xPx: xPx, yPx: yPx,
+                  dataIndex: 0,
+                  dataSetIndex: dataSetIndex,
+                  stackIndex: stackIndex,
+                  axis: axis)
+    }
+    
+    /// - Parameters:
+    ///   - x: the x-value of the highlighted value
+    ///   - y: the y-value of the highlighted value
+    ///   - xPx: the x-pixel of the highlighted value
+    ///   - yPx: the y-pixel of the highlighted value
+    ///   - dataIndex: the index of the Data the highlighted value belongs to
+    ///   - dataSetIndex: the index of the DataSet the highlighted value belongs to
+    ///   - stackIndex: references which value of a stacked-bar entry has been selected
+    ///   - axis: the axis the highlighted value belongs to
+    @objc public init(
+        x: Double, y: Double,
+        xPx: CGFloat, yPx: CGFloat,
+        dataSetIndex: Int,
+        axis: YAxis.AxisDependency)
+    {
+        super.init()
+        
+        _x = x
+        _y = y
+        _xPx = xPx
+        _yPx = yPx
+        _dataSetIndex = dataSetIndex
+        _axis = axis
+    }
+    
+    /// - Parameters:
+    ///   - x: the x-value of the highlighted value
+    ///   - y: the y-value of the highlighted value
+    ///   - dataSetIndex: the index of the DataSet the highlighted value belongs to
+    ///   - dataIndex: The data index to search in (only used in CombinedChartView currently)
+    @objc public init(x: Double, y: Double, dataSetIndex: Int, dataIndex: Int = -1)
+    {
+        _x = x
+        _y = y
+        _dataSetIndex = dataSetIndex
+        self.dataIndex = dataIndex
+    }
+    
+    /// - Parameters:
+    ///   - x: the x-value of the highlighted value
+    ///   - dataSetIndex: the index of the DataSet the highlighted value belongs to
+    ///   - stackIndex: references which value of a stacked-bar entry has been selected
+    @objc public convenience init(x: Double, dataSetIndex: Int, stackIndex: Int)
+    {
+        self.init(x: x, y: Double.nan, dataSetIndex: dataSetIndex)
+        _stackIndex = stackIndex
+    }
+    
+    @objc open var x: Double { return _x }
+    @objc open var y: Double { return _y }
+    @objc open var xPx: CGFloat { return _xPx }
+    @objc open var yPx: CGFloat { return _yPx }
+    @objc open var dataSetIndex: Int { return _dataSetIndex }
+    @objc open var stackIndex: Int { return _stackIndex }
+    @objc open var axis: YAxis.AxisDependency { return _axis }
+    
+    @objc open var isStacked: Bool { return _stackIndex >= 0 }
+    
+    /// Sets the x- and y-position (pixels) where this highlight was last drawn.
+    @objc open func setDraw(x: CGFloat, y: CGFloat)
+    {
+        self.drawX = x
+        self.drawY = y
+    }
+    
+    /// Sets the x- and y-position (pixels) where this highlight was last drawn.
+    @objc open func setDraw(pt: CGPoint)
+    {
+        self.drawX = pt.x
+        self.drawY = pt.y
+    }
+
+    // MARK: NSObject
+    
+    open override var description: String
+    {
+        return "Highlight, x: \(_x), y: \(_y), dataIndex (combined charts): \(dataIndex), dataSetIndex: \(_dataSetIndex), stackIndex (only stacked barentry): \(_stackIndex)"
+    }
+}
+
+
+// MARK: Equatable
+extension Highlight /*: Equatable*/ {
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let object = object as? Highlight else { return false }
+
+        if self === object
+        {
+            return true
+        }
+
+        return _x == object._x
+            && _y == object._y
+            && dataIndex == object.dataIndex
+            && _dataSetIndex == object._dataSetIndex
+            && _stackIndex == object._stackIndex
+    }
+}

+ 63 - 0
Pods/Charts/Source/Charts/Highlight/HorizontalBarHighlighter.swift

@@ -0,0 +1,63 @@
+//
+//  HorizontalBarHighlighter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(HorizontalBarChartHighlighter)
+open class HorizontalBarHighlighter: BarHighlighter
+{
+    open override func getHighlight(x: CGFloat, y: CGFloat) -> Highlight?
+    {
+        guard let barData = self.chart?.data as? BarChartData else { return nil }
+
+        let pos = getValsForTouch(x: y, y: x)
+        guard let high = getHighlight(xValue: Double(pos.y), x: y, y: x) else { return nil }
+
+        if let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet,
+            set.isStacked
+        {
+            return getStackedHighlight(high: high,
+                                       set: set,
+                                       xValue: Double(pos.y),
+                                       yValue: Double(pos.x))
+        }
+
+        return high
+    }
+    
+    internal override func buildHighlights(
+        dataSet set: IChartDataSet,
+        dataSetIndex: Int,
+        xValue: Double,
+        rounding: ChartDataSetRounding) -> [Highlight]
+    {
+        guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider else { return [] }
+        
+        var entries = set.entriesForXValue(xValue)
+        if entries.count == 0, let closest = set.entryForXValue(xValue, closestToY: .nan, rounding: rounding)
+        {
+            // Try to find closest x-value and take all entries for that x-value
+            entries = set.entriesForXValue(closest.x)
+        }
+
+        return entries.map { e in
+            let px = chart.getTransformer(forAxis: set.axisDependency)
+                .pixelForValues(x: e.y, y: e.x)
+            return Highlight(x: e.x, y: e.y, xPx: px.x, yPx: px.y, dataSetIndex: dataSetIndex, axis: set.axisDependency)
+        }
+    }
+    
+    internal override func getDistance(x1: CGFloat, y1: CGFloat, x2: CGFloat, y2: CGFloat) -> CGFloat
+    {
+        return abs(y1 - y2)
+    }
+}

+ 23 - 0
Pods/Charts/Source/Charts/Highlight/IHighlighter.swift

@@ -0,0 +1,23 @@
+//
+//  IHighlighter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(IChartHighlighter)
+public protocol IHighlighter: class
+{
+    /// - Parameters:
+    ///   - x:
+    ///   - y:
+    /// - Returns: A Highlight object corresponding to the given x- and y- touch positions in pixels.
+    func getHighlight(x: CGFloat, y: CGFloat) -> Highlight?
+}

+ 27 - 0
Pods/Charts/Source/Charts/Highlight/PieHighlighter.swift

@@ -0,0 +1,27 @@
+//
+//  PieHighlighter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(PieChartHighlighter)
+open class PieHighlighter: PieRadarHighlighter
+{
+    open override func closestHighlight(index: Int, x: CGFloat, y: CGFloat) -> Highlight?
+    {
+        guard
+            let set = chart?.data?.dataSets[0],
+            let entry = set.entryForIndex(index)
+            else { return nil }
+                
+        return Highlight(x: Double(index), y: entry.y, xPx: x, yPx: y, dataSetIndex: 0, axis: set.axisDependency)
+    }
+}

+ 61 - 0
Pods/Charts/Source/Charts/Highlight/PieRadarHighlighter.swift

@@ -0,0 +1,61 @@
+//
+//  PieRadarHighlighter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(PieRadarChartHighlighter)
+open class PieRadarHighlighter: ChartHighlighter
+{    
+    open override func getHighlight(x: CGFloat, y: CGFloat) -> Highlight?
+    {
+        guard let chart = self.chart as? PieRadarChartViewBase else { return nil }
+        
+        let touchDistanceToCenter = chart.distanceToCenter(x: x, y: y)
+        
+        // check if a slice was touched
+        guard touchDistanceToCenter <= chart.radius else
+        {
+            // if no slice was touched, highlight nothing
+            return nil
+        }
+
+        var angle = chart.angleForPoint(x: x ,y: y)
+
+        if chart is PieChartView
+        {
+            angle /= CGFloat(chart.chartAnimator.phaseY)
+        }
+
+        let index = chart.indexForAngle(angle)
+
+        // check if the index could be found
+        if index < 0 || index >= chart.data?.maxEntryCountSet?.entryCount ?? 0
+        {
+            return nil
+        }
+        else
+        {
+            return closestHighlight(index: index, x: x, y: y)
+        }
+
+    }
+    
+    /// - Parameters:
+    ///   - index:
+    ///   - x:
+    ///   - y:
+    /// - Returns: The closest Highlight object of the given objects based on the touch position inside the chart.
+    @objc open func closestHighlight(index: Int, x: CGFloat, y: CGFloat) -> Highlight?
+    {
+        fatalError("closestHighlight(index, x, y) cannot be called on PieRadarChartHighlighter")
+    }
+}

+ 78 - 0
Pods/Charts/Source/Charts/Highlight/RadarHighlighter.swift

@@ -0,0 +1,78 @@
+//
+//  RadarHighlighter.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc(RadarChartHighlighter)
+open class RadarHighlighter: PieRadarHighlighter
+{
+    open override func closestHighlight(index: Int, x: CGFloat, y: CGFloat) -> Highlight?
+    {
+        guard let chart = self.chart as? RadarChartView else { return nil }
+        
+        let highlights = getHighlights(forIndex: index)
+        
+        let distanceToCenter = Double(chart.distanceToCenter(x: x, y: y) / chart.factor)
+        
+        var closest: Highlight?
+        var distance = Double.greatestFiniteMagnitude
+        
+        for high in highlights
+        {
+            let cdistance = abs(high.y - distanceToCenter)
+            if cdistance < distance
+            {
+                closest = high
+                distance = cdistance
+            }
+        }
+        
+        return closest
+    }
+    
+    /// - Parameters:
+    ///   - index:
+    /// - Returns: An array of Highlight objects for the given index.
+    /// The Highlight objects give information about the value at the selected index and DataSet it belongs to.
+    internal func getHighlights(forIndex index: Int) -> [Highlight]
+    {
+        var vals = [Highlight]()
+        
+        guard
+            let chart = self.chart as? RadarChartView,
+            let chartData = chart.data
+            else { return vals }
+        
+        let phaseX = chart.chartAnimator.phaseX
+        let phaseY = chart.chartAnimator.phaseY
+        let sliceangle = chart.sliceAngle
+        let factor = chart.factor
+
+        for i in chartData.dataSets.indices
+        {
+            guard
+                let dataSet = chartData.getDataSetByIndex(i),
+                let entry = dataSet.entryForIndex(index)
+                else { continue }
+            
+            let y = (entry.y - chart.chartYMin)
+            
+            let p = chart.centerOffsets.moving(distance: CGFloat(y) * factor * CGFloat(phaseY),
+                                               atAngle: sliceangle * CGFloat(index) * CGFloat(phaseX) + chart.rotationAngle)
+
+            let highlight = Highlight(x: Double(index), y: entry.y, xPx: p.x, yPx: p.y, dataSetIndex: i, axis: dataSet.axisDependency)
+            vals.append(highlight)
+        }
+        
+        return vals
+    }
+}

+ 52 - 0
Pods/Charts/Source/Charts/Highlight/Range.swift

@@ -0,0 +1,52 @@
+//
+//  Range.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+
+@objc(ChartRange)
+open class Range: NSObject
+{
+    @objc open var from: Double
+    @objc open var to: Double
+    
+    @objc public init(from: Double, to: Double)
+    {
+        self.from = from
+        self.to = to
+        
+        super.init()
+    }
+
+    /// - Parameters:
+    ///   - value:
+    /// - Returns: `true` if this range contains (if the value is in between) the given value, `false` ifnot.
+    @objc open func contains(_ value: Double) -> Bool
+    {
+        if value > from && value <= to
+        {
+            return true
+        }
+        else
+        {
+            return false
+        }
+    }
+    
+    @objc open func isLarger(_ value: Double) -> Bool
+    {
+        return value > to
+    }
+    
+    @objc open func isSmaller(_ value: Double) -> Bool
+    {
+        return value < from
+    }
+}

+ 23 - 0
Pods/Charts/Source/Charts/Interfaces/BarChartDataProvider.swift

@@ -0,0 +1,23 @@
+//
+//  BarChartDataProvider.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol BarChartDataProvider: BarLineScatterCandleBubbleChartDataProvider
+{
+    var barData: BarChartData? { get }
+    
+    var isDrawBarShadowEnabled: Bool { get }
+    var isDrawValueAboveBarEnabled: Bool { get }
+    var isHighlightFullBarEnabled: Bool { get }
+}

+ 23 - 0
Pods/Charts/Source/Charts/Interfaces/BarLineScatterCandleBubbleChartDataProvider.swift

@@ -0,0 +1,23 @@
+//
+//  BarLineScatterCandleBubbleChartDataProvider.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol BarLineScatterCandleBubbleChartDataProvider: ChartDataProvider
+{
+    func getTransformer(forAxis: YAxis.AxisDependency) -> Transformer
+    func isInverted(axis: YAxis.AxisDependency) -> Bool
+    
+    var lowestVisibleX: Double { get }
+    var highestVisibleX: Double { get }
+}

+ 19 - 0
Pods/Charts/Source/Charts/Interfaces/BubbleChartDataProvider.swift

@@ -0,0 +1,19 @@
+//
+//  BubbleChartDataProvider.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol BubbleChartDataProvider: BarLineScatterCandleBubbleChartDataProvider
+{
+    var bubbleData: BubbleChartData? { get }
+}

+ 19 - 0
Pods/Charts/Source/Charts/Interfaces/CandleChartDataProvider.swift

@@ -0,0 +1,19 @@
+//
+//  CandleChartDataProvider.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol CandleChartDataProvider: BarLineScatterCandleBubbleChartDataProvider
+{
+    var candleData: CandleChartData? { get }
+}

+ 39 - 0
Pods/Charts/Source/Charts/Interfaces/ChartDataProvider.swift

@@ -0,0 +1,39 @@
+//
+//  ChartDataProvider.swift
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol ChartDataProvider
+{
+    /// The minimum x-value of the chart, regardless of zoom or translation.
+    var chartXMin: Double { get }
+    
+    /// The maximum x-value of the chart, regardless of zoom or translation.
+    var chartXMax: Double { get }
+    
+    /// The minimum y-value of the chart, regardless of zoom or translation.
+    var chartYMin: Double { get }
+    
+    /// The maximum y-value of the chart, regardless of zoom or translation.
+    var chartYMax: Double { get }
+    
+    var maxHighlightDistance: CGFloat { get }
+    
+    var xRange: Double { get }
+    
+    var centerOffsets: CGPoint { get }
+    
+    var data: ChartData? { get }
+    
+    var maxVisibleCount: Int { get }
+}

+ 19 - 0
Pods/Charts/Source/Charts/Interfaces/CombinedChartDataProvider.swift

@@ -0,0 +1,19 @@
+//
+//  CombinedChartDataProvider.swoft
+//  Charts
+//
+//  Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
+//  A port of MPAndroidChart for iOS
+//  Licensed under Apache License 2.0
+//
+//  https://github.com/danielgindi/Charts
+//
+
+import Foundation
+import CoreGraphics
+
+@objc
+public protocol CombinedChartDataProvider: LineChartDataProvider, BarChartDataProvider, BubbleChartDataProvider, CandleChartDataProvider, ScatterChartDataProvider
+{
+    var combinedData: CombinedChartData? { get }
+}

+ 0 - 0
Pods/Charts/Source/Charts/Interfaces/LineChartDataProvider.swift


この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません