remove Carthage vendor folder;

This commit is contained in:
Serhiy Mytrovtsiy
2020-01-22 23:14:57 +01:00
parent 0a3a4b2cd9
commit d9d51bdc84
698 changed files with 1 additions and 82274 deletions

2
.gitignore vendored
View File

@@ -1,7 +1,7 @@
.DS_Store
Pods
Carthage/Build/
Carthage
build
xcuserdata

View File

@@ -1,33 +0,0 @@
> Please fill out this template when filing an issue.
> All lines beginning with an symbol instruct you with what info we expect. You can delete those lines once you've filled in the info.
>
> Per our [*CONTRIBUTING guidelines](https://github.com/jjatie/Charts/blob/master/CONTRIBUTING.md), we use GitHub for
> bugs and feature requests, not general support. Other issues should be opened on Stack Overflow with the tag [`ios-charts`.](https://stackoverflow.com/questions/tagged/ios-charts)
>
> Please remove this line and everything above it before submitting.
* [ ] I've read, understood, and done my best to follow the [*CONTRIBUTING guidelines](https://github.com/jjatie/Charts/blob/master/CONTRIBUTING.md).
## What did you do?
Please replace this with what you did.
## What did you expect to happen?
Please replace this with what you expected to happen.
## What happened instead?
Please replace this with of what happened instead.
## Charts Environment
**Charts version/Branch/Commit Number:**
**Xcode version:**
**Swift version:**
**Platform(s) running Charts:**
**macOS version running Xcode:**
## Demo Project
Please link to or upload a project we can download that reproduces the issue.

View File

@@ -1,13 +0,0 @@
### Issue Link :link:
<!-- What issue does this fix? If an issue doesn't exist, remove this section. -->
### Goals :soccer:
<!-- List the high-level objectives of this pull request. -->
<!-- Include any relevant context. -->
### Implementation Details :construction:
<!-- Explain the reasoning behind any architectural changes. -->
<!-- Highlight any new functionality. -->
### Testing Details :mag:
<!-- Describe what tests you've added for your changes. -->

View File

@@ -1,75 +0,0 @@
# OS X
.DS_Store
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData/
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/
## Other
*.xccheckout
*.moved-aside
*.xcuserstate
## Obj-C/Swift specific
DerivedData
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
.build/
project.xcworkspace
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
Carthage
Charts.framework.zip
ChartsRealm.framework.zip
.swiftpm/

View File

@@ -1,25 +0,0 @@
language: objective-c
osx_image: xcode11
matrix:
include:
- osx_image: xcode11
env: PLATFORM="iOS"
- osx_image: xcode11
env: PLATFORM="tvOS"
- osx_image: xcode11
env: PLATFORM="macOS"
env:
global:
- LANG=en_US.UTF-8
- secure: HRl5Cg3/LmTJYCSDGtV8Fiqf6OgWXR6C5YkNviOElU9YmcCTvnmE7MCm+gK8hJNIQ2mWCBTlxTC7jJxeYlx0D+JQ6IhRc75B4zXgbtth6HCzlvhWDcBbNU/K+JPDjy2EAoVgvf8Xseq6GqM4WcVg2Pwr9PS3aaH/SKDE6yVoPXRM2wXRAxIdxayqm/RQgG88jAKgg+Ub5DKW/c9NLLbUf/WdY9SgQDJtqeZCMv7G3/IzW34KZgVPsqSrPByzZXbf7KgYkYLQlscH4mcUctk1qxhdCae//zcgUZo/utpXWbPXQqtvDpuqrg9IRvoGxa/D1I7dLSJsVnk4aP7RW18vn4HJ82C2AiEp+lU2TQE9y5lXcGssZVIa5aZNTWL90HVer3Kg6AnHffvdCSZ/UHsMZJFURUXL9fRIlWVGuEDeQOqlV6lUmEtp/BiEdV4D5PuCyT6snsmEwkc51goyqh6uS6XhJyqYEQdxdoybznwp91tVmASsRybppIGHTkcWN5csF4zQt40tEwd8LoqM+bBUo0wxKiKsNsecL4JA+YDYs2saZY9U3s8jAaIon+qDu071fPRaPEvBhYHYDhy4cTvBXibyGUYGHkrgLu0w19wDfHcJKt2In58yOmaCCLNoTGp/ZLNVRyZ8VDlj/NdJ2dWpMsL2Aj7OxU065kCL2FlvuRU=
cache:
- bundler
before_install:
- brew update
- brew upgrade carthage || true
- carthage version
- carthage bootstrap --platform $PLATFORM
script:
- bundle exec rake ci[$PLATFORM]
after_success:
- bash <(curl -s https://codecov.io/bash)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -1,49 +0,0 @@
# How to contribute
Bug-fixes and features often come from users of the Charts framework, and improving it greatly. We want to keep it as easy as possible to contribute changes that improve the experience for users all around the world. There are a few guidelines that we
need contributors to follow so that we can have a chance of keeping on
top of things.
## Simple issues and bug reports
If you are reporting a bug which can be observed visually, please add to your issue either:
* Screenshots, if the bug is easily explainable
* A working sample project that we can compile, run, and immediately observe the issue
## Getting Started with Contributions
* Make sure you have a [GitHub account](https://github.com/signup/free)
* Submit a ticket for your issue, assuming one does not already exist.
* Clearly describe the issue including steps to reproduce when it is a bug.
* Make sure you fill in the earliest version (or commit number) that you know has the issue.
* Fork the repository on GitHub
## Making Changes
* Create a topic branch from where you want to base your work. This is usually the master branch.
* Make commits of logical units.
* Make sure your code conforms to the code style around it. It's easy, just look around!
* If you have made changes back and forth, or have made merges, your commit history might look messy and hard to understand. A single issue or change should still be in one commit. So please squash those commits together and rebase them however you need to - to make our lives easier when reading it later.
* Check for unnecessary whitespace with `git diff --check` before committing.
* Make sure your commit messages are in the proper format.
````
First line must be up to 50 chars (Fixes #1234)
The first line should be a short statement as to what have changed, and should also include an issue number, prefixed with a hash.
The body of the message comes after an empty new line, and describes the changes
more thoroughly, especially if there was a special case handled there,
or maybe some trickery that only code wizards can understand.
````
* Make sure you have tested your changes well.
* If your changes could theoretically affect some other component or case, which you do not necessarily use, you still have to test it.
* Create a Pull Request from your topic branch to the relevant branch in the main repo. If you go to the main repo of the framework, you'll see a big green button which pretty much prepares the PR for you. You just have to hit it.
## Making Trivial Changes
For changes of a trivial nature to comments and documentation, it is not
always necessary to create a new ticket. In this case, it is
appropriate to start the first line of a commit with '(doc)' instead of
a ticket number. Even the default commit message the GitHub generates is fine with us.

View File

@@ -1 +0,0 @@
github "uber/ios-snapshot-test-case"

View File

@@ -1 +0,0 @@
github "uber/ios-snapshot-test-case" "6.1.0"

View File

@@ -1,19 +0,0 @@
Pod::Spec.new do |s|
s.name = "Charts"
s.version = "3.4.0"
s.summary = "Charts is a powerful & easy to use chart library for iOS, tvOS and OSX (and Android)"
s.homepage = "https://github.com/danielgindi/Charts"
s.license = { :type => "Apache License, Version 2.0", :file => "LICENSE" }
s.authors = "Daniel Cohen Gindi", "Philipp Jahoda"
s.ios.deployment_target = "8.0"
s.tvos.deployment_target = "9.0"
s.osx.deployment_target = "10.11"
s.source = { :git => "https://github.com/danielgindi/Charts.git", :tag => "v#{s.version}" }
s.default_subspec = "Core"
s.swift_version = '5.0'
s.cocoapods_version = '>= 1.5.0'
s.subspec "Core" do |ss|
ss.source_files = "Source/Charts/**/*.swift"
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,88 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A58A4ED274A941CA248EA921"
BuildableName = "Charts.framework"
BlueprintName = "Charts"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F2749BD5443C1CB5FE2080C2"
BuildableName = "ChartsTests.xctest"
BlueprintName = "ChartsTests"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A58A4ED274A941CA248EA921"
BuildableName = "Charts.framework"
BlueprintName = "Charts"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</MacroExpansion>
<EnvironmentVariables>
<EnvironmentVariable
key = "FB_REFERENCE_IMAGE_DIR"
value = "$(SOURCE_ROOT)/Tests/ReferenceImages"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -1,89 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F2749BD5443C1CB5FE2080C2"
BuildableName = "ChartsTests.xctest"
BlueprintName = "ChartsTests"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
codeCoverageEnabled = "YES"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F2749BD5443C1CB5FE2080C2"
BuildableName = "ChartsTests.xctest"
BlueprintName = "ChartsTests"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F2749BD5443C1CB5FE2080C2"
BuildableName = "ChartsTests.xctest"
BlueprintName = "ChartsTests"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</MacroExpansion>
<EnvironmentVariables>
<EnvironmentVariable
key = "FB_REFERENCE_IMAGE_DIR"
value = "$(SOURCE_ROOT)/Tests/ReferenceImages"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "container:Charts.xcodeproj">
</FileRef>
<FileRef
location = "group:ChartsDemo-iOS/ChartsDemo-iOS.xcodeproj">
</FileRef>
<FileRef
location = "group:ChartsDemo-macOS/ChartsDemo-macOS.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -1,8 +0,0 @@
<?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>

View File

@@ -1,996 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
06A5D1861B78675500915098 /* UIGraphics+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06A5D1851B78675500915098 /* UIGraphics+Extensions.swift */; };
55E356531ADC63BF00A57971 /* BubbleChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E356521ADC63BF00A57971 /* BubbleChartView.swift */; };
55E356571ADC63CD00A57971 /* BubbleChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E356541ADC63CD00A57971 /* BubbleChartData.swift */; };
55E356581ADC63CD00A57971 /* BubbleChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E356551ADC63CD00A57971 /* BubbleChartDataEntry.swift */; };
55E356591ADC63CD00A57971 /* BubbleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E356561ADC63CD00A57971 /* BubbleChartDataSet.swift */; };
55E3565B1ADC63EB00A57971 /* BubbleChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E3565A1ADC63EB00A57971 /* BubbleChartRenderer.swift */; };
5B0032451B6524AD00B6A2FE /* ChartHighlight.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0032441B6524AD00B6A2FE /* ChartHighlight.swift */; };
5B0032471B6524D300B6A2FE /* ChartRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0032461B6524D300B6A2FE /* ChartRange.swift */; };
5B0032491B6525FC00B6A2FE /* ChartHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0032481B6525FC00B6A2FE /* ChartHighlighter.swift */; };
5B00324B1B652BF900B6A2FE /* BarChartHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B00324A1B652BF900B6A2FE /* BarChartHighlighter.swift */; };
5B00324D1B65351C00B6A2FE /* HorizontalBarChartHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B00324C1B65351C00B6A2FE /* HorizontalBarChartHighlighter.swift */; };
5B378F171AD500A4009414A4 /* ChartAnimationEasing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B378F161AD500A4009414A4 /* ChartAnimationEasing.swift */; };
5B4BCD401AA9C4930063F019 /* ChartTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B4BCD3F1AA9C4930063F019 /* ChartTransformer.swift */; };
5B6556F71AB72BA000FFBFD3 /* ChartComponentBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6556F61AB72BA000FFBFD3 /* ChartComponentBase.swift */; };
5B6654D91BB0A86F00890030 /* ChartDefaultXAxisValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6654D51BB0A86F00890030 /* ChartDefaultXAxisValueFormatter.swift */; settings = {ASSET_TAGS = (); }; };
5B6654DA1BB0A86F00890030 /* ChartFillFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6654D61BB0A86F00890030 /* ChartFillFormatter.swift */; settings = {ASSET_TAGS = (); }; };
5B6654DB1BB0A86F00890030 /* ChartXAxisValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6654D71BB0A86F00890030 /* ChartXAxisValueFormatter.swift */; settings = {ASSET_TAGS = (); }; };
5B680D1D1A9D16F90026A057 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B680D1C1A9D16F90026A057 /* UIKit.framework */; };
5B680D1F1A9D17C30026A057 /* ChartAxisBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6A1A9D151C00CE82E1 /* ChartAxisBase.swift */; };
5B680D201A9D17C30026A057 /* ChartLegend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6B1A9D151C00CE82E1 /* ChartLegend.swift */; };
5B680D211A9D17C30026A057 /* ChartLimitLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6C1A9D151C00CE82E1 /* ChartLimitLine.swift */; };
5B680D221A9D17C30026A057 /* ChartXAxis.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6D1A9D151C00CE82E1 /* ChartXAxis.swift */; };
5B680D231A9D17C30026A057 /* ChartYAxis.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6E1A9D151C00CE82E1 /* ChartYAxis.swift */; };
5B680D271A9D17C30026A057 /* ChartColorTemplates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC791A9D151C00CE82E1 /* ChartColorTemplates.swift */; };
5B680D291A9D17C30026A057 /* ChartSelectionDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC7B1A9D151C00CE82E1 /* ChartSelectionDetail.swift */; };
5B680D2A1A9D17C30026A057 /* ChartUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC7C1A9D151C00CE82E1 /* ChartUtils.swift */; };
5B680D3D1A9D1AD90026A057 /* Charts.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B680D3C1A9D1AD90026A057 /* Charts.h */; settings = {ATTRIBUTES = (Public, ); }; };
5B6A546B1AA5C23F000F57C2 /* ChartMarker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A546A1AA5C23F000F57C2 /* ChartMarker.swift */; };
5B6A546E1AA5D2DC000F57C2 /* ChartAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A546D1AA5D2DC000F57C2 /* ChartAnimator.swift */; };
5B6A54701AA5DB34000F57C2 /* ChartRendererBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A546F1AA5DB34000F57C2 /* ChartRendererBase.swift */; };
5B6A54741AA5DEDC000F57C2 /* ChartXAxisRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54731AA5DEDC000F57C2 /* ChartXAxisRenderer.swift */; };
5B6A54761AA5DEE3000F57C2 /* ChartXAxisRendererBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54751AA5DEE3000F57C2 /* ChartXAxisRendererBarChart.swift */; };
5B6A54781AA5DEF0000F57C2 /* ChartXAxisRendererRadarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54771AA5DEF0000F57C2 /* ChartXAxisRendererRadarChart.swift */; };
5B6A547C1AA5DF02000F57C2 /* ChartXAxisRendererHorizontalBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A547B1AA5DF02000F57C2 /* ChartXAxisRendererHorizontalBarChart.swift */; };
5B6A547E1AA5DF1A000F57C2 /* ChartYAxisRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A547D1AA5DF1A000F57C2 /* ChartYAxisRenderer.swift */; };
5B6A54801AA5DF28000F57C2 /* ChartYAxisRendererHorizontalBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A547F1AA5DF28000F57C2 /* ChartYAxisRendererHorizontalBarChart.swift */; };
5B6A54821AA5DF34000F57C2 /* ChartYAxisRendererRadarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54811AA5DF34000F57C2 /* ChartYAxisRendererRadarChart.swift */; };
5B6A54851AA669C9000F57C2 /* ScatterChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54841AA669C9000F57C2 /* ScatterChartRenderer.swift */; };
5B6A54871AA669F4000F57C2 /* RadarChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54861AA669F4000F57C2 /* RadarChartRenderer.swift */; };
5B6A54891AA66A1A000F57C2 /* PieChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54881AA66A1A000F57C2 /* PieChartRenderer.swift */; };
5B6A548B1AA66A3D000F57C2 /* LineChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A548A1AA66A3D000F57C2 /* LineChartRenderer.swift */; };
5B6A548D1AA66A60000F57C2 /* ChartLegendRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A548C1AA66A60000F57C2 /* ChartLegendRenderer.swift */; };
5B6A548F1AA66A7A000F57C2 /* HorizontalBarChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A548E1AA66A7A000F57C2 /* HorizontalBarChartRenderer.swift */; };
5B6A54911AA66A8D000F57C2 /* ChartDataRendererBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54901AA66A8D000F57C2 /* ChartDataRendererBase.swift */; };
5B6A54931AA66AAB000F57C2 /* CombinedChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54921AA66AAB000F57C2 /* CombinedChartRenderer.swift */; };
5B6A54951AA66AC0000F57C2 /* CandleStickChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54941AA66AC0000F57C2 /* CandleStickChartRenderer.swift */; };
5B6A54971AA66AD2000F57C2 /* BarChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54961AA66AD2000F57C2 /* BarChartRenderer.swift */; };
5B6A54991AA66B14000F57C2 /* BarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54981AA66B14000F57C2 /* BarChartView.swift */; };
5B6A549B1AA66B2C000F57C2 /* BarLineChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A549A1AA66B2C000F57C2 /* BarLineChartViewBase.swift */; };
5B6A549D1AA66B3C000F57C2 /* CandleStickChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A549C1AA66B3C000F57C2 /* CandleStickChartView.swift */; };
5B6A549F1AA66B59000F57C2 /* CombinedChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A549E1AA66B59000F57C2 /* CombinedChartView.swift */; };
5B6A54A31AA66B7C000F57C2 /* LineChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54A21AA66B7C000F57C2 /* LineChartView.swift */; };
5B6A54A51AA66B92000F57C2 /* PieChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54A41AA66B92000F57C2 /* PieChartView.swift */; };
5B6A54A71AA66BA7000F57C2 /* PieRadarChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54A61AA66BA7000F57C2 /* PieRadarChartViewBase.swift */; };
5B6A54A91AA66BBA000F57C2 /* RadarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54A81AA66BBA000F57C2 /* RadarChartView.swift */; };
5B6A54AB1AA66BC8000F57C2 /* ScatterChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54AA1AA66BC8000F57C2 /* ScatterChartView.swift */; };
5B6A54AC1AA66C1E000F57C2 /* ChartAxisRendererBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54711AA5DCA8000F57C2 /* ChartAxisRendererBase.swift */; };
5B6A54CC1AA74516000F57C2 /* BarChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54B71AA74516000F57C2 /* BarChartData.swift */; };
5B6A54CD1AA74516000F57C2 /* BarChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54B81AA74516000F57C2 /* BarChartDataEntry.swift */; };
5B6A54CE1AA74516000F57C2 /* BarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54B91AA74516000F57C2 /* BarChartDataSet.swift */; };
5B6A54CF1AA74516000F57C2 /* BarLineScatterCandleBubbleChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BA1AA74516000F57C2 /* BarLineScatterCandleBubbleChartData.swift */; };
5B6A54D01AA74516000F57C2 /* BarLineScatterCandleBubbleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BB1AA74516000F57C2 /* BarLineScatterCandleBubbleChartDataSet.swift */; };
5B6A54D11AA74516000F57C2 /* CandleChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BC1AA74516000F57C2 /* CandleChartData.swift */; };
5B6A54D21AA74516000F57C2 /* CandleChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BD1AA74516000F57C2 /* CandleChartDataEntry.swift */; };
5B6A54D31AA74516000F57C2 /* CandleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BE1AA74516000F57C2 /* CandleChartDataSet.swift */; };
5B6A54D41AA74516000F57C2 /* CombinedChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BF1AA74516000F57C2 /* CombinedChartData.swift */; };
5B6A54D51AA74516000F57C2 /* ChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C01AA74516000F57C2 /* ChartData.swift */; };
5B6A54D61AA74516000F57C2 /* ChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C11AA74516000F57C2 /* ChartDataEntry.swift */; };
5B6A54D71AA74516000F57C2 /* ChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C21AA74516000F57C2 /* ChartDataSet.swift */; };
5B6A54D81AA74516000F57C2 /* LineChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C31AA74516000F57C2 /* LineChartData.swift */; };
5B6A54D91AA74516000F57C2 /* LineChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C41AA74516000F57C2 /* LineChartDataSet.swift */; };
5B6A54DA1AA74516000F57C2 /* LineRadarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C51AA74516000F57C2 /* LineRadarChartDataSet.swift */; };
5B6A54DB1AA74516000F57C2 /* PieChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C61AA74516000F57C2 /* PieChartData.swift */; };
5B6A54DC1AA74516000F57C2 /* PieChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C71AA74516000F57C2 /* PieChartDataSet.swift */; };
5B6A54DD1AA74516000F57C2 /* RadarChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C81AA74516000F57C2 /* RadarChartData.swift */; };
5B6A54DE1AA74516000F57C2 /* RadarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C91AA74516000F57C2 /* RadarChartDataSet.swift */; };
5B6A54DF1AA74516000F57C2 /* ScatterChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54CA1AA74516000F57C2 /* ScatterChartData.swift */; };
5B6A54E01AA74516000F57C2 /* ScatterChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54CB1AA74516000F57C2 /* ScatterChartDataSet.swift */; };
5B8FE2AF1B68F8F600910C9E /* LineScatterCandleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8FE2AE1B68F8F600910C9E /* LineScatterCandleChartDataSet.swift */; };
5B8FE2B11B68FFF900910C9E /* LineScatterCandleRadarChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8FE2B01B68FFF900910C9E /* LineScatterCandleRadarChartRenderer.swift */; };
5BA8EC7D1A9D151C00CE82E1 /* ChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC671A9D151C00CE82E1 /* ChartViewBase.swift */; };
5BA8EC881A9D151C00CE82E1 /* ChartDataApproximatorFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC751A9D151C00CE82E1 /* ChartDataApproximatorFilter.swift */; };
5BA8EC891A9D151C00CE82E1 /* ChartDataBaseFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC761A9D151C00CE82E1 /* ChartDataBaseFilter.swift */; };
5BAAA8561BB08E1D00B20D4D /* CombinedHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BAAA8551BB08E1D00B20D4D /* CombinedHighlighter.swift */; settings = {ASSET_TAGS = (); }; };
5BB6EC1D1ACC28AB006E9C25 /* ChartTransformerHorizontalBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB6EC1C1ACC28AB006E9C25 /* ChartTransformerHorizontalBarChart.swift */; };
5BD8F06D1AB897D500566E05 /* ChartViewPortHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD8F06C1AB897D500566E05 /* ChartViewPortHandler.swift */; };
5BD8F06E1AB89AD800566E05 /* HorizontalBarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54A01AA66B6A000F57C2 /* HorizontalBarChartView.swift */; };
A52C5C3A1BAC5CA400594CDD /* ChartsTV.h in Headers */ = {isa = PBXBuildFile; fileRef = A52C5C391BAC5CA400594CDD /* ChartsTV.h */; settings = {ATTRIBUTES = (Public, ); }; };
A52C5C3F1BAC5D1100594CDD /* ChartAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A546D1AA5D2DC000F57C2 /* ChartAnimator.swift */; };
A52C5C401BAC5D1100594CDD /* ChartAnimationEasing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B378F161AD500A4009414A4 /* ChartAnimationEasing.swift */; };
A52C5C411BAC5D1100594CDD /* BarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54981AA66B14000F57C2 /* BarChartView.swift */; };
A52C5C421BAC5D1100594CDD /* BarLineChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A549A1AA66B2C000F57C2 /* BarLineChartViewBase.swift */; };
A52C5C431BAC5D1100594CDD /* BubbleChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E356521ADC63BF00A57971 /* BubbleChartView.swift */; };
A52C5C441BAC5D1100594CDD /* CandleStickChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A549C1AA66B3C000F57C2 /* CandleStickChartView.swift */; };
A52C5C451BAC5D1100594CDD /* ChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC671A9D151C00CE82E1 /* ChartViewBase.swift */; };
A52C5C461BAC5D1100594CDD /* CombinedChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A549E1AA66B59000F57C2 /* CombinedChartView.swift */; };
A52C5C471BAC5D1100594CDD /* HorizontalBarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54A01AA66B6A000F57C2 /* HorizontalBarChartView.swift */; };
A52C5C481BAC5D1100594CDD /* LineChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54A21AA66B7C000F57C2 /* LineChartView.swift */; };
A52C5C491BAC5D1100594CDD /* PieChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54A41AA66B92000F57C2 /* PieChartView.swift */; };
A52C5C4A1BAC5D1100594CDD /* PieRadarChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54A61AA66BA7000F57C2 /* PieRadarChartViewBase.swift */; };
A52C5C4B1BAC5D1100594CDD /* RadarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54A81AA66BBA000F57C2 /* RadarChartView.swift */; };
A52C5C4C1BAC5D1100594CDD /* ScatterChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54AA1AA66BC8000F57C2 /* ScatterChartView.swift */; };
A52C5C4D1BAC5D1100594CDD /* ChartAxisBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6A1A9D151C00CE82E1 /* ChartAxisBase.swift */; };
A52C5C4E1BAC5D1100594CDD /* ChartComponentBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6556F61AB72BA000FFBFD3 /* ChartComponentBase.swift */; };
A52C5C4F1BAC5D1100594CDD /* ChartLegend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6B1A9D151C00CE82E1 /* ChartLegend.swift */; };
A52C5C501BAC5D1100594CDD /* ChartLimitLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6C1A9D151C00CE82E1 /* ChartLimitLine.swift */; };
A52C5C511BAC5D1100594CDD /* ChartMarker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A546A1AA5C23F000F57C2 /* ChartMarker.swift */; };
A52C5C521BAC5D1100594CDD /* ChartXAxis.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6D1A9D151C00CE82E1 /* ChartXAxis.swift */; };
A52C5C531BAC5D1100594CDD /* ChartYAxis.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6E1A9D151C00CE82E1 /* ChartYAxis.swift */; };
A52C5C541BAC5D1100594CDD /* BarChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54B71AA74516000F57C2 /* BarChartData.swift */; };
A52C5C551BAC5D1100594CDD /* BarChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54B81AA74516000F57C2 /* BarChartDataEntry.swift */; };
A52C5C561BAC5D1100594CDD /* BarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54B91AA74516000F57C2 /* BarChartDataSet.swift */; };
A52C5C571BAC5D1100594CDD /* BarLineScatterCandleChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BA1AA74516000F57C2 /* BarLineScatterCandleChartData.swift */; };
A52C5C581BAC5D1100594CDD /* BarLineScatterCandleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BB1AA74516000F57C2 /* BarLineScatterCandleChartDataSet.swift */; };
A52C5C591BAC5D1100594CDD /* BubbleChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E356541ADC63CD00A57971 /* BubbleChartData.swift */; };
A52C5C5A1BAC5D1100594CDD /* BubbleChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E356551ADC63CD00A57971 /* BubbleChartDataEntry.swift */; };
A52C5C5B1BAC5D1100594CDD /* BubbleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E356561ADC63CD00A57971 /* BubbleChartDataSet.swift */; };
A52C5C5C1BAC5D1100594CDD /* CandleChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BC1AA74516000F57C2 /* CandleChartData.swift */; };
A52C5C5D1BAC5D1100594CDD /* CandleChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BD1AA74516000F57C2 /* CandleChartDataEntry.swift */; };
A52C5C5E1BAC5D1100594CDD /* CandleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BE1AA74516000F57C2 /* CandleChartDataSet.swift */; };
A52C5C5F1BAC5D1100594CDD /* CombinedChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54BF1AA74516000F57C2 /* CombinedChartData.swift */; };
A52C5C601BAC5D1100594CDD /* ChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C01AA74516000F57C2 /* ChartData.swift */; };
A52C5C611BAC5D1100594CDD /* ChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C11AA74516000F57C2 /* ChartDataEntry.swift */; };
A52C5C621BAC5D1100594CDD /* ChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C21AA74516000F57C2 /* ChartDataSet.swift */; };
A52C5C631BAC5D1100594CDD /* LineChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C31AA74516000F57C2 /* LineChartData.swift */; };
A52C5C641BAC5D1100594CDD /* LineChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C41AA74516000F57C2 /* LineChartDataSet.swift */; };
A52C5C651BAC5D1100594CDD /* LineRadarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C51AA74516000F57C2 /* LineRadarChartDataSet.swift */; };
A52C5C661BAC5D1100594CDD /* LineScatterCandleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8FE2AE1B68F8F600910C9E /* LineScatterCandleChartDataSet.swift */; };
A52C5C671BAC5D1100594CDD /* PieChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C61AA74516000F57C2 /* PieChartData.swift */; };
A52C5C681BAC5D1100594CDD /* PieChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C71AA74516000F57C2 /* PieChartDataSet.swift */; };
A52C5C691BAC5D1100594CDD /* RadarChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C81AA74516000F57C2 /* RadarChartData.swift */; };
A52C5C6A1BAC5D1100594CDD /* RadarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54C91AA74516000F57C2 /* RadarChartDataSet.swift */; };
A52C5C6B1BAC5D1100594CDD /* ScatterChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54CA1AA74516000F57C2 /* ScatterChartData.swift */; };
A52C5C6C1BAC5D1100594CDD /* ScatterChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54CB1AA74516000F57C2 /* ScatterChartDataSet.swift */; };
A52C5C6D1BAC5D1100594CDD /* ChartDataApproximatorFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC751A9D151C00CE82E1 /* ChartDataApproximatorFilter.swift */; };
A52C5C6E1BAC5D1100594CDD /* ChartDataBaseFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC761A9D151C00CE82E1 /* ChartDataBaseFilter.swift */; };
A52C5C6F1BAC5D1100594CDD /* ChartHighlight.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0032441B6524AD00B6A2FE /* ChartHighlight.swift */; };
A52C5C701BAC5D1100594CDD /* ChartRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0032461B6524D300B6A2FE /* ChartRange.swift */; };
A52C5C711BAC5D1100594CDD /* ChartHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0032481B6525FC00B6A2FE /* ChartHighlighter.swift */; };
A52C5C721BAC5D1100594CDD /* BarChartHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B00324A1B652BF900B6A2FE /* BarChartHighlighter.swift */; };
A52C5C731BAC5D1100594CDD /* HorizontalBarChartHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B00324C1B65351C00B6A2FE /* HorizontalBarChartHighlighter.swift */; };
A52C5C741BAC5D1100594CDD /* ChartAxisRendererBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54711AA5DCA8000F57C2 /* ChartAxisRendererBase.swift */; };
A52C5C751BAC5D1100594CDD /* BarChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54961AA66AD2000F57C2 /* BarChartRenderer.swift */; };
A52C5C761BAC5D1100594CDD /* BubbleChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E3565A1ADC63EB00A57971 /* BubbleChartRenderer.swift */; };
A52C5C771BAC5D1100594CDD /* CandleStickChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54941AA66AC0000F57C2 /* CandleStickChartRenderer.swift */; };
A52C5C781BAC5D1100594CDD /* CombinedChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54921AA66AAB000F57C2 /* CombinedChartRenderer.swift */; };
A52C5C791BAC5D1100594CDD /* ChartDataRendererBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54901AA66A8D000F57C2 /* ChartDataRendererBase.swift */; };
A52C5C7A1BAC5D1200594CDD /* HorizontalBarChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A548E1AA66A7A000F57C2 /* HorizontalBarChartRenderer.swift */; };
A52C5C7B1BAC5D1200594CDD /* ChartLegendRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A548C1AA66A60000F57C2 /* ChartLegendRenderer.swift */; };
A52C5C7C1BAC5D1200594CDD /* LineChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A548A1AA66A3D000F57C2 /* LineChartRenderer.swift */; };
A52C5C7D1BAC5D1200594CDD /* LineScatterCandleRadarChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8FE2B01B68FFF900910C9E /* LineScatterCandleRadarChartRenderer.swift */; };
A52C5C7E1BAC5D1200594CDD /* PieChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54881AA66A1A000F57C2 /* PieChartRenderer.swift */; };
A52C5C7F1BAC5D1200594CDD /* RadarChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54861AA669F4000F57C2 /* RadarChartRenderer.swift */; };
A52C5C801BAC5D1200594CDD /* ChartRendererBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A546F1AA5DB34000F57C2 /* ChartRendererBase.swift */; };
A52C5C811BAC5D1200594CDD /* ScatterChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54841AA669C9000F57C2 /* ScatterChartRenderer.swift */; };
A52C5C821BAC5D1200594CDD /* ChartXAxisRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54731AA5DEDC000F57C2 /* ChartXAxisRenderer.swift */; };
A52C5C831BAC5D1200594CDD /* ChartXAxisRendererBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54751AA5DEE3000F57C2 /* ChartXAxisRendererBarChart.swift */; };
A52C5C841BAC5D1200594CDD /* ChartXAxisRendererHorizontalBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A547B1AA5DF02000F57C2 /* ChartXAxisRendererHorizontalBarChart.swift */; };
A52C5C851BAC5D1200594CDD /* ChartXAxisRendererRadarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54771AA5DEF0000F57C2 /* ChartXAxisRendererRadarChart.swift */; };
A52C5C861BAC5D1200594CDD /* ChartYAxisRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A547D1AA5DF1A000F57C2 /* ChartYAxisRenderer.swift */; };
A52C5C871BAC5D1200594CDD /* ChartYAxisRendererHorizontalBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A547F1AA5DF28000F57C2 /* ChartYAxisRendererHorizontalBarChart.swift */; };
A52C5C881BAC5D1200594CDD /* ChartYAxisRendererRadarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A54811AA5DF34000F57C2 /* ChartYAxisRendererRadarChart.swift */; };
A52C5C891BAC5D1200594CDD /* ChartColorTemplates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC791A9D151C00CE82E1 /* ChartColorTemplates.swift */; };
A52C5C8A1BAC5D1200594CDD /* ChartFillFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B4BCD3D1AA9C0A60063F019 /* ChartFillFormatter.swift */; };
A52C5C8B1BAC5D1200594CDD /* ChartSelectionDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC7B1A9D151C00CE82E1 /* ChartSelectionDetail.swift */; };
A52C5C8C1BAC5D1200594CDD /* ChartTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B4BCD3F1AA9C4930063F019 /* ChartTransformer.swift */; };
A52C5C8D1BAC5D1200594CDD /* ChartTransformerHorizontalBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB6EC1C1ACC28AB006E9C25 /* ChartTransformerHorizontalBarChart.swift */; };
A52C5C8E1BAC5D1200594CDD /* ChartUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC7C1A9D151C00CE82E1 /* ChartUtils.swift */; };
A52C5C8F1BAC5D1200594CDD /* ChartViewPortHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD8F06C1AB897D500566E05 /* ChartViewPortHandler.swift */; };
A52C5C901BAC5D1200594CDD /* UIGraphics+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06A5D1851B78675500915098 /* UIGraphics+Extensions.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
06A5D1851B78675500915098 /* UIGraphics+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIGraphics+Extensions.swift"; sourceTree = "<group>"; };
55E356521ADC63BF00A57971 /* BubbleChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleChartView.swift; sourceTree = "<group>"; };
55E356541ADC63CD00A57971 /* BubbleChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleChartData.swift; sourceTree = "<group>"; };
55E356551ADC63CD00A57971 /* BubbleChartDataEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleChartDataEntry.swift; sourceTree = "<group>"; };
55E356561ADC63CD00A57971 /* BubbleChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleChartDataSet.swift; sourceTree = "<group>"; };
55E3565A1ADC63EB00A57971 /* BubbleChartRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleChartRenderer.swift; sourceTree = "<group>"; };
5B0032441B6524AD00B6A2FE /* ChartHighlight.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartHighlight.swift; sourceTree = "<group>"; };
5B0032461B6524D300B6A2FE /* ChartRange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartRange.swift; sourceTree = "<group>"; };
5B0032481B6525FC00B6A2FE /* ChartHighlighter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartHighlighter.swift; sourceTree = "<group>"; };
5B00324A1B652BF900B6A2FE /* BarChartHighlighter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarChartHighlighter.swift; sourceTree = "<group>"; };
5B00324C1B65351C00B6A2FE /* HorizontalBarChartHighlighter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HorizontalBarChartHighlighter.swift; sourceTree = "<group>"; };
5B378F161AD500A4009414A4 /* ChartAnimationEasing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAnimationEasing.swift; sourceTree = "<group>"; };
5B4BCD3F1AA9C4930063F019 /* ChartTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartTransformer.swift; sourceTree = "<group>"; };
5B6556F61AB72BA000FFBFD3 /* ChartComponentBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartComponentBase.swift; sourceTree = "<group>"; };
5B6654D51BB0A86F00890030 /* ChartDefaultXAxisValueFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartDefaultXAxisValueFormatter.swift; sourceTree = "<group>"; };
5B6654D61BB0A86F00890030 /* ChartFillFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartFillFormatter.swift; sourceTree = "<group>"; };
5B6654D71BB0A86F00890030 /* ChartXAxisValueFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartXAxisValueFormatter.swift; sourceTree = "<group>"; };
5B680D1C1A9D16F90026A057 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
5B680D3C1A9D1AD90026A057 /* Charts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Charts.h; sourceTree = "<group>"; };
5B6A546A1AA5C23F000F57C2 /* ChartMarker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartMarker.swift; sourceTree = "<group>"; };
5B6A546D1AA5D2DC000F57C2 /* ChartAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAnimator.swift; sourceTree = "<group>"; };
5B6A546F1AA5DB34000F57C2 /* ChartRendererBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartRendererBase.swift; sourceTree = "<group>"; };
5B6A54711AA5DCA8000F57C2 /* ChartAxisRendererBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAxisRendererBase.swift; sourceTree = "<group>"; };
5B6A54731AA5DEDC000F57C2 /* ChartXAxisRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartXAxisRenderer.swift; sourceTree = "<group>"; };
5B6A54751AA5DEE3000F57C2 /* ChartXAxisRendererBarChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartXAxisRendererBarChart.swift; sourceTree = "<group>"; };
5B6A54771AA5DEF0000F57C2 /* ChartXAxisRendererRadarChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartXAxisRendererRadarChart.swift; sourceTree = "<group>"; };
5B6A547B1AA5DF02000F57C2 /* ChartXAxisRendererHorizontalBarChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartXAxisRendererHorizontalBarChart.swift; sourceTree = "<group>"; };
5B6A547D1AA5DF1A000F57C2 /* ChartYAxisRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartYAxisRenderer.swift; sourceTree = "<group>"; };
5B6A547F1AA5DF28000F57C2 /* ChartYAxisRendererHorizontalBarChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartYAxisRendererHorizontalBarChart.swift; sourceTree = "<group>"; };
5B6A54811AA5DF34000F57C2 /* ChartYAxisRendererRadarChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartYAxisRendererRadarChart.swift; sourceTree = "<group>"; };
5B6A54841AA669C9000F57C2 /* ScatterChartRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScatterChartRenderer.swift; sourceTree = "<group>"; };
5B6A54861AA669F4000F57C2 /* RadarChartRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadarChartRenderer.swift; sourceTree = "<group>"; };
5B6A54881AA66A1A000F57C2 /* PieChartRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PieChartRenderer.swift; sourceTree = "<group>"; };
5B6A548A1AA66A3D000F57C2 /* LineChartRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineChartRenderer.swift; sourceTree = "<group>"; };
5B6A548C1AA66A60000F57C2 /* ChartLegendRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartLegendRenderer.swift; sourceTree = "<group>"; };
5B6A548E1AA66A7A000F57C2 /* HorizontalBarChartRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HorizontalBarChartRenderer.swift; sourceTree = "<group>"; };
5B6A54901AA66A8D000F57C2 /* ChartDataRendererBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartDataRendererBase.swift; sourceTree = "<group>"; };
5B6A54921AA66AAB000F57C2 /* CombinedChartRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombinedChartRenderer.swift; sourceTree = "<group>"; };
5B6A54941AA66AC0000F57C2 /* CandleStickChartRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CandleStickChartRenderer.swift; sourceTree = "<group>"; };
5B6A54961AA66AD2000F57C2 /* BarChartRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BarChartRenderer.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
5B6A54981AA66B14000F57C2 /* BarChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarChartView.swift; sourceTree = "<group>"; };
5B6A549A1AA66B2C000F57C2 /* BarLineChartViewBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BarLineChartViewBase.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
5B6A549C1AA66B3C000F57C2 /* CandleStickChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CandleStickChartView.swift; sourceTree = "<group>"; };
5B6A549E1AA66B59000F57C2 /* CombinedChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombinedChartView.swift; sourceTree = "<group>"; };
5B6A54A01AA66B6A000F57C2 /* HorizontalBarChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HorizontalBarChartView.swift; sourceTree = "<group>"; };
5B6A54A21AA66B7C000F57C2 /* LineChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineChartView.swift; sourceTree = "<group>"; };
5B6A54A41AA66B92000F57C2 /* PieChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PieChartView.swift; sourceTree = "<group>"; };
5B6A54A61AA66BA7000F57C2 /* PieRadarChartViewBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PieRadarChartViewBase.swift; sourceTree = "<group>"; };
5B6A54A81AA66BBA000F57C2 /* RadarChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadarChartView.swift; sourceTree = "<group>"; };
5B6A54AA1AA66BC8000F57C2 /* ScatterChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScatterChartView.swift; sourceTree = "<group>"; };
5B6A54B71AA74516000F57C2 /* BarChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarChartData.swift; sourceTree = "<group>"; };
5B6A54B81AA74516000F57C2 /* BarChartDataEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarChartDataEntry.swift; sourceTree = "<group>"; };
5B6A54B91AA74516000F57C2 /* BarChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarChartDataSet.swift; sourceTree = "<group>"; };
5B6A54BA1AA74516000F57C2 /* BarLineScatterCandleBubbleChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarLineScatterCandleBubbleChartData.swift; sourceTree = "<group>"; };
5B6A54BB1AA74516000F57C2 /* BarLineScatterCandleBubbleChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarLineScatterCandleBubbleChartDataSet.swift; sourceTree = "<group>"; };
5B6A54BC1AA74516000F57C2 /* CandleChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CandleChartData.swift; sourceTree = "<group>"; };
5B6A54BD1AA74516000F57C2 /* CandleChartDataEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CandleChartDataEntry.swift; sourceTree = "<group>"; };
5B6A54BE1AA74516000F57C2 /* CandleChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CandleChartDataSet.swift; sourceTree = "<group>"; };
5B6A54BF1AA74516000F57C2 /* CombinedChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombinedChartData.swift; sourceTree = "<group>"; };
5B6A54C01AA74516000F57C2 /* ChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartData.swift; sourceTree = "<group>"; };
5B6A54C11AA74516000F57C2 /* ChartDataEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartDataEntry.swift; sourceTree = "<group>"; };
5B6A54C21AA74516000F57C2 /* ChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartDataSet.swift; sourceTree = "<group>"; };
5B6A54C31AA74516000F57C2 /* LineChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineChartData.swift; sourceTree = "<group>"; };
5B6A54C41AA74516000F57C2 /* LineChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineChartDataSet.swift; sourceTree = "<group>"; };
5B6A54C51AA74516000F57C2 /* LineRadarChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineRadarChartDataSet.swift; sourceTree = "<group>"; };
5B6A54C61AA74516000F57C2 /* PieChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PieChartData.swift; sourceTree = "<group>"; };
5B6A54C71AA74516000F57C2 /* PieChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PieChartDataSet.swift; sourceTree = "<group>"; };
5B6A54C81AA74516000F57C2 /* RadarChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadarChartData.swift; sourceTree = "<group>"; };
5B6A54C91AA74516000F57C2 /* RadarChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadarChartDataSet.swift; sourceTree = "<group>"; };
5B6A54CA1AA74516000F57C2 /* ScatterChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScatterChartData.swift; sourceTree = "<group>"; };
5B6A54CB1AA74516000F57C2 /* ScatterChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScatterChartDataSet.swift; sourceTree = "<group>"; };
5B8FE2AE1B68F8F600910C9E /* LineScatterCandleChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineScatterCandleChartDataSet.swift; sourceTree = "<group>"; };
5B8FE2B01B68FFF900910C9E /* LineScatterCandleRadarChartRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineScatterCandleRadarChartRenderer.swift; sourceTree = "<group>"; };
5BA8EC401A9D14DC00CE82E1 /* Charts.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Charts.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5BA8EC441A9D14DC00CE82E1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5BA8EC671A9D151C00CE82E1 /* ChartViewBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartViewBase.swift; sourceTree = "<group>"; };
5BA8EC6A1A9D151C00CE82E1 /* ChartAxisBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ChartAxisBase.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
5BA8EC6B1A9D151C00CE82E1 /* ChartLegend.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartLegend.swift; sourceTree = "<group>"; };
5BA8EC6C1A9D151C00CE82E1 /* ChartLimitLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartLimitLine.swift; sourceTree = "<group>"; };
5BA8EC6D1A9D151C00CE82E1 /* ChartXAxis.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartXAxis.swift; sourceTree = "<group>"; };
5BA8EC6E1A9D151C00CE82E1 /* ChartYAxis.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartYAxis.swift; sourceTree = "<group>"; };
5BA8EC751A9D151C00CE82E1 /* ChartDataApproximatorFilter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartDataApproximatorFilter.swift; sourceTree = "<group>"; };
5BA8EC761A9D151C00CE82E1 /* ChartDataBaseFilter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartDataBaseFilter.swift; sourceTree = "<group>"; };
5BA8EC791A9D151C00CE82E1 /* ChartColorTemplates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartColorTemplates.swift; sourceTree = "<group>"; };
5BA8EC7B1A9D151C00CE82E1 /* ChartSelectionDetail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartSelectionDetail.swift; sourceTree = "<group>"; };
5BA8EC7C1A9D151C00CE82E1 /* ChartUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartUtils.swift; sourceTree = "<group>"; };
5BAAA8551BB08E1D00B20D4D /* CombinedHighlighter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombinedHighlighter.swift; sourceTree = "<group>"; };
5BB6EC1C1ACC28AB006E9C25 /* ChartTransformerHorizontalBarChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartTransformerHorizontalBarChart.swift; sourceTree = "<group>"; };
5BD8F06C1AB897D500566E05 /* ChartViewPortHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartViewPortHandler.swift; sourceTree = "<group>"; };
A52C5C371BAC5CA400594CDD /* ChartsTV.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ChartsTV.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A52C5C391BAC5CA400594CDD /* ChartsTV.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChartsTV.h; sourceTree = "<group>"; };
A52C5C3B1BAC5CA400594CDD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
5BA8EC3C1A9D14DC00CE82E1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5B680D1D1A9D16F90026A057 /* UIKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A52C5C331BAC5CA400594CDD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
5B0032431B65247600B6A2FE /* Highlight */ = {
isa = PBXGroup;
children = (
5B0032441B6524AD00B6A2FE /* ChartHighlight.swift */,
5B0032461B6524D300B6A2FE /* ChartRange.swift */,
5B0032481B6525FC00B6A2FE /* ChartHighlighter.swift */,
5B00324A1B652BF900B6A2FE /* BarChartHighlighter.swift */,
5BAAA8551BB08E1D00B20D4D /* CombinedHighlighter.swift */,
5B00324C1B65351C00B6A2FE /* HorizontalBarChartHighlighter.swift */,
);
path = Highlight;
sourceTree = "<group>";
};
5B6654D41BB0A86F00890030 /* Formatters */ = {
isa = PBXGroup;
children = (
5B6654D51BB0A86F00890030 /* ChartDefaultXAxisValueFormatter.swift */,
5B6654D61BB0A86F00890030 /* ChartFillFormatter.swift */,
5B6654D71BB0A86F00890030 /* ChartXAxisValueFormatter.swift */,
);
path = Formatters;
sourceTree = "<group>";
};
5B680D1E1A9D170B0026A057 /* Frameworks */ = {
isa = PBXGroup;
children = (
5B680D1C1A9D16F90026A057 /* UIKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
5B6A546C1AA5D2D0000F57C2 /* Animation */ = {
isa = PBXGroup;
children = (
5B6A546D1AA5D2DC000F57C2 /* ChartAnimator.swift */,
5B378F161AD500A4009414A4 /* ChartAnimationEasing.swift */,
);
path = Animation;
sourceTree = "<group>";
};
5B759ED41A9F98A90039D97F /* Renderers */ = {
isa = PBXGroup;
children = (
5B6A54711AA5DCA8000F57C2 /* ChartAxisRendererBase.swift */,
5B6A54961AA66AD2000F57C2 /* BarChartRenderer.swift */,
55E3565A1ADC63EB00A57971 /* BubbleChartRenderer.swift */,
5B6A54941AA66AC0000F57C2 /* CandleStickChartRenderer.swift */,
5B6A54921AA66AAB000F57C2 /* CombinedChartRenderer.swift */,
5B6A54901AA66A8D000F57C2 /* ChartDataRendererBase.swift */,
5B6A548E1AA66A7A000F57C2 /* HorizontalBarChartRenderer.swift */,
5B6A548C1AA66A60000F57C2 /* ChartLegendRenderer.swift */,
5B6A548A1AA66A3D000F57C2 /* LineChartRenderer.swift */,
5B8FE2B01B68FFF900910C9E /* LineScatterCandleRadarChartRenderer.swift */,
5B6A54881AA66A1A000F57C2 /* PieChartRenderer.swift */,
5B6A54861AA669F4000F57C2 /* RadarChartRenderer.swift */,
5B6A546F1AA5DB34000F57C2 /* ChartRendererBase.swift */,
5B6A54841AA669C9000F57C2 /* ScatterChartRenderer.swift */,
5B6A54731AA5DEDC000F57C2 /* ChartXAxisRenderer.swift */,
5B6A54751AA5DEE3000F57C2 /* ChartXAxisRendererBarChart.swift */,
5B6A547B1AA5DF02000F57C2 /* ChartXAxisRendererHorizontalBarChart.swift */,
5B6A54771AA5DEF0000F57C2 /* ChartXAxisRendererRadarChart.swift */,
5B6A547D1AA5DF1A000F57C2 /* ChartYAxisRenderer.swift */,
5B6A547F1AA5DF28000F57C2 /* ChartYAxisRendererHorizontalBarChart.swift */,
5B6A54811AA5DF34000F57C2 /* ChartYAxisRendererRadarChart.swift */,
);
path = Renderers;
sourceTree = "<group>";
};
5BA8EC361A9D14DC00CE82E1 = {
isa = PBXGroup;
children = (
5BA8EC651A9D151C00CE82E1 /* Classes */,
5BA8EC431A9D14DC00CE82E1 /* Supporting Files */,
A52C5C381BAC5CA400594CDD /* ChartsTV */,
5BA8EC411A9D14DC00CE82E1 /* Products */,
5B680D1E1A9D170B0026A057 /* Frameworks */,
);
sourceTree = "<group>";
};
5BA8EC411A9D14DC00CE82E1 /* Products */ = {
isa = PBXGroup;
children = (
5BA8EC401A9D14DC00CE82E1 /* Charts.framework */,
A52C5C371BAC5CA400594CDD /* ChartsTV.framework */,
);
name = Products;
sourceTree = "<group>";
};
5BA8EC431A9D14DC00CE82E1 /* Supporting Files */ = {
isa = PBXGroup;
children = (
5B680D3C1A9D1AD90026A057 /* Charts.h */,
5BA8EC441A9D14DC00CE82E1 /* Info.plist */,
);
path = "Supporting Files";
sourceTree = "<group>";
};
5BA8EC651A9D151C00CE82E1 /* Classes */ = {
isa = PBXGroup;
children = (
5B6A546C1AA5D2D0000F57C2 /* Animation */,
5BA8EC661A9D151C00CE82E1 /* Charts */,
5BA8EC691A9D151C00CE82E1 /* Components */,
5BA8EC6F1A9D151C00CE82E1 /* Data */,
5BA8EC741A9D151C00CE82E1 /* Filters */,
5B6654D41BB0A86F00890030 /* Formatters */,
5B0032431B65247600B6A2FE /* Highlight */,
5B759ED41A9F98A90039D97F /* Renderers */,
5BA8EC781A9D151C00CE82E1 /* Utils */,
);
path = Classes;
sourceTree = "<group>";
};
5BA8EC661A9D151C00CE82E1 /* Charts */ = {
isa = PBXGroup;
children = (
5B6A54981AA66B14000F57C2 /* BarChartView.swift */,
5B6A549A1AA66B2C000F57C2 /* BarLineChartViewBase.swift */,
55E356521ADC63BF00A57971 /* BubbleChartView.swift */,
5B6A549C1AA66B3C000F57C2 /* CandleStickChartView.swift */,
5BA8EC671A9D151C00CE82E1 /* ChartViewBase.swift */,
5B6A549E1AA66B59000F57C2 /* CombinedChartView.swift */,
5B6A54A01AA66B6A000F57C2 /* HorizontalBarChartView.swift */,
5B6A54A21AA66B7C000F57C2 /* LineChartView.swift */,
5B6A54A41AA66B92000F57C2 /* PieChartView.swift */,
5B6A54A61AA66BA7000F57C2 /* PieRadarChartViewBase.swift */,
5B6A54A81AA66BBA000F57C2 /* RadarChartView.swift */,
5B6A54AA1AA66BC8000F57C2 /* ScatterChartView.swift */,
);
path = Charts;
sourceTree = "<group>";
};
5BA8EC691A9D151C00CE82E1 /* Components */ = {
isa = PBXGroup;
children = (
5BA8EC6A1A9D151C00CE82E1 /* ChartAxisBase.swift */,
5B6556F61AB72BA000FFBFD3 /* ChartComponentBase.swift */,
5BA8EC6B1A9D151C00CE82E1 /* ChartLegend.swift */,
5BA8EC6C1A9D151C00CE82E1 /* ChartLimitLine.swift */,
5B6A546A1AA5C23F000F57C2 /* ChartMarker.swift */,
5BA8EC6D1A9D151C00CE82E1 /* ChartXAxis.swift */,
5BA8EC6E1A9D151C00CE82E1 /* ChartYAxis.swift */,
);
path = Components;
sourceTree = "<group>";
};
5BA8EC6F1A9D151C00CE82E1 /* Data */ = {
isa = PBXGroup;
children = (
5B6A54B71AA74516000F57C2 /* BarChartData.swift */,
5B6A54B81AA74516000F57C2 /* BarChartDataEntry.swift */,
5B6A54B91AA74516000F57C2 /* BarChartDataSet.swift */,
5B6A54BA1AA74516000F57C2 /* BarLineScatterCandleBubbleChartData.swift */,
5B6A54BB1AA74516000F57C2 /* BarLineScatterCandleBubbleChartDataSet.swift */,
55E356541ADC63CD00A57971 /* BubbleChartData.swift */,
55E356551ADC63CD00A57971 /* BubbleChartDataEntry.swift */,
55E356561ADC63CD00A57971 /* BubbleChartDataSet.swift */,
5B6A54BC1AA74516000F57C2 /* CandleChartData.swift */,
5B6A54BD1AA74516000F57C2 /* CandleChartDataEntry.swift */,
5B6A54BE1AA74516000F57C2 /* CandleChartDataSet.swift */,
5B6A54BF1AA74516000F57C2 /* CombinedChartData.swift */,
5B6A54C01AA74516000F57C2 /* ChartData.swift */,
5B6A54C11AA74516000F57C2 /* ChartDataEntry.swift */,
5B6A54C21AA74516000F57C2 /* ChartDataSet.swift */,
5B6A54C31AA74516000F57C2 /* LineChartData.swift */,
5B6A54C41AA74516000F57C2 /* LineChartDataSet.swift */,
5B6A54C51AA74516000F57C2 /* LineRadarChartDataSet.swift */,
5B8FE2AE1B68F8F600910C9E /* LineScatterCandleChartDataSet.swift */,
5B6A54C61AA74516000F57C2 /* PieChartData.swift */,
5B6A54C71AA74516000F57C2 /* PieChartDataSet.swift */,
5B6A54C81AA74516000F57C2 /* RadarChartData.swift */,
5B6A54C91AA74516000F57C2 /* RadarChartDataSet.swift */,
5B6A54CA1AA74516000F57C2 /* ScatterChartData.swift */,
5B6A54CB1AA74516000F57C2 /* ScatterChartDataSet.swift */,
);
path = Data;
sourceTree = "<group>";
};
5BA8EC741A9D151C00CE82E1 /* Filters */ = {
isa = PBXGroup;
children = (
5BA8EC751A9D151C00CE82E1 /* ChartDataApproximatorFilter.swift */,
5BA8EC761A9D151C00CE82E1 /* ChartDataBaseFilter.swift */,
);
path = Filters;
sourceTree = "<group>";
};
5BA8EC781A9D151C00CE82E1 /* Utils */ = {
isa = PBXGroup;
children = (
5BA8EC791A9D151C00CE82E1 /* ChartColorTemplates.swift */,
5BA8EC7B1A9D151C00CE82E1 /* ChartSelectionDetail.swift */,
5B4BCD3F1AA9C4930063F019 /* ChartTransformer.swift */,
5BB6EC1C1ACC28AB006E9C25 /* ChartTransformerHorizontalBarChart.swift */,
5BA8EC7C1A9D151C00CE82E1 /* ChartUtils.swift */,
5BD8F06C1AB897D500566E05 /* ChartViewPortHandler.swift */,
06A5D1851B78675500915098 /* UIGraphics+Extensions.swift */,
);
path = Utils;
sourceTree = "<group>";
};
A52C5C381BAC5CA400594CDD /* ChartsTV */ = {
isa = PBXGroup;
children = (
A52C5C391BAC5CA400594CDD /* ChartsTV.h */,
A52C5C3B1BAC5CA400594CDD /* Info.plist */,
);
path = ChartsTV;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
5BA8EC3D1A9D14DC00CE82E1 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
5B680D3D1A9D1AD90026A057 /* Charts.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A52C5C341BAC5CA400594CDD /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
A52C5C3A1BAC5CA400594CDD /* ChartsTV.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
5BA8EC3F1A9D14DC00CE82E1 /* Charts */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5BA8EC561A9D14DC00CE82E1 /* Build configuration list for PBXNativeTarget "Charts" */;
buildPhases = (
5BA8EC3B1A9D14DC00CE82E1 /* Sources */,
5BA8EC3C1A9D14DC00CE82E1 /* Frameworks */,
5BA8EC3D1A9D14DC00CE82E1 /* Headers */,
5BA8EC3E1A9D14DC00CE82E1 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Charts;
productName = Charts;
productReference = 5BA8EC401A9D14DC00CE82E1 /* Charts.framework */;
productType = "com.apple.product-type.framework";
};
A52C5C361BAC5CA400594CDD /* ChartsTV */ = {
isa = PBXNativeTarget;
buildConfigurationList = A52C5C3E1BAC5CA400594CDD /* Build configuration list for PBXNativeTarget "ChartsTV" */;
buildPhases = (
A52C5C321BAC5CA400594CDD /* Sources */,
A52C5C331BAC5CA400594CDD /* Frameworks */,
A52C5C341BAC5CA400594CDD /* Headers */,
A52C5C351BAC5CA400594CDD /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = ChartsTV;
productName = ChartsTV;
productReference = A52C5C371BAC5CA400594CDD /* ChartsTV.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
5BA8EC371A9D14DC00CE82E1 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftMigration = 0700;
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = dcg;
TargetAttributes = {
5BA8EC3F1A9D14DC00CE82E1 = {
CreatedOnToolsVersion = 6.1.1;
};
A52C5C361BAC5CA400594CDD = {
CreatedOnToolsVersion = 7.1;
};
};
};
buildConfigurationList = 5BA8EC3A1A9D14DC00CE82E1 /* Build configuration list for PBXProject "Charts" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 5BA8EC361A9D14DC00CE82E1;
productRefGroup = 5BA8EC411A9D14DC00CE82E1 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
5BA8EC3F1A9D14DC00CE82E1 /* Charts */,
A52C5C361BAC5CA400594CDD /* ChartsTV */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
5BA8EC3E1A9D14DC00CE82E1 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
A52C5C351BAC5CA400594CDD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
5BA8EC3B1A9D14DC00CE82E1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5B680D1F1A9D17C30026A057 /* ChartAxisBase.swift in Sources */,
5B6A54DE1AA74516000F57C2 /* RadarChartDataSet.swift in Sources */,
5B8FE2AF1B68F8F600910C9E /* LineScatterCandleChartDataSet.swift in Sources */,
5BAAA8561BB08E1D00B20D4D /* CombinedHighlighter.swift in Sources */,
5B680D211A9D17C30026A057 /* ChartLimitLine.swift in Sources */,
5B6A54DB1AA74516000F57C2 /* PieChartData.swift in Sources */,
5B6A54D91AA74516000F57C2 /* LineChartDataSet.swift in Sources */,
5B6A54AC1AA66C1E000F57C2 /* ChartAxisRendererBase.swift in Sources */,
5B6A54CF1AA74516000F57C2 /* BarLineScatterCandleBubbleChartData.swift in Sources */,
5B6A54D11AA74516000F57C2 /* CandleChartData.swift in Sources */,
5B6654DA1BB0A86F00890030 /* ChartFillFormatter.swift in Sources */,
5B6A54AB1AA66BC8000F57C2 /* ScatterChartView.swift in Sources */,
5B6A54E01AA74516000F57C2 /* ScatterChartDataSet.swift in Sources */,
5B6A548B1AA66A3D000F57C2 /* LineChartRenderer.swift in Sources */,
5B6A54D01AA74516000F57C2 /* BarLineScatterCandleBubbleChartDataSet.swift in Sources */,
5B6A54821AA5DF34000F57C2 /* ChartYAxisRendererRadarChart.swift in Sources */,
5B6A54931AA66AAB000F57C2 /* CombinedChartRenderer.swift in Sources */,
5B680D221A9D17C30026A057 /* ChartXAxis.swift in Sources */,
5BA8EC891A9D151C00CE82E1 /* ChartDataBaseFilter.swift in Sources */,
5B6654DB1BB0A86F00890030 /* ChartXAxisValueFormatter.swift in Sources */,
5B6A54A31AA66B7C000F57C2 /* LineChartView.swift in Sources */,
5B6A54891AA66A1A000F57C2 /* PieChartRenderer.swift in Sources */,
5B6A54DD1AA74516000F57C2 /* RadarChartData.swift in Sources */,
5B6A54991AA66B14000F57C2 /* BarChartView.swift in Sources */,
5B680D231A9D17C30026A057 /* ChartYAxis.swift in Sources */,
5B6A54A91AA66BBA000F57C2 /* RadarChartView.swift in Sources */,
5B378F171AD500A4009414A4 /* ChartAnimationEasing.swift in Sources */,
5B6A548F1AA66A7A000F57C2 /* HorizontalBarChartRenderer.swift in Sources */,
5B6A54741AA5DEDC000F57C2 /* ChartXAxisRenderer.swift in Sources */,
5B6A547C1AA5DF02000F57C2 /* ChartXAxisRendererHorizontalBarChart.swift in Sources */,
5B4BCD401AA9C4930063F019 /* ChartTransformer.swift in Sources */,
5B6A54801AA5DF28000F57C2 /* ChartYAxisRendererHorizontalBarChart.swift in Sources */,
5B6A54D21AA74516000F57C2 /* CandleChartDataEntry.swift in Sources */,
5B6A54CC1AA74516000F57C2 /* BarChartData.swift in Sources */,
5B00324D1B65351C00B6A2FE /* HorizontalBarChartHighlighter.swift in Sources */,
5B6A54CE1AA74516000F57C2 /* BarChartDataSet.swift in Sources */,
5B6A54871AA669F4000F57C2 /* RadarChartRenderer.swift in Sources */,
5B6A548D1AA66A60000F57C2 /* ChartLegendRenderer.swift in Sources */,
55E356591ADC63CD00A57971 /* BubbleChartDataSet.swift in Sources */,
5BB6EC1D1ACC28AB006E9C25 /* ChartTransformerHorizontalBarChart.swift in Sources */,
5B680D271A9D17C30026A057 /* ChartColorTemplates.swift in Sources */,
5B6A54951AA66AC0000F57C2 /* CandleStickChartRenderer.swift in Sources */,
5B680D291A9D17C30026A057 /* ChartSelectionDetail.swift in Sources */,
5BA8EC7D1A9D151C00CE82E1 /* ChartViewBase.swift in Sources */,
5B6A54DC1AA74516000F57C2 /* PieChartDataSet.swift in Sources */,
5B6A54DA1AA74516000F57C2 /* LineRadarChartDataSet.swift in Sources */,
06A5D1861B78675500915098 /* UIGraphics+Extensions.swift in Sources */,
5B6A54701AA5DB34000F57C2 /* ChartRendererBase.swift in Sources */,
5B6A54761AA5DEE3000F57C2 /* ChartXAxisRendererBarChart.swift in Sources */,
5B6A54851AA669C9000F57C2 /* ScatterChartRenderer.swift in Sources */,
5B6A549D1AA66B3C000F57C2 /* CandleStickChartView.swift in Sources */,
5BA8EC881A9D151C00CE82E1 /* ChartDataApproximatorFilter.swift in Sources */,
5B6A549B1AA66B2C000F57C2 /* BarLineChartViewBase.swift in Sources */,
5B6A54A51AA66B92000F57C2 /* PieChartView.swift in Sources */,
5B6A54D81AA74516000F57C2 /* LineChartData.swift in Sources */,
55E356581ADC63CD00A57971 /* BubbleChartDataEntry.swift in Sources */,
5B6A54911AA66A8D000F57C2 /* ChartDataRendererBase.swift in Sources */,
5BD8F06D1AB897D500566E05 /* ChartViewPortHandler.swift in Sources */,
5B8FE2B11B68FFF900910C9E /* LineScatterCandleRadarChartRenderer.swift in Sources */,
5B6A54D51AA74516000F57C2 /* ChartData.swift in Sources */,
5B6A54971AA66AD2000F57C2 /* BarChartRenderer.swift in Sources */,
5B6A546B1AA5C23F000F57C2 /* ChartMarker.swift in Sources */,
5B6A54D61AA74516000F57C2 /* ChartDataEntry.swift in Sources */,
55E356571ADC63CD00A57971 /* BubbleChartData.swift in Sources */,
5B6A54DF1AA74516000F57C2 /* ScatterChartData.swift in Sources */,
5B6A54D31AA74516000F57C2 /* CandleChartDataSet.swift in Sources */,
5B0032491B6525FC00B6A2FE /* ChartHighlighter.swift in Sources */,
5B6A54D71AA74516000F57C2 /* ChartDataSet.swift in Sources */,
5B00324B1B652BF900B6A2FE /* BarChartHighlighter.swift in Sources */,
5B6A54781AA5DEF0000F57C2 /* ChartXAxisRendererRadarChart.swift in Sources */,
5B6A54A71AA66BA7000F57C2 /* PieRadarChartViewBase.swift in Sources */,
5B6A546E1AA5D2DC000F57C2 /* ChartAnimator.swift in Sources */,
55E3565B1ADC63EB00A57971 /* BubbleChartRenderer.swift in Sources */,
55E356531ADC63BF00A57971 /* BubbleChartView.swift in Sources */,
5B6654D91BB0A86F00890030 /* ChartDefaultXAxisValueFormatter.swift in Sources */,
5B6A547E1AA5DF1A000F57C2 /* ChartYAxisRenderer.swift in Sources */,
5B6A549F1AA66B59000F57C2 /* CombinedChartView.swift in Sources */,
5B6556F71AB72BA000FFBFD3 /* ChartComponentBase.swift in Sources */,
5B6A54CD1AA74516000F57C2 /* BarChartDataEntry.swift in Sources */,
5B6A54D41AA74516000F57C2 /* CombinedChartData.swift in Sources */,
5B680D2A1A9D17C30026A057 /* ChartUtils.swift in Sources */,
5B0032451B6524AD00B6A2FE /* ChartHighlight.swift in Sources */,
5B680D201A9D17C30026A057 /* ChartLegend.swift in Sources */,
5B0032471B6524D300B6A2FE /* ChartRange.swift in Sources */,
5BD8F06E1AB89AD800566E05 /* HorizontalBarChartView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A52C5C321BAC5CA400594CDD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A52C5C3F1BAC5D1100594CDD /* ChartAnimator.swift in Sources */,
A52C5C401BAC5D1100594CDD /* ChartAnimationEasing.swift in Sources */,
A52C5C411BAC5D1100594CDD /* BarChartView.swift in Sources */,
A52C5C421BAC5D1100594CDD /* BarLineChartViewBase.swift in Sources */,
A52C5C431BAC5D1100594CDD /* BubbleChartView.swift in Sources */,
A52C5C441BAC5D1100594CDD /* CandleStickChartView.swift in Sources */,
A52C5C451BAC5D1100594CDD /* ChartViewBase.swift in Sources */,
A52C5C461BAC5D1100594CDD /* CombinedChartView.swift in Sources */,
A52C5C471BAC5D1100594CDD /* HorizontalBarChartView.swift in Sources */,
A52C5C481BAC5D1100594CDD /* LineChartView.swift in Sources */,
A52C5C491BAC5D1100594CDD /* PieChartView.swift in Sources */,
A52C5C4A1BAC5D1100594CDD /* PieRadarChartViewBase.swift in Sources */,
A52C5C4B1BAC5D1100594CDD /* RadarChartView.swift in Sources */,
A52C5C4C1BAC5D1100594CDD /* ScatterChartView.swift in Sources */,
A52C5C4D1BAC5D1100594CDD /* ChartAxisBase.swift in Sources */,
A52C5C4E1BAC5D1100594CDD /* ChartComponentBase.swift in Sources */,
A52C5C4F1BAC5D1100594CDD /* ChartLegend.swift in Sources */,
A52C5C501BAC5D1100594CDD /* ChartLimitLine.swift in Sources */,
A52C5C511BAC5D1100594CDD /* ChartMarker.swift in Sources */,
A52C5C521BAC5D1100594CDD /* ChartXAxis.swift in Sources */,
A52C5C531BAC5D1100594CDD /* ChartYAxis.swift in Sources */,
A52C5C541BAC5D1100594CDD /* BarChartData.swift in Sources */,
A52C5C551BAC5D1100594CDD /* BarChartDataEntry.swift in Sources */,
A52C5C561BAC5D1100594CDD /* BarChartDataSet.swift in Sources */,
A52C5C571BAC5D1100594CDD /* BarLineScatterCandleChartData.swift in Sources */,
A52C5C581BAC5D1100594CDD /* BarLineScatterCandleChartDataSet.swift in Sources */,
A52C5C591BAC5D1100594CDD /* BubbleChartData.swift in Sources */,
A52C5C5A1BAC5D1100594CDD /* BubbleChartDataEntry.swift in Sources */,
A52C5C5B1BAC5D1100594CDD /* BubbleChartDataSet.swift in Sources */,
A52C5C5C1BAC5D1100594CDD /* CandleChartData.swift in Sources */,
A52C5C5D1BAC5D1100594CDD /* CandleChartDataEntry.swift in Sources */,
A52C5C5E1BAC5D1100594CDD /* CandleChartDataSet.swift in Sources */,
A52C5C5F1BAC5D1100594CDD /* CombinedChartData.swift in Sources */,
A52C5C601BAC5D1100594CDD /* ChartData.swift in Sources */,
A52C5C611BAC5D1100594CDD /* ChartDataEntry.swift in Sources */,
A52C5C621BAC5D1100594CDD /* ChartDataSet.swift in Sources */,
A52C5C631BAC5D1100594CDD /* LineChartData.swift in Sources */,
A52C5C641BAC5D1100594CDD /* LineChartDataSet.swift in Sources */,
A52C5C651BAC5D1100594CDD /* LineRadarChartDataSet.swift in Sources */,
A52C5C661BAC5D1100594CDD /* LineScatterCandleChartDataSet.swift in Sources */,
A52C5C671BAC5D1100594CDD /* PieChartData.swift in Sources */,
A52C5C681BAC5D1100594CDD /* PieChartDataSet.swift in Sources */,
A52C5C691BAC5D1100594CDD /* RadarChartData.swift in Sources */,
A52C5C6A1BAC5D1100594CDD /* RadarChartDataSet.swift in Sources */,
A52C5C6B1BAC5D1100594CDD /* ScatterChartData.swift in Sources */,
A52C5C6C1BAC5D1100594CDD /* ScatterChartDataSet.swift in Sources */,
A52C5C6D1BAC5D1100594CDD /* ChartDataApproximatorFilter.swift in Sources */,
A52C5C6E1BAC5D1100594CDD /* ChartDataBaseFilter.swift in Sources */,
A52C5C6F1BAC5D1100594CDD /* ChartHighlight.swift in Sources */,
A52C5C701BAC5D1100594CDD /* ChartRange.swift in Sources */,
A52C5C711BAC5D1100594CDD /* ChartHighlighter.swift in Sources */,
A52C5C721BAC5D1100594CDD /* BarChartHighlighter.swift in Sources */,
A52C5C731BAC5D1100594CDD /* HorizontalBarChartHighlighter.swift in Sources */,
A52C5C741BAC5D1100594CDD /* ChartAxisRendererBase.swift in Sources */,
A52C5C751BAC5D1100594CDD /* BarChartRenderer.swift in Sources */,
A52C5C761BAC5D1100594CDD /* BubbleChartRenderer.swift in Sources */,
A52C5C771BAC5D1100594CDD /* CandleStickChartRenderer.swift in Sources */,
A52C5C781BAC5D1100594CDD /* CombinedChartRenderer.swift in Sources */,
A52C5C791BAC5D1100594CDD /* ChartDataRendererBase.swift in Sources */,
A52C5C7A1BAC5D1200594CDD /* HorizontalBarChartRenderer.swift in Sources */,
A52C5C7B1BAC5D1200594CDD /* ChartLegendRenderer.swift in Sources */,
A52C5C7C1BAC5D1200594CDD /* LineChartRenderer.swift in Sources */,
A52C5C7D1BAC5D1200594CDD /* LineScatterCandleRadarChartRenderer.swift in Sources */,
A52C5C7E1BAC5D1200594CDD /* PieChartRenderer.swift in Sources */,
A52C5C7F1BAC5D1200594CDD /* RadarChartRenderer.swift in Sources */,
A52C5C801BAC5D1200594CDD /* ChartRendererBase.swift in Sources */,
A52C5C811BAC5D1200594CDD /* ScatterChartRenderer.swift in Sources */,
A52C5C821BAC5D1200594CDD /* ChartXAxisRenderer.swift in Sources */,
A52C5C831BAC5D1200594CDD /* ChartXAxisRendererBarChart.swift in Sources */,
A52C5C841BAC5D1200594CDD /* ChartXAxisRendererHorizontalBarChart.swift in Sources */,
A52C5C851BAC5D1200594CDD /* ChartXAxisRendererRadarChart.swift in Sources */,
A52C5C861BAC5D1200594CDD /* ChartYAxisRenderer.swift in Sources */,
A52C5C871BAC5D1200594CDD /* ChartYAxisRendererHorizontalBarChart.swift in Sources */,
A52C5C881BAC5D1200594CDD /* ChartYAxisRendererRadarChart.swift in Sources */,
A52C5C891BAC5D1200594CDD /* ChartColorTemplates.swift in Sources */,
A52C5C8A1BAC5D1200594CDD /* ChartFillFormatter.swift in Sources */,
A52C5C8B1BAC5D1200594CDD /* ChartSelectionDetail.swift in Sources */,
A52C5C8C1BAC5D1200594CDD /* ChartTransformer.swift in Sources */,
A52C5C8D1BAC5D1200594CDD /* ChartTransformerHorizontalBarChart.swift in Sources */,
A52C5C8E1BAC5D1200594CDD /* ChartUtils.swift in Sources */,
A52C5C8F1BAC5D1200594CDD /* ChartViewPortHandler.swift in Sources */,
A52C5C901BAC5D1200594CDD /* UIGraphics+Extensions.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
5BA8EC541A9D14DC00CE82E1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
5BA8EC551A9D14DC00CE82E1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 1;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
5BA8EC571A9D14DC00CE82E1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.dcg.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Debug;
};
5BA8EC581A9D14DC00CE82E1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.dcg.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
A52C5C3C1BAC5CA400594CDD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = ChartsTV/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.dcg.ChartsTV;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 9.0;
};
name = Debug;
};
A52C5C3D1BAC5CA400594CDD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = ChartsTV/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.dcg.ChartsTV;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 9.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
5BA8EC3A1A9D14DC00CE82E1 /* Build configuration list for PBXProject "Charts" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5BA8EC541A9D14DC00CE82E1 /* Debug */,
5BA8EC551A9D14DC00CE82E1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5BA8EC561A9D14DC00CE82E1 /* Build configuration list for PBXNativeTarget "Charts" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5BA8EC571A9D14DC00CE82E1 /* Debug */,
5BA8EC581A9D14DC00CE82E1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A52C5C3E1BAC5CA400594CDD /* Build configuration list for PBXNativeTarget "ChartsTV" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A52C5C3C1BAC5CA400594CDD /* Debug */,
A52C5C3D1BAC5CA400594CDD /* Release */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = 5BA8EC371A9D14DC00CE82E1 /* Project object */;
}

View File

@@ -1,103 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5BA8EC3F1A9D14DC00CE82E1"
BuildableName = "Charts.framework"
BlueprintName = "Charts"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5BA8EC4A1A9D14DC00CE82E1"
BuildableName = "ChartsTests.xctest"
BlueprintName = "ChartsTests"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5BA8EC3F1A9D14DC00CE82E1"
BuildableName = "Charts.framework"
BlueprintName = "Charts"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5BA8EC3F1A9D14DC00CE82E1"
BuildableName = "Charts.framework"
BlueprintName = "Charts"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5BA8EC3F1A9D14DC00CE82E1"
BuildableName = "Charts.framework"
BlueprintName = "Charts"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -1,80 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A52C5C361BAC5CA400594CDD"
BuildableName = "ChartsTV.framework"
BlueprintName = "ChartsTV"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A52C5C361BAC5CA400594CDD"
BuildableName = "ChartsTV.framework"
BlueprintName = "ChartsTV"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A52C5C361BAC5CA400594CDD"
BuildableName = "ChartsTV.framework"
BlueprintName = "ChartsTV"
ReferencedContainer = "container:Charts.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -1,19 +0,0 @@
//
// ChartsTV.h
// ChartsTV
//
// Created by Tracy Keeling on 9/18/15.
// Copyright © 2015 dcg. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for ChartsTV.
FOUNDATION_EXPORT double ChartsTVVersionNumber;
//! Project version string for ChartsTV.
FOUNDATION_EXPORT const unsigned char ChartsTVVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <ChartsTV/PublicHeader.h>

View File

@@ -1,26 +0,0 @@
<?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>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@@ -1,394 +0,0 @@
//
// ChartAnimationUtils.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-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: NSTimeInterval, duration: NSTimeInterval) -> CGFloat)
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: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in return CGFloat(elapsed / duration); }
internal static let EaseInQuad = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(elapsed / duration)
return position * position
}
internal static let EaseOutQuad = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(elapsed / duration)
return -position * (position - 2.0)
}
internal static let EaseInOutQuad = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(elapsed / (duration / 2.0))
if (position < 1.0)
{
return 0.5 * position * position
}
return -0.5 * ((--position) * (position - 2.0) - 1.0)
}
internal static let EaseInCubic = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(elapsed / duration)
return position * position * position
}
internal static let EaseOutCubic = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(elapsed / duration)
position--
return (position * position * position + 1.0)
}
internal static let EaseInOutCubic = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(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: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(elapsed / duration)
return position * position * position * position
}
internal static let EaseOutQuart = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(elapsed / duration)
position--
return -(position * position * position * position - 1.0)
}
internal static let EaseInOutQuart = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(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: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(elapsed / duration)
return position * position * position * position * position
}
internal static let EaseOutQuint = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(elapsed / duration)
position--
return (position * position * position * position * position + 1.0)
}
internal static let EaseInOutQuint = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(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: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position: NSTimeInterval = elapsed / duration
return CGFloat( -cos(position * M_PI_2) + 1.0 )
}
internal static let EaseOutSine = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position: NSTimeInterval = elapsed / duration
return CGFloat( sin(position * M_PI_2) )
}
internal static let EaseInOutSine = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position: NSTimeInterval = elapsed / duration
return CGFloat( -0.5 * (cos(M_PI * position) - 1.0) )
}
internal static let EaseInExpo = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
return (elapsed == 0) ? 0.0 : CGFloat(pow(2.0, 10.0 * (elapsed / duration - 1.0)))
}
internal static let EaseOutExpo = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
return (elapsed == duration) ? 1.0 : (-CGFloat(pow(2.0, -10.0 * elapsed / duration)) + 1.0)
}
internal static let EaseInOutExpo = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
if (elapsed == 0)
{
return 0.0
}
if (elapsed == duration)
{
return 1.0
}
var position: NSTimeInterval = elapsed / (duration / 2.0)
if (position < 1.0)
{
return CGFloat( 0.5 * pow(2.0, 10.0 * (position - 1.0)) )
}
return CGFloat( 0.5 * (-pow(2.0, -10.0 * --position) + 2.0) )
}
internal static let EaseInCirc = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(elapsed / duration)
return -(CGFloat(sqrt(1.0 - position * position)) - 1.0)
}
internal static let EaseOutCirc = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position = CGFloat(elapsed / duration)
position--
return CGFloat( sqrt(1 - position * position) )
}
internal static let EaseInOutCirc = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position: NSTimeInterval = elapsed / (duration / 2.0)
if (position < 1.0)
{
return CGFloat( -0.5 * (sqrt(1.0 - position * position) - 1.0) )
}
position -= 2.0
return CGFloat( 0.5 * (sqrt(1.0 - position * position) + 1.0) )
}
internal static let EaseInElastic = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
if (elapsed == 0.0)
{
return 0.0
}
var position: NSTimeInterval = elapsed / duration
if (position == 1.0)
{
return 1.0
}
var p = duration * 0.3
var s = p / (2.0 * M_PI) * asin(1.0)
position -= 1.0
return CGFloat( -(pow(2.0, 10.0 * position) * sin((position * duration - s) * (2.0 * M_PI) / p)) )
}
internal static let EaseOutElastic = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
if (elapsed == 0.0)
{
return 0.0
}
var position: NSTimeInterval = elapsed / duration
if (position == 1.0)
{
return 1.0
}
var p = duration * 0.3
var s = p / (2.0 * M_PI) * asin(1.0)
return CGFloat( pow(2.0, -10.0 * position) * sin((position * duration - s) * (2.0 * M_PI) / p) + 1.0 )
}
internal static let EaseInOutElastic = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
if (elapsed == 0.0)
{
return 0.0
}
var position: NSTimeInterval = elapsed / (duration / 2.0)
if (position == 2.0)
{
return 1.0
}
var p = duration * (0.3 * 1.5)
var s = p / (2.0 * M_PI) * asin(1.0)
if (position < 1.0)
{
position -= 1.0
return CGFloat( -0.5 * (pow(2.0, 10.0 * position) * sin((position * duration - s) * (2.0 * M_PI) / p)) )
}
position -= 1.0
return CGFloat( pow(2.0, -10.0 * position) * sin((position * duration - s) * (2.0 * M_PI) / p) * 0.5 + 1.0 )
}
internal static let EaseInBack = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
let s: NSTimeInterval = 1.70158
var position: NSTimeInterval = elapsed / duration
return CGFloat( position * position * ((s + 1.0) * position - s) )
}
internal static let EaseOutBack = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
let s: NSTimeInterval = 1.70158
var position: NSTimeInterval = elapsed / duration
position--
return CGFloat( (position * position * ((s + 1.0) * position + s) + 1.0) )
}
internal static let EaseInOutBack = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var s: NSTimeInterval = 1.70158
var position: NSTimeInterval = elapsed / (duration / 2.0)
if (position < 1.0)
{
s *= 1.525
return CGFloat( 0.5 * (position * position * ((s + 1.0) * position - s)) )
}
s *= 1.525
position -= 2.0
return CGFloat( 0.5 * (position * position * ((s + 1.0) * position + s) + 2.0) )
}
internal static let EaseInBounce = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
return 1.0 - EaseOutBounce(duration - elapsed, duration)
}
internal static let EaseOutBounce = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat in
var position: NSTimeInterval = elapsed / duration
if (position < (1.0 / 2.75))
{
return CGFloat( 7.5625 * position * position )
}
else if (position < (2.0 / 2.75))
{
position -= (1.5 / 2.75)
return CGFloat( 7.5625 * position * position + 0.75 )
}
else if (position < (2.5 / 2.75))
{
position -= (2.25 / 2.75)
return CGFloat( 7.5625 * position * position + 0.9375 )
}
else
{
position -= (2.625 / 2.75)
return CGFloat( 7.5625 * position * position + 0.984375 )
}
}
internal static let EaseInOutBounce = { (elapsed: NSTimeInterval, duration: NSTimeInterval) -> CGFloat 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
}
}

View File

@@ -1,272 +0,0 @@
//
// ChartAnimator.swift
// Charts
//
// Created by Daniel Cohen Gindi on 3/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
@objc
public protocol ChartAnimatorDelegate
{
/// Called when the Animator has stepped.
func chartAnimatorUpdated(chartAnimator: ChartAnimator)
/// Called when the Animator has stopped.
func chartAnimatorStopped(chartAnimator: ChartAnimator)
}
public class ChartAnimator: NSObject
{
public weak var delegate: ChartAnimatorDelegate?
public var updateBlock: (() -> Void)?
public var stopBlock: (() -> Void)?
/// the phase that is animated and influences the drawn values on the y-axis
public var phaseX: CGFloat = 1.0
/// the phase that is animated and influences the drawn values on the y-axis
public var phaseY: CGFloat = 1.0
private var _startTime: NSTimeInterval = 0.0
private var _displayLink: CADisplayLink!
private var _xDuration: NSTimeInterval = 0.0
private var _yDuration: NSTimeInterval = 0.0
private var _endTimeX: NSTimeInterval = 0.0
private var _endTimeY: NSTimeInterval = 0.0
private var _endTime: NSTimeInterval = 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()
}
public func stop()
{
if (_displayLink != nil)
{
_displayLink.removeFromRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
_displayLink = nil
_enabledX = false
_enabledY = false
if (delegate != nil)
{
delegate!.chartAnimatorStopped(self)
}
if (stopBlock != nil)
{
stopBlock?()
}
}
}
private func updateAnimationPhases(currentTime: NSTimeInterval)
{
let elapsedTime: NSTimeInterval = currentTime - _startTime
if (_enabledX)
{
let duration: NSTimeInterval = _xDuration
var elapsed: NSTimeInterval = elapsedTime
if (elapsed > duration)
{
elapsed = duration
}
if (_easingX != nil)
{
phaseX = _easingX!(elapsed: elapsed, duration: duration)
}
else
{
phaseX = CGFloat(elapsed / duration)
}
}
if (_enabledY)
{
let duration: NSTimeInterval = _yDuration
var elapsed: NSTimeInterval = elapsedTime
if (elapsed > duration)
{
elapsed = duration
}
if (_easingY != nil)
{
phaseY = _easingY!(elapsed: elapsed, duration: duration)
}
else
{
phaseY = CGFloat(elapsed / duration)
}
}
}
@objc private func animationLoop()
{
let currentTime: NSTimeInterval = CACurrentMediaTime()
updateAnimationPhases(currentTime)
if (delegate != nil)
{
delegate!.chartAnimatorUpdated(self)
}
if (updateBlock != nil)
{
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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easingX: an easing function for the animation on the x axis
/// - parameter easingY: an easing function for the animation on the y axis
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval, easingX: ChartEasingFunctionBlock?, easingY: ChartEasingFunctionBlock?)
{
stop()
_displayLink = CADisplayLink(target: self, selector: Selector("animationLoop"))
_startTime = CACurrentMediaTime()
_xDuration = xAxisDuration
_yDuration = yAxisDuration
_endTimeX = _startTime + xAxisDuration
_endTimeY = _startTime + 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(_startTime)
if (_enabledX || _enabledY)
{
_displayLink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
}
}
/// 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easingOptionX: the easing function for the animation on the x axis
/// - parameter easingOptionY: the easing function for the animation on the y axis
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval, 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easing: an easing function for the animation
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval, 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easingOption: the easing function for the animation
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval, easingOption: ChartEasingOption)
{
animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easing: easingFunctionFromOption(easingOption))
}
/// 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter yAxisDuration: duration for animating the y axis
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval)
{
animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easingOption: .EaseInOutSine)
}
/// 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter easing: an easing function for the animation
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, easing: ChartEasingFunctionBlock?)
{
animate(xAxisDuration: xAxisDuration, yAxisDuration: 0.0, easing: easing)
}
/// 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter easingOption: the easing function for the animation
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, easingOption: ChartEasingOption)
{
animate(xAxisDuration: xAxisDuration, yAxisDuration: 0.0, 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.
/// - parameter xAxisDuration: duration for animating the x axis
public func animate(xAxisDuration xAxisDuration: NSTimeInterval)
{
animate(xAxisDuration: xAxisDuration, yAxisDuration: 0.0, easingOption: .EaseInOutSine)
}
/// 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.
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easing: an easing function for the animation
public func animate(yAxisDuration yAxisDuration: NSTimeInterval, easing: ChartEasingFunctionBlock?)
{
animate(xAxisDuration: 0.0, yAxisDuration: yAxisDuration, easing: easing)
}
/// 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.
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easingOption: the easing function for the animation
public func animate(yAxisDuration yAxisDuration: NSTimeInterval, easingOption: ChartEasingOption)
{
animate(xAxisDuration: 0.0, yAxisDuration: yAxisDuration, 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.
/// - parameter yAxisDuration: duration for animating the y axis
public func animate(yAxisDuration yAxisDuration: NSTimeInterval)
{
animate(xAxisDuration: 0.0, yAxisDuration: yAxisDuration, easingOption: .EaseInOutSine)
}
}

View File

@@ -1,231 +0,0 @@
//
// BarChartView.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
/// Chart that draws bars.
public class BarChartView: BarLineChartViewBase, BarChartRendererDelegate
{
/// flag that enables or disables the highlighting arrow
private var _drawHighlightArrowEnabled = false
/// 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 darawn behind each bar that indicates the maximum value
private var _drawBarShadowEnabled = false
internal override func initialize()
{
super.initialize()
renderer = BarChartRenderer(delegate: self, animator: _animator, viewPortHandler: _viewPortHandler)
_xAxisRenderer = ChartXAxisRendererBarChart(viewPortHandler: _viewPortHandler, xAxis: _xAxis, transformer: _leftAxisTransformer, chart: self)
_highlighter = BarChartHighlighter(chart: self)
_chartXMin = -0.5
}
internal override func calcMinMax()
{
super.calcMinMax()
if (_data === nil)
{
return
}
let barData = _data as! BarChartData
// increase deltax by 1 because the bars have a width of 1
_deltaX += 0.5
// extend xDelta to make space for multiple datasets (if ther are one)
_deltaX *= CGFloat(_data.dataSetCount)
let groupSpace = barData.groupSpace
_deltaX += CGFloat(barData.xValCount) * groupSpace
_chartXMax = Double(_deltaX) - _chartXMin
}
/// - returns: the Highlight object (contains x-index and DataSet index) of the selected value at the given touch point inside the BarChart.
public override func getHighlightByTouchPoint(pt: CGPoint) -> ChartHighlight?
{
if (_dataNotSet || _data === nil)
{
print("Can't select by touch. No data set.", terminator: "\n")
return nil
}
return _highlighter?.getHighlight(x: Double(pt.x), y: Double(pt.y))
}
/// - 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.
public func getBarBounds(e: BarChartDataEntry) -> CGRect!
{
let set = _data.getDataSetForEntry(e) as! BarChartDataSet!
if (set === nil)
{
return nil
}
let barspace = set.barSpace
let y = CGFloat(e.value)
let x = CGFloat(e.xIndex)
let barWidth: CGFloat = 0.5
let spaceHalf = barspace / 2.0
let left = x - barWidth + spaceHalf
let right = x + barWidth - spaceHalf
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(set.axisDependency).rectValueToPixel(&bounds)
return bounds
}
public override var lowestVisibleXIndex: Int
{
let step = CGFloat(_data.dataSetCount)
let div = (step <= 1.0) ? 1.0 : step + (_data as! BarChartData).groupSpace
var pt = CGPoint(x: _viewPortHandler.contentLeft, y: _viewPortHandler.contentBottom)
getTransformer(ChartYAxis.AxisDependency.Left).pixelToValue(&pt)
return Int((pt.x <= CGFloat(chartXMin)) ? 0.0 : (pt.x / div) + 1.0)
}
public override var highestVisibleXIndex: Int
{
let step = CGFloat(_data.dataSetCount)
let div = (step <= 1.0) ? 1.0 : step + (_data as! BarChartData).groupSpace
var pt = CGPoint(x: _viewPortHandler.contentRight, y: _viewPortHandler.contentBottom)
getTransformer(ChartYAxis.AxisDependency.Left).pixelToValue(&pt)
return Int((pt.x >= CGFloat(chartXMax)) ? CGFloat(chartXMax) / div : (pt.x / div))
}
// MARK: Accessors
/// flag that enables or disables the highlighting arrow
public var drawHighlightArrowEnabled: Bool
{
get { return _drawHighlightArrowEnabled; }
set
{
_drawHighlightArrowEnabled = newValue
setNeedsDisplay()
}
}
/// if set to true, all values are drawn above their bars, instead of below their top
public 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
public var drawBarShadowEnabled: Bool
{
get { return _drawBarShadowEnabled; }
set
{
_drawBarShadowEnabled = newValue
setNeedsDisplay()
}
}
/// - returns: true if drawing the highlighting arrow is enabled, false if not
public var isDrawHighlightArrowEnabled: Bool { return drawHighlightArrowEnabled; }
/// - returns: true if drawing values above bars is enabled, false if not
public var isDrawValueAboveBarEnabled: Bool { return drawValueAboveBarEnabled; }
/// - returns: true if drawing shadows (maxvalue) for each bar is enabled, false if not
public var isDrawBarShadowEnabled: Bool { return drawBarShadowEnabled; }
// MARK: - BarChartRendererDelegate
public func barChartRendererData(renderer: BarChartRenderer) -> BarChartData!
{
return _data as! BarChartData!
}
public func barChartRenderer(renderer: BarChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
{
return getTransformer(which)
}
public func barChartRendererMaxVisibleValueCount(renderer: BarChartRenderer) -> Int
{
return maxVisibleValueCount
}
public func barChartDefaultRendererValueFormatter(renderer: BarChartRenderer) -> NSNumberFormatter!
{
return valueFormatter
}
public func barChartRendererChartYMax(renderer: BarChartRenderer) -> Double
{
return chartYMax
}
public func barChartRendererChartYMin(renderer: BarChartRenderer) -> Double
{
return chartYMin
}
public func barChartRendererChartXMax(renderer: BarChartRenderer) -> Double
{
return chartXMax
}
public func barChartRendererChartXMin(renderer: BarChartRenderer) -> Double
{
return chartXMin
}
public func barChartIsDrawHighlightArrowEnabled(renderer: BarChartRenderer) -> Bool
{
return drawHighlightArrowEnabled
}
public func barChartIsDrawValueAboveBarEnabled(renderer: BarChartRenderer) -> Bool
{
return drawValueAboveBarEnabled
}
public func barChartIsDrawBarShadowEnabled(renderer: BarChartRenderer) -> Bool
{
return drawBarShadowEnabled
}
public func barChartIsInverted(renderer: BarChartRenderer, axis: ChartYAxis.AxisDependency) -> Bool
{
return getAxis(axis).isInverted
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,105 +0,0 @@
//
// BubbleChartView.swift
// Charts
//
// Bubble chart implementation:
// Copyright 2015 Pierre-Marc Airoldi
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
public class BubbleChartView: BarLineChartViewBase, BubbleChartRendererDelegate
{
public override func initialize()
{
super.initialize()
renderer = BubbleChartRenderer(delegate: self, animator: _animator, viewPortHandler: _viewPortHandler)
}
public override func calcMinMax()
{
super.calcMinMax()
if (_deltaX == 0.0 && _data.yValCount > 0)
{
_deltaX = 1.0
}
_chartXMin = -0.5
_chartXMax = Double(_data.xVals.count) - 0.5
if renderer as? BubbleChartRenderer !== nil,
let sets = _data.dataSets as? [BubbleChartDataSet]
{
for set in sets {
let xmin = set.xMin
let xmax = set.xMax
if (xmin < _chartXMin)
{
_chartXMin = xmin
}
if (xmax > _chartXMax)
{
_chartXMax = xmax
}
}
}
_deltaX = CGFloat(abs(_chartXMax - _chartXMin))
}
// MARK: - BubbleChartRendererDelegate
public func bubbleChartRendererData(renderer: BubbleChartRenderer) -> BubbleChartData!
{
return _data as! BubbleChartData!
}
public func bubbleChartRenderer(renderer: BubbleChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
{
return getTransformer(which)
}
public func bubbleChartDefaultRendererValueFormatter(renderer: BubbleChartRenderer) -> NSNumberFormatter!
{
return self._defaultValueFormatter
}
public func bubbleChartRendererChartYMax(renderer: BubbleChartRenderer) -> Double
{
return self.chartYMax
}
public func bubbleChartRendererChartYMin(renderer: BubbleChartRenderer) -> Double
{
return self.chartYMin
}
public func bubbleChartRendererChartXMax(renderer: BubbleChartRenderer) -> Double
{
return self.chartXMax
}
public func bubbleChartRendererChartXMin(renderer: BubbleChartRenderer) -> Double
{
return self.chartXMin
}
public func bubbleChartRendererMaxVisibleValueCount(renderer: BubbleChartRenderer) -> Int
{
return self.maxVisibleValueCount
}
public func bubbleChartRendererXValCount(renderer: BubbleChartRenderer) -> Int
{
return _data.xValCount
}
}

View File

@@ -1,77 +0,0 @@
//
// CandleStickChartView.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
/// Financial chart type that draws candle-sticks.
public class CandleStickChartView: BarLineChartViewBase, CandleStickChartRendererDelegate
{
internal override func initialize()
{
super.initialize()
renderer = CandleStickChartRenderer(delegate: self, animator: _animator, viewPortHandler: _viewPortHandler)
_chartXMin = -0.5
}
internal override func calcMinMax()
{
super.calcMinMax()
_chartXMax += 0.5
_deltaX = CGFloat(abs(_chartXMax - _chartXMin))
}
// MARK: - CandleStickChartRendererDelegate
public func candleStickChartRendererCandleData(renderer: CandleStickChartRenderer) -> CandleChartData!
{
return _data as! CandleChartData!
}
public func candleStickChartRenderer(renderer: CandleStickChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
{
return self.getTransformer(which)
}
public func candleStickChartDefaultRendererValueFormatter(renderer: CandleStickChartRenderer) -> NSNumberFormatter!
{
return self.valueFormatter
}
public func candleStickChartRendererChartYMax(renderer: CandleStickChartRenderer) -> Double
{
return self.chartYMax
}
public func candleStickChartRendererChartYMin(renderer: CandleStickChartRenderer) -> Double
{
return self.chartYMin
}
public func candleStickChartRendererChartXMax(renderer: CandleStickChartRenderer) -> Double
{
return self.chartXMax
}
public func candleStickChartRendererChartXMin(renderer: CandleStickChartRenderer) -> Double
{
return self.chartXMin
}
public func candleStickChartRendererMaxVisibleValueCount(renderer: CandleStickChartRenderer) -> Int
{
return self.maxVisibleValueCount
}
}

View File

@@ -1,945 +0,0 @@
//
// ChartViewBase.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
// Based on https://github.com/PhilJay/MPAndroidChart/commit/c42b880
import Foundation
import UIKit
@objc
public protocol ChartViewDelegate
{
/// Called when a value has been selected inside the chart.
/// - parameter entry: The selected Entry.
/// - parameter dataSetIndex: The index in the datasets array of the data object the Entrys DataSet is in.
optional func chartValueSelected(chartView: ChartViewBase, entry: ChartDataEntry, dataSetIndex: Int, highlight: ChartHighlight)
// Called when nothing has been selected or an "un-select" has been made.
optional func chartValueNothingSelected(chartView: ChartViewBase)
// Callbacks when the chart is scaled / zoomed via pinch zoom gesture.
optional func chartScaled(chartView: ChartViewBase, scaleX: CGFloat, scaleY: CGFloat)
// Callbacks when the chart is moved / translated via drag gesture.
optional func chartTranslated(chartView: ChartViewBase, dX: CGFloat, dY: CGFloat)
}
public class ChartViewBase: UIView, ChartAnimatorDelegate
{
// MARK: - Properties
/// custom formatter that is used instead of the auto-formatter if set
internal var _valueFormatter = NSNumberFormatter()
/// the default value formatter
internal var _defaultValueFormatter = NSNumberFormatter()
/// object that holds all data that was originally set for the chart, before it was modified or any filtering algorithms had been applied
internal var _data: ChartData!
/// If set to true, chart continues to scroll after touch up
public var dragDecelerationEnabled = true
/// Deceleration friction coefficient in [0 ; 1] interval, higher values indicate that speed will decrease slowly, for example if it set to 0, it will stop immediately.
/// 1 is an invalid value, and will be converted to 0.999 automatically.
private var _dragDecelerationFrictionCoef: CGFloat = 0.9
/// font object used for drawing the description text in the bottom right corner of the chart
public var descriptionFont: UIFont? = UIFont(name: "HelveticaNeue", size: 9.0)
public var descriptionTextColor: UIColor! = UIColor.blackColor()
/// font object for drawing the information text when there are no values in the chart
public var infoFont: UIFont! = UIFont(name: "HelveticaNeue", size: 12.0)
public var infoTextColor: UIColor! = UIColor(red: 247.0/255.0, green: 189.0/255.0, blue: 51.0/255.0, alpha: 1.0) // orange
/// description text that appears in the bottom right corner of the chart
public var descriptionText = "Description"
/// flag that indicates if the chart has been fed with data yet
internal var _dataNotSet = true
/// if true, units are drawn next to the values in the chart
internal var _drawUnitInChart = false
/// the number of x-values the chart displays
internal var _deltaX = CGFloat(1.0)
internal var _chartXMin = Double(0.0)
internal var _chartXMax = Double(0.0)
/// the legend object containing all data associated with the legend
internal var _legend: ChartLegend!
/// delegate to receive chart events
public weak var delegate: ChartViewDelegate?
/// text that is displayed when the chart is empty
public var noDataText = "No chart data available."
/// text that is displayed when the chart is empty that describes why the chart is empty
public var noDataTextDescription: String?
internal var _legendRenderer: ChartLegendRenderer!
/// object responsible for rendering the data
public var renderer: ChartDataRendererBase?
internal var _highlighter: ChartHighlighter?
/// object that manages the bounds and drawing constraints of the chart
internal var _viewPortHandler: ChartViewPortHandler!
/// object responsible for animations
internal var _animator: ChartAnimator!
/// flag that indicates if offsets calculation has already been done or not
private var _offsetsCalculated = false
/// array of Highlight objects that reference the highlighted slices in the chart
internal var _indicesToHightlight = [ChartHighlight]()
/// if set to true, the marker is drawn when a value is clicked
public var drawMarkers = true
/// the view that represents the marker
public var marker: ChartMarker?
private var _interceptTouchEvents = false
/// An extra offset to be appended to the viewport's top
public var extraTopOffset: CGFloat = 0.0
/// An extra offset to be appended to the viewport's right
public var extraRightOffset: CGFloat = 0.0
/// An extra offset to be appended to the viewport's bottom
public var extraBottomOffset: CGFloat = 0.0
/// An extra offset to be appended to the viewport's left
public var extraLeftOffset: CGFloat = 0.0
public func setExtraOffsets(left left: CGFloat, top: CGFloat, right: CGFloat, bottom: CGFloat)
{
extraLeftOffset = left
extraTopOffset = top
extraRightOffset = right
extraBottomOffset = bottom
}
// MARK: - Initializers
public override init(frame: CGRect)
{
super.init(frame: frame)
self.backgroundColor = UIColor.clearColor()
initialize()
}
public required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
initialize()
}
deinit
{
self.removeObserver(self, forKeyPath: "bounds")
self.removeObserver(self, forKeyPath: "frame")
}
internal func initialize()
{
_animator = ChartAnimator()
_animator.delegate = self
_viewPortHandler = ChartViewPortHandler()
_viewPortHandler.setChartDimens(width: bounds.size.width, height: bounds.size.height)
_legend = ChartLegend()
_legendRenderer = ChartLegendRenderer(viewPortHandler: _viewPortHandler, legend: _legend)
_defaultValueFormatter.minimumIntegerDigits = 1
_defaultValueFormatter.maximumFractionDigits = 1
_defaultValueFormatter.minimumFractionDigits = 1
_defaultValueFormatter.usesGroupingSeparator = true
_valueFormatter = _defaultValueFormatter.copy() as! NSNumberFormatter
self.addObserver(self, forKeyPath: "bounds", options: .New, context: nil)
self.addObserver(self, forKeyPath: "frame", options: .New, context: nil)
}
// MARK: - ChartViewBase
/// The data for the chart
public var data: ChartData?
{
get
{
return _data
}
set
{
if newValue == nil
{
print("Charts: data argument is nil on setData()", terminator: "\n")
return
}
_dataNotSet = false
_offsetsCalculated = false
_data = newValue
// calculate how many digits are needed
calculateFormatter(min: _data.getYMin(), max: _data.getYMax())
notifyDataSetChanged()
}
}
/// Clears the chart from all data (sets it to null) and refreshes it (by calling setNeedsDisplay()).
public func clear()
{
_data = nil
_dataNotSet = true
_indicesToHightlight.removeAll()
setNeedsDisplay()
}
/// Removes all DataSets (and thereby Entries) from the chart. Does not remove the x-values. Also refreshes the chart by calling setNeedsDisplay().
public func clearValues()
{
if (_data !== nil)
{
_data.clearValues()
}
setNeedsDisplay()
}
/// - returns: true if the chart is empty (meaning it's data object is either null or contains no entries).
public func isEmpty() -> Bool
{
if (_data == nil)
{
return true
}
else
{
if (_data.yValCount <= 0)
{
return true
}
else
{
return false
}
}
}
/// Lets the chart know its underlying data has changed and should perform all necessary recalculations.
/// It is crucial that this method is called everytime data is changed dynamically. Not calling this method can lead to crashes or unexpected behaviour.
public func notifyDataSetChanged()
{
fatalError("notifyDataSetChanged() cannot be called on ChartViewBase")
}
/// calculates the offsets of the chart to the border depending on the position of an eventual legend or depending on the length of the y-axis and x-axis labels and their position
internal func calculateOffsets()
{
fatalError("calculateOffsets() cannot be called on ChartViewBase")
}
/// calcualtes the y-min and y-max value and the y-delta and x-delta value
internal func calcMinMax()
{
fatalError("calcMinMax() cannot be called on ChartViewBase")
}
/// calculates the required number of digits for the values that might be drawn in the chart (if enabled), and creates the default value formatter
internal func calculateFormatter(min min: Double, max: Double)
{
// check if a custom formatter is set or not
var reference = Double(0.0)
if (_data == nil || _data.xValCount < 2)
{
let absMin = fabs(min)
let absMax = fabs(max)
reference = absMin > absMax ? absMin : absMax
}
else
{
reference = fabs(max - min)
}
let digits = ChartUtils.decimals(reference)
_defaultValueFormatter.maximumFractionDigits = digits
_defaultValueFormatter.minimumFractionDigits = digits
}
public override func drawRect(rect: CGRect)
{
let context = UIGraphicsGetCurrentContext()
let frame = self.bounds
if (_dataNotSet || _data === nil || _data.yValCount == 0)
{ // check if there is data
CGContextSaveGState(context)
// if no data, inform the user
ChartUtils.drawText(context: context, text: noDataText, point: CGPoint(x: frame.width / 2.0, y: frame.height / 2.0), align: .Center, attributes: [NSFontAttributeName: infoFont, NSForegroundColorAttributeName: infoTextColor])
if (noDataTextDescription != nil && (noDataTextDescription!).characters.count > 0)
{
let textOffset = -infoFont.lineHeight / 2.0
ChartUtils.drawText(context: context, text: noDataTextDescription!, point: CGPoint(x: frame.width / 2.0, y: frame.height / 2.0 + textOffset), align: .Center, attributes: [NSFontAttributeName: infoFont, NSForegroundColorAttributeName: infoTextColor])
}
return
}
if (!_offsetsCalculated)
{
calculateOffsets()
_offsetsCalculated = true
}
}
/// draws the description text in the bottom right corner of the chart
internal func drawDescription(context context: CGContext?)
{
if (descriptionText.lengthOfBytesUsingEncoding(NSUTF16StringEncoding) == 0)
{
return
}
let frame = self.bounds
var attrs = [String : AnyObject]()
var font = descriptionFont
if (font == nil)
{
#if os(tvOS)
// 23 is the smallest recommened font size on the TV
font = UIFont.systemFontOfSize(23, weight: UIFontWeightMedium)
#else
font = UIFont.systemFontOfSize(UIFont.systemFontSize())
#endif
}
attrs[NSFontAttributeName] = font
attrs[NSForegroundColorAttributeName] = descriptionTextColor
ChartUtils.drawText(context: context, text: descriptionText, point: CGPoint(x: frame.width - _viewPortHandler.offsetRight - 10.0, y: frame.height - _viewPortHandler.offsetBottom - 10.0 - font!.lineHeight), align: .Right, attributes: attrs)
}
// MARK: - Highlighting
/// - returns: the array of currently highlighted values. This might an empty if nothing is highlighted.
public var highlighted: [ChartHighlight]
{
return _indicesToHightlight
}
/// Checks if the highlight array is null, has a length of zero or if the first object is null.
/// - returns: true if there are values to highlight, false if there are no values to highlight.
public func valuesToHighlight() -> Bool
{
return _indicesToHightlight.count > 0
}
/// Highlights the values at the given indices in the given DataSets. Provide
/// null or an empty array to undo all highlighting.
/// This should be used to programmatically highlight values.
/// This DOES NOT generate a callback to the delegate.
public func highlightValues(highs: [ChartHighlight]?)
{
// set the indices to highlight
_indicesToHightlight = highs ?? [ChartHighlight]()
if (_indicesToHightlight.isEmpty)
{
self.lastHighlighted = nil
}
// redraw the chart
setNeedsDisplay()
}
/// Highlights the value at the given x-index in the given DataSet.
/// Provide -1 as the x-index to undo all highlighting.
public func highlightValue(xIndex xIndex: Int, dataSetIndex: Int, callDelegate: Bool)
{
if (xIndex < 0 || dataSetIndex < 0 || xIndex >= _data.xValCount || dataSetIndex >= _data.dataSetCount)
{
highlightValue(highlight: nil, callDelegate: callDelegate)
}
else
{
highlightValue(highlight: ChartHighlight(xIndex: xIndex, dataSetIndex: dataSetIndex), callDelegate: callDelegate)
}
}
/// Highlights the value selected by touch gesture.
public func highlightValue(highlight highlight: ChartHighlight?, callDelegate: Bool)
{
var entry: ChartDataEntry?
var h = highlight
if (h == nil)
{
_indicesToHightlight.removeAll(keepCapacity: false)
}
else
{
// set the indices to highlight
entry = _data.getEntryForHighlight(h!)
if (entry === nil || entry!.xIndex != h?.xIndex)
{
h = nil
entry = nil
_indicesToHightlight.removeAll(keepCapacity: false)
}
else
{
_indicesToHightlight = [h!]
}
}
// redraw the chart
setNeedsDisplay()
if (callDelegate && delegate != nil)
{
if (h == nil)
{
delegate!.chartValueNothingSelected?(self)
}
else
{
// notify the listener
delegate!.chartValueSelected?(self, entry: entry!, dataSetIndex: h!.dataSetIndex, highlight: h!)
}
}
}
/// The last value that was highlighted via touch.
public var lastHighlighted: ChartHighlight?
// MARK: - Markers
/// draws all MarkerViews on the highlighted positions
internal func drawMarkers(context context: CGContext?)
{
// if there is no marker view or drawing marker is disabled
if (marker === nil || !drawMarkers || !valuesToHighlight())
{
return
}
for (var i = 0, count = _indicesToHightlight.count; i < count; i++)
{
let highlight = _indicesToHightlight[i]
let xIndex = highlight.xIndex
if (xIndex <= Int(_deltaX) && xIndex <= Int(_deltaX * _animator.phaseX))
{
let e = _data.getEntryForHighlight(highlight)
if (e === nil || e!.xIndex != highlight.xIndex)
{
continue
}
let pos = getMarkerPosition(entry: e!, 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)
let markerSize = marker!.size
if (pos.y - markerSize.height <= 0.0)
{
let y = markerSize.height - pos.y
marker!.draw(context: context, point: CGPoint(x: pos.x, y: pos.y + y))
}
else
{
marker!.draw(context: context, point: pos)
}
}
}
}
/// - returns: the actual position in pixels of the MarkerView for the given Entry in the given DataSet.
public func getMarkerPosition(entry entry: ChartDataEntry, highlight: ChartHighlight) -> CGPoint
{
fatalError("getMarkerPosition() cannot be called on ChartViewBase")
}
// MARK: - Animation
/// - returns: the animator responsible for animating chart values.
public var animator: ChartAnimator!
{
return _animator
}
/// 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easingX: an easing function for the animation on the x axis
/// - parameter easingY: an easing function for the animation on the y axis
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval, easingX: ChartEasingFunctionBlock?, easingY: ChartEasingFunctionBlock?)
{
_animator.animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easingX: easingX, easingY: easingY)
}
/// 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easingOptionX: the easing function for the animation on the x axis
/// - parameter easingOptionY: the easing function for the animation on the y axis
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval, easingOptionX: ChartEasingOption, easingOptionY: ChartEasingOption)
{
_animator.animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easingOptionX: easingOptionX, easingOptionY: 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easing: an easing function for the animation
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval, easing: ChartEasingFunctionBlock?)
{
_animator.animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easing: 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easingOption: the easing function for the animation
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval, easingOption: ChartEasingOption)
{
_animator.animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easingOption: easingOption)
}
/// 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter yAxisDuration: duration for animating the y axis
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval)
{
_animator.animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration)
}
/// 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter easing: an easing function for the animation
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, easing: ChartEasingFunctionBlock?)
{
_animator.animate(xAxisDuration: xAxisDuration, easing: easing)
}
/// 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.
/// - parameter xAxisDuration: duration for animating the x axis
/// - parameter easingOption: the easing function for the animation
public func animate(xAxisDuration xAxisDuration: NSTimeInterval, easingOption: ChartEasingOption)
{
_animator.animate(xAxisDuration: xAxisDuration, easingOption: 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.
/// - parameter xAxisDuration: duration for animating the x axis
public func animate(xAxisDuration xAxisDuration: NSTimeInterval)
{
_animator.animate(xAxisDuration: xAxisDuration)
}
/// 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.
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easing: an easing function for the animation
public func animate(yAxisDuration yAxisDuration: NSTimeInterval, easing: ChartEasingFunctionBlock?)
{
_animator.animate(yAxisDuration: yAxisDuration, easing: easing)
}
/// 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.
/// - parameter yAxisDuration: duration for animating the y axis
/// - parameter easingOption: the easing function for the animation
public func animate(yAxisDuration yAxisDuration: NSTimeInterval, easingOption: ChartEasingOption)
{
_animator.animate(yAxisDuration: yAxisDuration, easingOption: 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.
/// - parameter yAxisDuration: duration for animating the y axis
public func animate(yAxisDuration yAxisDuration: NSTimeInterval)
{
_animator.animate(yAxisDuration: yAxisDuration)
}
// MARK: - Accessors
/// - returns: the current y-max value across all DataSets
public var chartYMax: Double
{
return _data.yMax
}
/// - returns: the current y-min value across all DataSets
public var chartYMin: Double
{
return _data.yMin
}
public var chartXMax: Double
{
return _chartXMax
}
public var chartXMin: Double
{
return _chartXMin
}
/// - returns: the total number of (y) values the chart holds (across all DataSets)
public var getValueCount: Int
{
return _data.yValCount
}
/// *Note: (Equivalent of getCenter() in MPAndroidChart, as center is already a standard in iOS that returns the center point relative to superview, and MPAndroidChart returns relative to self)*
/// - returns: the center point of the chart (the whole View) in pixels.
public var midPoint: CGPoint
{
let bounds = self.bounds
return CGPoint(x: bounds.origin.x + bounds.size.width / 2.0, y: bounds.origin.y + bounds.size.height / 2.0)
}
/// - returns: the center of the chart taking offsets under consideration. (returns the center of the content rectangle)
public var centerOffsets: CGPoint
{
return _viewPortHandler.contentCenter
}
/// - returns: the Legend object of the chart. This method can be used to get an instance of the legend in order to customize the automatically generated Legend.
public var legend: ChartLegend
{
return _legend
}
/// - returns: the renderer object responsible for rendering / drawing the Legend.
public var legendRenderer: ChartLegendRenderer!
{
return _legendRenderer
}
/// - returns: the rectangle that defines the borders of the chart-value surface (into which the actual values are drawn).
public var contentRect: CGRect
{
return _viewPortHandler.contentRect
}
/// Sets the formatter to be used for drawing the values inside the chart.
/// 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. Set this to nil to re-enable auto formatting.
public var valueFormatter: NSNumberFormatter!
{
get
{
return _valueFormatter
}
set
{
if (newValue === nil)
{
_valueFormatter = _defaultValueFormatter.copy() as! NSNumberFormatter
}
else
{
_valueFormatter = newValue
}
}
}
/// - returns: the x-value at the given index
public func getXValue(index: Int) -> String!
{
if (_data == nil || _data.xValCount <= index)
{
return nil
}
else
{
return _data.xVals[index]
}
}
/// Get all Entry objects at the given index across all DataSets.
public func getEntriesAtIndex(xIndex: Int) -> [ChartDataEntry]
{
var vals = [ChartDataEntry]()
for (var i = 0, count = _data.dataSetCount; i < count; i++)
{
let set = _data.getDataSetByIndex(i)
let e = set.entryForXIndex(xIndex)
if (e !== nil)
{
vals.append(e!)
}
}
return vals
}
/// - returns: the percentage the given value has of the total y-value sum
public func percentOfTotal(val: Double) -> Double
{
return val / _data.yValueSum * 100.0
}
/// - returns: the ViewPortHandler of the chart that is responsible for the
/// content area of the chart and its offsets and dimensions.
public var viewPortHandler: ChartViewPortHandler!
{
return _viewPortHandler
}
/// - returns: the bitmap that represents the chart.
public func getChartImage(transparent transparent: Bool) -> UIImage
{
UIGraphicsBeginImageContextWithOptions(bounds.size, opaque || !transparent, UIScreen.mainScreen().scale)
let context = UIGraphicsGetCurrentContext()
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: bounds.size)
if (opaque || !transparent)
{
// Background color may be partially transparent, we must fill with white if we want to output an opaque image
CGContextSetFillColorWithColor(context, UIColor.whiteColor().CGColor)
CGContextFillRect(context, rect)
if (self.backgroundColor !== nil)
{
CGContextSetFillColorWithColor(context, self.backgroundColor?.CGColor)
CGContextFillRect(context, rect)
}
}
if let context = context
{
layer.renderInContext(context)
}
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
public enum ImageFormat
{
case JPEG
case PNG
}
/// Saves the current chart state with the given name to the given path on
/// the sdcard leaving the path empty "" will put the saved file directly on
/// the SD card chart is saved as a PNG image, example:
/// saveToPath("myfilename", "foldername1/foldername2")
///
/// - parameter filePath: path to the image to save
/// - parameter format: the format to save
/// - parameter compressionQuality: compression quality for lossless formats (JPEG)
///
/// - returns: true if the image was saved successfully
public func saveToPath(path: String, format: ImageFormat, compressionQuality: Double) -> Bool
{
let image = getChartImage(transparent: format != .JPEG)
var imageData: NSData!
switch (format)
{
case .PNG:
imageData = UIImagePNGRepresentation(image)
break
case .JPEG:
imageData = UIImageJPEGRepresentation(image, CGFloat(compressionQuality))
break
}
return imageData.writeToFile(path, atomically: true)
}
#if !os(tvOS)
/// Saves the current state of the chart to the camera roll
public func saveToCameraRoll()
{
UIImageWriteToSavedPhotosAlbum(getChartImage(transparent: false), nil, nil, nil)
}
#endif
internal typealias VoidClosureType = () -> ()
internal var _sizeChangeEventActions = [VoidClosureType]()
public override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>)
{
if (keyPath == "bounds" || keyPath == "frame")
{
let bounds = self.bounds
if (_viewPortHandler !== nil &&
(bounds.size.width != _viewPortHandler.chartWidth ||
bounds.size.height != _viewPortHandler.chartHeight))
{
_viewPortHandler.setChartDimens(width: bounds.size.width, height: bounds.size.height)
// Finish any pending viewport changes
while (!_sizeChangeEventActions.isEmpty)
{
_sizeChangeEventActions.removeAtIndex(0)()
}
notifyDataSetChanged()
}
}
}
public func clearPendingViewPortChanges()
{
_sizeChangeEventActions.removeAll(keepCapacity: false)
}
/// if true, value highlighting is enabled
public var highlightEnabled: Bool
{
get
{
return _data === nil ? true : _data.highlightEnabled
}
set
{
if (_data !== nil)
{
_data.highlightEnabled = newValue
}
}
}
/// if true, value highlightning is enabled
public var isHighlightEnabled: Bool { return highlightEnabled }
/// **default**: true
/// - returns: true if chart continues to scroll after touch up, false if not.
public var isDragDecelerationEnabled: Bool
{
return dragDecelerationEnabled
}
/// Deceleration friction coefficient in [0 ; 1] interval, higher values indicate that speed will decrease slowly, for example if it set to 0, it will stop immediately.
/// 1 is an invalid value, and will be converted to 0.999 automatically.
///
/// **default**: true
public var dragDecelerationFrictionCoef: CGFloat
{
get
{
return _dragDecelerationFrictionCoef
}
set
{
var val = newValue
if (val < 0.0)
{
val = 0.0
}
if (val >= 1.0)
{
val = 0.999
}
_dragDecelerationFrictionCoef = val
}
}
// MARK: - ChartAnimatorDelegate
public func chartAnimatorUpdated(chartAnimator: ChartAnimator)
{
setNeedsDisplay()
}
public func chartAnimatorStopped(chartAnimator: ChartAnimator)
{
}
// MARK: - Touches
public override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
if (!_interceptTouchEvents)
{
super.touchesBegan(touches, withEvent: event)
}
}
public override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?)
{
if (!_interceptTouchEvents)
{
super.touchesMoved(touches, withEvent: event)
}
}
public override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?)
{
if (!_interceptTouchEvents)
{
super.touchesEnded(touches, withEvent: event)
}
}
public override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?)
{
if (!_interceptTouchEvents)
{
super.touchesCancelled(touches, withEvent: event)
}
}
}

View File

@@ -1,214 +0,0 @@
//
// CombinedChartView.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
/// This chart class allows the combination of lines, bars, scatter and candle data all displayed in one chart area.
public class CombinedChartView: BarLineChartViewBase
{
/// the fill-formatter used for determining the position of the fill-line
internal var _fillFormatter: ChartFillFormatter!
/// enum that allows to specify the order in which the different data objects for the combined-chart are drawn
@objc
public enum CombinedChartDrawOrder: Int
{
case Bar
case Bubble
case Line
case Candle
case Scatter
}
public override func initialize()
{
super.initialize()
_highlighter = CombinedHighlighter(chart: self)
/// WORKAROUND: Swift 2.0 compiler malfunctions when optimizations are enabled, and assigning directly to _fillFormatter causes a crash with a EXC_BAD_ACCESS. See https://github.com/danielgindi/ios-charts/issues/406
let workaroundFormatter = BarLineChartFillFormatter(chart: self)
_fillFormatter = workaroundFormatter
renderer = CombinedChartRenderer(chart: self, animator: _animator, viewPortHandler: _viewPortHandler)
}
override func calcMinMax()
{
super.calcMinMax()
if (self.barData !== nil || self.candleData !== nil || self.bubbleData !== nil)
{
_chartXMin = -0.5
_chartXMax = Double(_data.xVals.count) - 0.5
if (self.bubbleData !== nil)
{
for set in self.bubbleData.dataSets as! [BubbleChartDataSet]
{
let xmin = set.xMin
let xmax = set.xMax
if (xmin < chartXMin)
{
_chartXMin = xmin
}
if (xmax > chartXMax)
{
_chartXMax = xmax
}
}
}
_deltaX = CGFloat(abs(_chartXMax - _chartXMin))
}
}
public override var data: ChartData?
{
get
{
return super.data
}
set
{
super.data = newValue
(renderer as! CombinedChartRenderer?)!.createRenderers()
}
}
public var fillFormatter: ChartFillFormatter
{
get
{
return _fillFormatter
}
set
{
_fillFormatter = newValue
if (_fillFormatter === nil)
{
_fillFormatter = BarLineChartFillFormatter(chart: self)
}
}
}
public var lineData: LineChartData!
{
get
{
if (_data === nil)
{
return nil
}
return (_data as! CombinedChartData!).lineData
}
}
public var barData: BarChartData!
{
get
{
if (_data === nil)
{
return nil
}
return (_data as! CombinedChartData!).barData
}
}
public var scatterData: ScatterChartData!
{
get
{
if (_data === nil)
{
return nil
}
return (_data as! CombinedChartData!).scatterData
}
}
public var candleData: CandleChartData!
{
get
{
if (_data === nil)
{
return nil
}
return (_data as! CombinedChartData!).candleData
}
}
public var bubbleData: BubbleChartData!
{
get
{
if (_data === nil)
{
return nil
}
return (_data as! CombinedChartData!).bubbleData
}
}
// MARK: Accessors
/// flag that enables or disables the highlighting arrow
public var drawHighlightArrowEnabled: Bool
{
get { return (renderer as! CombinedChartRenderer!).drawHighlightArrowEnabled; }
set { (renderer as! CombinedChartRenderer!).drawHighlightArrowEnabled = newValue; }
}
/// if set to true, all values are drawn above their bars, instead of below their top
public var drawValueAboveBarEnabled: Bool
{
get { return (renderer as! CombinedChartRenderer!).drawValueAboveBarEnabled; }
set { (renderer as! CombinedChartRenderer!).drawValueAboveBarEnabled = newValue; }
}
/// if set to true, a grey area is darawn behind each bar that indicates the maximum value
public var drawBarShadowEnabled: Bool
{
get { return (renderer as! CombinedChartRenderer!).drawBarShadowEnabled; }
set { (renderer as! CombinedChartRenderer!).drawBarShadowEnabled = newValue; }
}
/// - returns: true if drawing the highlighting arrow is enabled, false if not
public var isDrawHighlightArrowEnabled: Bool { return (renderer as! CombinedChartRenderer!).drawHighlightArrowEnabled; }
/// - returns: true if drawing values above bars is enabled, false if not
public var isDrawValueAboveBarEnabled: Bool { return (renderer as! CombinedChartRenderer!).drawValueAboveBarEnabled; }
/// - returns: true if drawing shadows (maxvalue) for each bar is enabled, false if not
public 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.
public var drawOrder: [Int]
{
get
{
return (renderer as! CombinedChartRenderer!).drawOrder.map { $0.rawValue }
}
set
{
(renderer as! CombinedChartRenderer!).drawOrder = newValue.map { CombinedChartDrawOrder(rawValue: $0)! }
}
}
}

View File

@@ -1,208 +0,0 @@
//
// HorizontalBarChartView.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
/// BarChart with horizontal bar orientation. In this implementation, x- and y-axis are switched.
public class HorizontalBarChartView: BarChartView
{
internal override func initialize()
{
super.initialize()
_leftAxisTransformer = ChartTransformerHorizontalBarChart(viewPortHandler: _viewPortHandler)
_rightAxisTransformer = ChartTransformerHorizontalBarChart(viewPortHandler: _viewPortHandler)
renderer = HorizontalBarChartRenderer(delegate: self, animator: _animator, viewPortHandler: _viewPortHandler)
_leftYAxisRenderer = ChartYAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, yAxis: _leftAxis, transformer: _leftAxisTransformer)
_rightYAxisRenderer = ChartYAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, yAxis: _rightAxis, transformer: _rightAxisTransformer)
_xAxisRenderer = ChartXAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, xAxis: _xAxis, transformer: _leftAxisTransformer, chart: self)
_highlighter = HorizontalBarChartHighlighter(chart: self)
}
internal override func calculateOffsets()
{
var offsetLeft: CGFloat = 0.0,
offsetRight: CGFloat = 0.0,
offsetTop: CGFloat = 0.0,
offsetBottom: CGFloat = 0.0
// setup offsets for legend
if (_legend !== nil && _legend.isEnabled)
{
if (_legend.position == .RightOfChart
|| _legend.position == .RightOfChartCenter)
{
offsetRight += min(_legend.neededWidth, _viewPortHandler.chartWidth * _legend.maxSizePercent) + _legend.xOffset * 2.0
}
else if (_legend.position == .LeftOfChart
|| _legend.position == .LeftOfChartCenter)
{
offsetLeft += min(_legend.neededWidth, _viewPortHandler.chartWidth * _legend.maxSizePercent) + _legend.xOffset * 2.0
}
else if (_legend.position == .BelowChartLeft
|| _legend.position == .BelowChartRight
|| _legend.position == .BelowChartCenter)
{
// 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 = _legend.textHeightMax
offsetBottom += min(_legend.neededHeight + yOffset, _viewPortHandler.chartHeight * _legend.maxSizePercent)
}
else if (_legend.position == .AboveChartLeft
|| _legend.position == .AboveChartRight
|| _legend.position == .AboveChartCenter)
{
// 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 = _legend.textHeightMax
offsetTop += min(_legend.neededHeight + yOffset, _viewPortHandler.chartHeight * _legend.maxSizePercent)
}
}
// offsets for y-labels
if (_leftAxis.needsOffset)
{
offsetTop += _leftAxis.getRequiredHeightSpace()
}
if (_rightAxis.needsOffset)
{
offsetBottom += _rightAxis.getRequiredHeightSpace()
}
let xlabelwidth = _xAxis.labelWidth
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: _deltaX, chartYMin: _chartXMin)
_leftAxisTransformer.prepareMatrixValuePx(chartXMin: _leftAxis.axisMinimum, deltaX: CGFloat(_leftAxis.axisRange), deltaY: _deltaX, chartYMin: _chartXMin)
}
internal override func calcModulus()
{
_xAxis.axisLabelModulus = Int(ceil((CGFloat(_data.xValCount) * _xAxis.labelHeight) / (_viewPortHandler.contentHeight * viewPortHandler.touchMatrix.d)))
if (_xAxis.axisLabelModulus < 1)
{
_xAxis.axisLabelModulus = 1
}
}
public override func getBarBounds(e: BarChartDataEntry) -> CGRect!
{
let set = _data.getDataSetForEntry(e) as! BarChartDataSet!
if (set === nil)
{
return nil
}
let barspace = set.barSpace
let y = CGFloat(e.value)
let x = CGFloat(e.xIndex)
let spaceHalf = barspace / 2.0
let top = x - 0.5 + spaceHalf
let bottom = x + 0.5 - spaceHalf
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(set.axisDependency).rectValueToPixel(&bounds)
return bounds
}
public override func getPosition(e: ChartDataEntry, axis: ChartYAxis.AxisDependency) -> CGPoint
{
var vals = CGPoint(x: CGFloat(e.value), y: CGFloat(e.xIndex))
getTransformer(axis).pointValueToPixel(&vals)
return vals
}
public override func getHighlightByTouchPoint(pt: CGPoint) -> ChartHighlight?
{
if (_dataNotSet || _data === nil)
{
print("Can't select by touch. No data set.", terminator: "\n")
return nil
}
return _highlighter?.getHighlight(x: Double(pt.y), y: Double(pt.x))
}
public override var lowestVisibleXIndex: Int
{
let step = CGFloat(_data.dataSetCount)
let div = (step <= 1.0) ? 1.0 : step + (_data as! BarChartData).groupSpace
var pt = CGPoint(x: _viewPortHandler.contentLeft, y: _viewPortHandler.contentBottom)
getTransformer(ChartYAxis.AxisDependency.Left).pixelToValue(&pt)
return Int(((pt.y <= 0.0) ? 0.0 : pt.y / div) + 1.0)
}
public override var highestVisibleXIndex: Int
{
let step = CGFloat(_data.dataSetCount)
let div = (step <= 1.0) ? 1.0 : step + (_data as! BarChartData).groupSpace
var pt = CGPoint(x: _viewPortHandler.contentLeft, y: _viewPortHandler.contentTop)
getTransformer(ChartYAxis.AxisDependency.Left).pixelToValue(&pt)
return Int((pt.y >= CGFloat(chartXMax)) ? CGFloat(chartXMax) / div : (pt.y / div))
}
}

View File

@@ -1,106 +0,0 @@
//
// LineChartView.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
/// Chart that draws lines, surfaces, circles, ...
public class LineChartView: BarLineChartViewBase, LineChartRendererDelegate
{
private var _fillFormatter: ChartFillFormatter!
internal override func initialize()
{
super.initialize()
renderer = LineChartRenderer(delegate: self, animator: _animator, viewPortHandler: _viewPortHandler)
_fillFormatter = BarLineChartFillFormatter(chart: self)
}
internal override func calcMinMax()
{
super.calcMinMax()
if (_deltaX == 0.0 && _data.yValCount > 0)
{
_deltaX = 1.0
}
}
public var fillFormatter: ChartFillFormatter!
{
get
{
return _fillFormatter
}
set
{
if (newValue === nil)
{
_fillFormatter = BarLineChartFillFormatter(chart: self)
}
else
{
_fillFormatter = newValue
}
}
}
// MARK: - LineChartRendererDelegate
public func lineChartRendererData(renderer: LineChartRenderer) -> LineChartData!
{
return _data as! LineChartData!
}
public func lineChartRenderer(renderer: LineChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
{
return self.getTransformer(which)
}
public func lineChartRendererFillFormatter(renderer: LineChartRenderer) -> ChartFillFormatter
{
return self.fillFormatter
}
public func lineChartDefaultRendererValueFormatter(renderer: LineChartRenderer) -> NSNumberFormatter!
{
return self._defaultValueFormatter
}
public func lineChartRendererChartYMax(renderer: LineChartRenderer) -> Double
{
return self.chartYMax
}
public func lineChartRendererChartYMin(renderer: LineChartRenderer) -> Double
{
return self.chartYMin
}
public func lineChartRendererChartXMax(renderer: LineChartRenderer) -> Double
{
return self.chartXMax
}
public func lineChartRendererChartXMin(renderer: LineChartRenderer) -> Double
{
return self.chartXMin
}
public func lineChartRendererMaxVisibleValueCount(renderer: LineChartRenderer) -> Int
{
return self.maxVisibleValueCount
}
}

View File

@@ -1,505 +0,0 @@
//
// PieChartView.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
/// View that represents a pie chart. Draws cake like slices.
public class PieChartView: PieRadarChartViewBase
{
/// rect object that represents the bounds of the piechart, needed for drawing the circle
private var _circleBox = CGRect()
/// 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]()
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)
}
public override func drawRect(rect: CGRect)
{
super.drawRect(rect)
if (_dataNotSet)
{
return
}
let context = UIGraphicsGetCurrentContext()
renderer!.drawData(context: context)
if (valuesToHighlight())
{
renderer!.drawHighlighted(context: context, indices: _indicesToHightlight)
}
renderer!.drawExtras(context: context)
renderer!.drawValues(context: context)
_legendRenderer.renderLegend(context: context)
drawDescription(context: context)
drawMarkers(context: context)
}
internal override func calculateOffsets()
{
super.calculateOffsets()
// prevent nullpointer when no data set
if (_dataNotSet)
{
return
}
let radius = diameter / 2.0
let c = centerOffsets
let dataSets = data?.dataSets as? [PieChartDataSet]
let maxShift = dataSets?.reduce(0.0, combine: { shift, dataSet in
return dataSet.selectionShift > shift ? dataSet.selectionShift : shift
}) ?? 0.0
// create the circle box that will contain the pie-chart (the bounds of the pie-chart)
_circleBox.origin.x = (c.x - radius) + (maxShift / 2.0)
_circleBox.origin.y = (c.y - radius) + (maxShift / 2.0)
_circleBox.size.width = diameter - maxShift
_circleBox.size.height = diameter - maxShift
}
internal override func calcMinMax()
{
super.calcMinMax()
calcAngles()
}
public override func getMarkerPosition(entry e: ChartDataEntry, highlight: ChartHighlight) -> 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 i = e.xIndex
// offset needed to center the drawn text in the slice
let offset = drawAngles[i] / 2.0
// calculate the text position
let x: CGFloat = (r * cos(((rotationAngle + absoluteAngles[i] - offset) * _animator.phaseY) * ChartUtils.Math.FDEG2RAD) + center.x)
let y: CGFloat = (r * sin(((rotationAngle + absoluteAngles[i] - offset) * _animator.phaseY) * ChartUtils.Math.FDEG2RAD) + center.y)
return CGPoint(x: x, y: y)
}
/// calculates the needed angles for the chart slices
private func calcAngles()
{
_drawAngles = [CGFloat]()
_absoluteAngles = [CGFloat]()
_drawAngles.reserveCapacity(_data.yValCount)
_absoluteAngles.reserveCapacity(_data.yValCount)
var dataSets = _data.dataSets
var cnt = 0
for (var i = 0; i < _data.dataSetCount; i++)
{
let set = dataSets[i]
var entries = set.yVals
for (var j = 0; j < entries.count; j++)
{
_drawAngles.append(calcAngle(abs(entries[j].value)))
if (cnt == 0)
{
_absoluteAngles.append(_drawAngles[cnt])
}
else
{
_absoluteAngles.append(_absoluteAngles[cnt - 1] + _drawAngles[cnt])
}
cnt++
}
}
}
/// checks if the given index in the given DataSet is set for highlighting or not
public func needsHighlight(xIndex xIndex: Int, dataSetIndex: Int) -> Bool
{
// no highlight
if (!valuesToHighlight() || dataSetIndex < 0)
{
return false
}
for (var i = 0; i < _indicesToHightlight.count; i++)
{
// check if the xvalue for the given dataset needs highlight
if (_indicesToHightlight[i].xIndex == xIndex
&& _indicesToHightlight[i].dataSetIndex == dataSetIndex)
{
return true
}
}
return false
}
/// calculates the needed angle for a given value
private func calcAngle(value: Double) -> CGFloat
{
return CGFloat(value) / CGFloat(_data.yValueSum) * 360.0
}
public override func indexForAngle(angle: CGFloat) -> Int
{
// take the current angle of the chart into consideration
let a = ChartUtils.normalizedAngleFromAngle(angle - self.rotationAngle)
for (var i = 0; i < _absoluteAngles.count; i++)
{
if (_absoluteAngles[i] > a)
{
return i
}
}
return -1; // return -1 if no index found
}
/// - returns: the index of the DataSet this x-index belongs to.
public func dataSetIndexForIndex(xIndex: Int) -> Int
{
var dataSets = _data.dataSets
for (var i = 0; i < dataSets.count; i++)
{
if (dataSets[i].entryForXIndex(xIndex) !== nil)
{
return i
}
}
return -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
public var drawAngles: [CGFloat]
{
return _drawAngles
}
/// - returns: the absolute angles of the different chart slices (where the
/// slices end)
public var absoluteAngles: [CGFloat]
{
return _absoluteAngles
}
/// Sets 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.*
public var holeColor: UIColor?
{
get
{
return (renderer as! PieChartRenderer).holeColor!
}
set
{
(renderer as! PieChartRenderer).holeColor = newValue
setNeedsDisplay()
}
}
/// Set the hole in the center of the PieChart transparent
public var holeTransparent: Bool
{
get
{
return (renderer as! PieChartRenderer).holeTransparent
}
set
{
(renderer as! PieChartRenderer).holeTransparent = newValue
setNeedsDisplay()
}
}
/// - returns: true if the hole in the center of the PieChart is transparent, false if not.
public var isHoleTransparent: Bool
{
return (renderer as! PieChartRenderer).holeTransparent
}
/// true if the hole in the center of the pie-chart is set to be visible, false if not
public var drawHoleEnabled: Bool
{
get
{
return (renderer as! PieChartRenderer).drawHoleEnabled
}
set
{
(renderer as! PieChartRenderer).drawHoleEnabled = newValue
setNeedsDisplay()
}
}
/// - returns: true if the hole in the center of the pie-chart is set to be visible, false if not
public var isDrawHoleEnabled: Bool
{
get
{
return (renderer as! PieChartRenderer).drawHoleEnabled
}
}
/// the text that is displayed in the center of the pie-chart. By default, the text is "Total value + sum of all values"
public var centerText: String!
{
get
{
return (renderer as! PieChartRenderer).centerText
}
set
{
(renderer as! PieChartRenderer).centerText = newValue
setNeedsDisplay()
}
}
/// true if drawing the center text is enabled
public var drawCenterTextEnabled: Bool
{
get
{
return (renderer as! PieChartRenderer).drawCenterTextEnabled
}
set
{
(renderer as! PieChartRenderer).drawCenterTextEnabled = newValue
setNeedsDisplay()
}
}
/// - returns: true if drawing the center text is enabled
public var isDrawCenterTextEnabled: Bool
{
get
{
return (renderer as! PieChartRenderer).drawCenterTextEnabled
}
}
internal override var requiredLegendOffset: CGFloat
{
return _legend.font.pointSize * 2.0
}
internal override var requiredBaseOffset: CGFloat
{
return 0.0
}
public override var radius: CGFloat
{
return _circleBox.width / 2.0
}
/// - returns: the circlebox, the boundingbox of the pie-chart slices
public var circleBox: CGRect
{
return _circleBox
}
/// - returns: the center of the circlebox
public var centerCircleBox: CGPoint
{
return CGPoint(x: _circleBox.midX, y: _circleBox.midY)
}
/// Sets the font of the center text of the piechart.
public var centerTextFont: UIFont
{
get
{
return (renderer as! PieChartRenderer).centerTextFont
}
set
{
(renderer as! PieChartRenderer).centerTextFont = newValue
setNeedsDisplay()
}
}
/// Sets the color of the center text of the piechart.
public var centerTextColor: UIColor
{
get
{
return (renderer as! PieChartRenderer).centerTextColor
}
set
{
(renderer as! PieChartRenderer).centerTextColor = newValue
setNeedsDisplay()
}
}
/// 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)
public var holeRadiusPercent: CGFloat
{
get
{
return (renderer as! PieChartRenderer).holeRadiusPercent
}
set
{
(renderer as! PieChartRenderer).holeRadiusPercent = 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
public var transparentCircleRadiusPercent: CGFloat
{
get
{
return (renderer as! PieChartRenderer).transparentCircleRadiusPercent
}
set
{
(renderer as! PieChartRenderer).transparentCircleRadiusPercent = newValue
setNeedsDisplay()
}
}
/// set this to true to draw the x-value text into the pie slices
public var drawSliceTextEnabled: Bool
{
get
{
return (renderer as! PieChartRenderer).drawXLabelsEnabled
}
set
{
(renderer as! PieChartRenderer).drawXLabelsEnabled = newValue
setNeedsDisplay()
}
}
/// - returns: true if drawing x-values is enabled, false if not
public var isDrawSliceTextEnabled: Bool
{
get
{
return (renderer as! PieChartRenderer).drawXLabelsEnabled
}
}
/// 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.
public var usePercentValuesEnabled: Bool
{
get
{
return (renderer as! PieChartRenderer).usePercentValuesEnabled
}
set
{
(renderer as! PieChartRenderer).usePercentValuesEnabled = newValue
setNeedsDisplay()
}
}
/// - returns: true if drawing x-values is enabled, false if not
public var isUsePercentValuesEnabled: Bool
{
get
{
return (renderer as! PieChartRenderer).usePercentValuesEnabled
}
}
/// the line break mode for center text.
/// note that different line break modes give different performance results - Clipping being the fastest, WordWrapping being the slowst.
public var centerTextLineBreakMode: NSLineBreakMode
{
get
{
return (renderer as! PieChartRenderer).centerTextLineBreakMode
}
set
{
(renderer as! PieChartRenderer).centerTextLineBreakMode = newValue
setNeedsDisplay()
}
}
/// the rectangular radius of the bounding box for the center text, as a percentage of the pie hole
public var centerTextRadiusPercent: CGFloat
{
get
{
return (renderer as! PieChartRenderer).centerTextRadiusPercent
}
set
{
(renderer as! PieChartRenderer).centerTextRadiusPercent = newValue
setNeedsDisplay()
}
}
}

View File

@@ -1,853 +0,0 @@
//
// PieRadarChartViewBase.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
/// Base class of PieChartView and RadarChartView.
public 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
public var rotationEnabled = true
/// Sets the minimum offset (padding) around the chart, defaults to 10
public var minOffset = CGFloat(10.0)
private var _rotationWithTwoFingers = false
private var _tapGestureRecognizer: UITapGestureRecognizer!
#if !os(tvOS)
private var _rotationGestureRecognizer: UIRotationGestureRecognizer!
#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 = UITapGestureRecognizer(target: self, action: Selector("tapGestureRecognized:"))
self.addGestureRecognizer(_tapGestureRecognizer)
#if !os(tvOS)
_rotationGestureRecognizer = UIRotationGestureRecognizer(target: self, action: Selector("rotationGestureRecognized:"))
self.addGestureRecognizer(_rotationGestureRecognizer)
_rotationGestureRecognizer.enabled = rotationWithTwoFingers
#endif
}
internal override func calcMinMax()
{
_deltaX = CGFloat(_data.xVals.count - 1)
}
public override func notifyDataSetChanged()
{
if (_dataNotSet)
{
return
}
calcMinMax()
if (_legend !== nil)
{
_legendRenderer.computeLegend(_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)
{
var fullLegendWidth = min(_legend.neededWidth, _viewPortHandler.chartWidth * _legend.maxSizePercent)
fullLegendWidth += _legend.formSize + _legend.formToTextSpace
if (_legend.position == .RightOfChartCenter)
{
// this is the space between the legend and the chart
let spacing = CGFloat(13.0)
legendRight = fullLegendWidth + spacing
}
else if (_legend.position == .RightOfChart)
{
// 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 bottomRight = CGPoint(x: self.bounds.width - legendWidth + 15.0, y: legendHeight + 15)
let distLegend = distanceToCenter(x: bottomRight.x, y: bottomRight.y)
let reference = getPosition(center: c, dist: self.radius,
angle: angleForPoint(x: bottomRight.x, y: bottomRight.y))
let distReference = distanceToCenter(x: reference.x, y: reference.y)
let minOffset = CGFloat(5.0)
if (distLegend < distReference)
{
let diff = distReference - distLegend
legendRight = minOffset + diff
}
if (bottomRight.y >= c.y && self.bounds.height - legendWidth > self.bounds.width)
{
legendRight = legendWidth
}
}
else if (_legend.position == .LeftOfChartCenter)
{
// this is the space between the legend and the chart
let spacing = CGFloat(13.0)
legendLeft = fullLegendWidth + spacing
}
else if (_legend.position == .LeftOfChart)
{
// 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 bottomLeft = CGPoint(x: legendWidth - 15.0, y: legendHeight + 15)
let distLegend = distanceToCenter(x: bottomLeft.x, y: bottomLeft.y)
let reference = getPosition(center: c, dist: self.radius,
angle: angleForPoint(x: bottomLeft.x, y: bottomLeft.y))
let distReference = distanceToCenter(x: reference.x, y: reference.y)
let min = CGFloat(5.0)
if (distLegend < distReference)
{
let diff = distReference - distLegend
legendLeft = min + diff
}
if (bottomLeft.y >= c.y && self.bounds.height - legendWidth > self.bounds.width)
{
legendLeft = legendWidth
}
}
else if (_legend.position == .BelowChartLeft
|| _legend.position == .BelowChartRight
|| _legend.position == .BelowChartCenter)
{
// 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
legendBottom = min(_legend.neededHeight + yOffset, _viewPortHandler.chartHeight * _legend.maxSizePercent)
}
else if (_legend.position == .AboveChartLeft
|| _legend.position == .AboveChartRight
|| _legend.position == .AboveChartCenter)
{
// 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
legendTop = min(_legend.neededHeight + yOffset, _viewPortHandler.chartHeight * _legend.maxSizePercent)
}
legendLeft += self.requiredBaseOffset
legendRight += self.requiredBaseOffset
legendTop += self.requiredBaseOffset
}
legendTop += self.extraTopOffset
legendRight += self.extraRightOffset
legendBottom += self.extraBottomOffset
legendLeft += self.extraLeftOffset
var minOffset = self.minOffset
if (self.isKindOfClass(RadarChartView))
{
let x = (self as! RadarChartView).xAxis
if x.isEnabled && x.drawLabelsEnabled
{
minOffset = max(minOffset, x.labelWidth)
}
}
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, ...
public func angleForPoint(x 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 * ChartUtils.Math.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.
internal func getPosition(center center: CGPoint, dist: CGFloat, angle: CGFloat) -> CGPoint
{
return CGPoint(x: center.x + dist * cos(angle * ChartUtils.Math.FDEG2RAD),
y: center.y + dist * sin(angle * ChartUtils.Math.FDEG2RAD))
}
/// - returns: the distance of a certain point on the chart to the center of the chart.
public func distanceToCenter(x 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.
public func indexForAngle(angle: CGFloat) -> Int
{
fatalError("indexForAngle() cannot be called on PieRadarChartViewBase")
}
/// current rotation angle of the pie chart
///
/// **default**: 270 --> top (NORTH)
/// - returns: will always return a normalized value, which will be between 0.0 < 360.0
public var rotationAngle: CGFloat
{
get
{
return _rotationAngle
}
set
{
_rawRotationAngle = newValue
_rotationAngle = ChartUtils.normalizedAngleFromAngle(newValue)
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.
public var rawRotationAngle: CGFloat
{
return _rawRotationAngle
}
/// - returns: the diameter of the pie- or radar-chart
public var diameter: CGFloat
{
let content = _viewPortHandler.contentRect
return min(content.width, content.height)
}
/// - returns: the radius of the chart in pixels.
public var radius: CGFloat
{
fatalError("radius cannot be called on PieRadarChartViewBase")
}
/// - returns: 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")
}
public override var chartXMax: Double
{
return 0.0
}
public override var chartXMin: Double
{
getSelectionDetailsAtIndex(1);
return 0.0
}
/// The SelectionDetail objects give information about the value at the selected index and the DataSet it belongs to.
/// - returns: an array of SelectionDetail objects for the given x-index.
public func getSelectionDetailsAtIndex(xIndex: Int) -> [ChartSelectionDetail]
{
var vals = [ChartSelectionDetail]()
for (var i = 0; i < _data.dataSetCount; i++)
{
let dataSet = _data.getDataSetByIndex(i)
if (dataSet === nil || !dataSet.isHighlightEnabled)
{
continue
}
// extract all y-values from all DataSets at the given x-index
let yVal = dataSet!.yValForXIndex(xIndex)
if (yVal.isNaN)
{
continue
}
vals.append(ChartSelectionDetail(value: yVal, dataSetIndex: i, dataSet: dataSet!))
}
return vals
}
public 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.
///
/// **default**: false
public var rotationWithTwoFingers: Bool
{
get
{
return _rotationWithTwoFingers
}
set
{
_rotationWithTwoFingers = newValue
#if !os(tvOS)
_rotationGestureRecognizer.enabled = _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.
///
/// **default**: false
public var isRotationWithTwoFingers: Bool
{
return _rotationWithTwoFingers
}
// MARK: - Animation
private var _spinAnimator: ChartAnimator!
/// Applys a spin animation to the Chart.
public func spin(duration duration: NSTimeInterval, fromAngle: CGFloat, toAngle: CGFloat, easing: ChartEasingFunctionBlock?)
{
if (_spinAnimator != nil)
{
_spinAnimator.stop()
}
_spinAnimator = ChartAnimator()
_spinAnimator.updateBlock = {
self.rotationAngle = (toAngle - fromAngle) * self._spinAnimator.phaseX + fromAngle
}
_spinAnimator.stopBlock = { self._spinAnimator = nil; }
_spinAnimator.animate(xAxisDuration: duration, easing: easing)
}
public func spin(duration duration: NSTimeInterval, fromAngle: CGFloat, toAngle: CGFloat, easingOption: ChartEasingOption)
{
spin(duration: duration, fromAngle: fromAngle, toAngle: toAngle, easing: easingFunctionFromOption(easingOption))
}
public func spin(duration duration: NSTimeInterval, fromAngle: CGFloat, toAngle: CGFloat)
{
spin(duration: duration, fromAngle: fromAngle, toAngle: toAngle, easing: nil)
}
public func stopSpinAnimation()
{
if (_spinAnimator != nil)
{
_spinAnimator.stop()
}
}
// MARK: - Gestures
private var _touchStartPoint: CGPoint!
private var _isRotating = false
private var _defaultTouchEventsWereEnabled = false
private var _startAngle = CGFloat(0.0)
private struct AngularVelocitySample
{
var time: NSTimeInterval
var angle: CGFloat
}
private var _velocitySamples = [AngularVelocitySample]()
private var _decelerationLastTime: NSTimeInterval = 0.0
private var _decelerationDisplayLink: CADisplayLink!
private var _decelerationAngularVelocity: CGFloat = 0.0
public override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
// if rotation by touch is enabled
if (rotationEnabled)
{
stopDeceleration()
if (!rotationWithTwoFingers)
{
let touch = touches.first as UITouch!
let touchLocation = touch.locationInView(self)
self.resetVelocity()
if (rotationEnabled)
{
self.sampleVelocity(touchLocation: touchLocation)
}
self.setGestureStartAngle(x: touchLocation.x, y: touchLocation.y)
_touchStartPoint = touchLocation
}
}
if (!_isRotating)
{
super.touchesBegan(touches, withEvent: event)
}
}
public override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?)
{
if (rotationEnabled && !rotationWithTwoFingers)
{
let touch = touches.first as UITouch!
let touchLocation = touch.locationInView(self)
if (isDragDecelerationEnabled)
{
sampleVelocity(touchLocation: touchLocation)
}
if (!_isRotating && distance(eventX: touchLocation.x, startX: _touchStartPoint.x, eventY: touchLocation.y, startY: _touchStartPoint.y) > CGFloat(8.0))
{
_isRotating = true
}
else
{
self.updateGestureRotation(x: touchLocation.x, y: touchLocation.y)
setNeedsDisplay()
}
}
if (!_isRotating)
{
super.touchesMoved(touches, withEvent: event)
}
}
public override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?)
{
if (!_isRotating)
{
super.touchesEnded(touches, withEvent: event)
}
if (rotationEnabled && !rotationWithTwoFingers)
{
let touch = touches.first as UITouch!
let touchLocation = touch.locationInView(self)
if (isDragDecelerationEnabled)
{
stopDeceleration()
sampleVelocity(touchLocation: touchLocation)
_decelerationAngularVelocity = calculateVelocity()
if (_decelerationAngularVelocity != 0.0)
{
_decelerationLastTime = CACurrentMediaTime()
_decelerationDisplayLink = CADisplayLink(target: self, selector: Selector("decelerationLoop"))
_decelerationDisplayLink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
}
}
}
if (_isRotating)
{
_isRotating = false
}
}
public override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?)
{
super.touchesCancelled(touches, withEvent: event)
if (_isRotating)
{
_isRotating = false
}
}
private func resetVelocity()
{
_velocitySamples.removeAll(keepCapacity: false)
}
private func sampleVelocity(touchLocation touchLocation: CGPoint)
{
let currentTime = CACurrentMediaTime()
_velocitySamples.append(AngularVelocitySample(time: currentTime, angle: angleForPoint(x: touchLocation.x, y: touchLocation.y)))
// Remove samples older than our sample time - 1 seconds
for (var i = 0, count = _velocitySamples.count; i < count - 2; i++)
{
if (currentTime - _velocitySamples[i].time > 1.0)
{
_velocitySamples.removeAtIndex(0)
i--
count--
}
else
{
break
}
}
}
private func calculateVelocity() -> CGFloat
{
if (_velocitySamples.isEmpty)
{
return 0.0
}
var firstSample = _velocitySamples[0]
var lastSample = _velocitySamples[_velocitySamples.count - 1]
// Look for a sample that's closest to the latest sample, but not the same, so we can deduce the direction
var beforeLastSample = firstSample
for (var i = _velocitySamples.count - 1; i >= 0; i--)
{
beforeLastSample = _velocitySamples[i]
if (beforeLastSample.angle != lastSample.angle)
{
break
}
}
// Calculate the sampling time
var timeDelta = lastSample.time - firstSample.time
if (timeDelta == 0.0)
{
timeDelta = 0.1
}
// 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"
var clockwise = lastSample.angle >= beforeLastSample.angle
if (abs(lastSample.angle - beforeLastSample.angle) > 270.0)
{
clockwise = !clockwise
}
// 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
var velocity = abs((lastSample.angle - firstSample.angle) / CGFloat(timeDelta))
// Direction?
if (!clockwise)
{
velocity = -velocity
}
return 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 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 x: CGFloat, y: CGFloat)
{
self.rotationAngle = angleForPoint(x: x, y: y) - _startAngle
}
public func stopDeceleration()
{
if (_decelerationDisplayLink !== nil)
{
_decelerationDisplayLink.removeFromRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
_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 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 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: ChartHighlight!
@objc private func tapGestureRecognized(recognizer: UITapGestureRecognizer)
{
if (recognizer.state == UIGestureRecognizerState.Ended)
{
let location = recognizer.locationInView(self)
let distance = distanceToCenter(x: location.x, y: location.y)
// check if a slice was touched
if (distance > self.radius)
{
// if no slice was touched, highlight nothing
self.highlightValues(nil)
_lastHighlight = nil
_lastHighlight = nil
}
else
{
var angle = angleForPoint(x: location.x, y: location.y)
if (self.isKindOfClass(PieChartView))
{
angle /= _animator.phaseY
}
let index = indexForAngle(angle)
// check if the index could be found
if (index < 0)
{
self.highlightValues(nil)
_lastHighlight = nil
}
else
{
let valsAtIndex = getSelectionDetailsAtIndex(index)
var dataSetIndex = 0
// get the dataset that is closest to the selection (PieChart only has one DataSet)
if (self.isKindOfClass(RadarChartView))
{
dataSetIndex = ChartUtils.closestDataSetIndex(valsAtIndex, value: Double(distance / (self as! RadarChartView).factor), axis: nil)
}
if (dataSetIndex < 0)
{
self.highlightValues(nil)
_lastHighlight = nil
}
else
{
let h = ChartHighlight(xIndex: index, dataSetIndex: dataSetIndex)
if (_lastHighlight !== nil && h == _lastHighlight)
{
self.highlightValue(highlight: nil, callDelegate: true)
_lastHighlight = nil
}
else
{
self.highlightValue(highlight: h, callDelegate: true)
_lastHighlight = h
}
}
}
}
}
}
#if !os(tvOS)
@objc private func rotationGestureRecognized(recognizer: UIRotationGestureRecognizer)
{
if (recognizer.state == UIGestureRecognizerState.Began)
{
stopDeceleration()
_startAngle = self.rawRotationAngle
}
if (recognizer.state == UIGestureRecognizerState.Began || recognizer.state == UIGestureRecognizerState.Changed)
{
let angle = ChartUtils.Math.FRAD2DEG * recognizer.rotation
self.rotationAngle = _startAngle + angle
setNeedsDisplay()
}
else if (recognizer.state == UIGestureRecognizerState.Ended)
{
let angle = ChartUtils.Math.FRAD2DEG * recognizer.rotation
self.rotationAngle = _startAngle + angle
setNeedsDisplay()
if (isDragDecelerationEnabled)
{
stopDeceleration()
_decelerationAngularVelocity = ChartUtils.Math.FRAD2DEG * recognizer.velocity
if (_decelerationAngularVelocity != 0.0)
{
_decelerationLastTime = CACurrentMediaTime()
_decelerationDisplayLink = CADisplayLink(target: self, selector: Selector("decelerationLoop"))
_decelerationDisplayLink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
}
}
}
}
#endif
}

View File

@@ -1,283 +0,0 @@
//
// RadarChartView.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
/// Implementation of the RadarChart, a "spidernet"-like chart. It works best
/// when displaying 5-10 entries per DataSet.
public class RadarChartView: PieRadarChartViewBase
{
/// width of the web lines that come from the center.
public var webLineWidth = CGFloat(1.5)
/// width of the web lines that are in between the lines coming from the center
public var innerWebLineWidth = CGFloat(0.75)
/// color for the web lines that come from the center
public var webColor = UIColor(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.
public var innerWebColor = UIColor(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)
public var webAlpha: CGFloat = 150.0 / 255.0
/// flag indicating if the web lines should be drawn or not
public var drawWeb = true
/// modulus that determines how many labels and web-lines are skipped before the next is drawn
private var _skipWebLineCount = 1
/// the object reprsenting the y-axis labels
private var _yAxis: ChartYAxis!
/// the object representing the x-axis labels
private var _xAxis: ChartXAxis!
internal var _yAxisRenderer: ChartYAxisRendererRadarChart!
internal var _xAxisRenderer: ChartXAxisRendererRadarChart!
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 = ChartYAxis(position: .Left)
_xAxis = ChartXAxis()
_xAxis.spaceBetweenLabels = 0
renderer = RadarChartRenderer(chart: self, animator: _animator, viewPortHandler: _viewPortHandler)
_yAxisRenderer = ChartYAxisRendererRadarChart(viewPortHandler: _viewPortHandler, yAxis: _yAxis, chart: self)
_xAxisRenderer = ChartXAxisRendererRadarChart(viewPortHandler: _viewPortHandler, xAxis: _xAxis, chart: self)
}
internal override func calcMinMax()
{
super.calcMinMax()
let minLeft = _data.getYMin(.Left)
let maxLeft = _data.getYMax(.Left)
_chartXMax = Double(_data.xVals.count) - 1.0
_deltaX = CGFloat(abs(_chartXMax - _chartXMin))
let leftRange = CGFloat(abs(maxLeft - (_yAxis.isStartAtZeroEnabled ? 0.0 : minLeft)))
let topSpaceLeft = Double(leftRange * _yAxis.spaceTop)
let bottomSpaceLeft = Double(leftRange * _yAxis.spaceBottom)
// Consider sticking one of the edges of the axis to zero (0.0)
if _yAxis.isStartAtZeroEnabled
{
if minLeft < 0.0 && maxLeft < 0.0
{
// If the values are all negative, let's stay in the negative zone
_yAxis.axisMinimum = min(0.0, !isnan(_yAxis.customAxisMin) ? _yAxis.customAxisMin : (minLeft - bottomSpaceLeft))
_yAxis.axisMaximum = 0.0
}
else if minLeft >= 0.0
{
// We have positive values only, stay in the positive zone
_yAxis.axisMinimum = 0.0
_yAxis.axisMaximum = max(0.0, !isnan(_yAxis.customAxisMax) ? _yAxis.customAxisMax : (maxLeft + topSpaceLeft))
}
else
{
// Stick the minimum to 0.0 or less, and maximum to 0.0 or more (startAtZero for negative/positive at the same time)
_yAxis.axisMinimum = min(0.0, !isnan(_yAxis.customAxisMin) ? _yAxis.customAxisMin : (minLeft - bottomSpaceLeft))
_yAxis.axisMaximum = max(0.0, !isnan(_yAxis.customAxisMax) ? _yAxis.customAxisMax : (maxLeft + topSpaceLeft))
}
}
else
{
// Use the values as they are
_yAxis.axisMinimum = !isnan(_yAxis.customAxisMin) ? _yAxis.customAxisMin : (minLeft - bottomSpaceLeft)
_yAxis.axisMaximum = !isnan(_yAxis.customAxisMax) ? _yAxis.customAxisMax : (maxLeft + topSpaceLeft)
}
_chartXMax = Double(_data.xVals.count) - 1.0
_deltaX = CGFloat(abs(_chartXMax - _chartXMin))
_yAxis.axisRange = abs(_yAxis.axisMaximum - _yAxis.axisMinimum)
}
public override func getMarkerPosition(entry entry: ChartDataEntry, highlight: ChartHighlight) -> CGPoint
{
let angle = self.sliceAngle * CGFloat(entry.xIndex) + self.rotationAngle
let val = CGFloat(entry.value) * self.factor
let c = self.centerOffsets
let p = CGPoint(x: c.x + val * cos(angle * ChartUtils.Math.FDEG2RAD),
y: c.y + val * sin(angle * ChartUtils.Math.FDEG2RAD))
return p
}
public override func notifyDataSetChanged()
{
if (_dataNotSet)
{
return
}
calcMinMax()
_yAxis?._defaultValueFormatter = _defaultValueFormatter
_yAxisRenderer?.computeAxis(yMin: _yAxis.axisMinimum, yMax: _yAxis.axisMaximum)
_xAxisRenderer?.computeAxis(xValAverageLength: _data.xValAverageLength, xValues: _data.xVals)
if (_legend !== nil && !_legend.isLegendCustom)
{
_legendRenderer?.computeLegend(_data)
}
calculateOffsets()
setNeedsDisplay()
}
public override func drawRect(rect: CGRect)
{
super.drawRect(rect)
if (_dataNotSet)
{
return
}
let context = UIGraphicsGetCurrentContext()
_xAxisRenderer?.renderAxisLabels(context: context)
if (drawWeb)
{
renderer!.drawExtras(context: context)
}
_yAxisRenderer.renderLimitLines(context: context)
renderer!.drawData(context: context)
if (valuesToHighlight())
{
renderer!.drawHighlighted(context: context, indices: _indicesToHightlight)
}
_yAxisRenderer.renderAxisLabels(context: context)
renderer!.drawValues(context: context)
_legendRenderer.renderLegend(context: context)
drawDescription(context: context)
drawMarkers(context: context)
}
/// - returns: the factor that is needed to transform values into pixels.
public var factor: CGFloat
{
let content = _viewPortHandler.contentRect
return min(content.width / 2.0, content.height / 2.0)
/ CGFloat(_yAxis.axisRange)
}
/// - returns: the angle that each slice in the radar chart occupies.
public var sliceAngle: CGFloat
{
return 360.0 / CGFloat(_data.xValCount)
}
public override func indexForAngle(angle: CGFloat) -> Int
{
// take the current angle of the chart into consideration
let a = ChartUtils.normalizedAngleFromAngle(angle - self.rotationAngle)
let sliceAngle = self.sliceAngle
for (var i = 0; i < _data.xValCount; i++)
{
if (sliceAngle * CGFloat(i + 1) - sliceAngle / 2.0 > a)
{
return i
}
}
return 0
}
/// - returns: the object that represents all y-labels of the RadarChart.
public var yAxis: ChartYAxis
{
return _yAxis
}
/// - returns: the object that represents all x-labels that are placed around the RadarChart.
public var xAxis: ChartXAxis
{
return _xAxis
}
/// 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
public 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.labelWidth : 10.0
}
public override var radius: CGFloat
{
let content = _viewPortHandler.contentRect
return min(content.width / 2.0, content.height / 2.0)
}
/// - returns: the maximum value this chart can display on it's y-axis.
public override var chartYMax: Double { return _yAxis.axisMaximum; }
/// - returns: the minimum value this chart can display on it's y-axis.
public override var chartYMin: Double { return _yAxis.axisMinimum; }
/// - returns: the range of y-values this chart can display.
public var yRange: Double { return _yAxis.axisRange}
}

View File

@@ -1,82 +0,0 @@
//
// ScatterChartView.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
/// The ScatterChart. Draws dots, triangles, squares and custom shapes into the chartview.
public class ScatterChartView: BarLineChartViewBase, ScatterChartRendererDelegate
{
public override func initialize()
{
super.initialize()
renderer = ScatterChartRenderer(delegate: self, animator: _animator, viewPortHandler: _viewPortHandler)
_chartXMin = -0.5
}
public override func calcMinMax()
{
super.calcMinMax()
if (_deltaX == 0.0 && _data.yValCount > 0)
{
_deltaX = 1.0
}
_chartXMax += 0.5
_deltaX = CGFloat(abs(_chartXMax - _chartXMin))
}
// MARK: - ScatterChartRendererDelegate
public func scatterChartRendererData(renderer: ScatterChartRenderer) -> ScatterChartData!
{
return _data as! ScatterChartData!
}
public func scatterChartRenderer(renderer: ScatterChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
{
return getTransformer(which)
}
public func scatterChartDefaultRendererValueFormatter(renderer: ScatterChartRenderer) -> NSNumberFormatter!
{
return self._defaultValueFormatter
}
public func scatterChartRendererChartYMax(renderer: ScatterChartRenderer) -> Double
{
return self.chartYMax
}
public func scatterChartRendererChartYMin(renderer: ScatterChartRenderer) -> Double
{
return self.chartYMin
}
public func scatterChartRendererChartXMax(renderer: ScatterChartRenderer) -> Double
{
return self.chartXMax
}
public func scatterChartRendererChartXMin(renderer: ScatterChartRenderer) -> Double
{
return self.chartXMin
}
public func scatterChartRendererMaxVisibleValueCount(renderer: ScatterChartRenderer) -> Int
{
return self.maxVisibleValueCount
}
}

View File

@@ -1,106 +0,0 @@
//
// ChartAxisBase.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
public class ChartAxisBase: ChartComponentBase
{
public var labelFont = UIFont.systemFontOfSize(10.0)
public var labelTextColor = UIColor.blackColor()
public var axisLineColor = UIColor.grayColor()
public var axisLineWidth = CGFloat(0.5)
public var axisLineDashPhase = CGFloat(0.0)
public var axisLineDashLengths: [CGFloat]!
public var gridColor = UIColor.grayColor().colorWithAlphaComponent(0.9)
public var gridLineWidth = CGFloat(0.5)
public var gridLineDashPhase = CGFloat(0.0)
public var gridLineDashLengths: [CGFloat]!
public var drawGridLinesEnabled = true
public var drawAxisLineEnabled = true
/// flag that indicates of the labels of this axis should be drawn or not
public var drawLabelsEnabled = true
/// Sets the used x-axis offset for the labels on this axis.
/// **default**: 5.0
public var xOffset = CGFloat(5.0)
/// Sets the used y-axis offset for the labels on this axis.
/// **default**: 5.0 (or 0.0 on ChartYAxis)
public var yOffset = CGFloat(5.0)
/// 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
public var drawLimitLinesBehindDataEnabled = false
public override init()
{
super.init()
}
public func getLongestLabel() -> String
{
fatalError("getLongestLabel() cannot be called on ChartAxisBase")
}
public var isDrawGridLinesEnabled: Bool { return drawGridLinesEnabled; }
public var isDrawAxisLineEnabled: Bool { return drawAxisLineEnabled; }
public var isDrawLabelsEnabled: Bool { return drawLabelsEnabled; }
/// Are the LimitLines drawn behind the data or in front of the data?
///
/// **default**: false
public var isDrawLimitLinesBehindDataEnabled: Bool { return drawLimitLinesBehindDataEnabled; }
/// Adds a new ChartLimitLine to this axis.
public func addLimitLine(line: ChartLimitLine)
{
_limitLines.append(line)
}
/// Removes the specified ChartLimitLine from the axis.
public func removeLimitLine(line: ChartLimitLine)
{
for (var i = 0; i < _limitLines.count; i++)
{
if (_limitLines[i] === line)
{
_limitLines.removeAtIndex(i)
return
}
}
}
/// Removes all LimitLines from the axis.
public func removeAllLimitLines()
{
_limitLines.removeAll(keepCapacity: false)
}
/// - returns: the LimitLines of this axis.
public var limitLines : [ChartLimitLine]
{
return _limitLines
}
}

View File

@@ -1,29 +0,0 @@
//
// ChartComponentBase.swift
// Charts
//
// Created by Daniel Cohen Gindi on 16/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
/// This class encapsulates everything both Axis and Legend have in common.
public class ChartComponentBase: NSObject
{
/// flag that indicates if this component is enabled or not
public var enabled = true
public override init()
{
super.init()
}
public var isEnabled: Bool { return enabled; }
}

View File

@@ -1,462 +0,0 @@
//
// ChartLegend.swift
// Charts
//
// Created by Daniel Cohen Gindi on 24/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
public class ChartLegend: ChartComponentBase
{
@objc
public enum ChartLegendPosition: Int
{
case RightOfChart
case RightOfChartCenter
case RightOfChartInside
case LeftOfChart
case LeftOfChartCenter
case LeftOfChartInside
case BelowChartLeft
case BelowChartRight
case BelowChartCenter
case AboveChartLeft
case AboveChartRight
case AboveChartCenter
case PiechartCenter
}
@objc
public enum ChartLegendForm: Int
{
case Square
case Circle
case Line
}
@objc
public enum ChartLegendDirection: Int
{
case LeftToRight
case RightToLeft
}
/// the legend colors array, each color is for the form drawn at the same index
public var colors = [UIColor?]()
// the legend text array. a nil label will start a group.
public var labels = [String?]()
internal var _extraColors = [UIColor?]()
internal var _extraLabels = [String?]()
/// colors that will be appended to the end of the colors array after calculating the legend.
public var extraColors: [UIColor?] { return _extraColors; }
/// labels that will be appended to the end of the labels array after calculating the legend. a nil label will start a group.
public var extraLabels: [String?] { return _extraLabels; }
/// 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
public var position = ChartLegendPosition.BelowChartLeft
public var direction = ChartLegendDirection.LeftToRight
public var font: UIFont = UIFont.systemFontOfSize(10.0)
public var textColor = UIColor.blackColor()
public var form = ChartLegendForm.Square
public var formSize = CGFloat(8.0)
public var formLineWidth = CGFloat(1.5)
public var xEntrySpace = CGFloat(6.0)
public var yEntrySpace = CGFloat(0.0)
public var formToTextSpace = CGFloat(5.0)
public var stackSpace = CGFloat(3.0)
/// Sets the x offset fo the legend.
/// Higher offset means the legend as a whole will be placed further away from the left/right.
/// Positive value will move the legend to the right when LTR, and to the left when RTL.
public var xOffset = CGFloat(5.0)
/// Sets the y offset fo the legend.
/// Higher offset means the legend as a whole will be placed further away from the top.
public var yOffset = CGFloat(7.0)
public var calculatedLabelSizes = [CGSize]()
public var calculatedLabelBreakPoints = [Bool]()
public var calculatedLineSizes = [CGSize]()
public override init()
{
super.init()
}
public init(colors: [UIColor?], labels: [String?])
{
super.init()
self.colors = colors
self.labels = labels
}
public init(colors: [NSObject], labels: [NSObject])
{
super.init()
self.colorsObjc = colors
self.labelsObjc = labels
}
public func getMaximumEntrySize(font: UIFont) -> CGSize
{
var maxW = CGFloat(0.0)
var maxH = CGFloat(0.0)
var labels = self.labels
for (var i = 0; i < labels.count; i++)
{
if (labels[i] == nil)
{
continue
}
let size = (labels[i] as NSString!).sizeWithAttributes([NSFontAttributeName: font])
if (size.width > maxW)
{
maxW = size.width
}
if (size.height > maxH)
{
maxH = size.height
}
}
return CGSize(
width: maxW + formSize + formToTextSpace,
height: maxH
)
}
public func getLabel(index: Int) -> String?
{
return labels[index]
}
public func getFullSize(labelFont: UIFont) -> CGSize
{
var width = CGFloat(0.0)
var height = CGFloat(0.0)
var labels = self.labels
for (var i = 0, count = labels.count; i < count; i++)
{
if (labels[i] != nil)
{
// make a step to the left
if (colors[i] != nil)
{
width += formSize + formToTextSpace
}
let size = (labels[i] as NSString!).sizeWithAttributes([NSFontAttributeName: labelFont])
width += size.width
height += size.height
if (i < count - 1)
{
width += xEntrySpace
height += yEntrySpace
}
}
else
{
width += formSize + stackSpace
if (i < count - 1)
{
width += stackSpace
}
}
}
return CGSize(width: width, height: height)
}
public var neededWidth = CGFloat(0.0)
public var neededHeight = CGFloat(0.0)
public var textWidthMax = CGFloat(0.0)
public var textHeightMax = CGFloat(0.0)
/// flag that indicates if word wrapping is enabled
/// this is currently supported only for: `BelowChartLeft`, `BelowChartRight`, `BelowChartCenter`.
/// note that word wrapping a legend takes a toll on performance.
/// you may want to set maxSizePercent when word wrapping, to set the point where the text wraps.
///
/// **default**: false
public var wordWrapEnabled = false
/// if this is set, then word wrapping the legend is enabled.
public 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.
/// If the legend is the center of the piechart, then this defines the size of the rectangular bounds out of the size of the "hole".
///
/// **default**: 0.95 (95%)
public var maxSizePercent: CGFloat = 0.95
public func calculateDimensions(labelFont labelFont: UIFont, viewPortHandler: ChartViewPortHandler)
{
if (position == .RightOfChart
|| position == .RightOfChartCenter
|| position == .LeftOfChart
|| position == .LeftOfChartCenter
|| position == .PiechartCenter)
{
let maxEntrySize = getMaximumEntrySize(labelFont)
let fullSize = getFullSize(labelFont)
neededWidth = maxEntrySize.width
neededHeight = fullSize.height
textWidthMax = maxEntrySize.width
textHeightMax = maxEntrySize.height
}
else if (position == .BelowChartLeft
|| position == .BelowChartRight
|| position == .BelowChartCenter
|| position == .AboveChartLeft
|| position == .AboveChartRight
|| position == .AboveChartCenter)
{
var labels = self.labels
var colors = self.colors
let labelCount = labels.count
let labelLineHeight = labelFont.lineHeight
let formSize = self.formSize
let formToTextSpace = self.formToTextSpace
let xEntrySpace = self.xEntrySpace
let stackSpace = self.stackSpace
let wordWrapEnabled = self.wordWrapEnabled
let contentWidth: CGFloat = viewPortHandler.contentWidth
// Prepare arrays for calculated layout
if (calculatedLabelSizes.count != labelCount)
{
calculatedLabelSizes = [CGSize](count: labelCount, repeatedValue: CGSize())
}
if (calculatedLabelBreakPoints.count != labelCount)
{
calculatedLabelBreakPoints = [Bool](count: labelCount, repeatedValue: false)
}
calculatedLineSizes.removeAll(keepCapacity: true)
// Start calculating layout
let labelAttrs = [NSFontAttributeName: labelFont]
var maxLineWidth: CGFloat = 0.0
var currentLineWidth: CGFloat = 0.0
var requiredWidth: CGFloat = 0.0
var stackedStartIndex: Int = -1
for (var i = 0; i < labelCount; i++)
{
let drawingForm = colors[i] != nil
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 (labels[i] != nil)
{
calculatedLabelSizes[i] = (labels[i] as NSString!).sizeWithAttributes(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 (labels[i] != nil || i == labelCount - 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 == labelCount - 1)
{ // Add last line size to array
calculatedLineSizes.append(CGSize(width: currentLineWidth, height: labelLineHeight))
maxLineWidth = max(maxLineWidth, currentLineWidth)
}
}
stackedStartIndex = labels[i] != nil ? -1 : stackedStartIndex
}
let maxEntrySize = getMaximumEntrySize(labelFont)
textWidthMax = maxEntrySize.width
textHeightMax = maxEntrySize.height
neededWidth = maxLineWidth
neededHeight = labelLineHeight * CGFloat(calculatedLineSizes.count) +
yEntrySpace * CGFloat(calculatedLineSizes.count == 0 ? 0 : (calculatedLineSizes.count - 1))
}
else
{
let maxEntrySize = getMaximumEntrySize(labelFont)
let fullSize = getFullSize(labelFont)
/* RightOfChartInside, LeftOfChartInside */
neededWidth = fullSize.width
neededHeight = maxEntrySize.height
textWidthMax = maxEntrySize.width
textHeightMax = maxEntrySize.height
}
}
/// MARK: - Custom legend
/// colors and labels that will be appended to the end of the auto calculated colors and labels after calculating the legend.
/// (if the legend has already been calculated, you will need to call notifyDataSetChanged() to let the changes take effect)
public func setExtra(colors colors: [UIColor?], labels: [String?])
{
self._extraLabels = labels
self._extraColors = colors
}
/// Sets a custom legend's labels and colors arrays.
/// The colors count should match the labels count.
/// * Each color is for the form drawn at the same index.
/// * A nil label will start a group.
/// * A nil color will avoid drawing a form, and a clearColor will leave a space for the form.
/// This will disable the feature that automatically calculates the legend labels and colors from the datasets.
/// Call `resetCustom(...)` to re-enable automatic calculation (and then `notifyDataSetChanged()` is needed).
public func setCustom(colors colors: [UIColor?], labels: [String?])
{
self.labels = labels
self.colors = colors
_isLegendCustom = true
}
/// Calling this will disable the custom legend labels (set by `setLegend(...)`). Instead, the labels will again be calculated automatically (after `notifyDataSetChanged()` is called).
public func resetCustom()
{
_isLegendCustom = false
}
/// **default**: false (automatic legend)
/// - returns: true if a custom legend labels and colors has been set
public var isLegendCustom: Bool
{
return _isLegendCustom
}
/// MARK: - ObjC compatibility
/// colors that will be appended to the end of the colors array after calculating the legend.
public var extraColorsObjc: [NSObject] { return ChartUtils.bridgedObjCGetUIColorArray(swift: _extraColors); }
/// labels that will be appended to the end of the labels array after calculating the legend. a nil label will start a group.
public var extraLabelsObjc: [NSObject] { return ChartUtils.bridgedObjCGetStringArray(swift: _extraLabels); }
/// the legend colors array, each color is for the form drawn at the same index
/// (ObjC bridging functions, as Swift 1.2 does not bridge optionals in array to `NSNull`s)
public var colorsObjc: [NSObject]
{
get { return ChartUtils.bridgedObjCGetUIColorArray(swift: colors); }
set { self.colors = ChartUtils.bridgedObjCGetUIColorArray(objc: newValue); }
}
// the legend text array. a nil label will start a group.
/// (ObjC bridging functions, as Swift 1.2 does not bridge optionals in array to `NSNull`s)
public var labelsObjc: [NSObject]
{
get { return ChartUtils.bridgedObjCGetStringArray(swift: labels); }
set { self.labels = ChartUtils.bridgedObjCGetStringArray(objc: newValue); }
}
/// colors and labels that will be appended to the end of the auto calculated colors and labels after calculating the legend.
/// (if the legend has already been calculated, you will need to call `notifyDataSetChanged()` to let the changes take effect)
public func setExtra(colors colors: [NSObject], labels: [NSObject])
{
if (colors.count != labels.count)
{
fatalError("ChartLegend:setExtra() - colors array and labels array need to be of same size")
}
self._extraLabels = ChartUtils.bridgedObjCGetStringArray(objc: labels)
self._extraColors = ChartUtils.bridgedObjCGetUIColorArray(objc: colors)
}
/// Sets a custom legend's labels and colors arrays.
/// The colors count should match the labels count.
/// * Each color is for the form drawn at the same index.
/// * A nil label will start a group.
/// * A nil color will avoid drawing a form, and a clearColor will leave a space for the form.
/// This will disable the feature that automatically calculates the legend labels and colors from the datasets.
/// Call `resetLegendToAuto(...)` to re-enable automatic calculation, and then if needed - call `notifyDataSetChanged()` on the chart to make it refresh the data.
public func setCustom(colors colors: [NSObject], labels: [NSObject])
{
if (colors.count != labels.count)
{
fatalError("ChartLegend:setCustom() - colors array and labels array need to be of same size")
}
self.labelsObjc = labels
self.colorsObjc = colors
_isLegendCustom = true
}
}

View File

@@ -1,84 +0,0 @@
//
// ChartLimitLine.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
/// 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).
public class ChartLimitLine: ChartComponentBase
{
@objc
public enum ChartLimitLabelPosition: Int
{
case LeftTop
case LeftBottom
case RightTop
case RightBottom
}
/// limit / maximum (the y-value or xIndex)
public var limit = Double(0.0)
private var _lineWidth = CGFloat(2.0)
public var lineColor = UIColor(red: 237.0/255.0, green: 91.0/255.0, blue: 91.0/255.0, alpha: 1.0)
public var lineDashPhase = CGFloat(0.0)
public var lineDashLengths: [CGFloat]?
public var valueTextColor = UIColor.blackColor()
public var valueFont = UIFont.systemFontOfSize(13.0)
public var label = ""
public var labelPosition = ChartLimitLabelPosition.RightTop
public override init()
{
super.init()
}
public init(limit: Double)
{
super.init()
self.limit = limit
}
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
public var lineWidth: CGFloat
{
get
{
return _lineWidth
}
set
{
if (newValue < 0.2)
{
_lineWidth = 0.2
}
else if (newValue > 12.0)
{
_lineWidth = 12.0
}
else
{
_lineWidth = newValue
}
}
}
}

View File

@@ -1,59 +0,0 @@
//
// ChartMarker.swift
// Charts
//
// Created by Daniel Cohen Gindi on 3/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
public class ChartMarker: ChartComponentBase
{
/// The marker image to render
public var image: UIImage?
/// Use this to return the desired offset you wish the MarkerView to have on the x-axis.
public var offset: CGPoint = CGPoint()
/// The marker's size
public var size: CGSize
{
get
{
return image!.size
}
}
public override init()
{
super.init()
}
/// Draws the ChartMarker on the given position on the given context
public func draw(context context: CGContext?, point: CGPoint)
{
let offset = self.offset
let size = self.size
let rect = CGRect(x: point.x + offset.x, y: point.y + offset.y, width: size.width, height: size.height)
UIGraphicsPushContext(context)
image!.drawInRect(rect)
UIGraphicsPopContext()
}
/// This method enables a custom ChartMarker to update it's content everytime the MarkerView is redrawn according to the data entry it points to.
///
/// - parameter 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).
public func refreshContent(entry entry: ChartDataEntry, highlight: ChartHighlight)
{
// Do nothing here...
}
}

View File

@@ -1,151 +0,0 @@
//
// ChartXAxis.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
public class ChartXAxis: ChartAxisBase
{
@objc
public enum XAxisLabelPosition: Int
{
case Top
case Bottom
case BothSided
case TopInside
case BottomInside
}
public var values = [String?]()
public var labelWidth = CGFloat(1.0)
public var labelHeight = CGFloat(1.0)
/// the space that should be left out (in characters) between the x-axis labels
/// This only applies if the number of labels that will be skipped in between drawn axis labels is not custom set.
///
/// **default**: 4
public var spaceBetweenLabels = Int(4)
/// the modulus that indicates if a value at a specified index in an array(list) for the x-axis-labels is drawn or not. Draw when `(index % modulus) == 0`.
public var axisLabelModulus = Int(1)
/// Is axisLabelModulus a custom value or auto calculated? If false, then it's auto, if true, then custom.
///
/// **default**: false (automatic modulus)
private var _isAxisModulusCustom = false
/// the modulus that indicates if a value at a specified index in an array(list) for the y-axis-labels is drawn or not. Draw when `(index % modulus) == 0`.
/// Used only for Horizontal BarChart
public var yAxisLabelModulus = Int(1)
/// 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
public var avoidFirstLastClippingEnabled = false
/// Custom formatter for adjusting x-value strings
private var _xAxisValueFormatter: ChartXAxisValueFormatter = ChartDefaultXAxisValueFormatter()
/// Custom XValueFormatter for the data object that allows custom-formatting of all x-values before rendering them.
/// Provide null to reset back to the default formatting.
public var valueFormatter: ChartXAxisValueFormatter?
{
get
{
return _xAxisValueFormatter
}
set
{
_xAxisValueFormatter = newValue ?? ChartDefaultXAxisValueFormatter()
}
}
/// the position of the x-labels relative to the chart
public var labelPosition = XAxisLabelPosition.Top
/// if set to true, word wrapping the labels will be enabled.
/// word wrapping is done using `(value width * labelWidth)`
///
/// *Note: currently supports all charts except pie/radar/horizontal-bar*
public var wordWrapEnabled = false
/// - returns: true if word wrapping the labels is enabled
public 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
public var wordWrapWidthPercent: CGFloat = 1.0
public override init()
{
super.init()
}
public override func getLongestLabel() -> String
{
var longest = ""
for (var i = 0; i < values.count; i++)
{
let text = values[i]
if (text != nil && longest.characters.count < (text!).characters.count)
{
longest = text!
}
}
return longest
}
public var isAvoidFirstLastClippingEnabled: Bool
{
return avoidFirstLastClippingEnabled
}
/// Sets the number of labels that should be skipped on the axis before the next label is drawn.
/// This will disable the feature that automatically calculates an adequate space between the axis labels and set the number of labels to be skipped to the fixed number provided by this method.
/// Call `resetLabelsToSkip(...)` to re-enable automatic calculation.
public func setLabelsToSkip(count: Int)
{
_isAxisModulusCustom = true
if (count < 0)
{
axisLabelModulus = 1
}
else
{
axisLabelModulus = count + 1
}
}
/// Calling this will disable a custom number of labels to be skipped (set by `setLabelsToSkip(...)`) while drawing the x-axis. Instead, the number of values to skip will again be calculated automatically.
public func resetLabelsToSkip()
{
_isAxisModulusCustom = false
}
/// - returns: true if a custom axis-modulus has been set that determines the number of labels to skip when drawing.
public var isAxisModulusCustom: Bool
{
return _isAxisModulusCustom
}
public var valuesObjc: [NSObject]
{
get { return ChartUtils.bridgedObjCGetStringArray(swift: values); }
set { self.values = ChartUtils.bridgedObjCGetStringArray(objc: newValue); }
}
}

View File

@@ -1,246 +0,0 @@
//
// ChartYAxis.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
/// 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.
public class ChartYAxis: ChartAxisBase
{
@objc
public enum YAxisLabelPosition: 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
}
public var entries = [Double]()
public var entryCount: Int { return entries.count; }
/// the number of y-label entries the y-labels should have, default 6
private var _labelCount = Int(6)
/// indicates if the top y-label entry is drawn or not
public var drawTopYLabelEntryEnabled = true
/// if true, the y-labels show only the minimum and maximum value
public var showOnlyMinMaxEnabled = false
/// flag that indicates if the axis is inverted or not
public var inverted = false
/// if true, the y-label entries will always start at zero
public var startAtZeroEnabled = true
/// if true, the set number of y-labels will be forced
public var forceLabelsEnabled = false
/// the formatter used to customly format the y-labels
public var valueFormatter: NSNumberFormatter?
/// the formatter used to customly format the y-labels
internal var _defaultValueFormatter = NSNumberFormatter()
/// A custom minimum value for this axis.
/// If set, this value will not be calculated automatically depending on the provided data.
/// Use `resetCustomAxisMin()` to undo this.
/// Do not forget to set startAtZeroEnabled = false if you use this method.
/// Otherwise, the axis-minimum value will still be forced to 0.
public var customAxisMin = Double.NaN
/// Set a custom maximum value for this axis.
/// If set, this value will not be calculated automatically depending on the provided data.
/// Use `resetCustomAxisMax()` to undo this.
public var customAxisMax = Double.NaN
/// axis space from the largest value to the top in percent of the total axis range
public var spaceTop = CGFloat(0.1)
/// axis space from the smallest value to the bottom in percent of the total axis range
public var spaceBottom = CGFloat(0.1)
public var axisMaximum = Double(0)
public var axisMinimum = Double(0)
/// the total range of values this axis covers
public var axisRange = Double(0)
/// the position of the y-labels relative to the chart
public var labelPosition = YAxisLabelPosition.OutsideChart
/// the side this axis object represents
private var _axisDependency = AxisDependency.Left
/// the minimum width that the axis should take
///
/// **default**: 0.0
public var minWidth = CGFloat(0)
/// the maximum width that the axis can take.
/// use zero for disabling the maximum
///
/// **default**: 0.0 (no maximum specified)
public var maxWidth = CGFloat(0)
public override init()
{
super.init()
_defaultValueFormatter.minimumIntegerDigits = 1
_defaultValueFormatter.maximumFractionDigits = 1
_defaultValueFormatter.minimumFractionDigits = 1
_defaultValueFormatter.usesGroupingSeparator = true
self.yOffset = 0.0
}
public init(position: AxisDependency)
{
super.init()
_axisDependency = position
_defaultValueFormatter.minimumIntegerDigits = 1
_defaultValueFormatter.maximumFractionDigits = 1
_defaultValueFormatter.minimumFractionDigits = 1
_defaultValueFormatter.usesGroupingSeparator = true
self.yOffset = 0.0
}
public var axisDependency: AxisDependency
{
return _axisDependency
}
public func setLabelCount(count: Int, force: Bool)
{
_labelCount = count
if (_labelCount > 25)
{
_labelCount = 25
}
if (_labelCount < 2)
{
_labelCount = 2
}
forceLabelsEnabled = force
}
/// the number of label entries the y-axis should have
/// max = 25,
/// min = 2,
/// default = 6,
/// be aware that this number is not fixed and can only be approximated
public var labelCount: Int
{
get
{
return _labelCount
}
set
{
setLabelCount(newValue, force: false);
}
}
/// By calling this method, any custom minimum value that has been previously set is reseted, and the calculation is done automatically.
public func resetCustomAxisMin()
{
customAxisMin = Double.NaN
}
/// By calling this method, any custom maximum value that has been previously set is reseted, and the calculation is done automatically.
public func resetCustomAxisMax()
{
customAxisMax = Double.NaN
}
public func requiredSize() -> CGSize
{
let label = getLongestLabel() as NSString
var size = label.sizeWithAttributes([NSFontAttributeName: 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
}
public func getRequiredHeightSpace() -> CGFloat
{
return requiredSize().height + 2.5 * 2.0 + yOffset
}
public override func getLongestLabel() -> String
{
var longest = ""
for (var i = 0; i < entries.count; i++)
{
let text = getFormattedLabel(i)
if (longest.characters.count < text.characters.count)
{
longest = text
}
}
return longest
}
/// - returns: the formatted y-label at the specified index. This will either use the auto-formatter or the custom formatter (if one is set).
public func getFormattedLabel(index: Int) -> String
{
if (index < 0 || index >= entries.count)
{
return ""
}
return (valueFormatter ?? _defaultValueFormatter).stringFromNumber(entries[index])!
}
/// - returns: true if this axis needs horizontal offset, false if no offset is needed.
public var needsOffset: Bool
{
if (isEnabled && isDrawLabelsEnabled && labelPosition == .OutsideChart)
{
return true
}
else
{
return false
}
}
public var isInverted: Bool { return inverted; }
public var isStartAtZeroEnabled: Bool { return startAtZeroEnabled; }
/// - returns: true if focing the y-label count is enabled. Default: false
public var isForceLabelsEnabled: Bool { return forceLabelsEnabled }
public var isShowOnlyMinMaxEnabled: Bool { return showOnlyMinMaxEnabled; }
public var isDrawTopYLabelEntryEnabled: Bool { return drawTopYLabelEntryEnabled; }
}

View File

@@ -1,58 +0,0 @@
//
// BarChartData.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
public class BarChartData: BarLineScatterCandleBubbleChartData
{
public override init()
{
super.init()
}
public override init(xVals: [String?]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
public override init(xVals: [NSObject]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
private var _groupSpace = CGFloat(0.8)
/// The spacing is relative to a full bar width
public var groupSpace: CGFloat
{
get
{
if (_dataSets.count <= 1)
{
return 0.0
}
return _groupSpace
}
set
{
_groupSpace = newValue
}
}
/// - returns: true if this BarData object contains grouped DataSets (more than 1 DataSet).
public var isGrouped: Bool
{
return _dataSets.count > 1 ? true : false
}
}

View File

@@ -1,166 +0,0 @@
//
// BarChartDataEntry.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
public class BarChartDataEntry: ChartDataEntry
{
/// the values the stacked barchart holds
private var _values: [Double]?
/// 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 stacked bar entries.
public init(values: [Double], xIndex: Int)
{
super.init(value: BarChartDataEntry.calcSum(values), xIndex: xIndex)
self.values = values
calcPosNegSum()
}
/// Constructor for normal bars (not stacked).
public override init(value: Double, xIndex: Int)
{
super.init(value: value, xIndex: xIndex)
}
/// Constructor for stacked bar entries.
public init(values: [Double], xIndex: Int, label: String)
{
super.init(value: BarChartDataEntry.calcSum(values), xIndex: xIndex, data: label)
self.values = values
}
/// Constructor for normal bars (not stacked).
public override init(value: Double, xIndex: Int, data: AnyObject?)
{
super.init(value: value, xIndex: xIndex, data: data)
}
public func getBelowSum(stackIndex :Int) -> Double
{
if (values == nil)
{
return 0
}
var remainder: Double = 0.0
var index = values!.count - 1
while (index > stackIndex && index >= 0)
{
remainder += values![index]
index--
}
return remainder
}
/// - returns: the sum of all negative values this entry (if stacked) contains. (this is a positive number)
public var negativeSum: Double
{
return _negativeSum
}
/// - returns: the sum of all positive values this entry (if stacked) contains.
public var positiveSum: Double
{
return _positiveSum
}
public func calcPosNegSum()
{
if _values == nil
{
_positiveSum = 0.0
_negativeSum = 0.0
return
}
var sumNeg: Double = 0.0
var sumPos: Double = 0.0
for f in _values!
{
if f < 0.0
{
sumNeg += -f
}
else
{
sumPos += f
}
}
_negativeSum = sumNeg
_positiveSum = sumPos
}
// MARK: Accessors
/// the values the stacked barchart holds
public var isStacked: Bool { return _values != nil }
/// the values the stacked barchart holds
public var values: [Double]?
{
get { return self._values }
set
{
self.value = BarChartDataEntry.calcSum(newValue)
self._values = newValue
calcPosNegSum()
}
}
// MARK: NSCopying
public override func copyWithZone(zone: NSZone) -> AnyObject
{
let copy = super.copyWithZone(zone) as! BarChartDataEntry
copy._values = _values
copy.value = value
copy._negativeSum = _negativeSum
return copy
}
/// Calculates the sum across all values of the given stack.
///
/// - parameter vals:
/// - returns:
private static func calcSum(vals: [Double]?) -> Double
{
if vals == nil
{
return 0.0
}
var sum = 0.0
for f in vals!
{
sum += f
}
return sum
}
}

View File

@@ -1,188 +0,0 @@
//
// BarChartDataSet.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet
{
/// space indicator between the bars in percentage of the whole width of one value (0.15 == 15% of bar width)
public var barSpace: CGFloat = 0.15
/// 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 color used for drawing the bar-shadows. The bar shadows is a surface behind the bar that indicates the maximum value
public var barShadowColor = UIColor(red: 215.0/255.0, green: 215.0/255.0, blue: 215.0/255.0, alpha: 1.0)
/// the alpha value (transparency) that is used for drawing the highlight indicator bar. min = 0.0 (fully transparent), max = 1.0 (fully opaque)
public var highLightAlpha = CGFloat(120.0 / 255.0)
/// the overall entry count, including counting each stack-value individually
private var _entryCountStacks = 0
/// array of labels used to describe the different values of the stacked bars
public var stackLabels: [String] = ["Stack"]
public required init()
{
super.init()
}
public override init(yVals: [ChartDataEntry]?, label: String?)
{
super.init(yVals: yVals, label: label)
self.highlightColor = UIColor.blackColor()
self.calcStackSize(yVals as! [BarChartDataEntry]?)
self.calcEntryCountIncludingStacks(yVals as! [BarChartDataEntry]?)
}
// MARK: NSCopying
public override func copyWithZone(zone: NSZone) -> AnyObject
{
let copy = super.copyWithZone(zone) as! BarChartDataSet
copy.barSpace = barSpace
copy._stackSize = _stackSize
copy.barShadowColor = barShadowColor
copy.highLightAlpha = highLightAlpha
copy._entryCountStacks = _entryCountStacks
copy.stackLabels = stackLabels
return copy
}
/// Calculates the total number of entries this DataSet represents, including
/// stacks. All values belonging to a stack are calculated separately.
private func calcEntryCountIncludingStacks(yVals: [BarChartDataEntry]!)
{
_entryCountStacks = 0
for (var i = 0; i < yVals.count; i++)
{
let vals = yVals[i].values
if (vals == nil)
{
_entryCountStacks++
}
else
{
_entryCountStacks += vals!.count
}
}
}
/// calculates the maximum stacksize that occurs in the Entries array of this DataSet
private func calcStackSize(yVals: [BarChartDataEntry]!)
{
for (var i = 0; i < yVals.count; i++)
{
if let vals = yVals[i].values
{
if vals.count > _stackSize
{
_stackSize = vals.count
}
}
}
}
internal override func calcMinMax(start start : Int, end: Int)
{
let yValCount = _yVals.count
if yValCount == 0
{
return
}
var endValue : Int
if end == 0 || end >= yValCount
{
endValue = yValCount - 1
}
else
{
endValue = end
}
_lastStart = start
_lastEnd = endValue
_yMin = DBL_MAX
_yMax = -DBL_MAX
for (var i = start; i <= endValue; i++)
{
if let e = _yVals[i] as? BarChartDataEntry
{
if !e.value.isNaN
{
if e.values == nil
{
if e.value < _yMin
{
_yMin = e.value
}
if e.value > _yMax
{
_yMax = e.value
}
}
else
{
if -e.negativeSum < _yMin
{
_yMin = -e.negativeSum
}
if e.positiveSum > _yMax
{
_yMax = e.positiveSum
}
}
}
}
}
if (_yMin == DBL_MAX)
{
_yMin = 0.0
_yMax = 0.0
}
}
/// - returns: the maximum number of bars that can be stacked upon another in this DataSet.
public var stackSize: Int
{
return _stackSize
}
/// - returns: true if this DataSet is stacked (stacksize > 1) or not.
public var isStacked: Bool
{
return _stackSize > 1 ? true : false
}
/// - returns: the overall entry count, including counting each stack-value individually
public var entryCountStacks: Int
{
return _entryCountStacks
}
}

View File

@@ -1,32 +0,0 @@
//
// BarLineScatterCandleBubbleChartData.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
public class BarLineScatterCandleBubbleChartData: ChartData
{
public override init()
{
super.init()
}
public override init(xVals: [String?]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
public override init(xVals: [NSObject]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
}

View File

@@ -1,35 +0,0 @@
//
// BarLineScatterCandleBubbleChartDataSet.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
public class BarLineScatterCandleBubbleChartDataSet: ChartDataSet
{
public var highlightColor = UIColor(red: 255.0/255.0, green: 187.0/255.0, blue: 115.0/255.0, alpha: 1.0)
public var highlightLineWidth = CGFloat(0.5)
public var highlightLineDashPhase = CGFloat(0.0)
public var highlightLineDashLengths: [CGFloat]?
// MARK: NSCopying
public override func copyWithZone(zone: NSZone) -> AnyObject
{
let copy = super.copyWithZone(zone) as! BarLineScatterCandleBubbleChartDataSet
copy.highlightColor = highlightColor
copy.highlightLineWidth = highlightLineWidth
copy.highlightLineDashPhase = highlightLineDashPhase
copy.highlightLineDashLengths = highlightLineDashLengths
return copy
}
}

View File

@@ -1,40 +0,0 @@
//
// BubbleChartData.swift
// Charts
//
// Bubble chart implementation:
// Copyright 2015 Pierre-Marc Airoldi
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
public class BubbleChartData: BarLineScatterCandleBubbleChartData
{
public override init()
{
super.init()
}
public override init(xVals: [String?]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
public override init(xVals: [NSObject]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
/// Sets the width of the circle that surrounds the bubble when highlighted for all DataSet objects this data object contains
public func setHighlightCircleWidth(width: CGFloat)
{
for set in _dataSets as! [BubbleChartDataSet]!
{
set.highlightCircleWidth = width
}
}
}

View File

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

View File

@@ -1,125 +0,0 @@
//
// BubbleChartDataSet.swift
// Charts
//
// Bubble chart implementation:
// Copyright 2015 Pierre-Marc Airoldi
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class BubbleChartDataSet: BarLineScatterCandleBubbleChartDataSet
{
internal var _xMax = Double(0.0)
internal var _xMin = Double(0.0)
internal var _maxSize = CGFloat(0.0)
public var xMin: Double { return _xMin }
public var xMax: Double { return _xMax }
public var maxSize: CGFloat { return _maxSize }
public func setColor(color: UIColor, alpha: CGFloat)
{
super.setColor(color.colorWithAlphaComponent(alpha))
}
internal override func calcMinMax(start start: Int, end: Int)
{
if (yVals.count == 0)
{
return
}
let entries = yVals as! [BubbleChartDataEntry]
// need chart width to guess this properly
var endValue : Int
if end == 0
{
endValue = entries.count - 1
}
else
{
endValue = end
}
_lastStart = start
_lastEnd = end
_yMin = yMin(entries[start])
_yMax = yMax(entries[start])
for (var i = start; i <= endValue; i++)
{
let entry = entries[i]
let ymin = yMin(entry)
let ymax = yMax(entry)
if (ymin < _yMin)
{
_yMin = ymin
}
if (ymax > _yMax)
{
_yMax = ymax
}
let xmin = xMin(entry)
let xmax = xMax(entry)
if (xmin < _xMin)
{
_xMin = xmin
}
if (xmax > _xMax)
{
_xMax = xmax
}
let size = largestSize(entry)
if (size > _maxSize)
{
_maxSize = size
}
}
}
/// Sets/gets the width of the circle that surrounds the bubble when highlighted
public var highlightCircleWidth: CGFloat = 2.5
private func yMin(entry: BubbleChartDataEntry) -> Double
{
return entry.value
}
private func yMax(entry: BubbleChartDataEntry) -> Double
{
return entry.value
}
private func xMin(entry: BubbleChartDataEntry) -> Double
{
return Double(entry.xIndex)
}
private func xMax(entry: BubbleChartDataEntry) -> Double
{
return Double(entry.xIndex)
}
private func largestSize(entry: BubbleChartDataEntry) -> CGFloat
{
return entry.size
}
}

View File

@@ -1,32 +0,0 @@
//
// CandleChartData.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
public class CandleChartData: BarLineScatterCandleBubbleChartData
{
public override init()
{
super.init()
}
public override init(xVals: [String?]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
public override init(xVals: [NSObject]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
}

View File

@@ -1,91 +0,0 @@
//
// CandleChartDataEntry.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
public class CandleChartDataEntry: ChartDataEntry
{
/// shadow-high value
public var high = Double(0.0)
/// shadow-low value
public var low = Double(0.0)
/// close value
public var close = Double(0.0)
/// open value
public var open = Double(0.0)
public required init()
{
super.init()
}
public init(xIndex: Int, shadowH: Double, shadowL: Double, open: Double, close: Double)
{
super.init(value: (shadowH + shadowL) / 2.0, xIndex: xIndex)
self.high = shadowH
self.low = shadowL
self.open = open
self.close = close
}
public init(xIndex: Int, shadowH: Double, shadowL: Double, open: Double, close: Double, data: AnyObject?)
{
super.init(value: (shadowH + shadowL) / 2.0, xIndex: xIndex, data: data)
self.high = shadowH
self.low = shadowL
self.open = open
self.close = close
}
/// - returns: the overall range (difference) between shadow-high and shadow-low.
public var shadowRange: Double
{
return abs(high - low)
}
/// - returns: the body size (difference between open and close).
public var bodyRange: Double
{
return abs(open - close)
}
/// the center value of the candle. (Middle value between high and low)
public override var value: Double
{
get
{
return super.value
}
set
{
super.value = (high + low) / 2.0
}
}
// MARK: NSCopying
public override func copyWithZone(zone: NSZone) -> AnyObject
{
let copy = super.copyWithZone(zone) as! CandleChartDataEntry
copy.high = high
copy.high = low
copy.high = open
copy.high = close
return copy
}
}

View File

@@ -1,133 +0,0 @@
//
// CandleChartDataSet.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class CandleChartDataSet: LineScatterCandleChartDataSet
{
/// the width of the candle-shadow-line in pixels.
///
/// **default**: 3.0
public var shadowWidth = CGFloat(1.5)
/// the space between the candle entries
///
/// **default**: 0.1 (10%)
private var _bodySpace = CGFloat(0.1)
/// the color of the shadow line
public var shadowColor: UIColor?
/// use candle color for the shadow
public var shadowColorSameAsCandle = false
/// color for open <= close
public var decreasingColor: UIColor?
/// color for open > close
public var increasingColor: UIColor?
/// Are decreasing values drawn as filled?
public var decreasingFilled = false
/// Are increasing values drawn as filled?
public var increasingFilled = true
public required init()
{
super.init()
}
public override init(yVals: [ChartDataEntry]?, label: String?)
{
super.init(yVals: yVals, label: label)
}
internal override func calcMinMax(start start: Int, end: Int)
{
if (yVals.count == 0)
{
return
}
var entries = yVals as! [CandleChartDataEntry]
var endValue : Int
if end == 0 || end >= entries.count
{
endValue = entries.count - 1
}
else
{
endValue = end
}
_lastStart = start
_lastEnd = end
_yMin = entries[start].low
_yMax = entries[start].high
for (var i = start + 1; i <= endValue; i++)
{
let e = entries[i]
if (e.low < _yMin)
{
_yMin = e.low
}
if (e.high > _yMax)
{
_yMax = e.high
}
}
}
/// 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
public var bodySpace: CGFloat
{
set
{
if (newValue < 0.0)
{
_bodySpace = 0.0
}
else if (newValue > 0.45)
{
_bodySpace = 0.45
}
else
{
_bodySpace = newValue
}
}
get
{
return _bodySpace
}
}
/// Is the shadow color same as the candle color?
public var isShadowColorSameAsCandle: Bool { return shadowColorSameAsCandle }
/// Are increasing values drawn as filled?
public var isIncreasingFilled: Bool { return increasingFilled; }
/// Are decreasing values drawn as filled?
public var isDecreasingFilled: Bool { return decreasingFilled; }
}

View File

@@ -1,949 +0,0 @@
//
// ChartData.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
public class ChartData: NSObject
{
internal var _yMax = Double(0.0)
internal var _yMin = Double(0.0)
internal var _leftAxisMax = Double(0.0)
internal var _leftAxisMin = Double(0.0)
internal var _rightAxisMax = Double(0.0)
internal var _rightAxisMin = Double(0.0)
private var _yValueSum = Double(0.0)
private var _yValCount = Int(0)
/// the last start value used for calcMinMax
internal var _lastStart: Int = 0
/// the last end value used for calcMinMax
internal var _lastEnd: Int = 0
/// the average length (in characters) across all x-value strings
private var _xValAverageLength = Double(0.0)
internal var _xVals: [String?]!
internal var _dataSets: [ChartDataSet]!
public override init()
{
super.init()
_xVals = [String?]()
_dataSets = [ChartDataSet]()
}
public init(xVals: [String?]?, dataSets: [ChartDataSet]?)
{
super.init()
_xVals = xVals == nil ? [String?]() : xVals
_dataSets = dataSets == nil ? [ChartDataSet]() : dataSets
self.initialize(_dataSets)
}
public init(xVals: [NSObject]?, dataSets: [ChartDataSet]?)
{
super.init()
_xVals = xVals == nil ? [String?]() : ChartUtils.bridgedObjCGetStringArray(objc: xVals!)
_dataSets = dataSets == nil ? [ChartDataSet]() : dataSets
self.initialize(_dataSets)
}
public convenience init(xVals: [String?]?)
{
self.init(xVals: xVals, dataSets: [ChartDataSet]())
}
public convenience init(xVals: [NSObject]?)
{
self.init(xVals: xVals, dataSets: [ChartDataSet]())
}
public convenience init(xVals: [String?]?, dataSet: ChartDataSet?)
{
self.init(xVals: xVals, dataSets: dataSet === nil ? nil : [dataSet!])
}
public convenience init(xVals: [NSObject]?, dataSet: ChartDataSet?)
{
self.init(xVals: xVals, dataSets: dataSet === nil ? nil : [dataSet!])
}
internal func initialize(dataSets: [ChartDataSet])
{
checkIsLegal(dataSets)
calcMinMax(start: _lastStart, end: _lastEnd)
calcYValueSum()
calcYValueCount()
calcXValAverageLength()
}
// calculates the average length (in characters) across all x-value strings
internal func calcXValAverageLength()
{
if (_xVals.count == 0)
{
_xValAverageLength = 1
return
}
var sum = 1
for (var i = 0; i < _xVals.count; i++)
{
sum += _xVals[i] == nil ? 0 : (_xVals[i]!).characters.count
}
_xValAverageLength = Double(sum) / Double(_xVals.count)
}
// Checks if the combination of x-values array and DataSet array is legal or not.
// :param: dataSets
internal func checkIsLegal(dataSets: [ChartDataSet]!)
{
if (dataSets == nil)
{
return
}
if self is ScatterChartData
{ // In scatter chart it makes sense to have more than one y-value value for an x-index
return
}
for (var i = 0; i < dataSets.count; i++)
{
if (dataSets[i].yVals.count > _xVals.count)
{
print("One or more of the DataSet Entry arrays are longer than the x-values array of this Data object.", terminator: "\n")
return
}
}
}
public func notifyDataChanged()
{
initialize(_dataSets)
}
/// calc minimum and maximum y value over all datasets
internal func calcMinMax(start start: Int, end: Int)
{
if (_dataSets == nil || _dataSets.count < 1)
{
_yMax = 0.0
_yMin = 0.0
}
else
{
_lastStart = start
_lastEnd = end
_yMin = DBL_MAX
_yMax = -DBL_MAX
for (var i = 0; i < _dataSets.count; i++)
{
_dataSets[i].calcMinMax(start: start, end: end)
if (_dataSets[i].yMin < _yMin)
{
_yMin = _dataSets[i].yMin
}
if (_dataSets[i].yMax > _yMax)
{
_yMax = _dataSets[i].yMax
}
}
if (_yMin == DBL_MAX)
{
_yMin = 0.0
_yMax = 0.0
}
// left axis
let firstLeft = getFirstLeft()
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()
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
}
}
}
}
// in case there is only one axis, adjust the second axis
handleEmptyAxis(firstLeft, firstRight: firstRight)
}
}
/// calculates the sum of all y-values in all datasets
internal func calcYValueSum()
{
_yValueSum = 0
if (_dataSets == nil)
{
return
}
for (var i = 0; i < _dataSets.count; i++)
{
_yValueSum += fabs(_dataSets[i].yValueSum)
}
}
/// Calculates the total number of y-values across all ChartDataSets the ChartData represents.
internal func calcYValueCount()
{
_yValCount = 0
if (_dataSets == nil)
{
return
}
var count = 0
for (var i = 0; i < _dataSets.count; i++)
{
count += _dataSets[i].entryCount
}
_yValCount = count
}
/// - returns: the number of LineDataSets this object contains
public var dataSetCount: Int
{
if (_dataSets == nil)
{
return 0
}
return _dataSets.count
}
/// - returns: the average value across all entries in this Data object (all entries from the DataSets this data object holds)
public var average: Double
{
return yValueSum / Double(yValCount)
}
/// - returns: the smallest y-value the data object contains.
public var yMin: Double
{
return _yMin
}
public func getYMin() -> Double
{
return _yMin
}
public func getYMin(axis: ChartYAxis.AxisDependency) -> Double
{
if (axis == .Left)
{
return _leftAxisMin
}
else
{
return _rightAxisMin
}
}
/// - returns: the greatest y-value the data object contains.
public var yMax: Double
{
return _yMax
}
public func getYMax() -> Double
{
return _yMax
}
public func getYMax(axis: ChartYAxis.AxisDependency) -> Double
{
if (axis == .Left)
{
return _leftAxisMax
}
else
{
return _rightAxisMax
}
}
/// - returns: the average length (in characters) across all values in the x-vals array
public var xValAverageLength: Double
{
return _xValAverageLength
}
/// - returns: the total y-value sum across all DataSet objects the this object represents.
public var yValueSum: Double
{
return _yValueSum
}
/// - returns: the total number of y-values across all DataSet objects the this object represents.
public var yValCount: Int
{
return _yValCount
}
/// - returns: the x-values the chart represents
public var xVals: [String?]
{
return _xVals
}
///Adds a new x-value to the chart data.
public func addXValue(xVal: String?)
{
_xVals.append(xVal)
}
/// Removes the x-value at the specified index.
public func removeXValue(index: Int)
{
_xVals.removeAtIndex(index)
}
/// - returns: the array of ChartDataSets this object holds.
public var dataSets: [ChartDataSet]
{
get
{
return _dataSets
}
set
{
_dataSets = newValue
}
}
/// 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.**
///
/// - parameter dataSets: the DataSet array to search
/// - parameter type:
/// - parameter 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
{
if (ignorecase)
{
for (var i = 0; i < dataSets.count; i++)
{
if (dataSets[i].label == nil)
{
continue
}
if (label.caseInsensitiveCompare(dataSets[i].label!) == NSComparisonResult.OrderedSame)
{
return i
}
}
}
else
{
for (var i = 0; i < dataSets.count; i++)
{
if (label == dataSets[i].label)
{
return i
}
}
}
return -1
}
/// - returns: the total number of x-values this ChartData object represents (the size of the x-values array)
public var xValCount: Int
{
return _xVals.count
}
/// - returns: the labels of all DataSets as a string array.
internal func dataSetLabels() -> [String]
{
var types = [String]()
for (var i = 0; i < _dataSets.count; i++)
{
if (dataSets[i].label == nil)
{
continue
}
types[i] = _dataSets[i].label!
}
return types
}
/// Get the Entry for a corresponding highlight object
///
/// - parameter highlight:
/// - returns: the entry that is highlighted
public func getEntryForHighlight(highlight: ChartHighlight) -> ChartDataEntry?
{
if highlight.dataSetIndex >= dataSets.count
{
return nil
}
else
{
return _dataSets[highlight.dataSetIndex].entryForXIndex(highlight.xIndex)
}
}
/// **IMPORTANT: This method does calculations at runtime. Use with care in performance critical situations.**
///
/// - parameter label:
/// - parameter ignorecase:
/// - returns: the DataSet Object with the given label. Sensitive or not.
public func getDataSetByLabel(label: String, ignorecase: Bool) -> ChartDataSet?
{
let index = getDataSetIndexByLabel(label, ignorecase: ignorecase)
if (index < 0 || index >= _dataSets.count)
{
return nil
}
else
{
return _dataSets[index]
}
}
public func getDataSetByIndex(index: Int) -> ChartDataSet!
{
if (_dataSets == nil || index < 0 || index >= _dataSets.count)
{
return nil
}
return _dataSets[index]
}
public func addDataSet(d: ChartDataSet!)
{
if (_dataSets == nil)
{
return
}
_yValCount += d.entryCount
_yValueSum += d.yValueSum
if (_dataSets.count == 0)
{
_yMax = d.yMax
_yMin = d.yMin
if (d.axisDependency == .Left)
{
_leftAxisMax = d.yMax
_leftAxisMin = d.yMin
}
else
{
_rightAxisMax = d.yMax
_rightAxisMin = d.yMin
}
}
else
{
if (_yMax < d.yMax)
{
_yMax = d.yMax
}
if (_yMin > d.yMin)
{
_yMin = d.yMin
}
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
}
}
}
_dataSets.append(d)
handleEmptyAxis(getFirstLeft(), firstRight: getFirstRight())
}
public func handleEmptyAxis(firstLeft: ChartDataSet?, firstRight: ChartDataSet?)
{
// in case there is only one axis, adjust the second axis
if (firstLeft === nil)
{
_leftAxisMax = _rightAxisMax
_leftAxisMin = _rightAxisMin
}
else if (firstRight === nil)
{
_rightAxisMax = _leftAxisMax
_rightAxisMin = _leftAxisMin
}
}
/// Removes the given DataSet from this data object.
/// Also recalculates all minimum and maximum values.
///
/// - returns: true if a DataSet was removed, false if no DataSet could be removed.
public func removeDataSet(dataSet: ChartDataSet!) -> Bool
{
if (_dataSets == nil || dataSet === nil)
{
return false
}
for (var i = 0; i < _dataSets.count; i++)
{
if (_dataSets[i] === dataSet)
{
return removeDataSetByIndex(i)
}
}
return false
}
/// 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 if no DataSet could be removed.
public func removeDataSetByIndex(index: Int) -> Bool
{
if (_dataSets == nil || index >= _dataSets.count || index < 0)
{
return false
}
let d = _dataSets.removeAtIndex(index)
_yValCount -= d.entryCount
_yValueSum -= d.yValueSum
calcMinMax(start: _lastStart, end: _lastEnd)
return true
}
/// Adds an Entry to the DataSet at the specified index. Entries are added to the end of the list.
public func addEntry(e: ChartDataEntry, dataSetIndex: Int)
{
if (_dataSets != nil && _dataSets.count > dataSetIndex && dataSetIndex >= 0)
{
let val = e.value
let set = _dataSets[dataSetIndex]
if (_yValCount == 0)
{
_yMin = val
_yMax = val
if (set.axisDependency == .Left)
{
_leftAxisMax = e.value
_leftAxisMin = e.value
}
else
{
_rightAxisMax = e.value
_rightAxisMin = e.value
}
}
else
{
if (_yMax < val)
{
_yMax = val
}
if (_yMin > val)
{
_yMin = val
}
if (set.axisDependency == .Left)
{
if (_leftAxisMax < e.value)
{
_leftAxisMax = e.value
}
if (_leftAxisMin > e.value)
{
_leftAxisMin = e.value
}
}
else
{
if (_rightAxisMax < e.value)
{
_rightAxisMax = e.value
}
if (_rightAxisMin > e.value)
{
_rightAxisMin = e.value
}
}
}
_yValCount += 1
_yValueSum += val
handleEmptyAxis(getFirstLeft(), firstRight: getFirstRight())
set.addEntry(e)
}
else
{
print("ChartData.addEntry() - dataSetIndex our of range.", terminator: "\n")
}
}
/// Removes the given Entry object from the DataSet at the specified index.
public func removeEntry(entry: ChartDataEntry!, dataSetIndex: Int) -> Bool
{
// entry null, outofbounds
if (entry === nil || dataSetIndex >= _dataSets.count)
{
return false
}
// remove the entry from the dataset
let removed = _dataSets[dataSetIndex].removeEntry(xIndex: entry.xIndex)
if (removed)
{
let val = entry.value
_yValCount -= 1
_yValueSum -= val
calcMinMax(start: _lastStart, end: _lastEnd)
}
return removed
}
/// Removes the Entry object at the given xIndex from the ChartDataSet at the
/// specified index.
/// - returns: true if an entry was removed, false if no Entry was found that meets the specified requirements.
public func removeEntryByXIndex(xIndex: Int, dataSetIndex: Int) -> Bool
{
if (dataSetIndex >= _dataSets.count)
{
return false
}
let entry = _dataSets[dataSetIndex].entryForXIndex(xIndex)
if (entry?.xIndex != xIndex)
{
return false
}
return removeEntry(entry, dataSetIndex: dataSetIndex)
}
/// - returns: the DataSet that contains the provided Entry, or null, if no DataSet contains this entry.
public func getDataSetForEntry(e: ChartDataEntry!) -> ChartDataSet?
{
if (e == nil)
{
return nil
}
for (var i = 0; i < _dataSets.count; i++)
{
let set = _dataSets[i]
for (var j = 0; j < set.entryCount; j++)
{
if (e === set.entryForXIndex(e.xIndex))
{
return set
}
}
}
return nil
}
/// - returns: the index of the provided DataSet inside the DataSets array of this data object. -1 if the DataSet was not found.
public func indexOfDataSet(dataSet: ChartDataSet) -> Int
{
for (var i = 0; i < _dataSets.count; i++)
{
if (_dataSets[i] === dataSet)
{
return i
}
}
return -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.
public func getFirstLeft() -> ChartDataSet?
{
for dataSet in _dataSets
{
if (dataSet.axisDependency == .Left)
{
return dataSet
}
}
return nil
}
/// - 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.
public func getFirstRight() -> ChartDataSet?
{
for dataSet in _dataSets
{
if (dataSet.axisDependency == .Right)
{
return dataSet
}
}
return nil
}
/// - returns: all colors used across all DataSet objects this object represents.
public func getColors() -> [UIColor]?
{
if (_dataSets == nil)
{
return nil
}
var clrcnt = 0
for (var i = 0; i < _dataSets.count; i++)
{
clrcnt += _dataSets[i].colors.count
}
var colors = [UIColor]()
for (var i = 0; i < _dataSets.count; i++)
{
let clrs = _dataSets[i].colors
for clr in clrs
{
colors.append(clr)
}
}
return colors
}
/// Generates an x-values array filled with numbers in range specified by the parameters. Can be used for convenience.
public func generateXVals(from: Int, to: Int) -> [String]
{
var xvals = [String]()
for (var i = from; i < to; i++)
{
xvals.append(String(i))
}
return xvals
}
/// Sets a custom ValueFormatter for all DataSets this data object contains.
public func setValueFormatter(formatter: NSNumberFormatter!)
{
for set in dataSets
{
set.valueFormatter = formatter
}
}
/// Sets the color of the value-text (color in which the value-labels are drawn) for all DataSets this data object contains.
public func setValueTextColor(color: UIColor!)
{
for set in dataSets
{
set.valueTextColor = color ?? set.valueTextColor
}
}
/// Sets the font for all value-labels for all DataSets this data object contains.
public func setValueFont(font: UIFont!)
{
for set in dataSets
{
set.valueFont = font ?? set.valueFont
}
}
/// Enables / disables drawing values (value-text) for all DataSets this data object contains.
public func setDrawValues(enabled: Bool)
{
for set in dataSets
{
set.drawValuesEnabled = enabled
}
}
/// Enables / disables highlighting values for all DataSets this data object contains.
public var highlightEnabled: Bool
{
get
{
for set in dataSets
{
if (!set.highlightEnabled)
{
return false
}
}
return true
}
set
{
for set in dataSets
{
set.highlightEnabled = newValue
}
}
}
/// if true, value highlightning is enabled
public 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.
public func clearValues()
{
dataSets.removeAll(keepCapacity: false)
notifyDataChanged()
}
/// Checks if this data object contains the specified Entry.
/// - returns: true if so, false if not.
public func contains(entry entry: ChartDataEntry) -> Bool
{
for set in dataSets
{
if (set.contains(entry))
{
return true
}
}
return false
}
/// Checks if this data object contains the specified DataSet.
/// - returns: true if so, false if not.
public func contains(dataSet dataSet: ChartDataSet) -> Bool
{
for set in dataSets
{
if (set.isEqual(dataSet))
{
return true
}
}
return false
}
/// MARK: - ObjC compatibility
/// - returns: the average length (in characters) across all values in the x-vals array
public var xValsObjc: [NSObject] { return ChartUtils.bridgedObjCGetStringArray(swift: _xVals); }
}

View File

@@ -1,131 +0,0 @@
//
// ChartDataEntry.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
public class ChartDataEntry: NSObject
{
/// the actual value (y axis)
public var value = Double(0.0)
/// the index on the x-axis
public var xIndex = Int(0)
/// optional spot for additional data this Entry represents
public var data: AnyObject?
public override required init()
{
super.init()
}
public init(value: Double, xIndex: Int)
{
super.init()
self.value = value
self.xIndex = xIndex
}
public init(value: Double, xIndex: Int, data: AnyObject?)
{
super.init()
self.value = value
self.xIndex = xIndex
self.data = data
}
// MARK: NSObject
public override func isEqual(object: AnyObject?) -> Bool
{
if (object === nil)
{
return false
}
if (!object!.isKindOfClass(self.dynamicType))
{
return false
}
if (object!.data !== data && !object!.data.isEqual(self.data))
{
return false
}
if (object!.xIndex != xIndex)
{
return false
}
if (fabs(object!.value - value) > 0.00001)
{
return false
}
return true
}
// MARK: NSObject
public override var description: String
{
return "ChartDataEntry, xIndex: \(xIndex), value \(value)"
}
// MARK: NSCopying
public func copyWithZone(zone: NSZone) -> AnyObject
{
let copy = self.dynamicType.init()
copy.value = value
copy.xIndex = xIndex
copy.data = data
return copy
}
}
public func ==(lhs: ChartDataEntry, rhs: ChartDataEntry) -> Bool
{
if (lhs === rhs)
{
return true
}
if (!lhs.isKindOfClass(rhs.dynamicType))
{
return false
}
if (lhs.data !== rhs.data && !lhs.data!.isEqual(rhs.data))
{
return false
}
if (lhs.xIndex != rhs.xIndex)
{
return false
}
if (fabs(lhs.value - rhs.value) > 0.00001)
{
return false
}
return true
}

View File

@@ -1,550 +0,0 @@
//
// ChartDataSet.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
public class ChartDataSet: NSObject
{
public var colors = [UIColor]()
internal var _yVals: [ChartDataEntry]!
internal var _yMax = Double(0.0)
internal var _yMin = Double(0.0)
internal var _yValueSum = Double(0.0)
/// the last start value used for calcMinMax
internal var _lastStart: Int = 0
/// the last end value used for calcMinMax
internal var _lastEnd: Int = 0
public var label: String? = "DataSet"
public var visible = true
public var drawValuesEnabled = true
/// the color used for the value-text
public var valueTextColor: UIColor = UIColor.blackColor()
/// the font for the value-text labels
public var valueFont: UIFont = UIFont.systemFontOfSize(7.0)
/// the formatter used to customly format the values
public var valueFormatter: NSNumberFormatter?
/// the axis this DataSet should be plotted against.
public var axisDependency = ChartYAxis.AxisDependency.Left
public var yVals: [ChartDataEntry] { return _yVals }
public var yValueSum: Double { return _yValueSum }
public var yMin: Double { return _yMin }
public var yMax: Double { return _yMax }
/// if true, value highlighting is enabled
public var highlightEnabled = true
/// - returns: true if value highlighting is enabled for this dataset
public var isHighlightEnabled: Bool { return highlightEnabled }
public override required init()
{
super.init()
}
public init(yVals: [ChartDataEntry]?, label: String?)
{
super.init()
self.label = label
_yVals = yVals == nil ? [ChartDataEntry]() : yVals
// default color
colors.append(UIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0))
self.calcMinMax(start: _lastStart, end: _lastEnd)
self.calcYValueSum()
}
public convenience init(yVals: [ChartDataEntry]?)
{
self.init(yVals: yVals, label: "DataSet")
}
/// Use this method to tell the data set that the underlying data has changed
public func notifyDataSetChanged()
{
calcMinMax(start: _lastStart, end: _lastEnd)
calcYValueSum()
}
internal func calcMinMax(start start : Int, end: Int)
{
let yValCount = _yVals.count
if yValCount == 0
{
return
}
var endValue : Int
if end == 0 || end >= yValCount
{
endValue = yValCount - 1
}
else
{
endValue = end
}
_lastStart = start
_lastEnd = endValue
_yMin = DBL_MAX
_yMax = -DBL_MAX
for (var i = start; i <= endValue; i++)
{
let e = _yVals[i]
if (!e.value.isNaN)
{
if (e.value < _yMin)
{
_yMin = e.value
}
if (e.value > _yMax)
{
_yMax = e.value
}
}
}
if (_yMin == DBL_MAX)
{
_yMin = 0.0
_yMax = 0.0
}
}
private func calcYValueSum()
{
_yValueSum = 0
for var i = 0; i < _yVals.count; i++
{
_yValueSum += fabs(_yVals[i].value)
}
}
/// - returns: the average value across all entries in this DataSet.
public var average: Double
{
return yValueSum / Double(valueCount)
}
public var entryCount: Int { return _yVals!.count; }
public func yValForXIndex(x: Int) -> Double
{
let e = self.entryForXIndex(x)
if (e !== nil && e!.xIndex == x) { return e!.value }
else { return Double.NaN }
}
/// - returns: the first Entry object found at the given xIndex with binary search.
/// If the no Entry at the specifed x-index is found, this method returns the Entry at the closest x-index.
/// nil if no Entry object at that index.
public func entryForXIndex(x: Int) -> ChartDataEntry?
{
let index = self.entryIndex(xIndex: x)
if (index > -1)
{
return _yVals[index]
}
return nil
}
public func entriesForXIndex(x: Int) -> [ChartDataEntry]
{
var entries = [ChartDataEntry]()
var low = 0
var high = _yVals.count - 1
while (low <= high)
{
var m = Int((high + low) / 2)
var entry = _yVals[m]
if (x == entry.xIndex)
{
while (m > 0 && _yVals[m - 1].xIndex == x)
{
m--
}
high = _yVals.count
for (; m < high; m++)
{
entry = _yVals[m]
if (entry.xIndex == x)
{
entries.append(entry)
}
else
{
break
}
}
}
if (x > _yVals[m].xIndex)
{
low = m + 1
}
else
{
high = m - 1
}
}
return entries
}
public func entryIndex(xIndex x: Int) -> Int
{
var low = 0
var high = _yVals.count - 1
var closest = -1
while (low <= high)
{
var m = (high + low) / 2
let entry = _yVals[m]
if (x == entry.xIndex)
{
while (m > 0 && _yVals[m - 1].xIndex == x)
{
m--
}
return m
}
if (x > entry.xIndex)
{
low = m + 1
}
else
{
high = m - 1
}
closest = m
}
return closest
}
public func entryIndex(entry e: ChartDataEntry, isEqual: Bool) -> Int
{
if (isEqual)
{
for (var i = 0; i < _yVals.count; i++)
{
if (_yVals[i].isEqual(e))
{
return i
}
}
}
else
{
for (var i = 0; i < _yVals.count; i++)
{
if (_yVals[i] === e)
{
return i
}
}
}
return -1
}
/// - returns: the number of entries this DataSet holds.
public var valueCount: Int { return _yVals.count; }
/// 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.
/// - parameter e: the entry to add
public func addEntry(e: ChartDataEntry)
{
let val = e.value
if (_yVals == nil)
{
_yVals = [ChartDataEntry]()
}
if (_yVals.count == 0)
{
_yMax = val
_yMin = val
}
else
{
if (_yMax < val)
{
_yMax = val
}
if (_yMin > val)
{
_yMin = val
}
}
_yValueSum += val
_yVals.append(e)
}
/// 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.
/// - parameter e: the entry to add
public func addEntryOrdered(e: ChartDataEntry)
{
let val = e.value
if (_yVals == nil)
{
_yVals = [ChartDataEntry]()
}
if (_yVals.count == 0)
{
_yMax = val
_yMin = val
}
else
{
if (_yMax < val)
{
_yMax = val
}
if (_yMin > val)
{
_yMin = val
}
}
_yValueSum += val
if _yVals.last?.xIndex > e.xIndex
{
var closestIndex = entryIndex(xIndex: e.xIndex)
if _yVals[closestIndex].xIndex < e.xIndex
{
closestIndex++
}
_yVals.insert(e, atIndex: closestIndex)
return;
}
_yVals.append(e)
}
public func removeEntry(entry: ChartDataEntry) -> Bool
{
var removed = false
for (var i = 0; i < _yVals.count; i++)
{
if (_yVals[i] === entry)
{
_yVals.removeAtIndex(i)
removed = true
break
}
}
if (removed)
{
_yValueSum -= entry.value
calcMinMax(start: _lastStart, end: _lastEnd)
}
return removed
}
public func removeEntry(xIndex xIndex: Int) -> Bool
{
let index = self.entryIndex(xIndex: xIndex)
if (index > -1)
{
let e = _yVals.removeAtIndex(index)
_yValueSum -= e.value
calcMinMax(start: _lastStart, end: _lastEnd)
return true
}
return false
}
/// Removes the first Entry (at index 0) of this DataSet from the entries array.
///
/// - returns: true if successful, false if not.
public func removeFirst() -> Bool
{
let entry: ChartDataEntry? = _yVals.isEmpty ? nil : _yVals.removeFirst()
let removed = entry != nil
if (removed)
{
let val = entry!.value
_yValueSum -= val
calcMinMax(start: _lastStart, end: _lastEnd)
}
return removed;
}
/// Removes the last Entry (at index size-1) of this DataSet from the entries array.
///
/// - returns: true if successful, false if not.
public func removeLast() -> Bool
{
let entry: ChartDataEntry? = _yVals.isEmpty ? nil : _yVals.removeLast()
let removed = entry != nil
if (removed)
{
let val = entry!.value
_yValueSum -= val
calcMinMax(start: _lastStart, end: _lastEnd)
}
return removed;
}
public func resetColors()
{
colors.removeAll(keepCapacity: false)
}
public func addColor(color: UIColor)
{
colors.append(color)
}
public func setColor(color: UIColor)
{
colors.removeAll(keepCapacity: false)
colors.append(color)
}
public func colorAt(var index: Int) -> UIColor
{
if (index < 0)
{
index = 0
}
return colors[index % colors.count]
}
public var isVisible: Bool
{
return visible
}
public var isDrawValuesEnabled: Bool
{
return drawValuesEnabled
}
/// Checks if this DataSet contains the specified Entry.
/// - returns: true if contains the entry, false if not.
public func contains(e: ChartDataEntry) -> Bool
{
for entry in _yVals
{
if (entry.isEqual(e))
{
return true
}
}
return false
}
/// Removes all values from this DataSet and recalculates min and max value.
public func clear()
{
_yVals.removeAll(keepCapacity: true)
_lastStart = 0
_lastEnd = 0
notifyDataSetChanged()
}
// MARK: NSObject
public override var description: String
{
return String(format: "ChartDataSet, label: %@, %i entries", arguments: [self.label ?? "", _yVals.count])
}
public override var debugDescription: String
{
var desc = description + ":"
for (var i = 0; i < _yVals.count; i++)
{
desc += "\n" + _yVals[i].description
}
return desc
}
// MARK: NSCopying
public func copyWithZone(zone: NSZone) -> AnyObject
{
let copy = self.dynamicType.init()
copy.colors = colors
copy._yVals = _yVals
copy._yMax = _yMax
copy._yMin = _yMin
copy._yValueSum = _yValueSum
copy._lastStart = _lastStart
copy._lastEnd = _lastEnd
copy.label = label
return copy
}
}

View File

@@ -1,213 +0,0 @@
//
// CombinedChartData.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
public 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(xVals: [String?]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
public override init(xVals: [NSObject]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
public var lineData: LineChartData!
{
get
{
return _lineData
}
set
{
_lineData = newValue
for dataSet in newValue.dataSets
{
_dataSets.append(dataSet)
}
checkIsLegal(newValue.dataSets)
calcMinMax(start: _lastStart, end: _lastEnd)
calcYValueSum()
calcYValueCount()
calcXValAverageLength()
}
}
public var barData: BarChartData!
{
get
{
return _barData
}
set
{
_barData = newValue
for dataSet in newValue.dataSets
{
_dataSets.append(dataSet)
}
checkIsLegal(newValue.dataSets)
calcMinMax(start: _lastStart, end: _lastEnd)
calcYValueSum()
calcYValueCount()
calcXValAverageLength()
}
}
public var scatterData: ScatterChartData!
{
get
{
return _scatterData
}
set
{
_scatterData = newValue
for dataSet in newValue.dataSets
{
_dataSets.append(dataSet)
}
checkIsLegal(newValue.dataSets)
calcMinMax(start: _lastStart, end: _lastEnd)
calcYValueSum()
calcYValueCount()
calcXValAverageLength()
}
}
public var candleData: CandleChartData!
{
get
{
return _candleData
}
set
{
_candleData = newValue
for dataSet in newValue.dataSets
{
_dataSets.append(dataSet)
}
checkIsLegal(newValue.dataSets)
calcMinMax(start: _lastStart, end: _lastEnd)
calcYValueSum()
calcYValueCount()
calcXValAverageLength()
}
}
public var bubbleData: BubbleChartData!
{
get
{
return _bubbleData
}
set
{
_bubbleData = newValue
for dataSet in newValue.dataSets
{
_dataSets.append(dataSet)
}
checkIsLegal(newValue.dataSets)
calcMinMax(start: _lastStart, end: _lastEnd)
calcYValueSum()
calcYValueCount()
calcXValAverageLength()
}
}
/// - returns: all data objects in row: line-bar-scatter-candle-bubble if not null.
public 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;
}
public 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
}
}

View File

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

View File

@@ -1,119 +0,0 @@
//
// LineChartDataSet.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class LineChartDataSet: LineRadarChartDataSet
{
public var circleColors = [UIColor]()
public var circleHoleColor = UIColor.whiteColor()
public var circleRadius = CGFloat(8.0)
private var _cubicIntensity = CGFloat(0.2)
public var lineDashPhase = CGFloat(0.0)
public var lineDashLengths: [CGFloat]!
/// if true, drawing circles is enabled
public var drawCirclesEnabled = true
/// if true, cubic lines are drawn instead of linear
public var drawCubicEnabled = false
public var drawCircleHoleEnabled = true
public required init()
{
super.init()
circleColors.append(UIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0))
}
public override init(yVals: [ChartDataEntry]?, label: String?)
{
super.init(yVals: yVals, label: label)
circleColors.append(UIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0))
}
/// intensity for cubic lines (min = 0.05, max = 1)
///
/// **default**: 0.2
public var cubicIntensity: CGFloat
{
get
{
return _cubicIntensity
}
set
{
_cubicIntensity = newValue
if (_cubicIntensity > 1.0)
{
_cubicIntensity = 1.0
}
if (_cubicIntensity < 0.05)
{
_cubicIntensity = 0.05
}
}
}
/// - returns: the color at the given index of the DataSet's circle-color array.
/// Performs a IndexOutOfBounds check by modulus.
public func getCircleColor(var index: Int) -> UIColor?
{
let size = circleColors.count
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.
public func setCircleColor(color: UIColor)
{
circleColors.removeAll(keepCapacity: false)
circleColors.append(color)
}
/// resets the circle-colors array and creates a new one
public func resetCircleColors(index: Int)
{
circleColors.removeAll(keepCapacity: false)
}
public var isDrawCirclesEnabled: Bool { return drawCirclesEnabled; }
public var isDrawCubicEnabled: Bool { return drawCubicEnabled; }
public var isDrawCircleHoleEnabled: Bool { return drawCircleHoleEnabled; }
// MARK: NSCopying
public override func copyWithZone(zone: NSZone) -> AnyObject
{
let copy = super.copyWithZone(zone) as! LineChartDataSet
copy.circleColors = circleColors
copy.circleRadius = circleRadius
copy.cubicIntensity = cubicIntensity
copy.lineDashPhase = lineDashPhase
copy.lineDashLengths = lineDashLengths
copy.drawCirclesEnabled = drawCirclesEnabled
copy.drawCubicEnabled = drawCubicEnabled
return copy
}
}

View File

@@ -1,66 +0,0 @@
//
// LineRadarChartDataSet.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class LineRadarChartDataSet: LineScatterCandleChartDataSet
{
public var fillColor = UIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0)
public var fillAlpha = CGFloat(0.33)
private var _lineWidth = CGFloat(1.0)
public var drawFilledEnabled = false
/// line width of the chart (min = 0.2, max = 10)
///
/// **default**: 1
public var lineWidth: CGFloat
{
get
{
return _lineWidth
}
set
{
if (newValue < 0.2)
{
_lineWidth = 0.2
}
else if (newValue > 10.0)
{
_lineWidth = 10.0
}
else
{
_lineWidth = newValue
}
}
}
public var isDrawFilledEnabled: Bool
{
return drawFilledEnabled
}
// MARK: NSCopying
public override func copyWithZone(zone: NSZone) -> AnyObject
{
let copy = super.copyWithZone(zone) as! LineRadarChartDataSet
copy.fillColor = fillColor
copy._lineWidth = _lineWidth
copy.drawFilledEnabled = drawFilledEnabled
return copy
}
}

View File

@@ -1,45 +0,0 @@
//
// LineScatterCandleChartDataSet.swift
// Charts
//
// Created by Daniel Cohen Gindi on 29/7/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
public class LineScatterCandleChartDataSet: BarLineScatterCandleBubbleChartDataSet
{
/// Enables / disables the horizontal highlight-indicator. If disabled, the indicator is not drawn.
public var drawHorizontalHighlightIndicatorEnabled = true
/// Enables / disables the vertical highlight-indicator. If disabled, the indicator is not drawn.
public var drawVerticalHighlightIndicatorEnabled = true
public var isHorizontalHighlightIndicatorEnabled: Bool { return drawHorizontalHighlightIndicatorEnabled }
public var isVerticalHighlightIndicatorEnabled: Bool { return drawVerticalHighlightIndicatorEnabled }
/// Enables / disables both vertical and horizontal highlight-indicators.
/// :param: enabled
public func setDrawHighlightIndicators(enabled: Bool)
{
drawHorizontalHighlightIndicatorEnabled = enabled
drawVerticalHighlightIndicatorEnabled = enabled
}
// MARK: NSCopying
public override func copyWithZone(zone: NSZone) -> AnyObject
{
let copy = super.copyWithZone(zone) as! LineScatterCandleChartDataSet
copy.drawHorizontalHighlightIndicatorEnabled = drawHorizontalHighlightIndicatorEnabled
copy.drawVerticalHighlightIndicatorEnabled = drawVerticalHighlightIndicatorEnabled
return copy
}
}

View File

@@ -1,84 +0,0 @@
//
// PieData.swift
// Charts
//
// Created by Daniel Cohen Gindi on 24/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
public class PieChartData: ChartData
{
public override init()
{
super.init()
}
public override init(xVals: [String?]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
public override init(xVals: [NSObject]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
var dataSet: PieChartDataSet?
{
get
{
return dataSets.count > 0 ? dataSets[0] as? PieChartDataSet : nil
}
set
{
if (newValue != nil)
{
dataSets = [newValue!]
}
else
{
dataSets = []
}
}
}
public override func getDataSetByIndex(index: Int) -> ChartDataSet?
{
if (index != 0)
{
return nil
}
return super.getDataSetByIndex(index)
}
public override func getDataSetByLabel(label: String, ignorecase: Bool) -> ChartDataSet?
{
if (dataSets.count == 0 || dataSets[0].label == nil)
{
return nil
}
if (ignorecase)
{
if (label.caseInsensitiveCompare(dataSets[0].label!) == NSComparisonResult.OrderedSame)
{
return dataSets[0]
}
}
else
{
if (label == dataSets[0].label)
{
return dataSets[0]
}
}
return nil
}
}

View File

@@ -1,73 +0,0 @@
//
// PieChartDataSet.swift
// Charts
//
// Created by Daniel Cohen Gindi on 24/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class PieChartDataSet: ChartDataSet
{
private var _sliceSpace = CGFloat(0.0)
/// indicates the selection distance of a pie slice
public var selectionShift = CGFloat(18.0)
public required init()
{
super.init()
self.valueTextColor = UIColor.whiteColor()
self.valueFont = UIFont.systemFontOfSize(13.0)
}
public override init(yVals: [ChartDataEntry]?, label: String?)
{
super.init(yVals: yVals, label: label)
self.valueTextColor = UIColor.whiteColor()
self.valueFont = UIFont.systemFontOfSize(13.0)
}
/// the space that is left out between the piechart-slices, default: 0°
/// --> no space, maximum 45, minimum 0 (no space)
public var sliceSpace: CGFloat
{
get
{
return _sliceSpace
}
set
{
_sliceSpace = newValue
if (_sliceSpace > 45.0)
{
_sliceSpace = 45.0
}
if (_sliceSpace < 0.0)
{
_sliceSpace = 0.0
}
}
}
// MARK: NSCopying
public override func copyWithZone(zone: NSZone) -> AnyObject
{
let copy = super.copyWithZone(zone) as! PieChartDataSet
copy._sliceSpace = _sliceSpace
copy.selectionShift = selectionShift
return copy
}
}

View File

@@ -1,39 +0,0 @@
//
// RadarChartData.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class RadarChartData: ChartData
{
public var highlightColor = UIColor(red: 255.0/255.0, green: 187.0/255.0, blue: 115.0/255.0, alpha: 1.0)
public var highlightLineWidth = CGFloat(1.0)
public var highlightLineDashPhase = CGFloat(0.0)
public var highlightLineDashLengths: [CGFloat]?
public override init()
{
super.init()
}
public override init(xVals: [String?]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
public override init(xVals: [NSObject]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
}

View File

@@ -1,33 +0,0 @@
//
// RadarChartDataSet.swift
// Charts
//
// Created by Daniel Cohen Gindi on 24/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
public class RadarChartDataSet: LineRadarChartDataSet
{
public required init()
{
super.init()
self.valueFont = UIFont.systemFontOfSize(13.0)
}
public override init(yVals: [ChartDataEntry]?, label: String?)
{
super.init(yVals: yVals, label: label)
self.valueFont = UIFont.systemFontOfSize(13.0)
}
}

View File

@@ -1,59 +0,0 @@
//
// ScatterChartData.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import UIKit
public class ScatterChartData: BarLineScatterCandleBubbleChartData
{
public override init()
{
super.init()
}
public override init(xVals: [String?]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
public override init(xVals: [NSObject]?, dataSets: [ChartDataSet]?)
{
super.init(xVals: xVals, dataSets: dataSets)
}
/// - returns: the maximum shape-size across all DataSets.
public func getGreatestShapeSize() -> CGFloat
{
var max = CGFloat(0.0)
for set in _dataSets
{
let scatterDataSet = set as? ScatterChartDataSet
if (scatterDataSet == nil)
{
print("ScatterChartData: Found a DataSet which is not a ScatterChartDataSet", terminator: "\n")
}
else
{
let size = scatterDataSet!.scatterShapeSize
if (size > max)
{
max = size
}
}
}
return max
}
}

View File

@@ -1,43 +0,0 @@
//
// ScatterChartDataSet.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
public class ScatterChartDataSet: LineScatterCandleChartDataSet
{
@objc
public enum ScatterShape: Int
{
case Cross
case Triangle
case Circle
case Square
case Custom
}
public var scatterShapeSize = CGFloat(15.0)
public var scatterShape = ScatterShape.Square
public var customScatterShape: CGPath?
// MARK: NSCopying
public override func copyWithZone(zone: NSZone) -> AnyObject
{
let copy = super.copyWithZone(zone) as! ScatterChartDataSet
copy.scatterShapeSize = scatterShapeSize
copy.scatterShape = scatterShape
copy.customScatterShape = customScatterShape
return copy
}
}

View File

@@ -1,214 +0,0 @@
//
// ChartDataApproximator.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
public class ChartDataApproximatorFilter: ChartDataBaseFilter
{
@objc
public enum ApproximatorType: Int
{
case None
case RamerDouglasPeucker
}
/// the type of filtering algorithm to use
public var type = ApproximatorType.None
/// the tolerance to be filtered with
/// When using the Douglas-Peucker-Algorithm, the tolerance is an angle in degrees, that will trigger the filtering
public var tolerance = Double(0.0)
public var scaleRatio = Double(1.0)
public var deltaRatio = Double(1.0)
public override init()
{
super.init()
}
/// Initializes the approximator with the given type and tolerance.
/// If toleranec <= 0, no filtering will be done.
public init(type: ApproximatorType, tolerance: Double)
{
super.init()
setup(type, tolerance: tolerance)
}
/// Sets type and tolerance.
/// If tolerance <= 0, no filtering will be done.
public func setup(type: ApproximatorType, tolerance: Double)
{
self.type = type
self.tolerance = tolerance
}
/// Sets the ratios for x- and y-axis, as well as the ratio of the scale levels
public func setRatios(deltaRatio: Double, scaleRatio: Double)
{
self.deltaRatio = deltaRatio
self.scaleRatio = scaleRatio
}
/// Filters according to type. Uses the pre set set tolerance
///
/// - parameter points: the points to filter
public override func filter(points: [ChartDataEntry]) -> [ChartDataEntry]
{
return filter(points, tolerance: tolerance)
}
/// Filters according to type.
///
/// - parameter points: the points to filter
/// - parameter tolerance: the angle in degrees that will trigger the filtering
public func filter(points: [ChartDataEntry], tolerance: Double) -> [ChartDataEntry]
{
if (tolerance <= 0)
{
return points
}
switch (type)
{
case .RamerDouglasPeucker:
return reduceWithDouglasPeuker(points, epsilon: tolerance)
case .None:
return points
}
}
/// uses the douglas peuker algorithm to reduce the given arraylist of entries
private func reduceWithDouglasPeuker(entries: [ChartDataEntry], epsilon: Double) -> [ChartDataEntry]
{
// if a shape has 2 or less points it cannot be reduced
if (epsilon <= 0 || entries.count < 3)
{
return entries
}
var keep = [Bool](count: entries.count, repeatedValue: false)
// first and last always stay
keep[0] = true
keep[entries.count - 1] = true
// first and last entry are entry point to recursion
algorithmDouglasPeucker(entries, epsilon: epsilon, start: 0, end: entries.count - 1, keep: &keep)
// create a new array with series, only take the kept ones
var reducedEntries = [ChartDataEntry]()
for (var i = 0; i < entries.count; i++)
{
if (keep[i])
{
let curEntry = entries[i]
reducedEntries.append(ChartDataEntry(value: curEntry.value, xIndex: curEntry.xIndex))
}
}
return reducedEntries
}
/// apply the Douglas-Peucker-Reduction to an ArrayList of Entry with a given epsilon (tolerance)
///
/// - parameter entries:
/// - parameter epsilon: as y-value
/// - parameter start:
/// - parameter end:
private func algorithmDouglasPeucker(entries: [ChartDataEntry], epsilon: Double, start: Int, end: Int, inout keep: [Bool])
{
if (end <= start + 1)
{
// recursion finished
return
}
// find the greatest distance between start and endpoint
var maxDistIndex = Int(0)
var distMax = Double(0.0)
let firstEntry = entries[start]
let lastEntry = entries[end]
for (var i = start + 1; i < end; i++)
{
let dist = calcAngleBetweenLines(firstEntry, end1: lastEntry, start2: firstEntry, end2: entries[i])
// keep the point with the greatest distance
if (dist > distMax)
{
distMax = dist
maxDistIndex = i
}
}
if (distMax > epsilon)
{
// keep max dist point
keep[maxDistIndex] = true
// recursive call
algorithmDouglasPeucker(entries, epsilon: epsilon, start: start, end: maxDistIndex, keep: &keep)
algorithmDouglasPeucker(entries, epsilon: epsilon, start: maxDistIndex, end: end, keep: &keep)
} // else don't keep the point...
}
/// calculate the distance between a line between two entries and an entry (point)
///
/// - parameter startEntry: line startpoint
/// - parameter endEntry: line endpoint
/// - parameter entryPoint: the point to which the distance is measured from the line
private func calcPointToLineDistance(startEntry: ChartDataEntry, endEntry: ChartDataEntry, entryPoint: ChartDataEntry) -> Double
{
let xDiffEndStart = Double(endEntry.xIndex) - Double(startEntry.xIndex)
let xDiffEntryStart = Double(entryPoint.xIndex) - Double(startEntry.xIndex)
let normalLength = sqrt((xDiffEndStart)
* (xDiffEndStart)
+ (endEntry.value - startEntry.value)
* (endEntry.value - startEntry.value))
return Double(fabs((xDiffEntryStart)
* (endEntry.value - startEntry.value)
- (entryPoint.value - startEntry.value)
* (xDiffEndStart))) / Double(normalLength)
}
/// Calculates the angle between two given lines. The provided entries mark the starting and end points of the lines.
private func calcAngleBetweenLines(start1: ChartDataEntry, end1: ChartDataEntry, start2: ChartDataEntry, end2: ChartDataEntry) -> Double
{
let angle1 = calcAngleWithRatios(start1, p2: end1)
let angle2 = calcAngleWithRatios(start2, p2: end2)
return fabs(angle1 - angle2)
}
/// calculates the angle between two entries (points) in the chart taking ratios into consideration
private func calcAngleWithRatios(p1: ChartDataEntry, p2: ChartDataEntry) -> Double
{
let dx = Double(p2.xIndex) * Double(deltaRatio) - Double(p1.xIndex) * Double(deltaRatio)
let dy = p2.value * scaleRatio - p1.value * scaleRatio
return atan2(Double(dy), dx) * ChartUtils.Math.RAD2DEG
}
// calculates the angle between two entries (points) in the chart
private func calcAngle(p1: ChartDataEntry, p2: ChartDataEntry) -> Double
{
let dx = p2.xIndex - p1.xIndex
let dy = p2.value - p1.value
return atan2(Double(dy), Double(dx)) * ChartUtils.Math.RAD2DEG
}
}

View File

@@ -1,28 +0,0 @@
//
// ChartDataFilter.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
public class ChartDataBaseFilter: NSObject
{
public override init()
{
super.init()
}
public func filter(points: [ChartDataEntry]) -> [ChartDataEntry]
{
fatalError("filter() cannot be called on ChartDataBaseFilter")
}
}

View File

@@ -1,25 +0,0 @@
//
// ChartDefaultXAxisValueFormatter.swift
// Charts
//
// Created by Daniel Cohen Gindi on 27/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
/// An interface for providing custom x-axis Strings.
public class ChartDefaultXAxisValueFormatter: NSObject, ChartXAxisValueFormatter
{
public func stringForXValue(index: Int, original: String, viewPortHandler: ChartViewPortHandler) -> String
{
return original // just return original, no adjustments
}
}

View File

@@ -1,23 +0,0 @@
//
// ChartFillFormatter.swift
// Charts
//
// Created by Daniel Cohen Gindi on 6/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-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
public protocol ChartFillFormatter
{
/// - returns: the vertical (y-axis) position where the filled-line of the LineDataSet should end.
func getFillLinePosition(dataSet dataSet: LineChartDataSet, data: LineChartData, chartMaxY: Double, chartMinY: Double) -> CGFloat
}

View File

@@ -1,30 +0,0 @@
//
// ChartXAxisValueFormatter.swift
// Charts
//
// Created by Daniel Cohen Gindi on 27/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
/// An interface for providing custom x-axis Strings.
@objc
public protocol ChartXAxisValueFormatter
{
/// For performance reasons, avoid excessive calculations and memory allocations inside this method.
///
/// - returns: the customized label that is drawn on the x-axis.
/// - parameter index: the x-index that is currently being drawn
/// - parameter original: the original x-axis label to be drawn
/// - parameter viewPortHandler: provides information about the current chart state (scale, translation, ...)
///
func stringForXValue(index: Int, original: String, viewPortHandler: ChartViewPortHandler) -> String
}

View File

@@ -1,244 +0,0 @@
//
// ChartBarHighlighter.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/7/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
internal class BarChartHighlighter: ChartHighlighter
{
internal init(chart: BarChartView)
{
super.init(chart: chart)
}
internal override func getHighlight(x x: Double, y: Double) -> ChartHighlight?
{
let h = super.getHighlight(x: x, y: y)
if h === nil
{
return h
}
else
{
if let set = _chart?.data?.getDataSetByIndex(h!.dataSetIndex) as? BarChartDataSet
{
if set.isStacked
{
// create an array of the touch-point
var pt = CGPoint()
pt.y = CGFloat(y)
// take any transformer to determine the x-axis value
_chart?.getTransformer(set.axisDependency).pixelToValue(&pt)
return getStackedHighlight(old: h, set: set, xIndex: h!.xIndex, dataSetIndex: h!.dataSetIndex, yValue: Double(pt.y))
}
}
return h
}
}
internal override func getXIndex(x: Double) -> Int
{
if let barChartData = _chart?.data as? BarChartData
{
if !barChartData.isGrouped
{
return super.getXIndex(x)
}
else
{
let baseNoSpace = getBase(x)
let setCount = barChartData.dataSetCount
var xIndex = Int(baseNoSpace) / setCount
let valCount = barChartData.xValCount
if xIndex < 0
{
xIndex = 0
}
else if xIndex >= valCount
{
xIndex = valCount - 1
}
return xIndex
}
}
else
{
return 0
}
}
internal override func getDataSetIndex(xIndex xIndex: Int, x: Double, y: Double) -> Int
{
if let barChartData = _chart?.data as? BarChartData
{
if !barChartData.isGrouped
{
return 0
}
else
{
let baseNoSpace = getBase(x)
let setCount = barChartData.dataSetCount
var dataSetIndex = Int(baseNoSpace) % setCount
if dataSetIndex < 0
{
dataSetIndex = 0
}
else if dataSetIndex >= setCount
{
dataSetIndex = setCount - 1
}
return dataSetIndex
}
}
else
{
return 0
}
}
/// This method creates the Highlight object that also indicates which value of a stacked BarEntry has been selected.
/// - parameter old: the old highlight object before looking for stacked values
/// - parameter set:
/// - parameter xIndex:
/// - parameter dataSetIndex:
/// - parameter yValue:
/// - returns:
internal func getStackedHighlight(old old: ChartHighlight?, set: BarChartDataSet, xIndex: Int, dataSetIndex: Int, yValue: Double) -> ChartHighlight?
{
let entry = set.entryForXIndex(xIndex) as? BarChartDataEntry
if entry?.values === nil
{
return old
}
if let ranges = getRanges(entry: entry!)
{
let stackIndex = getClosestStackIndex(ranges: ranges, value: yValue)
let h = ChartHighlight(xIndex: xIndex, dataSetIndex: dataSetIndex, stackIndex: stackIndex, range: ranges[stackIndex])
return h
}
return nil
}
/// Returns the index of the closest value inside the values array / ranges (stacked barchart) to the value given as a parameter.
/// - parameter entry:
/// - parameter value:
/// - returns:
internal func getClosestStackIndex(ranges ranges: [ChartRange]?, value: Double) -> Int
{
if ranges == nil
{
return 0
}
var stackIndex = 0
for range in ranges!
{
if range.contains(value)
{
return stackIndex
}
else
{
stackIndex++
}
}
let length = ranges!.count - 1
return (value > ranges![length].to) ? length : 0
}
/// Returns the base x-value to the corresponding x-touch value in pixels.
/// - parameter x:
/// - returns:
internal func getBase(x: Double) -> Double
{
if let barChartData = _chart?.data as? BarChartData
{
// create an array of the touch-point
var pt = CGPoint()
pt.x = CGFloat(x)
// take any transformer to determine the x-axis value
_chart?.getTransformer(ChartYAxis.AxisDependency.Left).pixelToValue(&pt)
let xVal = Double(pt.x)
let setCount = barChartData.dataSetCount ?? 0
// calculate how often the group-space appears
let steps = Int(xVal / (Double(setCount) + Double(barChartData.groupSpace)))
let groupSpaceSum = Double(barChartData.groupSpace) * Double(steps)
let baseNoSpace = xVal - groupSpaceSum
return baseNoSpace
}
else
{
return 0.0
}
}
/// Splits up the stack-values of the given bar-entry into Range objects.
/// - parameter entry:
/// - returns:
internal func getRanges(entry entry: BarChartDataEntry) -> [ChartRange]?
{
let values = entry.values
if (values == nil)
{
return nil
}
var negRemain = -entry.negativeSum
var posRemain: Double = 0.0
var ranges = [ChartRange]()
ranges.reserveCapacity(values!.count)
for (var i = 0, count = values!.count; i < count; i++)
{
let value = values![i]
if value < 0
{
ranges.append(ChartRange(from: negRemain, to: negRemain + abs(value)))
negRemain += abs(value)
}
else
{
ranges.append(ChartRange(from: posRemain, to: posRemain+value))
posRemain += value
}
}
return ranges
}
}

View File

@@ -1,141 +0,0 @@
//
// ChartHighlight.swift
// Charts
//
// Created by Daniel Cohen Gindi on 23/2/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
public class ChartHighlight: NSObject
{
/// the x-index of the highlighted value
private var _xIndex = Int(0)
/// the index of the dataset the highlighted value is in
private var _dataSetIndex = Int(0)
/// index which value of a stacked bar entry is highlighted
///
/// **default**: -1
private var _stackIndex = Int(-1)
/// the range of the bar that is selected (only for stacked-barchart)
private var _range: ChartRange?
public override init()
{
super.init()
}
public init(xIndex x: Int, dataSetIndex: Int)
{
super.init()
_xIndex = x
_dataSetIndex = dataSetIndex
}
public init(xIndex x: Int, dataSetIndex: Int, stackIndex: Int)
{
super.init()
_xIndex = x
_dataSetIndex = dataSetIndex
_stackIndex = stackIndex
}
/// Constructor, only used for stacked-barchart.
///
/// - parameter x: the index of the highlighted value on the x-axis
/// - parameter dataSet: the index of the DataSet the highlighted value belongs to
/// - parameter stackIndex: references which value of a stacked-bar entry has been selected
/// - parameter range: the range the selected stack-value is in
public convenience init(xIndex x: Int, dataSetIndex: Int, stackIndex: Int, range: ChartRange)
{
self.init(xIndex: x, dataSetIndex: dataSetIndex, stackIndex: stackIndex)
_range = range
}
public var dataSetIndex: Int { return _dataSetIndex; }
public var xIndex: Int { return _xIndex; }
public var stackIndex: Int { return _stackIndex; }
/// - returns: the range of values the selected value of a stacked bar is in. (this is only relevant for stacked-barchart)
public var range: ChartRange? { return _range }
// MARK: NSObject
public override var description: String
{
return "Highlight, xIndex: \(_xIndex), dataSetIndex: \(_dataSetIndex), stackIndex (only stacked barentry): \(_stackIndex)"
}
public override func isEqual(object: AnyObject?) -> Bool
{
if (object === nil)
{
return false
}
if (!object!.isKindOfClass(self.dynamicType))
{
return false
}
if (object!.xIndex != _xIndex)
{
return false
}
if (object!.dataSetIndex != _dataSetIndex)
{
return false
}
if (object!.stackIndex != _stackIndex)
{
return false
}
return true
}
}
func ==(lhs: ChartHighlight, rhs: ChartHighlight) -> Bool
{
if (lhs === rhs)
{
return true
}
if (!lhs.isKindOfClass(rhs.dynamicType))
{
return false
}
if (lhs._xIndex != rhs._xIndex)
{
return false
}
if (lhs._dataSetIndex != rhs._dataSetIndex)
{
return false
}
if (lhs._stackIndex != rhs._stackIndex)
{
return false
}
return true
}

View File

@@ -1,119 +0,0 @@
//
// ChartHighlighter.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/7/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
internal class ChartHighlighter
{
/// instance of the data-provider
internal weak var _chart: BarLineChartViewBase?;
internal init(chart: BarLineChartViewBase)
{
_chart = chart;
}
/// Returns a Highlight object corresponding to the given x- and y- touch positions in pixels.
/// - parameter x:
/// - parameter y:
/// - returns:
internal func getHighlight(x x: Double, y: Double) -> ChartHighlight?
{
let xIndex = getXIndex(x)
if (xIndex == -Int.max)
{
return nil
}
let dataSetIndex = getDataSetIndex(xIndex: xIndex, x: x, y: y)
if (dataSetIndex == -Int.max)
{
return nil
}
return ChartHighlight(xIndex: xIndex, dataSetIndex: dataSetIndex)
}
/// Returns the corresponding x-index for a given touch-position in pixels.
/// - parameter x:
/// - returns:
internal func getXIndex(x: Double) -> Int
{
// create an array of the touch-point
var pt = CGPoint(x: x, y: 0.0)
// take any transformer to determine the x-axis value
_chart?.getTransformer(ChartYAxis.AxisDependency.Left).pixelToValue(&pt)
return Int(round(pt.x))
}
/// Returns the corresponding dataset-index for a given xIndex and xy-touch position in pixels.
/// - parameter xIndex:
/// - parameter x:
/// - parameter y:
/// - returns:
internal func getDataSetIndex(xIndex xIndex: Int, x: Double, y: Double) -> Int
{
let valsAtIndex = getSelectionDetailsAtIndex(xIndex)
let leftdist = ChartUtils.getMinimumDistance(valsAtIndex, val: y, axis: ChartYAxis.AxisDependency.Left)
let rightdist = ChartUtils.getMinimumDistance(valsAtIndex, val: y, axis: ChartYAxis.AxisDependency.Right)
let axis = leftdist < rightdist ? ChartYAxis.AxisDependency.Left : ChartYAxis.AxisDependency.Right
let dataSetIndex = ChartUtils.closestDataSetIndex(valsAtIndex, value: y, axis: axis)
return dataSetIndex
}
/// Returns a list of SelectionDetail object corresponding to the given xIndex.
/// - parameter xIndex:
/// - returns:
internal func getSelectionDetailsAtIndex(xIndex: Int) -> [ChartSelectionDetail]
{
var vals = [ChartSelectionDetail]()
var pt = CGPoint()
for (var i = 0, dataSetCount = _chart?.data?.dataSetCount; i < dataSetCount; i++)
{
let dataSet = _chart!.data!.getDataSetByIndex(i)
// dont include datasets that cannot be highlighted
if !dataSet.isHighlightEnabled
{
continue
}
// extract all y-values from all DataSets at the given x-index
let yVal: Double = dataSet.yValForXIndex(xIndex)
if yVal.isNaN
{
continue
}
pt.y = CGFloat(yVal)
_chart!.getTransformer(dataSet.axisDependency).pointValueToPixel(&pt)
if !pt.y.isNaN
{
vals.append(ChartSelectionDetail(value: Double(pt.y), dataSetIndex: i, dataSet: dataSet))
}
}
return vals
}
}

View File

@@ -1,53 +0,0 @@
//
// ChartRange.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/7/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
public class ChartRange: NSObject
{
public var from: Double
public var to: Double
public init(from: Double, to: Double)
{
self.from = from
self.to = to
super.init()
}
/// Returns true if this range contains (if the value is in between) the given value, false if not.
/// - parameter value:
public func contains(value: Double) -> Bool
{
if value > from && value <= to
{
return true
}
else
{
return false
}
}
public func isLarger(value: Double) -> Bool
{
return value > to
}
public func isSmaller(value: Double) -> Bool
{
return value < from
}
}

View File

@@ -1,72 +0,0 @@
//
// CombinedHighlighter.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/7/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
internal class CombinedHighlighter: ChartHighlighter
{
internal init(chart: CombinedChartView)
{
super.init(chart: chart)
}
/// Returns a list of SelectionDetail object corresponding to the given xIndex.
/// - parameter xIndex:
/// - returns:
internal override func getSelectionDetailsAtIndex(xIndex: Int) -> [ChartSelectionDetail]
{
var vals = [ChartSelectionDetail]()
if let data = _chart?.data as? CombinedChartData
{
// get all chartdata objects
var dataObjects = data.allData
var pt = CGPoint()
for var i = 0; i < dataObjects.count; i++
{
for var j = 0; j < dataObjects[i].dataSetCount; j++
{
let dataSet = dataObjects[i].getDataSetByIndex(j)
// dont include datasets that cannot be highlighted
if !dataSet.isHighlightEnabled
{
continue
}
// extract all y-values from all DataSets at the given x-index
let yVal = dataSet.yValForXIndex(xIndex)
if yVal.isNaN
{
continue
}
pt.y = CGFloat(yVal)
_chart!.getTransformer(dataSet.axisDependency).pointValueToPixel(&pt)
if !pt.y.isNaN
{
vals.append(ChartSelectionDetail(value: Double(pt.y), dataSetIndex: j, dataSet: dataSet))
}
}
}
}
return vals
}
}

View File

@@ -1,121 +0,0 @@
//
// HorizontalBarChartHighlighter.swift
// Charts
//
// Created by Daniel Cohen Gindi on 26/7/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
internal class HorizontalBarChartHighlighter: BarChartHighlighter
{
internal override func getHighlight(x x: Double, y: Double) -> ChartHighlight?
{
let h = super.getHighlight(x: x, y: y)
if h === nil
{
return h
}
else
{
if let set = _chart?.data?.getDataSetByIndex(h!.dataSetIndex) as? BarChartDataSet
{
if set.isStacked
{
// create an array of the touch-point
var pt = CGPoint()
pt.x = CGFloat(y)
// take any transformer to determine the x-axis value
_chart?.getTransformer(set.axisDependency).pixelToValue(&pt)
return getStackedHighlight(old: h, set: set, xIndex: h!.xIndex, dataSetIndex: h!.dataSetIndex, yValue: Double(pt.x))
}
}
return h
}
}
internal override func getXIndex(x: Double) -> Int
{
if let barChartData = _chart?.data as? BarChartData
{
if !barChartData.isGrouped
{
// create an array of the touch-point
var pt = CGPoint(x: 0.0, y: x)
// take any transformer to determine the x-axis value
_chart?.getTransformer(ChartYAxis.AxisDependency.Left).pixelToValue(&pt)
return Int(round(pt.y))
}
else
{
let baseNoSpace = getBase(x)
let setCount = barChartData.dataSetCount
var xIndex = Int(baseNoSpace) / setCount
let valCount = barChartData.xValCount
if xIndex < 0
{
xIndex = 0
}
else if xIndex >= valCount
{
xIndex = valCount - 1
}
return xIndex
}
}
else
{
return 0
}
}
/// Returns the base y-value to the corresponding x-touch value in pixels.
/// - parameter y:
/// - returns:
internal override func getBase(y: Double) -> Double
{
if let barChartData = _chart?.data as? BarChartData
{
// create an array of the touch-point
var pt = CGPoint()
pt.y = CGFloat(y)
// take any transformer to determine the x-axis value
_chart?.getTransformer(ChartYAxis.AxisDependency.Left).pixelToValue(&pt)
let yVal = Double(pt.y)
let setCount = barChartData.dataSetCount ?? 0
// calculate how often the group-space appears
let steps = Int(yVal / (Double(setCount) + Double(barChartData.groupSpace)))
let groupSpaceSum = Double(barChartData.groupSpace) * Double(steps)
let baseNoSpace = yVal - groupSpaceSum
return baseNoSpace
}
else
{
return 0.0
}
}
}

View File

@@ -1,589 +0,0 @@
//
// BarChartRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
@objc
public protocol BarChartRendererDelegate
{
func barChartRendererData(renderer: BarChartRenderer) -> BarChartData!
func barChartRenderer(renderer: BarChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
func barChartRendererMaxVisibleValueCount(renderer: BarChartRenderer) -> Int
func barChartDefaultRendererValueFormatter(renderer: BarChartRenderer) -> NSNumberFormatter!
func barChartRendererChartYMax(renderer: BarChartRenderer) -> Double
func barChartRendererChartYMin(renderer: BarChartRenderer) -> Double
func barChartRendererChartXMax(renderer: BarChartRenderer) -> Double
func barChartRendererChartXMin(renderer: BarChartRenderer) -> Double
func barChartIsDrawHighlightArrowEnabled(renderer: BarChartRenderer) -> Bool
func barChartIsDrawValueAboveBarEnabled(renderer: BarChartRenderer) -> Bool
func barChartIsDrawBarShadowEnabled(renderer: BarChartRenderer) -> Bool
func barChartIsInverted(renderer: BarChartRenderer, axis: ChartYAxis.AxisDependency) -> Bool
}
public class BarChartRenderer: ChartDataRendererBase
{
public weak var delegate: BarChartRendererDelegate?
public init(delegate: BarChartRendererDelegate?, animator: ChartAnimator?, viewPortHandler: ChartViewPortHandler)
{
super.init(animator: animator, viewPortHandler: viewPortHandler)
self.delegate = delegate
}
public override func drawData(context context: CGContext?)
{
let barData = delegate!.barChartRendererData(self)
if (barData === nil)
{
return
}
for (var i = 0; i < barData.dataSetCount; i++)
{
let set = barData.getDataSetByIndex(i)
if set !== nil && set!.isVisible && set.entryCount > 0
{
drawDataSet(context: context, dataSet: set as! BarChartDataSet, index: i)
}
}
}
internal func drawDataSet(context context: CGContext?, dataSet: BarChartDataSet, index: Int)
{
CGContextSaveGState(context)
let barData = delegate!.barChartRendererData(self)
let trans = delegate!.barChartRenderer(self, transformerForAxis: dataSet.axisDependency)
let drawBarShadowEnabled: Bool = delegate!.barChartIsDrawBarShadowEnabled(self)
let dataSetOffset = (barData.dataSetCount - 1)
let groupSpace = barData.groupSpace
let groupSpaceHalf = groupSpace / 2.0
let barSpace = dataSet.barSpace
let barSpaceHalf = barSpace / 2.0
let containsStacks = dataSet.isStacked
let isInverted = delegate!.barChartIsInverted(self, axis: dataSet.axisDependency)
var entries = dataSet.yVals as! [BarChartDataEntry]
let barWidth: CGFloat = 0.5
let phaseY = _animator.phaseY
var barRect = CGRect()
var barShadow = CGRect()
var y: Double
// do the drawing
for (var j = 0, count = Int(ceil(CGFloat(dataSet.entryCount) * _animator.phaseX)); j < count; j++)
{
let e = entries[j]
// calculate the x-position, depending on datasetcount
let x = CGFloat(e.xIndex + e.xIndex * dataSetOffset) + CGFloat(index)
+ groupSpace * CGFloat(e.xIndex) + groupSpaceHalf
var vals = e.values
if (!containsStacks || vals == nil)
{
y = e.value
let left = x - barWidth + barSpaceHalf
let right = x + barWidth - barSpaceHalf
var top = isInverted ? (y <= 0.0 ? CGFloat(y) : 0) : (y >= 0.0 ? CGFloat(y) : 0)
var bottom = isInverted ? (y >= 0.0 ? CGFloat(y) : 0) : (y <= 0.0 ? CGFloat(y) : 0)
// multiply the height of the rect with the phase
if (top > 0)
{
top *= phaseY
}
else
{
bottom *= phaseY
}
barRect.origin.x = left
barRect.size.width = right - left
barRect.origin.y = top
barRect.size.height = bottom - top
trans.rectValueToPixel(&barRect)
if (!viewPortHandler.isInBoundsLeft(barRect.origin.x + barRect.size.width))
{
continue
}
if (!viewPortHandler.isInBoundsRight(barRect.origin.x))
{
break
}
// if drawing the bar shadow is enabled
if (drawBarShadowEnabled)
{
barShadow.origin.x = barRect.origin.x
barShadow.origin.y = viewPortHandler.contentTop
barShadow.size.width = barRect.size.width
barShadow.size.height = viewPortHandler.contentHeight
CGContextSetFillColorWithColor(context, dataSet.barShadowColor.CGColor)
CGContextFillRect(context, barShadow)
}
// Set the color for the currently drawn value. If the index is out of bounds, reuse colors.
CGContextSetFillColorWithColor(context, dataSet.colorAt(j).CGColor)
CGContextFillRect(context, barRect)
}
else
{
var posY = 0.0
var negY = -e.negativeSum
var yStart = 0.0
// if drawing the bar shadow is enabled
if (drawBarShadowEnabled)
{
y = e.value
let left = x - barWidth + barSpaceHalf
let right = x + barWidth - barSpaceHalf
var top = isInverted ? (y <= 0.0 ? CGFloat(y) : 0) : (y >= 0.0 ? CGFloat(y) : 0)
var bottom = isInverted ? (y >= 0.0 ? CGFloat(y) : 0) : (y <= 0.0 ? CGFloat(y) : 0)
// multiply the height of the rect with the phase
if (top > 0)
{
top *= phaseY
}
else
{
bottom *= phaseY
}
barRect.origin.x = left
barRect.size.width = right - left
barRect.origin.y = top
barRect.size.height = bottom - top
trans.rectValueToPixel(&barRect)
barShadow.origin.x = barRect.origin.x
barShadow.origin.y = viewPortHandler.contentTop
barShadow.size.width = barRect.size.width
barShadow.size.height = viewPortHandler.contentHeight
CGContextSetFillColorWithColor(context, dataSet.barShadowColor.CGColor)
CGContextFillRect(context, barShadow)
}
// fill the stack
for (var k = 0; k < vals!.count; k++)
{
let value = vals![k]
if value >= 0.0
{
y = posY
yStart = posY + value
posY = yStart
}
else
{
y = negY
yStart = negY + abs(value)
negY += abs(value)
}
let left = x - barWidth + barSpaceHalf
let right = x + barWidth - barSpaceHalf
var top: CGFloat, bottom: CGFloat
if isInverted
{
bottom = y >= yStart ? CGFloat(y) : CGFloat(yStart)
top = y <= yStart ? CGFloat(y) : CGFloat(yStart)
}
else
{
top = y >= yStart ? CGFloat(y) : CGFloat(yStart)
bottom = y <= yStart ? CGFloat(y) : CGFloat(yStart)
}
// multiply the height of the rect with the phase
top *= phaseY
bottom *= phaseY
barRect.origin.x = left
barRect.size.width = right - left
barRect.origin.y = top
barRect.size.height = bottom - top
trans.rectValueToPixel(&barRect)
if (k == 0 && !viewPortHandler.isInBoundsLeft(barRect.origin.x + barRect.size.width))
{
// Skip to next bar
break
}
// avoid drawing outofbounds values
if (!viewPortHandler.isInBoundsRight(barRect.origin.x))
{
break
}
// Set the color for the currently drawn value. If the index is out of bounds, reuse colors.
CGContextSetFillColorWithColor(context, dataSet.colorAt(k).CGColor)
CGContextFillRect(context, barRect)
}
}
}
CGContextRestoreGState(context)
}
/// Prepares a bar for being highlighted.
internal func prepareBarHighlight(x x: CGFloat, y1: Double, y2: Double, barspacehalf: CGFloat, trans: ChartTransformer, inout rect: CGRect)
{
let barWidth: CGFloat = 0.5
let left = x - barWidth + barspacehalf
let right = x + barWidth - barspacehalf
let top = CGFloat(y1)
let bottom = CGFloat(y2)
rect.origin.x = left
rect.origin.y = top
rect.size.width = right - left
rect.size.height = bottom - top
trans.rectValueToPixel(&rect, phaseY: _animator.phaseY)
}
public override func drawValues(context context: CGContext?)
{
// if values are drawn
if (passesCheck())
{
let barData = delegate!.barChartRendererData(self)
let defaultValueFormatter = delegate!.barChartDefaultRendererValueFormatter(self)
var dataSets = barData.dataSets
let drawValueAboveBar = delegate!.barChartIsDrawValueAboveBarEnabled(self)
var posOffset: CGFloat
var negOffset: CGFloat
for (var i = 0, count = barData.dataSetCount; i < count; i++)
{
let dataSet = dataSets[i] as! BarChartDataSet
if !dataSet.isDrawValuesEnabled || dataSet.entryCount == 0
{
continue
}
let isInverted = delegate!.barChartIsInverted(self, axis: dataSet.axisDependency)
// calculate the correct offset depending on the draw position of the value
let valueOffsetPlus: CGFloat = 4.5
let valueFont = dataSet.valueFont
let valueTextHeight = valueFont.lineHeight
posOffset = (drawValueAboveBar ? -(valueTextHeight + valueOffsetPlus) : valueOffsetPlus)
negOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextHeight + valueOffsetPlus))
if (isInverted)
{
posOffset = -posOffset - valueTextHeight
negOffset = -negOffset - valueTextHeight
}
let valueTextColor = dataSet.valueTextColor
var formatter = dataSet.valueFormatter
if (formatter === nil)
{
formatter = defaultValueFormatter
}
let trans = delegate!.barChartRenderer(self, transformerForAxis: dataSet.axisDependency)
var entries = dataSet.yVals as! [BarChartDataEntry]
var valuePoints = getTransformedValues(trans: trans, entries: entries, dataSetIndex: i)
// if only single values are drawn (sum)
if (!dataSet.isStacked)
{
for (var j = 0, count = Int(ceil(CGFloat(valuePoints.count) * _animator.phaseX)); j < count; j++)
{
if (!viewPortHandler.isInBoundsRight(valuePoints[j].x))
{
break
}
if (!viewPortHandler.isInBoundsY(valuePoints[j].y)
|| !viewPortHandler.isInBoundsLeft(valuePoints[j].x))
{
continue
}
let val = entries[j].value
drawValue(context: context,
value: formatter!.stringFromNumber(val)!,
xPos: valuePoints[j].x,
yPos: valuePoints[j].y + (val >= 0.0 ? posOffset : negOffset),
font: valueFont,
align: .Center,
color: valueTextColor)
}
}
else
{
// if we have stacks
for (var j = 0, count = Int(ceil(CGFloat(valuePoints.count) * _animator.phaseX)); j < count; j++)
{
let e = entries[j]
let values = e.values
// we still draw stacked bars, but there is one non-stacked in between
if (values == nil)
{
if (!viewPortHandler.isInBoundsRight(valuePoints[j].x))
{
break
}
if (!viewPortHandler.isInBoundsY(valuePoints[j].y)
|| !viewPortHandler.isInBoundsLeft(valuePoints[j].x))
{
continue
}
drawValue(context: context,
value: formatter!.stringFromNumber(e.value)!,
xPos: valuePoints[j].x,
yPos: valuePoints[j].y + (e.value >= 0.0 ? posOffset : negOffset),
font: valueFont,
align: .Center,
color: valueTextColor)
}
else
{
// draw stack values
let vals = values!
var transformed = [CGPoint]()
var posY = 0.0
var negY = -e.negativeSum
for (var k = 0; k < vals.count; k++)
{
let value = vals[k]
var y: Double
if value >= 0.0
{
posY += value
y = posY
}
else
{
y = negY
negY -= value
}
transformed.append(CGPoint(x: 0.0, y: CGFloat(y) * _animator.phaseY))
}
trans.pointValuesToPixel(&transformed)
for (var k = 0; k < transformed.count; k++)
{
let x = valuePoints[j].x
let y = transformed[k].y + (vals[k] >= 0 ? posOffset : negOffset)
if (!viewPortHandler.isInBoundsRight(x))
{
break
}
if (!viewPortHandler.isInBoundsY(y) || !viewPortHandler.isInBoundsLeft(x))
{
continue
}
drawValue(context: context,
value: formatter!.stringFromNumber(vals[k])!,
xPos: x,
yPos: y,
font: valueFont,
align: .Center,
color: valueTextColor)
}
}
}
}
}
}
}
/// Draws a value at the specified x and y position.
internal func drawValue(context context: CGContext?, value: String, xPos: CGFloat, yPos: CGFloat, font: UIFont, align: NSTextAlignment, color: UIColor)
{
ChartUtils.drawText(context: context, text: value, point: CGPoint(x: xPos, y: yPos), align: align, attributes: [NSFontAttributeName: font, NSForegroundColorAttributeName: color])
}
public override func drawExtras(context context: CGContext?)
{
}
private var _highlightArrowPtsBuffer = [CGPoint](count: 3, repeatedValue: CGPoint())
public override func drawHighlighted(context context: CGContext?, indices: [ChartHighlight])
{
let barData = delegate!.barChartRendererData(self)
if (barData === nil)
{
return
}
CGContextSaveGState(context)
let setCount = barData.dataSetCount
let drawHighlightArrowEnabled = delegate!.barChartIsDrawHighlightArrowEnabled(self)
var barRect = CGRect()
for (var i = 0; i < indices.count; i++)
{
let h = indices[i]
let index = h.xIndex
let dataSetIndex = h.dataSetIndex
let set = barData.getDataSetByIndex(dataSetIndex) as! BarChartDataSet!
if (set === nil || !set.isHighlightEnabled)
{
continue
}
let barspaceHalf = set.barSpace / 2.0
let trans = delegate!.barChartRenderer(self, transformerForAxis: set.axisDependency)
CGContextSetFillColorWithColor(context, set.highlightColor.CGColor)
CGContextSetAlpha(context, set.highLightAlpha)
// check outofbounds
if (CGFloat(index) < (CGFloat(delegate!.barChartRendererChartXMax(self)) * _animator.phaseX) / CGFloat(setCount))
{
let e = set.entryForXIndex(index) as! BarChartDataEntry!
if (e === nil || e.xIndex != index)
{
continue
}
let groupspace = barData.groupSpace
let isStack = h.stackIndex < 0 ? false : true
// calculate the correct x-position
let x = CGFloat(index * setCount + dataSetIndex) + groupspace / 2.0 + groupspace * CGFloat(index)
let y1: Double
let y2: Double
if (isStack)
{
y1 = h.range?.from ?? 0.0
y2 = h.range?.to ?? 0.0
}
else
{
y1 = e.value
y2 = 0.0
}
prepareBarHighlight(x: x, y1: y1, y2: y2, barspacehalf: barspaceHalf, trans: trans, rect: &barRect)
CGContextFillRect(context, barRect)
if (drawHighlightArrowEnabled)
{
CGContextSetAlpha(context, 1.0)
// distance between highlight arrow and bar
let offsetY = _animator.phaseY * 0.07
CGContextSaveGState(context)
let pixelToValueMatrix = trans.pixelToValueMatrix
let xToYRel = abs(sqrt(pixelToValueMatrix.b * pixelToValueMatrix.b + pixelToValueMatrix.d * pixelToValueMatrix.d) / sqrt(pixelToValueMatrix.a * pixelToValueMatrix.a + pixelToValueMatrix.c * pixelToValueMatrix.c))
let arrowWidth = set.barSpace / 2.0
let arrowHeight = arrowWidth * xToYRel
let yArrow = (y1 > -y2 ? y1 : y1) * Double(_animator.phaseY)
_highlightArrowPtsBuffer[0].x = CGFloat(x) + 0.4
_highlightArrowPtsBuffer[0].y = CGFloat(yArrow) + offsetY
_highlightArrowPtsBuffer[1].x = CGFloat(x) + 0.4 + arrowWidth
_highlightArrowPtsBuffer[1].y = CGFloat(yArrow) + offsetY - arrowHeight
_highlightArrowPtsBuffer[2].x = CGFloat(x) + 0.4 + arrowWidth
_highlightArrowPtsBuffer[2].y = CGFloat(yArrow) + offsetY + arrowHeight
trans.pointValuesToPixel(&_highlightArrowPtsBuffer)
CGContextBeginPath(context)
CGContextMoveToPoint(context, _highlightArrowPtsBuffer[0].x, _highlightArrowPtsBuffer[0].y)
CGContextAddLineToPoint(context, _highlightArrowPtsBuffer[1].x, _highlightArrowPtsBuffer[1].y)
CGContextAddLineToPoint(context, _highlightArrowPtsBuffer[2].x, _highlightArrowPtsBuffer[2].y)
CGContextClosePath(context)
CGContextFillPath(context)
CGContextRestoreGState(context)
}
}
}
CGContextRestoreGState(context)
}
public func getTransformedValues(trans trans: ChartTransformer, entries: [BarChartDataEntry], dataSetIndex: Int) -> [CGPoint]
{
return trans.generateTransformedValuesBarChart(entries, dataSet: dataSetIndex, barData: delegate!.barChartRendererData(self)!, phaseY: _animator.phaseY)
}
internal func passesCheck() -> Bool
{
let barData = delegate!.barChartRendererData(self)
if (barData === nil)
{
return false
}
return CGFloat(barData.yValCount) < CGFloat(delegate!.barChartRendererMaxVisibleValueCount(self)) * viewPortHandler.scaleX
}
}

View File

@@ -1,306 +0,0 @@
//
// BubbleChartRenderer.swift
// Charts
//
// Bubble chart implementation:
// Copyright 2015 Pierre-Marc Airoldi
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
@objc
public protocol BubbleChartRendererDelegate
{
func bubbleChartRendererData(renderer: BubbleChartRenderer) -> BubbleChartData!
func bubbleChartRenderer(renderer: BubbleChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
func bubbleChartDefaultRendererValueFormatter(renderer: BubbleChartRenderer) -> NSNumberFormatter!
func bubbleChartRendererChartYMax(renderer: BubbleChartRenderer) -> Double
func bubbleChartRendererChartYMin(renderer: BubbleChartRenderer) -> Double
func bubbleChartRendererChartXMax(renderer: BubbleChartRenderer) -> Double
func bubbleChartRendererChartXMin(renderer: BubbleChartRenderer) -> Double
func bubbleChartRendererMaxVisibleValueCount(renderer: BubbleChartRenderer) -> Int
func bubbleChartRendererXValCount(renderer: BubbleChartRenderer) -> Int
}
public class BubbleChartRenderer: ChartDataRendererBase
{
public weak var delegate: BubbleChartRendererDelegate?
public init(delegate: BubbleChartRendererDelegate?, animator: ChartAnimator?, viewPortHandler: ChartViewPortHandler)
{
super.init(animator: animator, viewPortHandler: viewPortHandler)
self.delegate = delegate
}
public override func drawData(context context: CGContext?)
{
let bubbleData = delegate!.bubbleChartRendererData(self)
for set in bubbleData.dataSets as! [BubbleChartDataSet]
{
if set.isVisible && set.entryCount > 0
{
drawDataSet(context: context, dataSet: set)
}
}
}
private func getShapeSize(entrySize entrySize: CGFloat, maxSize: CGFloat, reference: CGFloat) -> CGFloat
{
let factor: CGFloat = (maxSize == 0.0) ? 1.0 : sqrt(entrySize / maxSize)
let shapeSize: CGFloat = reference * factor
return shapeSize
}
private var _pointBuffer = CGPoint()
private var _sizeBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
internal func drawDataSet(context context: CGContext?, dataSet: BubbleChartDataSet)
{
let trans = delegate!.bubbleChartRenderer(self, transformerForAxis: dataSet.axisDependency)
let phaseX = _animator.phaseX
let phaseY = _animator.phaseY
let entries = dataSet.yVals as! [BubbleChartDataEntry]
let valueToPixelMatrix = trans.valueToPixelMatrix
CGContextSaveGState(context)
let entryFrom = dataSet.entryForXIndex(_minX)
let entryTo = dataSet.entryForXIndex(_maxX)
let minx = max(dataSet.entryIndex(entry: entryFrom!, isEqual: true), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo!, isEqual: true) + 1, entries.count)
_sizeBuffer[0].x = 0.0
_sizeBuffer[0].y = 0.0
_sizeBuffer[1].x = 1.0
_sizeBuffer[1].y = 0.0
trans.pointValuesToPixel(&_sizeBuffer)
// calcualte the full width of 1 step on the x-axis
let maxBubbleWidth: CGFloat = abs(_sizeBuffer[1].x - _sizeBuffer[0].x)
let maxBubbleHeight: CGFloat = abs(viewPortHandler.contentBottom - viewPortHandler.contentTop)
let referenceSize: CGFloat = min(maxBubbleHeight, maxBubbleWidth)
for (var j = minx; j < maxx; j++)
{
let entry = entries[j]
_pointBuffer.x = CGFloat(entry.xIndex - minx) * phaseX + CGFloat(minx)
_pointBuffer.y = CGFloat(entry.value) * phaseY
_pointBuffer = CGPointApplyAffineTransform(_pointBuffer, valueToPixelMatrix)
let shapeSize = getShapeSize(entrySize: entry.size, maxSize: dataSet.maxSize, reference: referenceSize)
let shapeHalf = shapeSize / 2.0
if (!viewPortHandler.isInBoundsTop(_pointBuffer.y + shapeHalf)
|| !viewPortHandler.isInBoundsBottom(_pointBuffer.y - shapeHalf))
{
continue
}
if (!viewPortHandler.isInBoundsLeft(_pointBuffer.x + shapeHalf))
{
continue
}
if (!viewPortHandler.isInBoundsRight(_pointBuffer.x - shapeHalf))
{
break
}
let color = dataSet.colorAt(entry.xIndex)
let rect = CGRect(
x: _pointBuffer.x - shapeHalf,
y: _pointBuffer.y - shapeHalf,
width: shapeSize,
height: shapeSize
)
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillEllipseInRect(context, rect)
}
CGContextRestoreGState(context)
}
public override func drawValues(context context: CGContext?)
{
let bubbleData = delegate!.bubbleChartRendererData(self)
if (bubbleData === nil)
{
return
}
let defaultValueFormatter = delegate!.bubbleChartDefaultRendererValueFormatter(self)
// if values are drawn
if (bubbleData.yValCount < Int(ceil(CGFloat(delegate!.bubbleChartRendererMaxVisibleValueCount(self)) * viewPortHandler.scaleX)))
{
let dataSets = bubbleData.dataSets as! [BubbleChartDataSet]
for dataSet in dataSets
{
if !dataSet.isDrawValuesEnabled || dataSet.entryCount == 0
{
continue
}
let phaseX = _animator.phaseX
let phaseY = _animator.phaseY
let alpha = phaseX == 1 ? phaseY : phaseX
let valueTextColor = dataSet.valueTextColor.colorWithAlphaComponent(alpha)
let formatter = dataSet.valueFormatter === nil ? defaultValueFormatter : dataSet.valueFormatter
let entries = dataSet.yVals
let entryFrom = dataSet.entryForXIndex(_minX)
let entryTo = dataSet.entryForXIndex(_maxX)
let minx = max(dataSet.entryIndex(entry: entryFrom!, isEqual: true), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo!, isEqual: true) + 1, entries.count)
let positions = delegate!.bubbleChartRenderer(self, transformerForAxis: dataSet.axisDependency).generateTransformedValuesBubble(entries, phaseX: phaseX, phaseY: phaseY, from: minx, to: maxx)
for (var j = 0, count = positions.count; j < count; j++)
{
if (!viewPortHandler.isInBoundsRight(positions[j].x))
{
break
}
if ((!viewPortHandler.isInBoundsLeft(positions[j].x) || !viewPortHandler.isInBoundsY(positions[j].y)))
{
continue
}
let entry = entries[j + minx] as! BubbleChartDataEntry
let val = entry.size
let text = formatter!.stringFromNumber(val)
// Larger font for larger bubbles?
let valueFont = dataSet.valueFont
let lineHeight = valueFont.lineHeight
ChartUtils.drawText(context: context, text: text!, point: CGPoint(x: positions[j].x, y: positions[j].y - ( 0.5 * lineHeight)), align: .Center, attributes: [NSFontAttributeName: valueFont, NSForegroundColorAttributeName: valueTextColor])
}
}
}
}
public override func drawExtras(context context: CGContext?)
{
}
public override func drawHighlighted(context context: CGContext?, indices: [ChartHighlight])
{
let bubbleData = delegate!.bubbleChartRendererData(self)
CGContextSaveGState(context)
let phaseX = _animator.phaseX
let phaseY = _animator.phaseY
for indice in indices
{
let dataSet = bubbleData.getDataSetByIndex(indice.dataSetIndex) as! BubbleChartDataSet!
if (dataSet === nil || !dataSet.isHighlightEnabled)
{
continue
}
let entryFrom = dataSet.entryForXIndex(_minX)
let entryTo = dataSet.entryForXIndex(_maxX)
let minx = max(dataSet.entryIndex(entry: entryFrom!, isEqual: true), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo!, isEqual: true) + 1, dataSet.entryCount)
let entry: BubbleChartDataEntry! = bubbleData.getEntryForHighlight(indice) as! BubbleChartDataEntry
if (entry === nil || entry.xIndex != indice.xIndex)
{
continue
}
let trans = delegate!.bubbleChartRenderer(self, transformerForAxis: dataSet.axisDependency)
_sizeBuffer[0].x = 0.0
_sizeBuffer[0].y = 0.0
_sizeBuffer[1].x = 1.0
_sizeBuffer[1].y = 0.0
trans.pointValuesToPixel(&_sizeBuffer)
// calcualte the full width of 1 step on the x-axis
let maxBubbleWidth: CGFloat = abs(_sizeBuffer[1].x - _sizeBuffer[0].x)
let maxBubbleHeight: CGFloat = abs(viewPortHandler.contentBottom - viewPortHandler.contentTop)
let referenceSize: CGFloat = min(maxBubbleHeight, maxBubbleWidth)
_pointBuffer.x = CGFloat(entry.xIndex - minx) * phaseX + CGFloat(minx)
_pointBuffer.y = CGFloat(entry.value) * phaseY
trans.pointValueToPixel(&_pointBuffer)
let shapeSize = getShapeSize(entrySize: entry.size, maxSize: dataSet.maxSize, reference: referenceSize)
let shapeHalf = shapeSize / 2.0
if (!viewPortHandler.isInBoundsTop(_pointBuffer.y + shapeHalf)
|| !viewPortHandler.isInBoundsBottom(_pointBuffer.y - shapeHalf))
{
continue
}
if (!viewPortHandler.isInBoundsLeft(_pointBuffer.x + shapeHalf))
{
continue
}
if (!viewPortHandler.isInBoundsRight(_pointBuffer.x - shapeHalf))
{
break
}
if (indice.xIndex < minx || indice.xIndex >= maxx)
{
continue
}
let originalColor = dataSet.colorAt(entry.xIndex)
var h: CGFloat = 0.0
var s: CGFloat = 0.0
var b: CGFloat = 0.0
var a: CGFloat = 0.0
originalColor.getHue(&h, saturation: &s, brightness: &b, alpha: &a)
let color = UIColor(hue: h, saturation: s, brightness: b * 0.5, alpha: a)
let rect = CGRect(
x: _pointBuffer.x - shapeHalf,
y: _pointBuffer.y - shapeHalf,
width: shapeSize,
height: shapeSize)
CGContextSetLineWidth(context, dataSet.highlightCircleWidth)
CGContextSetStrokeColorWithColor(context, color.CGColor)
CGContextStrokeEllipseInRect(context, rect)
}
CGContextRestoreGState(context)
}
}

View File

@@ -1,299 +0,0 @@
//
// CandleStickChartRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
@objc
public protocol CandleStickChartRendererDelegate
{
func candleStickChartRendererCandleData(renderer: CandleStickChartRenderer) -> CandleChartData!
func candleStickChartRenderer(renderer: CandleStickChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
func candleStickChartDefaultRendererValueFormatter(renderer: CandleStickChartRenderer) -> NSNumberFormatter!
func candleStickChartRendererChartYMax(renderer: CandleStickChartRenderer) -> Double
func candleStickChartRendererChartYMin(renderer: CandleStickChartRenderer) -> Double
func candleStickChartRendererChartXMax(renderer: CandleStickChartRenderer) -> Double
func candleStickChartRendererChartXMin(renderer: CandleStickChartRenderer) -> Double
func candleStickChartRendererMaxVisibleValueCount(renderer: CandleStickChartRenderer) -> Int
}
public class CandleStickChartRenderer: LineScatterCandleRadarChartRenderer
{
public weak var delegate: CandleStickChartRendererDelegate?
public init(delegate: CandleStickChartRendererDelegate?, animator: ChartAnimator?, viewPortHandler: ChartViewPortHandler)
{
super.init(animator: animator, viewPortHandler: viewPortHandler)
self.delegate = delegate
}
public override func drawData(context context: CGContext?)
{
let candleData = delegate!.candleStickChartRendererCandleData(self)
for set in candleData.dataSets as! [CandleChartDataSet]
{
if set.isVisible && set.entryCount > 0
{
drawDataSet(context: context, dataSet: set)
}
}
}
private var _shadowPoints = [CGPoint](count: 2, repeatedValue: CGPoint())
private var _bodyRect = CGRect()
private var _lineSegments = [CGPoint](count: 2, repeatedValue: CGPoint())
internal func drawDataSet(context context: CGContext?, dataSet: CandleChartDataSet)
{
let trans = delegate!.candleStickChartRenderer(self, transformerForAxis: dataSet.axisDependency)
let phaseX = _animator.phaseX
let phaseY = _animator.phaseY
let bodySpace = dataSet.bodySpace
var entries = dataSet.yVals as! [CandleChartDataEntry]
let minx = max(_minX, 0)
let maxx = min(_maxX + 1, entries.count)
CGContextSaveGState(context)
CGContextSetLineWidth(context, dataSet.shadowWidth)
for (var j = minx, count = Int(ceil(CGFloat(maxx - minx) * phaseX + CGFloat(minx))); j < count; j++)
{
// get the entry
let e = entries[j]
if (e.xIndex < _minX || e.xIndex > _maxX)
{
continue
}
// calculate the shadow
_shadowPoints[0].x = CGFloat(e.xIndex)
_shadowPoints[0].y = CGFloat(e.high) * phaseY
_shadowPoints[1].x = CGFloat(e.xIndex)
_shadowPoints[1].y = CGFloat(e.low) * phaseY
trans.pointValuesToPixel(&_shadowPoints)
// draw the shadow
var shadowColor: UIColor! = nil
if (dataSet.shadowColorSameAsCandle)
{
if (e.open > e.close)
{
shadowColor = dataSet.decreasingColor ?? dataSet.colorAt(j)
}
else if (e.open < e.close)
{
shadowColor = dataSet.increasingColor ?? dataSet.colorAt(j)
}
}
if (shadowColor === nil)
{
shadowColor = dataSet.shadowColor ?? dataSet.colorAt(j);
}
CGContextSetStrokeColorWithColor(context, shadowColor.CGColor)
CGContextStrokeLineSegments(context, _shadowPoints, 2)
// calculate the body
_bodyRect.origin.x = CGFloat(e.xIndex) - 0.5 + bodySpace
_bodyRect.origin.y = CGFloat(e.close) * phaseY
_bodyRect.size.width = (CGFloat(e.xIndex) + 0.5 - bodySpace) - _bodyRect.origin.x
_bodyRect.size.height = (CGFloat(e.open) * phaseY) - _bodyRect.origin.y
trans.rectValueToPixel(&_bodyRect)
// draw body differently for increasing and decreasing entry
if (e.open > e.close)
{
let color = dataSet.decreasingColor ?? dataSet.colorAt(j)
if (dataSet.isDecreasingFilled)
{
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, _bodyRect)
}
else
{
CGContextSetStrokeColorWithColor(context, color.CGColor)
CGContextStrokeRect(context, _bodyRect)
}
}
else if (e.open < e.close)
{
let color = dataSet.increasingColor ?? dataSet.colorAt(j)
if (dataSet.isIncreasingFilled)
{
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, _bodyRect)
}
else
{
CGContextSetStrokeColorWithColor(context, color.CGColor)
CGContextStrokeRect(context, _bodyRect)
}
}
else
{
CGContextSetStrokeColorWithColor(context, shadowColor.CGColor)
CGContextStrokeRect(context, _bodyRect)
}
}
CGContextRestoreGState(context)
}
public override func drawValues(context context: CGContext?)
{
let candleData = delegate!.candleStickChartRendererCandleData(self)
if (candleData === nil)
{
return
}
let defaultValueFormatter = delegate!.candleStickChartDefaultRendererValueFormatter(self)
// if values are drawn
if (candleData.yValCount < Int(ceil(CGFloat(delegate!.candleStickChartRendererMaxVisibleValueCount(self)) * viewPortHandler.scaleX)))
{
var dataSets = candleData.dataSets
for (var i = 0; i < dataSets.count; i++)
{
let dataSet = dataSets[i]
if !dataSet.isDrawValuesEnabled || dataSet.entryCount == 0
{
continue
}
let valueFont = dataSet.valueFont
let valueTextColor = dataSet.valueTextColor
var formatter = dataSet.valueFormatter
if (formatter === nil)
{
formatter = defaultValueFormatter
}
let trans = delegate!.candleStickChartRenderer(self, transformerForAxis: dataSet.axisDependency)
var entries = dataSet.yVals as! [CandleChartDataEntry]
let minx = max(_minX, 0)
let maxx = min(_maxX + 1, entries.count)
var positions = trans.generateTransformedValuesCandle(entries, phaseY: _animator.phaseY)
let lineHeight = valueFont.lineHeight
let yOffset: CGFloat = lineHeight + 5.0
for (var j = minx, count = Int(ceil(CGFloat(maxx - minx) * _animator.phaseX + CGFloat(minx))); j < count; j++)
{
let x = positions[j].x
let y = positions[j].y
if (!viewPortHandler.isInBoundsRight(x))
{
break
}
if (!viewPortHandler.isInBoundsLeft(x) || !viewPortHandler.isInBoundsY(y))
{
continue
}
let val = entries[j].high
ChartUtils.drawText(context: context, text: formatter!.stringFromNumber(val)!, point: CGPoint(x: x, y: y - yOffset), align: .Center, attributes: [NSFontAttributeName: valueFont, NSForegroundColorAttributeName: valueTextColor])
}
}
}
}
public override func drawExtras(context context: CGContext?)
{
}
private var _highlightPointBuffer = CGPoint()
public override func drawHighlighted(context context: CGContext?, indices: [ChartHighlight])
{
let candleData = delegate!.candleStickChartRendererCandleData(self)
if (candleData === nil)
{
return
}
CGContextSaveGState(context)
for (var i = 0; i < indices.count; i++)
{
let xIndex = indices[i].xIndex; // get the x-position
let set = candleData.getDataSetByIndex(indices[i].dataSetIndex) as! CandleChartDataSet!
if (set === nil || !set.isHighlightEnabled)
{
continue
}
let e = set.entryForXIndex(xIndex) as! CandleChartDataEntry!
if (e === nil || e.xIndex != xIndex)
{
continue
}
let trans = delegate!.candleStickChartRenderer(self, transformerForAxis: set.axisDependency)
CGContextSetStrokeColorWithColor(context, set.highlightColor.CGColor)
CGContextSetLineWidth(context, set.highlightLineWidth)
if (set.highlightLineDashLengths != nil)
{
CGContextSetLineDash(context, set.highlightLineDashPhase, set.highlightLineDashLengths!, set.highlightLineDashLengths!.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
let low = CGFloat(e.low) * _animator.phaseY
let high = CGFloat(e.high) * _animator.phaseY
let y = (low + high) / 2.0
_highlightPointBuffer.x = CGFloat(xIndex)
_highlightPointBuffer.y = y
trans.pointValueToPixel(&_highlightPointBuffer)
// draw the lines
drawHighlightLines(context: context, point: _highlightPointBuffer, set: set)
}
CGContextRestoreGState(context)
}
}

View File

@@ -1,56 +0,0 @@
//
// ChartAxisRendererBase.swift
// Charts
//
// Created by Daniel Cohen Gindi on 3/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import UIKit
public class ChartAxisRendererBase: ChartRendererBase
{
internal var transformer: ChartTransformer!
public override init()
{
super.init()
}
public init(viewPortHandler: ChartViewPortHandler, transformer: ChartTransformer!)
{
super.init(viewPortHandler: viewPortHandler)
self.transformer = transformer
}
/// Draws the axis labels on the specified context
public func renderAxisLabels(context context: CGContext?)
{
fatalError("renderAxisLabels() cannot be called on ChartAxisRendererBase")
}
/// Draws the grid lines belonging to the axis.
public func renderGridLines(context context: CGContext?)
{
fatalError("renderGridLines() cannot be called on ChartAxisRendererBase")
}
/// Draws the line that goes alongside the axis.
public func renderAxisLine(context context: CGContext?)
{
fatalError("renderAxisLine() cannot be called on ChartAxisRendererBase")
}
/// Draws the LimitLines associated with this axis to the screen.
public func renderLimitLines(context context: CGContext?)
{
fatalError("renderLimitLines() cannot be called on ChartAxisRendererBase")
}
}

View File

@@ -1,49 +0,0 @@
//
// ChartDataRendererBase.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
public class ChartDataRendererBase: ChartRendererBase
{
internal var _animator: ChartAnimator!
public init(animator: ChartAnimator?, viewPortHandler: ChartViewPortHandler)
{
super.init(viewPortHandler: viewPortHandler)
_animator = animator
}
public func drawData(context context: CGContext?)
{
fatalError("drawData() cannot be called on ChartDataRendererBase")
}
public func drawValues(context context: CGContext?)
{
fatalError("drawValues() cannot be called on ChartDataRendererBase")
}
public func drawExtras(context context: CGContext?)
{
fatalError("drawExtras() cannot be called on ChartDataRendererBase")
}
/// Draws all highlight indicators for the values that are currently highlighted.
///
/// - parameter indices: the highlighted values
public func drawHighlighted(context context: CGContext?, indices: [ChartHighlight])
{
fatalError("drawHighlighted() cannot be called on ChartDataRendererBase")
}
}

View File

@@ -1,426 +0,0 @@
//
// ChartLegendRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class ChartLegendRenderer: ChartRendererBase
{
/// the legend object this renderer renders
internal var _legend: ChartLegend!
public init(viewPortHandler: ChartViewPortHandler, legend: ChartLegend?)
{
super.init(viewPortHandler: viewPortHandler)
_legend = legend
}
/// Prepares the legend and calculates all needed forms, labels and colors.
public func computeLegend(data: ChartData)
{
if (!_legend.isLegendCustom)
{
var labels = [String?]()
var colors = [UIColor?]()
// loop for building up the colors and labels used in the legend
for (var i = 0, count = data.dataSetCount; i < count; i++)
{
let dataSet = data.getDataSetByIndex(i)!
var clrs: [UIColor] = dataSet.colors
let entryCount = dataSet.entryCount
// if we have a barchart with stacked bars
if (dataSet.isKindOfClass(BarChartDataSet) && (dataSet as! BarChartDataSet).isStacked)
{
let bds = dataSet as! BarChartDataSet
var sLabels = bds.stackLabels
for (var j = 0; j < clrs.count && j < bds.stackSize; j++)
{
labels.append(sLabels[j % sLabels.count])
colors.append(clrs[j])
}
if (bds.label != nil)
{
// add the legend description label
colors.append(nil)
labels.append(bds.label)
}
}
else if (dataSet.isKindOfClass(PieChartDataSet))
{
var xVals = data.xVals
let pds = dataSet as! PieChartDataSet
for (var j = 0; j < clrs.count && j < entryCount && j < xVals.count; j++)
{
labels.append(xVals[j])
colors.append(clrs[j])
}
if (pds.label != nil)
{
// add the legend description label
colors.append(nil)
labels.append(pds.label)
}
}
else
{ // all others
for (var j = 0; j < clrs.count && j < entryCount; j++)
{
// if multiple colors are set for a DataSet, group them
if (j < clrs.count - 1 && j < entryCount - 1)
{
labels.append(nil)
}
else
{ // add label to the last entry
labels.append(dataSet.label)
}
colors.append(clrs[j])
}
}
}
_legend.colors = colors + _legend._extraColors
_legend.labels = labels + _legend._extraLabels
}
// calculate all dimensions of the legend
_legend.calculateDimensions(labelFont: _legend.font, viewPortHandler: viewPortHandler)
}
public func renderLegend(context context: CGContext?)
{
if (_legend === nil || !_legend.enabled)
{
return
}
let labelFont = _legend.font
let labelTextColor = _legend.textColor
let labelLineHeight = labelFont.lineHeight
let formYOffset = labelLineHeight / 2.0
var labels = _legend.labels
var colors = _legend.colors
let formSize = _legend.formSize
let formToTextSpace = _legend.formToTextSpace
let xEntrySpace = _legend.xEntrySpace
let direction = _legend.direction
// space between the entries
let stackSpace = _legend.stackSpace
let yoffset = _legend.yOffset
let xoffset = _legend.xOffset
let legendPosition = _legend.position
switch (legendPosition)
{
case .BelowChartLeft: fallthrough
case .BelowChartRight: fallthrough
case .BelowChartCenter: fallthrough
case .AboveChartLeft: fallthrough
case .AboveChartRight: fallthrough
case .AboveChartCenter:
let contentWidth: CGFloat = viewPortHandler.contentWidth
var originPosX: CGFloat
if (legendPosition == .BelowChartLeft || legendPosition == .AboveChartLeft)
{
originPosX = viewPortHandler.contentLeft + xoffset
if (direction == .RightToLeft)
{
originPosX += _legend.neededWidth
}
}
else if (legendPosition == .BelowChartRight || legendPosition == .AboveChartRight)
{
originPosX = viewPortHandler.contentRight - xoffset
if (direction == .LeftToRight)
{
originPosX -= _legend.neededWidth
}
}
else // .BelowChartCenter || .AboveChartCenter
{
originPosX = viewPortHandler.contentLeft + contentWidth / 2.0
}
var calculatedLineSizes = _legend.calculatedLineSizes
var calculatedLabelSizes = _legend.calculatedLabelSizes
var calculatedLabelBreakPoints = _legend.calculatedLabelBreakPoints
var posX: CGFloat = originPosX
var posY: CGFloat
if (legendPosition == .AboveChartLeft
|| legendPosition == .AboveChartRight
|| legendPosition == .AboveChartCenter)
{
posY = 0
}
else
{
posY = viewPortHandler.chartHeight - yoffset - _legend.neededHeight
}
var lineIndex: Int = 0
for (var i = 0, count = labels.count; i < count; i++)
{
if (i < calculatedLabelBreakPoints.count && calculatedLabelBreakPoints[i])
{
posX = originPosX
posY += labelLineHeight
}
if (posX == originPosX && legendPosition == .BelowChartCenter && lineIndex < calculatedLineSizes.count)
{
posX += (direction == .RightToLeft ? calculatedLineSizes[lineIndex].width : -calculatedLineSizes[lineIndex].width) / 2.0
lineIndex++
}
let drawingForm = colors[i] != nil
let isStacked = labels[i] == nil; // grouped forms have null labels
if (drawingForm)
{
if (direction == .RightToLeft)
{
posX -= formSize
}
drawForm(context, x: posX, y: posY + formYOffset, colorIndex: i, legend: _legend)
if (direction == .LeftToRight)
{
posX += formSize
}
}
if (!isStacked)
{
if (drawingForm)
{
posX += direction == .RightToLeft ? -formToTextSpace : formToTextSpace
}
if (direction == .RightToLeft)
{
posX -= calculatedLabelSizes[i].width
}
drawLabel(context, x: posX, y: posY, label: labels[i]!, font: labelFont, textColor: labelTextColor)
if (direction == .LeftToRight)
{
posX += calculatedLabelSizes[i].width
}
posX += direction == .RightToLeft ? -xEntrySpace : xEntrySpace
}
else
{
posX += direction == .RightToLeft ? -stackSpace : stackSpace
}
}
break
case .PiechartCenter: fallthrough
case .RightOfChart: fallthrough
case .RightOfChartCenter: fallthrough
case .RightOfChartInside: fallthrough
case .LeftOfChart: fallthrough
case .LeftOfChartCenter: fallthrough
case .LeftOfChartInside:
// contains the stacked legend size in pixels
var stack = CGFloat(0.0)
var wasStacked = false
var posX: CGFloat = 0.0, posY: CGFloat = 0.0
if (legendPosition == .PiechartCenter)
{
posX = viewPortHandler.chartWidth / 2.0 + (direction == .LeftToRight ? -_legend.textWidthMax / 2.0 : _legend.textWidthMax / 2.0)
posY = viewPortHandler.chartHeight / 2.0 - _legend.neededHeight / 2.0 + _legend.yOffset
}
else
{
let isRightAligned = legendPosition == .RightOfChart ||
legendPosition == .RightOfChartCenter ||
legendPosition == .RightOfChartInside
if (isRightAligned)
{
posX = viewPortHandler.chartWidth - xoffset
if (direction == .LeftToRight)
{
posX -= _legend.textWidthMax
}
}
else
{
posX = xoffset
if (direction == .RightToLeft)
{
posX += _legend.textWidthMax
}
}
if (legendPosition == .RightOfChart ||
legendPosition == .LeftOfChart)
{
posY = viewPortHandler.contentTop + yoffset
}
else if (legendPosition == .RightOfChartCenter ||
legendPosition == .LeftOfChartCenter)
{
posY = viewPortHandler.chartHeight / 2.0 - _legend.neededHeight / 2.0
}
else /*if (legend.position == .RightOfChartInside ||
legend.position == .LeftOfChartInside)*/
{
posY = viewPortHandler.contentTop + yoffset
}
}
for (var i = 0; i < labels.count; i++)
{
let drawingForm = colors[i] != nil
var x = posX
if (drawingForm)
{
if (direction == .LeftToRight)
{
x += stack
}
else
{
x -= formSize - stack
}
drawForm(context, x: x, y: posY + formYOffset, colorIndex: i, legend: _legend)
if (direction == .LeftToRight)
{
x += formSize
}
}
if (labels[i] != nil)
{
if (drawingForm && !wasStacked)
{
x += direction == .LeftToRight ? formToTextSpace : -formToTextSpace
}
else if (wasStacked)
{
x = posX
}
if (direction == .RightToLeft)
{
x -= (labels[i] as NSString!).sizeWithAttributes([NSFontAttributeName: labelFont]).width
}
if (!wasStacked)
{
drawLabel(context, x: x, y: posY, label: labels[i]!, font: labelFont, textColor: labelTextColor)
}
else
{
posY += labelLineHeight
drawLabel(context, x: x, y: posY, label: labels[i]!, font: labelFont, textColor: labelTextColor)
}
// make a step down
posY += labelLineHeight
stack = 0.0
}
else
{
stack += formSize + stackSpace
wasStacked = true
}
}
break
}
}
private var _formLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
/// Draws the Legend-form at the given position with the color at the given index.
internal func drawForm(context: CGContext?, x: CGFloat, y: CGFloat, colorIndex: Int, legend: ChartLegend)
{
let formColor = legend.colors[colorIndex]
if (formColor === nil || formColor == UIColor.clearColor())
{
return
}
let formsize = legend.formSize
CGContextSaveGState(context)
switch (legend.form)
{
case .Circle:
CGContextSetFillColorWithColor(context, formColor!.CGColor)
CGContextFillEllipseInRect(context, CGRect(x: x, y: y - formsize / 2.0, width: formsize, height: formsize))
break
case .Square:
CGContextSetFillColorWithColor(context, formColor!.CGColor)
CGContextFillRect(context, CGRect(x: x, y: y - formsize / 2.0, width: formsize, height: formsize))
break
case .Line:
CGContextSetLineWidth(context, legend.formLineWidth)
CGContextSetStrokeColorWithColor(context, formColor!.CGColor)
_formLineSegmentsBuffer[0].x = x
_formLineSegmentsBuffer[0].y = y
_formLineSegmentsBuffer[1].x = x + formsize
_formLineSegmentsBuffer[1].y = y
CGContextStrokeLineSegments(context, _formLineSegmentsBuffer, 2)
break
}
CGContextRestoreGState(context)
}
/// Draws the provided label at the given position.
internal func drawLabel(context: CGContext?, x: CGFloat, y: CGFloat, label: String, font: UIFont, textColor: UIColor)
{
ChartUtils.drawText(context: context, text: label, point: CGPoint(x: x, y: y), align: .Left, attributes: [NSFontAttributeName: font, NSForegroundColorAttributeName: textColor])
}
}

View File

@@ -1,64 +0,0 @@
//
// ChartRendererBase.swift
// Charts
//
// Created by Daniel Cohen Gindi on 3/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
public class ChartRendererBase: NSObject
{
/// the component that handles the drawing area of the chart and it's offsets
public var viewPortHandler: ChartViewPortHandler!
/// the minimum value on the x-axis that should be plotted
internal var _minX: Int = 0
/// the maximum value on the x-axis that should be plotted
internal var _maxX: Int = 0
public override init()
{
super.init()
}
public init(viewPortHandler: ChartViewPortHandler)
{
super.init()
self.viewPortHandler = viewPortHandler
}
/// - returns: true if the specified value fits in between the provided min and max bounds, false if not.
internal func fitsBounds(val: Double, min: Double, max: Double) -> Bool
{
if (val < min || val > max)
{
return false
}
else
{
return true
}
}
/// Calculates the minimum and maximum x-value the chart can currently display (with the given zoom level).
public func calcXBounds(chart chart: BarLineChartViewBase, xAxisModulus: Int)
{
let low = chart.lowestVisibleXIndex
let high = chart.highestVisibleXIndex
let subLow = (low % xAxisModulus == 0) ? xAxisModulus : 0
_minX = max((low / xAxisModulus) * (xAxisModulus) - subLow, 0)
_maxX = min((high / xAxisModulus) * (xAxisModulus) + xAxisModulus, Int(chart.chartXMax))
}
}

View File

@@ -1,339 +0,0 @@
//
// ChartXAxisRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 3/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class ChartXAxisRenderer: ChartAxisRendererBase
{
internal var _xAxis: ChartXAxis!
public init(viewPortHandler: ChartViewPortHandler, xAxis: ChartXAxis, transformer: ChartTransformer!)
{
super.init(viewPortHandler: viewPortHandler, transformer: transformer)
_xAxis = xAxis
}
public func computeAxis(xValAverageLength xValAverageLength: Double, xValues: [String?])
{
var a = ""
let max = Int(round(xValAverageLength + Double(_xAxis.spaceBetweenLabels)))
for (var i = 0; i < max; i++)
{
a += "h"
}
let widthText = a as NSString
_xAxis.labelWidth = widthText.sizeWithAttributes([NSFontAttributeName: _xAxis.labelFont]).width
_xAxis.labelHeight = _xAxis.labelFont.lineHeight
_xAxis.values = xValues
}
public override func renderAxisLabels(context context: CGContext?)
{
if (!_xAxis.isEnabled || !_xAxis.isDrawLabelsEnabled)
{
return
}
let yoffset = CGFloat(4.0)
if (_xAxis.labelPosition == .Top)
{
drawLabels(context: context, pos: viewPortHandler.offsetTop - _xAxis.labelHeight - yoffset)
}
else if (_xAxis.labelPosition == .Bottom)
{
drawLabels(context: context, pos: viewPortHandler.contentBottom + yoffset * 1.5)
}
else if (_xAxis.labelPosition == .BottomInside)
{
drawLabels(context: context, pos: viewPortHandler.contentBottom - _xAxis.labelHeight - yoffset)
}
else if (_xAxis.labelPosition == .TopInside)
{
drawLabels(context: context, pos: viewPortHandler.offsetTop + yoffset)
}
else
{ // BOTH SIDED
drawLabels(context: context, pos: viewPortHandler.offsetTop - _xAxis.labelHeight - yoffset)
drawLabels(context: context, pos: viewPortHandler.contentBottom + yoffset * 1.6)
}
}
private var _axisLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderAxisLine(context context: CGContext?)
{
if (!_xAxis.isEnabled || !_xAxis.isDrawAxisLineEnabled)
{
return
}
CGContextSaveGState(context)
CGContextSetStrokeColorWithColor(context, _xAxis.axisLineColor.CGColor)
CGContextSetLineWidth(context, _xAxis.axisLineWidth)
if (_xAxis.axisLineDashLengths != nil)
{
CGContextSetLineDash(context, _xAxis.axisLineDashPhase, _xAxis.axisLineDashLengths, _xAxis.axisLineDashLengths.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
if (_xAxis.labelPosition == .Top
|| _xAxis.labelPosition == .TopInside
|| _xAxis.labelPosition == .BothSided)
{
_axisLineSegmentsBuffer[0].x = viewPortHandler.contentLeft
_axisLineSegmentsBuffer[0].y = viewPortHandler.contentTop
_axisLineSegmentsBuffer[1].x = viewPortHandler.contentRight
_axisLineSegmentsBuffer[1].y = viewPortHandler.contentTop
CGContextStrokeLineSegments(context, _axisLineSegmentsBuffer, 2)
}
if (_xAxis.labelPosition == .Bottom
|| _xAxis.labelPosition == .BottomInside
|| _xAxis.labelPosition == .BothSided)
{
_axisLineSegmentsBuffer[0].x = viewPortHandler.contentLeft
_axisLineSegmentsBuffer[0].y = viewPortHandler.contentBottom
_axisLineSegmentsBuffer[1].x = viewPortHandler.contentRight
_axisLineSegmentsBuffer[1].y = viewPortHandler.contentBottom
CGContextStrokeLineSegments(context, _axisLineSegmentsBuffer, 2)
}
CGContextRestoreGState(context)
}
/// draws the x-labels on the specified y-position
internal func drawLabels(context context: CGContext?, pos: CGFloat)
{
let paraStyle = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle
paraStyle.alignment = .Center
let labelAttrs = [NSFontAttributeName: _xAxis.labelFont,
NSForegroundColorAttributeName: _xAxis.labelTextColor,
NSParagraphStyleAttributeName: paraStyle]
let valueToPixelMatrix = transformer.valueToPixelMatrix
var position = CGPoint(x: 0.0, y: 0.0)
var labelMaxSize = CGSize()
if (_xAxis.isWordWrapEnabled)
{
labelMaxSize.width = _xAxis.wordWrapWidthPercent * valueToPixelMatrix.a
}
for (var i = _minX, maxX = min(_maxX + 1, _xAxis.values.count); i < maxX; i += _xAxis.axisLabelModulus)
{
let label = _xAxis.values[i]
if (label == nil)
{
continue
}
position.x = CGFloat(i)
position.y = 0.0
position = CGPointApplyAffineTransform(position, valueToPixelMatrix)
if (viewPortHandler.isInBoundsX(position.x))
{
let labelns = label! as NSString
if (_xAxis.isAvoidFirstLastClippingEnabled)
{
// avoid clipping of the last
if (i == _xAxis.values.count - 1 && _xAxis.values.count > 1)
{
let width = labelns.boundingRectWithSize(labelMaxSize, options: .UsesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width
if (width > viewPortHandler.offsetRight * 2.0
&& position.x + width > viewPortHandler.chartWidth)
{
position.x -= width / 2.0
}
}
else if (i == 0)
{ // avoid clipping of the first
let width = labelns.boundingRectWithSize(labelMaxSize, options: .UsesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width
position.x += width / 2.0
}
}
drawLabel(context: context, label: label!, xIndex: i, x: position.x, y: pos, align: .Center, attributes: labelAttrs, constrainedToSize: labelMaxSize)
}
}
}
internal func drawLabel(context context: CGContext?, label: String, xIndex: Int, x: CGFloat, y: CGFloat, align: NSTextAlignment, attributes: [String: NSObject], constrainedToSize: CGSize)
{
let formattedLabel = _xAxis.valueFormatter?.stringForXValue(xIndex, original: label, viewPortHandler: viewPortHandler) ?? label
ChartUtils.drawMultilineText(context: context, text: formattedLabel, point: CGPoint(x: x, y: y), align: align, attributes: attributes, constrainedToSize: constrainedToSize)
}
private var _gridLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderGridLines(context context: CGContext?)
{
if (!_xAxis.isDrawGridLinesEnabled || !_xAxis.isEnabled)
{
return
}
CGContextSaveGState(context)
CGContextSetStrokeColorWithColor(context, _xAxis.gridColor.CGColor)
CGContextSetLineWidth(context, _xAxis.gridLineWidth)
if (_xAxis.gridLineDashLengths != nil)
{
CGContextSetLineDash(context, _xAxis.gridLineDashPhase, _xAxis.gridLineDashLengths, _xAxis.gridLineDashLengths.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
let valueToPixelMatrix = transformer.valueToPixelMatrix
var position = CGPoint(x: 0.0, y: 0.0)
for (var i = _minX; i <= _maxX; i += _xAxis.axisLabelModulus)
{
position.x = CGFloat(i)
position.y = 0.0
position = CGPointApplyAffineTransform(position, valueToPixelMatrix)
if (position.x >= viewPortHandler.offsetLeft
&& position.x <= viewPortHandler.chartWidth)
{
_gridLineSegmentsBuffer[0].x = position.x
_gridLineSegmentsBuffer[0].y = viewPortHandler.contentTop
_gridLineSegmentsBuffer[1].x = position.x
_gridLineSegmentsBuffer[1].y = viewPortHandler.contentBottom
CGContextStrokeLineSegments(context, _gridLineSegmentsBuffer, 2)
}
}
CGContextRestoreGState(context)
}
private var _limitLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderLimitLines(context context: CGContext?)
{
var limitLines = _xAxis.limitLines
if (limitLines.count == 0)
{
return
}
CGContextSaveGState(context)
let trans = transformer.valueToPixelMatrix
var position = CGPoint(x: 0.0, y: 0.0)
for (var i = 0; i < limitLines.count; i++)
{
let l = limitLines[i]
position.x = CGFloat(l.limit)
position.y = 0.0
position = CGPointApplyAffineTransform(position, trans)
_limitLineSegmentsBuffer[0].x = position.x
_limitLineSegmentsBuffer[0].y = viewPortHandler.contentTop
_limitLineSegmentsBuffer[1].x = position.x
_limitLineSegmentsBuffer[1].y = viewPortHandler.contentBottom
CGContextSetStrokeColorWithColor(context, l.lineColor.CGColor)
CGContextSetLineWidth(context, l.lineWidth)
if (l.lineDashLengths != nil)
{
CGContextSetLineDash(context, l.lineDashPhase, l.lineDashLengths!, l.lineDashLengths!.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
CGContextStrokeLineSegments(context, _limitLineSegmentsBuffer, 2)
let label = l.label
// if drawing the limit-value label is enabled
if (label.characters.count > 0)
{
let labelLineHeight = l.valueFont.lineHeight
let add = CGFloat(4.0)
let xOffset: CGFloat = l.lineWidth
let yOffset: CGFloat = add / 2.0
if (l.labelPosition == .RightTop)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: position.x + xOffset,
y: viewPortHandler.contentTop + yOffset),
align: .Left,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else if (l.labelPosition == .RightBottom)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: position.x + xOffset,
y: viewPortHandler.contentBottom - labelLineHeight - yOffset),
align: .Left,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else if (l.labelPosition == .LeftTop)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: position.x - xOffset,
y: viewPortHandler.contentTop + yOffset),
align: .Right,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: position.x - xOffset,
y: viewPortHandler.contentBottom - labelLineHeight - yOffset),
align: .Right,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
}
}
CGContextRestoreGState(context)
}
}

View File

@@ -1,151 +0,0 @@
//
// ChartXAxisRendererBarChart.swift
// Charts
//
// Created by Daniel Cohen Gindi on 3/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class ChartXAxisRendererBarChart: ChartXAxisRenderer
{
internal weak var _chart: BarChartView!
public init(viewPortHandler: ChartViewPortHandler, xAxis: ChartXAxis, transformer: ChartTransformer!, chart: BarChartView)
{
super.init(viewPortHandler: viewPortHandler, xAxis: xAxis, transformer: transformer)
self._chart = chart
}
/// draws the x-labels on the specified y-position
internal override func drawLabels(context context: CGContext?, pos: CGFloat)
{
if (_chart.data === nil)
{
return
}
let paraStyle = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle
paraStyle.alignment = .Center
let labelAttrs = [NSFontAttributeName: _xAxis.labelFont,
NSForegroundColorAttributeName: _xAxis.labelTextColor,
NSParagraphStyleAttributeName: paraStyle]
let barData = _chart.data as! BarChartData
let step = barData.dataSetCount
let valueToPixelMatrix = transformer.valueToPixelMatrix
var position = CGPoint(x: 0.0, y: 0.0)
var labelMaxSize = CGSize()
if (_xAxis.isWordWrapEnabled)
{
labelMaxSize.width = _xAxis.wordWrapWidthPercent * valueToPixelMatrix.a
}
for (var i = _minX, maxX = min(_maxX + 1, _xAxis.values.count); i < maxX; i += _xAxis.axisLabelModulus)
{
let label = i >= 0 && i < _xAxis.values.count ? _xAxis.values[i] : nil
if (label == nil)
{
continue
}
position.x = CGFloat(i * step) + CGFloat(i) * barData.groupSpace + barData.groupSpace / 2.0
position.y = 0.0
// consider groups (center label for each group)
if (step > 1)
{
position.x += (CGFloat(step) - 1.0) / 2.0
}
position = CGPointApplyAffineTransform(position, valueToPixelMatrix)
if (viewPortHandler.isInBoundsX(position.x))
{
if (_xAxis.isAvoidFirstLastClippingEnabled)
{
// avoid clipping of the last
if (i == _xAxis.values.count - 1)
{
let width = label!.sizeWithAttributes(labelAttrs).width
if (width > viewPortHandler.offsetRight * 2.0
&& position.x + width > viewPortHandler.chartWidth)
{
position.x -= width / 2.0
}
}
else if (i == 0)
{ // avoid clipping of the first
let width = label!.sizeWithAttributes(labelAttrs).width
position.x += width / 2.0
}
}
drawLabel(context: context, label: label!, xIndex: i, x: position.x, y: pos, align: .Center, attributes: labelAttrs, constrainedToSize: labelMaxSize)
}
}
}
private var _gridLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderGridLines(context context: CGContext?)
{
if (!_xAxis.isDrawGridLinesEnabled || !_xAxis.isEnabled)
{
return
}
let barData = _chart.data as! BarChartData
let step = barData.dataSetCount
CGContextSaveGState(context)
CGContextSetStrokeColorWithColor(context, _xAxis.gridColor.CGColor)
CGContextSetLineWidth(context, _xAxis.gridLineWidth)
if (_xAxis.gridLineDashLengths != nil)
{
CGContextSetLineDash(context, _xAxis.gridLineDashPhase, _xAxis.gridLineDashLengths, _xAxis.gridLineDashLengths.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
let valueToPixelMatrix = transformer.valueToPixelMatrix
var position = CGPoint(x: 0.0, y: 0.0)
for (var i = _minX; i < _maxX; i += _xAxis.axisLabelModulus)
{
position.x = CGFloat(i * step) + CGFloat(i) * barData.groupSpace - 0.5
position.y = 0.0
position = CGPointApplyAffineTransform(position, valueToPixelMatrix)
if (viewPortHandler.isInBoundsX(position.x))
{
_gridLineSegmentsBuffer[0].x = position.x
_gridLineSegmentsBuffer[0].y = viewPortHandler.contentTop
_gridLineSegmentsBuffer[1].x = position.x
_gridLineSegmentsBuffer[1].y = viewPortHandler.contentBottom
CGContextStrokeLineSegments(context, _gridLineSegmentsBuffer, 2)
}
}
CGContextRestoreGState(context)
}
}

View File

@@ -1,307 +0,0 @@
//
// ChartXAxisRendererHorizontalBarChart.swift
// Charts
//
// Created by Daniel Cohen Gindi on 3/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class ChartXAxisRendererHorizontalBarChart: ChartXAxisRendererBarChart
{
public override init(viewPortHandler: ChartViewPortHandler, xAxis: ChartXAxis, transformer: ChartTransformer!, chart: BarChartView)
{
super.init(viewPortHandler: viewPortHandler, xAxis: xAxis, transformer: transformer, chart: chart)
}
public override func computeAxis(xValAverageLength xValAverageLength: Double, xValues: [String?])
{
_xAxis.values = xValues
let longest = _xAxis.getLongestLabel() as NSString
let longestSize = longest.sizeWithAttributes([NSFontAttributeName: _xAxis.labelFont])
_xAxis.labelWidth = floor(longestSize.width + _xAxis.xOffset * 3.5)
_xAxis.labelHeight = longestSize.height
}
public override func renderAxisLabels(context context: CGContext?)
{
if (!_xAxis.isEnabled || !_xAxis.isDrawLabelsEnabled || _chart.data === nil)
{
return
}
let xoffset = _xAxis.xOffset
if (_xAxis.labelPosition == .Top)
{
drawLabels(context: context, pos: viewPortHandler.contentRight + xoffset, align: .Left)
}
else if (_xAxis.labelPosition == .Bottom)
{
drawLabels(context: context, pos: viewPortHandler.contentLeft - xoffset, align: .Right)
}
else if (_xAxis.labelPosition == .BottomInside)
{
drawLabels(context: context, pos: viewPortHandler.contentLeft + xoffset, align: .Left)
}
else if (_xAxis.labelPosition == .TopInside)
{
drawLabels(context: context, pos: viewPortHandler.contentRight - xoffset, align: .Right)
}
else
{ // BOTH SIDED
drawLabels(context: context, pos: viewPortHandler.contentLeft - xoffset, align: .Right)
drawLabels(context: context, pos: viewPortHandler.contentRight + xoffset, align: .Left)
}
}
/// draws the x-labels on the specified y-position
internal func drawLabels(context context: CGContext?, pos: CGFloat, align: NSTextAlignment)
{
let labelFont = _xAxis.labelFont
let labelTextColor = _xAxis.labelTextColor
// pre allocate to save performance (dont allocate in loop)
var position = CGPoint(x: 0.0, y: 0.0)
let bd = _chart.data as! BarChartData
let step = bd.dataSetCount
for (var i = _minX, maxX = min(_maxX + 1, _xAxis.values.count); i < maxX; i += _xAxis.axisLabelModulus)
{
let label = _xAxis.values[i]
if (label == nil)
{
continue
}
position.x = 0.0
position.y = CGFloat(i * step) + CGFloat(i) * bd.groupSpace + bd.groupSpace / 2.0
// consider groups (center label for each group)
if (step > 1)
{
position.y += (CGFloat(step) - 1.0) / 2.0
}
transformer.pointValueToPixel(&position)
if (viewPortHandler.isInBoundsY(position.y))
{
drawLabel(context: context, label: label!, xIndex: i, x: pos, y: position.y - _xAxis.labelHeight / 2.0, align: align, attributes: [NSFontAttributeName: labelFont, NSForegroundColorAttributeName: labelTextColor])
}
}
}
internal func drawLabel(context context: CGContext?, label: String, xIndex: Int, x: CGFloat, y: CGFloat, align: NSTextAlignment, attributes: [String: NSObject])
{
let formattedLabel = _xAxis.valueFormatter?.stringForXValue(xIndex, original: label, viewPortHandler: viewPortHandler) ?? label
ChartUtils.drawText(context: context, text: formattedLabel, point: CGPoint(x: x, y: y), align: align, attributes: attributes)
}
private var _gridLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderGridLines(context context: CGContext?)
{
if (!_xAxis.isEnabled || !_xAxis.isDrawGridLinesEnabled || _chart.data === nil)
{
return
}
CGContextSaveGState(context)
CGContextSetStrokeColorWithColor(context, _xAxis.gridColor.CGColor)
CGContextSetLineWidth(context, _xAxis.gridLineWidth)
if (_xAxis.gridLineDashLengths != nil)
{
CGContextSetLineDash(context, _xAxis.gridLineDashPhase, _xAxis.gridLineDashLengths, _xAxis.gridLineDashLengths.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
var position = CGPoint(x: 0.0, y: 0.0)
let bd = _chart.data as! BarChartData
// take into consideration that multiple DataSets increase _deltaX
let step = bd.dataSetCount
for (var i = _minX, maxX = min(_maxX + 1, _xAxis.values.count); i < maxX; i += _xAxis.axisLabelModulus)
{
position.x = 0.0
position.y = CGFloat(i * step) + CGFloat(i) * bd.groupSpace - 0.5
transformer.pointValueToPixel(&position)
if (viewPortHandler.isInBoundsY(position.y))
{
_gridLineSegmentsBuffer[0].x = viewPortHandler.contentLeft
_gridLineSegmentsBuffer[0].y = position.y
_gridLineSegmentsBuffer[1].x = viewPortHandler.contentRight
_gridLineSegmentsBuffer[1].y = position.y
CGContextStrokeLineSegments(context, _gridLineSegmentsBuffer, 2)
}
}
CGContextRestoreGState(context)
}
private var _axisLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderAxisLine(context context: CGContext?)
{
if (!_xAxis.isEnabled || !_xAxis.isDrawAxisLineEnabled)
{
return
}
CGContextSaveGState(context)
CGContextSetStrokeColorWithColor(context, _xAxis.axisLineColor.CGColor)
CGContextSetLineWidth(context, _xAxis.axisLineWidth)
if (_xAxis.axisLineDashLengths != nil)
{
CGContextSetLineDash(context, _xAxis.axisLineDashPhase, _xAxis.axisLineDashLengths, _xAxis.axisLineDashLengths.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
if (_xAxis.labelPosition == .Top
|| _xAxis.labelPosition == .TopInside
|| _xAxis.labelPosition == .BothSided)
{
_axisLineSegmentsBuffer[0].x = viewPortHandler.contentRight
_axisLineSegmentsBuffer[0].y = viewPortHandler.contentTop
_axisLineSegmentsBuffer[1].x = viewPortHandler.contentRight
_axisLineSegmentsBuffer[1].y = viewPortHandler.contentBottom
CGContextStrokeLineSegments(context, _axisLineSegmentsBuffer, 2)
}
if (_xAxis.labelPosition == .Bottom
|| _xAxis.labelPosition == .BottomInside
|| _xAxis.labelPosition == .BothSided)
{
_axisLineSegmentsBuffer[0].x = viewPortHandler.contentLeft
_axisLineSegmentsBuffer[0].y = viewPortHandler.contentTop
_axisLineSegmentsBuffer[1].x = viewPortHandler.contentLeft
_axisLineSegmentsBuffer[1].y = viewPortHandler.contentBottom
CGContextStrokeLineSegments(context, _axisLineSegmentsBuffer, 2)
}
CGContextRestoreGState(context)
}
private var _limitLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderLimitLines(context context: CGContext?)
{
var limitLines = _xAxis.limitLines
if (limitLines.count == 0)
{
return
}
CGContextSaveGState(context)
let trans = transformer.valueToPixelMatrix
var position = CGPoint(x: 0.0, y: 0.0)
for (var i = 0; i < limitLines.count; i++)
{
let l = limitLines[i]
position.x = 0.0
position.y = CGFloat(l.limit)
position = CGPointApplyAffineTransform(position, trans)
_limitLineSegmentsBuffer[0].x = viewPortHandler.contentLeft
_limitLineSegmentsBuffer[0].y = position.y
_limitLineSegmentsBuffer[1].x = viewPortHandler.contentRight
_limitLineSegmentsBuffer[1].y = position.y
CGContextSetStrokeColorWithColor(context, l.lineColor.CGColor)
CGContextSetLineWidth(context, l.lineWidth)
if (l.lineDashLengths != nil)
{
CGContextSetLineDash(context, l.lineDashPhase, l.lineDashLengths!, l.lineDashLengths!.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
CGContextStrokeLineSegments(context, _limitLineSegmentsBuffer, 2)
let label = l.label
// if drawing the limit-value label is enabled
if (label.characters.count > 0)
{
let labelLineHeight = l.valueFont.lineHeight
let add = CGFloat(4.0)
let xOffset: CGFloat = add
let yOffset: CGFloat = l.lineWidth + labelLineHeight
if (l.labelPosition == .RightTop)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: viewPortHandler.contentRight - xOffset,
y: position.y - yOffset),
align: .Right,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else if (l.labelPosition == .RightBottom)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: viewPortHandler.contentRight - xOffset,
y: position.y + yOffset - labelLineHeight),
align: .Right,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else if (l.labelPosition == .LeftTop)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: viewPortHandler.contentLeft + xOffset,
y: position.y - yOffset),
align: .Left,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: viewPortHandler.contentLeft + xOffset,
y: position.y + yOffset - labelLineHeight),
align: .Left,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
}
}
CGContextRestoreGState(context)
}
}

View File

@@ -1,74 +0,0 @@
//
// ChartXAxisRendererRadarChart.swift
// Charts
//
// Created by Daniel Cohen Gindi on 3/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class ChartXAxisRendererRadarChart: ChartXAxisRenderer
{
private weak var _chart: RadarChartView!
public init(viewPortHandler: ChartViewPortHandler, xAxis: ChartXAxis, chart: RadarChartView)
{
super.init(viewPortHandler: viewPortHandler, xAxis: xAxis, transformer: nil)
_chart = chart
}
public override func renderAxisLabels(context context: CGContext?)
{
if (!_xAxis.isEnabled || !_xAxis.isDrawLabelsEnabled)
{
return
}
let labelFont = _xAxis.labelFont
let labelTextColor = _xAxis.labelTextColor
let sliceangle = _chart.sliceAngle
// calculate the factor that is needed for transforming the value to pixels
let factor = _chart.factor
let center = _chart.centerOffsets
let modulus = _xAxis.axisLabelModulus
for var i = 0, count = _xAxis.values.count; i < count; i += modulus
{
let label = _xAxis.values[i]
if (label == nil)
{
continue
}
let angle = (sliceangle * CGFloat(i) + _chart.rotationAngle) % 360.0
let p = ChartUtils.getPosition(center: center, dist: CGFloat(_chart.yRange) * factor + _xAxis.labelWidth / 2.0, angle: angle)
drawLabel(context: context, label: label!, xIndex: i, x: p.x, y: p.y - _xAxis.labelHeight / 2.0, align: .Center, attributes: [NSFontAttributeName: labelFont, NSForegroundColorAttributeName: labelTextColor])
}
}
internal func drawLabel(context context: CGContext?, label: String, xIndex: Int, x: CGFloat, y: CGFloat, align: NSTextAlignment, attributes: [String: NSObject])
{
let formattedLabel = _xAxis.valueFormatter?.stringForXValue(xIndex, original: label, viewPortHandler: viewPortHandler) ?? label
ChartUtils.drawText(context: context, text: formattedLabel, point: CGPoint(x: x, y: y), align: align, attributes: attributes)
}
public override func renderLimitLines(context context: CGContext?)
{
/// XAxis LimitLines on RadarChart not yet supported.
}
}

View File

@@ -1,409 +0,0 @@
//
// ChartYAxisRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 3/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class ChartYAxisRenderer: ChartAxisRendererBase
{
internal var _yAxis: ChartYAxis!
public init(viewPortHandler: ChartViewPortHandler, yAxis: ChartYAxis, transformer: ChartTransformer!)
{
super.init(viewPortHandler: viewPortHandler, transformer: transformer)
_yAxis = yAxis
}
/// Computes the axis values.
public func computeAxis(var yMin yMin: Double, var yMax: Double)
{
// calculate the starting and entry point of the y-labels (depending on
// zoom / contentrect bounds)
if (viewPortHandler.contentWidth > 10.0 && !viewPortHandler.isFullyZoomedOutY)
{
let p1 = transformer.getValueByTouchPoint(CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop))
let p2 = transformer.getValueByTouchPoint(CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentBottom))
if (!_yAxis.isInverted)
{
yMin = Double(p2.y)
yMax = Double(p1.y)
}
else
{
yMin = Double(p1.y)
yMax = Double(p2.y)
}
}
computeAxisValues(min: yMin, max: yMax)
}
/// Sets up the y-axis labels. Computes the desired number of labels between
/// the two given extremes. Unlike the papareXLabels() method, this method
/// needs to be called upon every refresh of the view.
internal func computeAxisValues(min min: Double, max: Double)
{
let yMin = min
let yMax = max
let labelCount = _yAxis.labelCount
let range = abs(yMax - yMin)
if (labelCount == 0 || range <= 0)
{
_yAxis.entries = [Double]()
return
}
let rawInterval = range / Double(labelCount)
var interval = ChartUtils.roundToNextSignificant(number: Double(rawInterval))
let intervalMagnitude = pow(10.0, round(log10(interval)))
let intervalSigDigit = (interval / intervalMagnitude)
if (intervalSigDigit > 5)
{
// Use one order of magnitude higher, to avoid intervals like 0.9 or 90
interval = floor(10.0 * intervalMagnitude)
}
// force label count
if _yAxis.isForceLabelsEnabled
{
let step = Double(range) / Double(labelCount - 1)
if _yAxis.entries.count < labelCount
{
// Ensure stops contains at least numStops elements.
_yAxis.entries.removeAll(keepCapacity: true)
}
else
{
_yAxis.entries = [Double]()
_yAxis.entries.reserveCapacity(labelCount)
}
var v = yMin
for (var i = 0; i < labelCount; i++)
{
_yAxis.entries.append(v)
v += step
}
}
else
{
// no forced count
// if the labels should only show min and max
if (_yAxis.isShowOnlyMinMaxEnabled)
{
_yAxis.entries = [yMin, yMax]
}
else
{
let first = ceil(Double(yMin) / interval) * interval
let last = ChartUtils.nextUp(floor(Double(yMax) / interval) * interval)
var f: Double
var i: Int
var n = 0
for (f = first; f <= last; f += interval)
{
++n
}
if (_yAxis.entries.count < n)
{
// Ensure stops contains at least numStops elements.
_yAxis.entries = [Double](count: n, repeatedValue: 0.0)
}
else if (_yAxis.entries.count > n)
{
_yAxis.entries.removeRange(n..<_yAxis.entries.count)
}
for (f = first, i = 0; i < n; f += interval, ++i)
{
_yAxis.entries[i] = Double(f)
}
}
}
}
/// draws the y-axis labels to the screen
public override func renderAxisLabels(context context: CGContext?)
{
if (!_yAxis.isEnabled || !_yAxis.isDrawLabelsEnabled)
{
return
}
let xoffset = _yAxis.xOffset
let yoffset = _yAxis.labelFont.lineHeight / 2.5 + _yAxis.yOffset
let dependency = _yAxis.axisDependency
let labelPosition = _yAxis.labelPosition
var xPos = CGFloat(0.0)
var textAlign: NSTextAlignment
if (dependency == .Left)
{
if (labelPosition == .OutsideChart)
{
textAlign = .Right
xPos = viewPortHandler.offsetLeft - xoffset
}
else
{
textAlign = .Left
xPos = viewPortHandler.offsetLeft + xoffset
}
}
else
{
if (labelPosition == .OutsideChart)
{
textAlign = .Left
xPos = viewPortHandler.contentRight + xoffset
}
else
{
textAlign = .Right
xPos = viewPortHandler.contentRight - xoffset
}
}
drawYLabels(context: context, fixedPosition: xPos, offset: yoffset - _yAxis.labelFont.lineHeight, textAlign: textAlign)
}
private var _axisLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderAxisLine(context context: CGContext?)
{
if (!_yAxis.isEnabled || !_yAxis.drawAxisLineEnabled)
{
return
}
CGContextSaveGState(context)
CGContextSetStrokeColorWithColor(context, _yAxis.axisLineColor.CGColor)
CGContextSetLineWidth(context, _yAxis.axisLineWidth)
if (_yAxis.axisLineDashLengths != nil)
{
CGContextSetLineDash(context, _yAxis.axisLineDashPhase, _yAxis.axisLineDashLengths, _yAxis.axisLineDashLengths.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
if (_yAxis.axisDependency == .Left)
{
_axisLineSegmentsBuffer[0].x = viewPortHandler.contentLeft
_axisLineSegmentsBuffer[0].y = viewPortHandler.contentTop
_axisLineSegmentsBuffer[1].x = viewPortHandler.contentLeft
_axisLineSegmentsBuffer[1].y = viewPortHandler.contentBottom
CGContextStrokeLineSegments(context, _axisLineSegmentsBuffer, 2)
}
else
{
_axisLineSegmentsBuffer[0].x = viewPortHandler.contentRight
_axisLineSegmentsBuffer[0].y = viewPortHandler.contentTop
_axisLineSegmentsBuffer[1].x = viewPortHandler.contentRight
_axisLineSegmentsBuffer[1].y = viewPortHandler.contentBottom
CGContextStrokeLineSegments(context, _axisLineSegmentsBuffer, 2)
}
CGContextRestoreGState(context)
}
/// draws the y-labels on the specified x-position
internal func drawYLabels(context context: CGContext?, fixedPosition: CGFloat, offset: CGFloat, textAlign: NSTextAlignment)
{
let labelFont = _yAxis.labelFont
let labelTextColor = _yAxis.labelTextColor
let valueToPixelMatrix = transformer.valueToPixelMatrix
var pt = CGPoint()
for (var i = 0; i < _yAxis.entryCount; i++)
{
let text = _yAxis.getFormattedLabel(i)
if (!_yAxis.isDrawTopYLabelEntryEnabled && i >= _yAxis.entryCount - 1)
{
break
}
pt.x = 0
pt.y = CGFloat(_yAxis.entries[i])
pt = CGPointApplyAffineTransform(pt, valueToPixelMatrix)
pt.x = fixedPosition
pt.y += offset
ChartUtils.drawText(context: context, text: text, point: pt, align: textAlign, attributes: [NSFontAttributeName: labelFont, NSForegroundColorAttributeName: labelTextColor])
}
}
private var _gridLineBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderGridLines(context context: CGContext?)
{
if (!_yAxis.isDrawGridLinesEnabled || !_yAxis.isEnabled)
{
return
}
CGContextSaveGState(context)
CGContextSetStrokeColorWithColor(context, _yAxis.gridColor.CGColor)
CGContextSetLineWidth(context, _yAxis.gridLineWidth)
if (_yAxis.gridLineDashLengths != nil)
{
CGContextSetLineDash(context, _yAxis.gridLineDashPhase, _yAxis.gridLineDashLengths, _yAxis.gridLineDashLengths.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
let valueToPixelMatrix = transformer.valueToPixelMatrix
var position = CGPoint(x: 0.0, y: 0.0)
// draw the horizontal grid
for (var i = 0, count = _yAxis.entryCount; i < count; i++)
{
position.x = 0.0
position.y = CGFloat(_yAxis.entries[i])
position = CGPointApplyAffineTransform(position, valueToPixelMatrix)
_gridLineBuffer[0].x = viewPortHandler.contentLeft
_gridLineBuffer[0].y = position.y
_gridLineBuffer[1].x = viewPortHandler.contentRight
_gridLineBuffer[1].y = position.y
CGContextStrokeLineSegments(context, _gridLineBuffer, 2)
}
CGContextRestoreGState(context)
}
private var _limitLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderLimitLines(context context: CGContext?)
{
var limitLines = _yAxis.limitLines
if (limitLines.count == 0)
{
return
}
CGContextSaveGState(context)
let trans = transformer.valueToPixelMatrix
var position = CGPoint(x: 0.0, y: 0.0)
for (var i = 0; i < limitLines.count; i++)
{
let l = limitLines[i]
position.x = 0.0
position.y = CGFloat(l.limit)
position = CGPointApplyAffineTransform(position, trans)
_limitLineSegmentsBuffer[0].x = viewPortHandler.contentLeft
_limitLineSegmentsBuffer[0].y = position.y
_limitLineSegmentsBuffer[1].x = viewPortHandler.contentRight
_limitLineSegmentsBuffer[1].y = position.y
CGContextSetStrokeColorWithColor(context, l.lineColor.CGColor)
CGContextSetLineWidth(context, l.lineWidth)
if (l.lineDashLengths != nil)
{
CGContextSetLineDash(context, l.lineDashPhase, l.lineDashLengths!, l.lineDashLengths!.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
CGContextStrokeLineSegments(context, _limitLineSegmentsBuffer, 2)
let label = l.label
// if drawing the limit-value label is enabled
if (label.characters.count > 0)
{
let labelLineHeight = l.valueFont.lineHeight
let add = CGFloat(4.0)
let xOffset: CGFloat = add
let yOffset: CGFloat = l.lineWidth + labelLineHeight
if (l.labelPosition == .RightTop)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: viewPortHandler.contentRight - xOffset,
y: position.y - yOffset),
align: .Right,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else if (l.labelPosition == .RightBottom)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: viewPortHandler.contentRight - xOffset,
y: position.y + yOffset - labelLineHeight),
align: .Right,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else if (l.labelPosition == .LeftTop)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: viewPortHandler.contentLeft + xOffset,
y: position.y - yOffset),
align: .Left,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: viewPortHandler.contentLeft + xOffset,
y: position.y + yOffset - labelLineHeight),
align: .Left,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
}
}
CGContextRestoreGState(context)
}
}

View File

@@ -1,304 +0,0 @@
//
// ChartYAxisRendererHorizontalBarChart.swift
// Charts
//
// Created by Daniel Cohen Gindi on 3/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class ChartYAxisRendererHorizontalBarChart: ChartYAxisRenderer
{
public override init(viewPortHandler: ChartViewPortHandler, yAxis: ChartYAxis, transformer: ChartTransformer!)
{
super.init(viewPortHandler: viewPortHandler, yAxis: yAxis, transformer: transformer)
}
/// Computes the axis values.
public override func computeAxis(var yMin yMin: Double, var yMax: Double)
{
// calculate the starting and entry point of the y-labels (depending on zoom / contentrect bounds)
if (viewPortHandler.contentHeight > 10.0 && !viewPortHandler.isFullyZoomedOutX)
{
let p1 = transformer.getValueByTouchPoint(CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop))
let p2 = transformer.getValueByTouchPoint(CGPoint(x: viewPortHandler.contentRight, y: viewPortHandler.contentTop))
if (!_yAxis.isInverted)
{
yMin = Double(p1.x)
yMax = Double(p2.x)
}
else
{
yMin = Double(p2.x)
yMax = Double(p1.x)
}
}
computeAxisValues(min: yMin, max: yMax)
}
/// draws the y-axis labels to the screen
public override func renderAxisLabels(context context: CGContext?)
{
if (!_yAxis.isEnabled || !_yAxis.isDrawLabelsEnabled)
{
return
}
var positions = [CGPoint]()
positions.reserveCapacity(_yAxis.entries.count)
for (var i = 0; i < _yAxis.entries.count; i++)
{
positions.append(CGPoint(x: CGFloat(_yAxis.entries[i]), y: 0.0))
}
transformer.pointValuesToPixel(&positions)
let lineHeight = _yAxis.labelFont.lineHeight
let baseYOffset: CGFloat = 2.5
let dependency = _yAxis.axisDependency
let labelPosition = _yAxis.labelPosition
var yPos: CGFloat = 0.0
if (dependency == .Left)
{
if (labelPosition == .OutsideChart)
{
yPos = viewPortHandler.contentTop - baseYOffset
}
else
{
yPos = viewPortHandler.contentTop - baseYOffset
}
}
else
{
if (labelPosition == .OutsideChart)
{
yPos = viewPortHandler.contentBottom + lineHeight + baseYOffset
}
else
{
yPos = viewPortHandler.contentBottom + lineHeight + baseYOffset
}
}
// For compatibility with Android code, we keep above calculation the same,
// And here we pull the line back up
yPos -= lineHeight
drawYLabels(context: context, fixedPosition: yPos, positions: positions, offset: _yAxis.yOffset)
}
private var _axisLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderAxisLine(context context: CGContext?)
{
if (!_yAxis.isEnabled || !_yAxis.drawAxisLineEnabled)
{
return
}
CGContextSaveGState(context)
CGContextSetStrokeColorWithColor(context, _yAxis.axisLineColor.CGColor)
CGContextSetLineWidth(context, _yAxis.axisLineWidth)
if (_yAxis.axisLineDashLengths != nil)
{
CGContextSetLineDash(context, _yAxis.axisLineDashPhase, _yAxis.axisLineDashLengths, _yAxis.axisLineDashLengths.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
if (_yAxis.axisDependency == .Left)
{
_axisLineSegmentsBuffer[0].x = viewPortHandler.contentLeft
_axisLineSegmentsBuffer[0].y = viewPortHandler.contentTop
_axisLineSegmentsBuffer[1].x = viewPortHandler.contentRight
_axisLineSegmentsBuffer[1].y = viewPortHandler.contentTop
CGContextStrokeLineSegments(context, _axisLineSegmentsBuffer, 2)
}
else
{
_axisLineSegmentsBuffer[0].x = viewPortHandler.contentLeft
_axisLineSegmentsBuffer[0].y = viewPortHandler.contentBottom
_axisLineSegmentsBuffer[1].x = viewPortHandler.contentRight
_axisLineSegmentsBuffer[1].y = viewPortHandler.contentBottom
CGContextStrokeLineSegments(context, _axisLineSegmentsBuffer, 2)
}
CGContextRestoreGState(context)
}
/// draws the y-labels on the specified x-position
internal func drawYLabels(context context: CGContext?, fixedPosition: CGFloat, positions: [CGPoint], offset: CGFloat)
{
let labelFont = _yAxis.labelFont
let labelTextColor = _yAxis.labelTextColor
for (var i = 0; i < _yAxis.entryCount; i++)
{
let text = _yAxis.getFormattedLabel(i)
if (!_yAxis.isDrawTopYLabelEntryEnabled && i >= _yAxis.entryCount - 1)
{
return
}
ChartUtils.drawText(context: context, text: text, point: CGPoint(x: positions[i].x, y: fixedPosition - offset), align: .Center, attributes: [NSFontAttributeName: labelFont, NSForegroundColorAttributeName: labelTextColor])
}
}
public override func renderGridLines(context context: CGContext?)
{
if (!_yAxis.isEnabled || !_yAxis.isDrawGridLinesEnabled)
{
return
}
CGContextSaveGState(context)
// pre alloc
var position = CGPoint()
CGContextSetStrokeColorWithColor(context, _yAxis.gridColor.CGColor)
CGContextSetLineWidth(context, _yAxis.gridLineWidth)
if (_yAxis.gridLineDashLengths != nil)
{
CGContextSetLineDash(context, _yAxis.gridLineDashPhase, _yAxis.gridLineDashLengths, _yAxis.gridLineDashLengths.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
// draw the horizontal grid
for (var i = 0; i < _yAxis.entryCount; i++)
{
position.x = CGFloat(_yAxis.entries[i])
position.y = 0.0
transformer.pointValueToPixel(&position)
CGContextBeginPath(context)
CGContextMoveToPoint(context, position.x, viewPortHandler.contentTop)
CGContextAddLineToPoint(context, position.x, viewPortHandler.contentBottom)
CGContextStrokePath(context)
}
CGContextRestoreGState(context)
}
private var _limitLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
public override func renderLimitLines(context context: CGContext?)
{
var limitLines = _yAxis.limitLines
if (limitLines.count <= 0)
{
return
}
CGContextSaveGState(context)
let trans = transformer.valueToPixelMatrix
var position = CGPoint(x: 0.0, y: 0.0)
for (var i = 0; i < limitLines.count; i++)
{
let l = limitLines[i]
position.x = CGFloat(l.limit)
position.y = 0.0
position = CGPointApplyAffineTransform(position, trans)
_limitLineSegmentsBuffer[0].x = position.x
_limitLineSegmentsBuffer[0].y = viewPortHandler.contentTop
_limitLineSegmentsBuffer[1].x = position.x
_limitLineSegmentsBuffer[1].y = viewPortHandler.contentBottom
CGContextSetStrokeColorWithColor(context, l.lineColor.CGColor)
CGContextSetLineWidth(context, l.lineWidth)
if (l.lineDashLengths != nil)
{
CGContextSetLineDash(context, l.lineDashPhase, l.lineDashLengths!, l.lineDashLengths!.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
CGContextStrokeLineSegments(context, _limitLineSegmentsBuffer, 2)
let label = l.label
// if drawing the limit-value label is enabled
if (label.characters.count > 0)
{
let labelLineHeight = l.valueFont.lineHeight
let add = CGFloat(4.0)
let xOffset: CGFloat = l.lineWidth
let yOffset: CGFloat = add / 2.0
if (l.labelPosition == .RightTop)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: position.x + xOffset,
y: viewPortHandler.contentTop + yOffset),
align: .Left,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else if (l.labelPosition == .RightBottom)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: position.x + xOffset,
y: viewPortHandler.contentBottom - labelLineHeight - yOffset),
align: .Left,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else if (l.labelPosition == .LeftTop)
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: position.x - xOffset,
y: viewPortHandler.contentTop + yOffset),
align: .Right,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
else
{
ChartUtils.drawText(context: context,
text: label,
point: CGPoint(
x: position.x - xOffset,
y: viewPortHandler.contentBottom - labelLineHeight - yOffset),
align: .Right,
attributes: [NSFontAttributeName: l.valueFont, NSForegroundColorAttributeName: l.valueTextColor])
}
}
}
CGContextRestoreGState(context)
}
}

View File

@@ -1,244 +0,0 @@
//
// ChartYAxisRendererRadarChart.swift
// Charts
//
// Created by Daniel Cohen Gindi on 3/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class ChartYAxisRendererRadarChart: ChartYAxisRenderer
{
private weak var _chart: RadarChartView!
public init(viewPortHandler: ChartViewPortHandler, yAxis: ChartYAxis, chart: RadarChartView)
{
super.init(viewPortHandler: viewPortHandler, yAxis: yAxis, transformer: nil)
_chart = chart
}
public override func computeAxis(yMin yMin: Double, yMax: Double)
{
computeAxisValues(min: yMin, max: yMax)
}
internal override func computeAxisValues(min yMin: Double, max yMax: Double)
{
let labelCount = _yAxis.labelCount
let range = abs(yMax - yMin)
if (labelCount == 0 || range <= 0)
{
_yAxis.entries = [Double]()
return
}
let rawInterval = range / Double(labelCount)
var interval = ChartUtils.roundToNextSignificant(number: Double(rawInterval))
let intervalMagnitude = pow(10.0, round(log10(interval)))
let intervalSigDigit = Int(interval / intervalMagnitude)
if (intervalSigDigit > 5)
{
// Use one order of magnitude higher, to avoid intervals like 0.9 or
// 90
interval = floor(10 * intervalMagnitude)
}
// force label count
if _yAxis.isForceLabelsEnabled
{
let step = Double(range) / Double(labelCount - 1)
if _yAxis.entries.count < labelCount
{
// Ensure stops contains at least numStops elements.
_yAxis.entries.removeAll(keepCapacity: true)
}
else
{
_yAxis.entries = [Double]()
_yAxis.entries.reserveCapacity(labelCount)
}
var v = yMin
for (var i = 0; i < labelCount; i++)
{
_yAxis.entries.append(v)
v += step
}
}
else
{
// no forced count
// clean old values
if (_yAxis.entries.count > 0)
{
_yAxis.entries.removeAll(keepCapacity: false)
}
// if the labels should only show min and max
if (_yAxis.isShowOnlyMinMaxEnabled)
{
_yAxis.entries = [Double]()
_yAxis.entries.append(yMin)
_yAxis.entries.append(yMax)
}
else
{
let rawCount = Double(yMin) / interval
var first = rawCount < 0.0 ? floor(rawCount) * interval : ceil(rawCount) * interval;
if (first < yMin && _yAxis.isStartAtZeroEnabled)
{ // Force the first label to be at the 0 (or smallest negative value)
first = yMin
}
if (first == 0.0)
{ // Fix for IEEE negative zero case (Where value == -0.0, and 0.0 == -0.0)
first = 0.0
}
let last = ChartUtils.nextUp(floor(Double(yMax) / interval) * interval)
var f: Double
var i: Int
var n = 0
for (f = first; f <= last; f += interval)
{
++n
}
if (isnan(_yAxis.customAxisMax))
{
n += 1
}
if (_yAxis.entries.count < n)
{
// Ensure stops contains at least numStops elements.
_yAxis.entries = [Double](count: n, repeatedValue: 0.0)
}
for (f = first, i = 0; i < n; f += interval, ++i)
{
_yAxis.entries[i] = Double(f)
}
}
}
if !_yAxis.isStartAtZeroEnabled && _yAxis.entries[0] < yMin
{
// If startAtZero is disabled, and the first label is lower that the axis minimum,
// Then adjust the axis minimum
_yAxis.axisMinimum = _yAxis.entries[0]
}
_yAxis.axisMaximum = _yAxis.entries[_yAxis.entryCount - 1]
_yAxis.axisRange = abs(_yAxis.axisMaximum - _yAxis.axisMinimum)
}
public override func renderAxisLabels(context context: CGContext?)
{
if (!_yAxis.isEnabled || !_yAxis.isDrawLabelsEnabled)
{
return
}
let labelFont = _yAxis.labelFont
let labelTextColor = _yAxis.labelTextColor
let center = _chart.centerOffsets
let factor = _chart.factor
let labelCount = _yAxis.entryCount
let labelLineHeight = _yAxis.labelFont.lineHeight
for (var j = 0; j < labelCount; j++)
{
if (j == labelCount - 1 && _yAxis.isDrawTopYLabelEntryEnabled == false)
{
break
}
let r = CGFloat(_yAxis.entries[j] - _yAxis.axisMinimum) * factor
let p = ChartUtils.getPosition(center: center, dist: r, angle: _chart.rotationAngle)
let label = _yAxis.getFormattedLabel(j)
ChartUtils.drawText(context: context, text: label, point: CGPoint(x: p.x + 10.0, y: p.y - labelLineHeight), align: .Left, attributes: [NSFontAttributeName: labelFont, NSForegroundColorAttributeName: labelTextColor])
}
}
public override func renderLimitLines(context context: CGContext?)
{
var limitLines = _yAxis.limitLines
if (limitLines.count == 0)
{
return
}
CGContextSaveGState(context)
let sliceangle = _chart.sliceAngle
// calculate the factor that is needed for transforming the value to pixels
let factor = _chart.factor
let center = _chart.centerOffsets
for (var i = 0; i < limitLines.count; i++)
{
let l = limitLines[i]
CGContextSetStrokeColorWithColor(context, l.lineColor.CGColor)
CGContextSetLineWidth(context, l.lineWidth)
if (l.lineDashLengths != nil)
{
CGContextSetLineDash(context, l.lineDashPhase, l.lineDashLengths!, l.lineDashLengths!.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
let r = CGFloat(l.limit - _chart.chartYMin) * factor
CGContextBeginPath(context)
for (var j = 0, count = _chart.data!.xValCount; j < count; j++)
{
let p = ChartUtils.getPosition(center: center, dist: r, angle: sliceangle * CGFloat(j) + _chart.rotationAngle)
if (j == 0)
{
CGContextMoveToPoint(context, p.x, p.y)
}
else
{
CGContextAddLineToPoint(context, p.x, p.y)
}
}
CGContextClosePath(context)
CGContextStrokePath(context)
}
CGContextRestoreGState(context)
}
}

View File

@@ -1,424 +0,0 @@
//
// CombinedChartRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
public class CombinedChartRenderer: ChartDataRendererBase,
LineChartRendererDelegate,
BarChartRendererDelegate,
ScatterChartRendererDelegate,
CandleStickChartRendererDelegate,
BubbleChartRendererDelegate
{
private weak var _chart: CombinedChartView!
/// flag that enables or disables the highlighting arrow
public var drawHighlightArrowEnabled = false
/// if set to true, all values are drawn above their bars, instead of below their top
public var drawValueAboveBarEnabled = true
/// if set to true, a grey area is darawn behind each bar that indicates the maximum value
public var drawBarShadowEnabled = true
internal var _renderers = [ChartDataRendererBase]()
internal var _drawOrder: [CombinedChartView.CombinedChartDrawOrder] = [.Bar, .Bubble, .Line, .Candle, .Scatter]
public init(chart: CombinedChartView, animator: ChartAnimator, viewPortHandler: ChartViewPortHandler)
{
super.init(animator: animator, viewPortHandler: viewPortHandler)
_chart = chart
createRenderers()
}
/// Creates the renderers needed for this combined-renderer in the required order. Also takes the DrawOrder into consideration.
internal func createRenderers()
{
_renderers = [ChartDataRendererBase]()
for order in drawOrder
{
switch (order)
{
case .Bar:
if (_chart.barData !== nil)
{
_renderers.append(BarChartRenderer(delegate: self, animator: _animator, viewPortHandler: viewPortHandler))
}
break
case .Line:
if (_chart.lineData !== nil)
{
_renderers.append(LineChartRenderer(delegate: self, animator: _animator, viewPortHandler: viewPortHandler))
}
break
case .Candle:
if (_chart.candleData !== nil)
{
_renderers.append(CandleStickChartRenderer(delegate: self, animator: _animator, viewPortHandler: viewPortHandler))
}
break
case .Scatter:
if (_chart.scatterData !== nil)
{
_renderers.append(ScatterChartRenderer(delegate: self, animator: _animator, viewPortHandler: viewPortHandler))
}
break
case .Bubble:
if (_chart.bubbleData !== nil)
{
_renderers.append(BubbleChartRenderer(delegate: self, animator: _animator, viewPortHandler: viewPortHandler))
}
break
}
}
}
public override func drawData(context context: CGContext?)
{
for renderer in _renderers
{
renderer.drawData(context: context)
}
}
public override func drawValues(context context: CGContext?)
{
for renderer in _renderers
{
renderer.drawValues(context: context)
}
}
public override func drawExtras(context context: CGContext?)
{
for renderer in _renderers
{
renderer.drawExtras(context: context)
}
}
public override func drawHighlighted(context context: CGContext?, indices: [ChartHighlight])
{
for renderer in _renderers
{
renderer.drawHighlighted(context: context, indices: indices)
}
}
public override func calcXBounds(chart chart: BarLineChartViewBase, xAxisModulus: Int)
{
for renderer in _renderers
{
renderer.calcXBounds(chart: chart, xAxisModulus: xAxisModulus)
}
}
/// - returns: the sub-renderer object at the specified index.
public func getSubRenderer(index index: Int) -> ChartDataRendererBase?
{
if (index >= _renderers.count || index < 0)
{
return nil
}
else
{
return _renderers[index]
}
}
/// Returns all sub-renderers.
public var subRenderers: [ChartDataRendererBase]
{
get { return _renderers }
set { _renderers = newValue }
}
// MARK: - LineChartRendererDelegate
public func lineChartRendererData(renderer: LineChartRenderer) -> LineChartData!
{
return _chart.lineData
}
public func lineChartRenderer(renderer: LineChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
{
return _chart.getTransformer(which)
}
public func lineChartRendererFillFormatter(renderer: LineChartRenderer) -> ChartFillFormatter
{
return _chart.fillFormatter
}
public func lineChartDefaultRendererValueFormatter(renderer: LineChartRenderer) -> NSNumberFormatter!
{
return _chart._defaultValueFormatter
}
public func lineChartRendererChartYMax(renderer: LineChartRenderer) -> Double
{
return _chart.chartYMax
}
public func lineChartRendererChartYMin(renderer: LineChartRenderer) -> Double
{
return _chart.chartYMin
}
public func lineChartRendererChartXMax(renderer: LineChartRenderer) -> Double
{
return _chart.chartXMax
}
public func lineChartRendererChartXMin(renderer: LineChartRenderer) -> Double
{
return _chart.chartXMin
}
public func lineChartRendererMaxVisibleValueCount(renderer: LineChartRenderer) -> Int
{
return _chart.maxVisibleValueCount
}
// MARK: - BarChartRendererDelegate
public func barChartRendererData(renderer: BarChartRenderer) -> BarChartData!
{
return _chart.barData
}
public func barChartRenderer(renderer: BarChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
{
return _chart.getTransformer(which)
}
public func barChartRendererMaxVisibleValueCount(renderer: BarChartRenderer) -> Int
{
return _chart.maxVisibleValueCount
}
public func barChartDefaultRendererValueFormatter(renderer: BarChartRenderer) -> NSNumberFormatter!
{
return _chart._defaultValueFormatter
}
public func barChartRendererChartYMax(renderer: BarChartRenderer) -> Double
{
return _chart.chartYMax
}
public func barChartRendererChartYMin(renderer: BarChartRenderer) -> Double
{
return _chart.chartYMin
}
public func barChartRendererChartXMax(renderer: BarChartRenderer) -> Double
{
return _chart.chartXMax
}
public func barChartRendererChartXMin(renderer: BarChartRenderer) -> Double
{
return _chart.chartXMin
}
public func barChartIsDrawHighlightArrowEnabled(renderer: BarChartRenderer) -> Bool
{
return drawHighlightArrowEnabled
}
public func barChartIsDrawValueAboveBarEnabled(renderer: BarChartRenderer) -> Bool
{
return drawValueAboveBarEnabled
}
public func barChartIsDrawBarShadowEnabled(renderer: BarChartRenderer) -> Bool
{
return drawBarShadowEnabled
}
public func barChartIsInverted(renderer: BarChartRenderer, axis: ChartYAxis.AxisDependency) -> Bool
{
return _chart.getAxis(axis).isInverted
}
// MARK: - ScatterChartRendererDelegate
public func scatterChartRendererData(renderer: ScatterChartRenderer) -> ScatterChartData!
{
return _chart.scatterData
}
public func scatterChartRenderer(renderer: ScatterChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
{
return _chart.getTransformer(which)
}
public func scatterChartDefaultRendererValueFormatter(renderer: ScatterChartRenderer) -> NSNumberFormatter!
{
return _chart._defaultValueFormatter
}
public func scatterChartRendererChartYMax(renderer: ScatterChartRenderer) -> Double
{
return _chart.chartYMax
}
public func scatterChartRendererChartYMin(renderer: ScatterChartRenderer) -> Double
{
return _chart.chartYMin
}
public func scatterChartRendererChartXMax(renderer: ScatterChartRenderer) -> Double
{
return _chart.chartXMax
}
public func scatterChartRendererChartXMin(renderer: ScatterChartRenderer) -> Double
{
return _chart.chartXMin
}
public func scatterChartRendererMaxVisibleValueCount(renderer: ScatterChartRenderer) -> Int
{
return _chart.maxVisibleValueCount
}
// MARK: - CandleStickChartRendererDelegate
public func candleStickChartRendererCandleData(renderer: CandleStickChartRenderer) -> CandleChartData!
{
return _chart.candleData
}
public func candleStickChartRenderer(renderer: CandleStickChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
{
return _chart.getTransformer(which)
}
public func candleStickChartDefaultRendererValueFormatter(renderer: CandleStickChartRenderer) -> NSNumberFormatter!
{
return _chart._defaultValueFormatter
}
public func candleStickChartRendererChartYMax(renderer: CandleStickChartRenderer) -> Double
{
return _chart.chartYMax
}
public func candleStickChartRendererChartYMin(renderer: CandleStickChartRenderer) -> Double
{
return _chart.chartYMin
}
public func candleStickChartRendererChartXMax(renderer: CandleStickChartRenderer) -> Double
{
return _chart.chartXMax
}
public func candleStickChartRendererChartXMin(renderer: CandleStickChartRenderer) -> Double
{
return _chart.chartXMin
}
public func candleStickChartRendererMaxVisibleValueCount(renderer: CandleStickChartRenderer) -> Int
{
return _chart.maxVisibleValueCount
}
// MARK: - BubbleChartRendererDelegate
public func bubbleChartRendererData(renderer: BubbleChartRenderer) -> BubbleChartData!
{
return _chart.bubbleData
}
public func bubbleChartRenderer(renderer: BubbleChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
{
return _chart.getTransformer(which)
}
public func bubbleChartDefaultRendererValueFormatter(renderer: BubbleChartRenderer) -> NSNumberFormatter!
{
return _chart._defaultValueFormatter
}
public func bubbleChartRendererChartYMax(renderer: BubbleChartRenderer) -> Double
{
return _chart.chartYMax
}
public func bubbleChartRendererChartYMin(renderer: BubbleChartRenderer) -> Double
{
return _chart.chartYMin
}
public func bubbleChartRendererChartXMax(renderer: BubbleChartRenderer) -> Double
{
return _chart.chartXMax
}
public func bubbleChartRendererChartXMin(renderer: BubbleChartRenderer) -> Double
{
return _chart.chartXMin
}
public func bubbleChartRendererMaxVisibleValueCount(renderer: BubbleChartRenderer) -> Int
{
return _chart.maxVisibleValueCount
}
public func bubbleChartRendererXValCount(renderer: BubbleChartRenderer) -> Int
{
return _chart.data!.xValCount
}
// MARK: Accessors
/// - returns: true if drawing the highlighting arrow is enabled, false if not
public var isDrawHighlightArrowEnabled: Bool { return drawHighlightArrowEnabled; }
/// - returns: true if drawing values above bars is enabled, false if not
public var isDrawValueAboveBarEnabled: Bool { return drawValueAboveBarEnabled; }
/// - returns: true if drawing shadows (maxvalue) for each bar is enabled, false if not
public var isDrawBarShadowEnabled: Bool { return 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.
public var drawOrder: [CombinedChartView.CombinedChartDrawOrder]
{
get
{
return _drawOrder
}
set
{
if (newValue.count > 0)
{
_drawOrder = newValue
}
}
}
}

View File

@@ -1,470 +0,0 @@
//
// HorizontalBarChartRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class HorizontalBarChartRenderer: BarChartRenderer
{
public override init(delegate: BarChartRendererDelegate?, animator: ChartAnimator?, viewPortHandler: ChartViewPortHandler)
{
super.init(delegate: delegate, animator: animator, viewPortHandler: viewPortHandler)
}
internal override func drawDataSet(context context: CGContext?, dataSet: BarChartDataSet, index: Int)
{
CGContextSaveGState(context)
let barData = delegate!.barChartRendererData(self)
let trans = delegate!.barChartRenderer(self, transformerForAxis: dataSet.axisDependency)
let drawBarShadowEnabled: Bool = delegate!.barChartIsDrawBarShadowEnabled(self)
let dataSetOffset = (barData.dataSetCount - 1)
let groupSpace = barData.groupSpace
let groupSpaceHalf = groupSpace / 2.0
let barSpace = dataSet.barSpace
let barSpaceHalf = barSpace / 2.0
let containsStacks = dataSet.isStacked
let isInverted = delegate!.barChartIsInverted(self, axis: dataSet.axisDependency)
var entries = dataSet.yVals as! [BarChartDataEntry]
let barWidth: CGFloat = 0.5
let phaseY = _animator.phaseY
var barRect = CGRect()
var barShadow = CGRect()
var y: Double
// do the drawing
for (var j = 0, count = Int(ceil(CGFloat(dataSet.entryCount) * _animator.phaseX)); j < count; j++)
{
let e = entries[j]
// calculate the x-position, depending on datasetcount
let x = CGFloat(e.xIndex + e.xIndex * dataSetOffset) + CGFloat(index)
+ groupSpace * CGFloat(e.xIndex) + groupSpaceHalf
let values = e.values
if (!containsStacks || values == nil)
{
y = e.value
let bottom = x - barWidth + barSpaceHalf
let top = x + barWidth - barSpaceHalf
var right = isInverted ? (y <= 0.0 ? CGFloat(y) : 0) : (y >= 0.0 ? CGFloat(y) : 0)
var left = isInverted ? (y >= 0.0 ? CGFloat(y) : 0) : (y <= 0.0 ? CGFloat(y) : 0)
// multiply the height of the rect with the phase
if (right > 0)
{
right *= phaseY
}
else
{
left *= phaseY
}
barRect.origin.x = left
barRect.size.width = right - left
barRect.origin.y = top
barRect.size.height = bottom - top
trans.rectValueToPixel(&barRect)
if (!viewPortHandler.isInBoundsLeft(barRect.origin.x + barRect.size.width))
{
continue
}
if (!viewPortHandler.isInBoundsRight(barRect.origin.x))
{
break
}
// if drawing the bar shadow is enabled
if (drawBarShadowEnabled)
{
barShadow.origin.x = viewPortHandler.contentLeft
barShadow.origin.y = barRect.origin.y
barShadow.size.width = viewPortHandler.contentWidth
barShadow.size.height = barRect.size.height
CGContextSetFillColorWithColor(context, dataSet.barShadowColor.CGColor)
CGContextFillRect(context, barShadow)
}
// Set the color for the currently drawn value. If the index is out of bounds, reuse colors.
CGContextSetFillColorWithColor(context, dataSet.colorAt(j).CGColor)
CGContextFillRect(context, barRect)
}
else
{
let vals = values!
var posY = 0.0
var negY = -e.negativeSum
var yStart = 0.0
// if drawing the bar shadow is enabled
if (drawBarShadowEnabled)
{
y = e.value
let bottom = x - barWidth + barSpaceHalf
let top = x + barWidth - barSpaceHalf
var right = isInverted ? (y <= 0.0 ? CGFloat(y) : 0) : (y >= 0.0 ? CGFloat(y) : 0)
var left = isInverted ? (y >= 0.0 ? CGFloat(y) : 0) : (y <= 0.0 ? CGFloat(y) : 0)
// multiply the height of the rect with the phase
if (right > 0)
{
right *= phaseY
}
else
{
left *= phaseY
}
barRect.origin.x = left
barRect.size.width = right - left
barRect.origin.y = top
barRect.size.height = bottom - top
trans.rectValueToPixel(&barRect)
barShadow.origin.x = viewPortHandler.contentLeft
barShadow.origin.y = barRect.origin.y
barShadow.size.width = viewPortHandler.contentWidth
barShadow.size.height = barRect.size.height
CGContextSetFillColorWithColor(context, dataSet.barShadowColor.CGColor)
CGContextFillRect(context, barShadow)
}
// fill the stack
for (var k = 0; k < vals.count; k++)
{
let value = vals[k]
if value >= 0.0
{
y = posY
yStart = posY + value
posY = yStart
}
else
{
y = negY
yStart = negY + abs(value)
negY += abs(value)
}
let bottom = x - barWidth + barSpaceHalf
let top = x + barWidth - barSpaceHalf
var right: CGFloat, left: CGFloat
if isInverted
{
left = y >= yStart ? CGFloat(y) : CGFloat(yStart)
right = y <= yStart ? CGFloat(y) : CGFloat(yStart)
}
else
{
right = y >= yStart ? CGFloat(y) : CGFloat(yStart)
left = y <= yStart ? CGFloat(y) : CGFloat(yStart)
}
// multiply the height of the rect with the phase
right *= phaseY
left *= phaseY
barRect.origin.x = left
barRect.size.width = right - left
barRect.origin.y = top
barRect.size.height = bottom - top
trans.rectValueToPixel(&barRect)
if (k == 0 && !viewPortHandler.isInBoundsTop(barRect.origin.y + barRect.size.height))
{
// Skip to next bar
break
}
// avoid drawing outofbounds values
if (!viewPortHandler.isInBoundsBottom(barRect.origin.y))
{
break
}
// Set the color for the currently drawn value. If the index is out of bounds, reuse colors.
CGContextSetFillColorWithColor(context, dataSet.colorAt(k).CGColor)
CGContextFillRect(context, barRect)
}
}
}
CGContextRestoreGState(context)
}
internal override func prepareBarHighlight(x x: CGFloat, y1: Double, y2: Double, barspacehalf: CGFloat, trans: ChartTransformer, inout rect: CGRect)
{
let barWidth: CGFloat = 0.5
let top = x - barWidth + barspacehalf
let bottom = x + barWidth - barspacehalf
let left = CGFloat(y1)
let right = CGFloat(y2)
rect.origin.x = left
rect.origin.y = top
rect.size.width = right - left
rect.size.height = bottom - top
trans.rectValueToPixelHorizontal(&rect, phaseY: _animator.phaseY)
}
public override func getTransformedValues(trans trans: ChartTransformer, entries: [BarChartDataEntry], dataSetIndex: Int) -> [CGPoint]
{
return trans.generateTransformedValuesHorizontalBarChart(entries, dataSet: dataSetIndex, barData: delegate!.barChartRendererData(self)!, phaseY: _animator.phaseY)
}
public override func drawValues(context context: CGContext?)
{
// if values are drawn
if (passesCheck())
{
let barData = delegate!.barChartRendererData(self)
let defaultValueFormatter = delegate!.barChartDefaultRendererValueFormatter(self)
var dataSets = barData.dataSets
let drawValueAboveBar = delegate!.barChartIsDrawValueAboveBarEnabled(self)
let textAlign = drawValueAboveBar ? NSTextAlignment.Left : NSTextAlignment.Right
let valueOffsetPlus: CGFloat = 5.0
var posOffset: CGFloat
var negOffset: CGFloat
for (var i = 0, count = barData.dataSetCount; i < count; i++)
{
let dataSet = dataSets[i] as! BarChartDataSet
if !dataSet.isDrawValuesEnabled || dataSet.entryCount == 0
{
continue
}
let isInverted = delegate!.barChartIsInverted(self, axis: dataSet.axisDependency)
let valueFont = dataSet.valueFont
let valueTextColor = dataSet.valueTextColor
let yOffset = -valueFont.lineHeight / 2.0
var formatter = dataSet.valueFormatter
if (formatter === nil)
{
formatter = defaultValueFormatter
}
let trans = delegate!.barChartRenderer(self, transformerForAxis: dataSet.axisDependency)
var entries = dataSet.yVals as! [BarChartDataEntry]
var valuePoints = getTransformedValues(trans: trans, entries: entries, dataSetIndex: i)
// if only single values are drawn (sum)
if (!dataSet.isStacked)
{
for (var j = 0, count = Int(ceil(CGFloat(valuePoints.count) * _animator.phaseX)); j < count; j++)
{
if (!viewPortHandler.isInBoundsTop(valuePoints[j].y))
{
break
}
if (!viewPortHandler.isInBoundsX(valuePoints[j].x))
{
continue
}
if (!viewPortHandler.isInBoundsBottom(valuePoints[j].y))
{
continue
}
let val = entries[j].value
let valueText = formatter!.stringFromNumber(val)!
// calculate the correct offset depending on the draw position of the value
let valueTextWidth = valueText.sizeWithAttributes([NSFontAttributeName: valueFont]).width
posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus))
negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus)
if (isInverted)
{
posOffset = -posOffset - valueTextWidth
negOffset = -negOffset - valueTextWidth
}
drawValue(
context: context,
value: valueText,
xPos: valuePoints[j].x + (val >= 0.0 ? posOffset : negOffset),
yPos: valuePoints[j].y + yOffset,
font: valueFont,
align: textAlign,
color: valueTextColor)
}
}
else
{
// if each value of a potential stack should be drawn
for (var j = 0, count = Int(ceil(CGFloat(valuePoints.count) * _animator.phaseX)); j < count; j++)
{
let e = entries[j]
let values = e.values
// we still draw stacked bars, but there is one non-stacked in between
if (values == nil)
{
if (!viewPortHandler.isInBoundsTop(valuePoints[j].y))
{
break
}
if (!viewPortHandler.isInBoundsX(valuePoints[j].x))
{
continue
}
if (!viewPortHandler.isInBoundsBottom(valuePoints[j].y))
{
continue
}
let val = e.value
let valueText = formatter!.stringFromNumber(val)!
// calculate the correct offset depending on the draw position of the value
let valueTextWidth = valueText.sizeWithAttributes([NSFontAttributeName: valueFont]).width
posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus))
negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus)
if (isInverted)
{
posOffset = -posOffset - valueTextWidth
negOffset = -negOffset - valueTextWidth
}
drawValue(
context: context,
value: valueText,
xPos: valuePoints[j].x + (val >= 0.0 ? posOffset : negOffset),
yPos: valuePoints[j].y + yOffset,
font: valueFont,
align: textAlign,
color: valueTextColor)
}
else
{
let vals = values!
var transformed = [CGPoint]()
var posY = 0.0
var negY = -e.negativeSum
for (var k = 0; k < vals.count; k++)
{
let value = vals[k]
var y: Double
if value >= 0.0
{
posY += value
y = posY
}
else
{
y = negY
negY -= value
}
transformed.append(CGPoint(x: CGFloat(y) * _animator.phaseY, y: 0.0))
}
trans.pointValuesToPixel(&transformed)
for (var k = 0; k < transformed.count; k++)
{
let val = vals[k]
let valueText = formatter!.stringFromNumber(val)!
// calculate the correct offset depending on the draw position of the value
let valueTextWidth = valueText.sizeWithAttributes([NSFontAttributeName: valueFont]).width
posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus))
negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus)
if (isInverted)
{
posOffset = -posOffset - valueTextWidth
negOffset = -negOffset - valueTextWidth
}
let x = transformed[k].x + (val >= 0 ? posOffset : negOffset)
let y = valuePoints[j].y
if (!viewPortHandler.isInBoundsTop(y))
{
break
}
if (!viewPortHandler.isInBoundsX(x))
{
continue
}
if (!viewPortHandler.isInBoundsBottom(y))
{
continue
}
drawValue(context: context,
value: valueText,
xPos: x,
yPos: y + yOffset,
font: valueFont,
align: textAlign,
color: valueTextColor)
}
}
}
}
}
}
}
internal override func passesCheck() -> Bool
{
let barData = delegate!.barChartRendererData(self)
if (barData === nil)
{
return false
}
return CGFloat(barData.yValCount) < CGFloat(delegate!.barChartRendererMaxVisibleValueCount(self)) * viewPortHandler.scaleY
}
}

View File

@@ -1,628 +0,0 @@
//
// LineChartRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
@objc
public protocol LineChartRendererDelegate
{
func lineChartRendererData(renderer: LineChartRenderer) -> LineChartData!
func lineChartRenderer(renderer: LineChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
func lineChartRendererFillFormatter(renderer: LineChartRenderer) -> ChartFillFormatter
func lineChartDefaultRendererValueFormatter(renderer: LineChartRenderer) -> NSNumberFormatter!
func lineChartRendererChartYMax(renderer: LineChartRenderer) -> Double
func lineChartRendererChartYMin(renderer: LineChartRenderer) -> Double
func lineChartRendererChartXMax(renderer: LineChartRenderer) -> Double
func lineChartRendererChartXMin(renderer: LineChartRenderer) -> Double
func lineChartRendererMaxVisibleValueCount(renderer: LineChartRenderer) -> Int
}
public class LineChartRenderer: LineScatterCandleRadarChartRenderer
{
public weak var delegate: LineChartRendererDelegate?
public init(delegate: LineChartRendererDelegate?, animator: ChartAnimator?, viewPortHandler: ChartViewPortHandler)
{
super.init(animator: animator, viewPortHandler: viewPortHandler)
self.delegate = delegate
}
public override func drawData(context context: CGContext?)
{
let lineData = delegate!.lineChartRendererData(self)
if (lineData === nil)
{
return
}
for (var i = 0; i < lineData.dataSetCount; i++)
{
let set = lineData.getDataSetByIndex(i)
if (set !== nil && set!.isVisible)
{
drawDataSet(context: context, dataSet: set as! LineChartDataSet)
}
}
}
internal struct CGCPoint
{
internal var x: CGFloat = 0.0
internal var y: CGFloat = 0.0
/// x-axis distance
internal var dx: CGFloat = 0.0
/// y-axis distance
internal var dy: CGFloat = 0.0
internal init(x: CGFloat, y: CGFloat)
{
self.x = x
self.y = y
}
}
internal func drawDataSet(context context: CGContext?, dataSet: LineChartDataSet)
{
let entries = dataSet.yVals
if (entries.count < 1)
{
return
}
CGContextSaveGState(context)
CGContextSetLineWidth(context, dataSet.lineWidth)
if (dataSet.lineDashLengths != nil)
{
CGContextSetLineDash(context, dataSet.lineDashPhase, dataSet.lineDashLengths, dataSet.lineDashLengths.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
// if drawing cubic lines is enabled
if (dataSet.isDrawCubicEnabled)
{
drawCubic(context: context, dataSet: dataSet, entries: entries)
}
else
{ // draw normal (straight) lines
drawLinear(context: context, dataSet: dataSet, entries: entries)
}
CGContextRestoreGState(context)
}
internal func drawCubic(context context: CGContext?, dataSet: LineChartDataSet, entries: [ChartDataEntry])
{
let trans = delegate?.lineChartRenderer(self, transformerForAxis: dataSet.axisDependency)
let entryFrom = dataSet.entryForXIndex(_minX)
let entryTo = dataSet.entryForXIndex(_maxX)
let minx = max(dataSet.entryIndex(entry: entryFrom!, isEqual: true), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo!, isEqual: true) + 1, entries.count)
let phaseX = _animator.phaseX
let phaseY = _animator.phaseY
// get the color that is specified for this position from the DataSet
let drawingColor = dataSet.colors.first!
let intensity = dataSet.cubicIntensity
// the path for the cubic-spline
let cubicPath = CGPathCreateMutable()
var valueToPixelMatrix = trans!.valueToPixelMatrix
let size = Int(ceil(CGFloat(maxx - minx) * phaseX + CGFloat(minx)))
if (size - minx >= 2)
{
var prevDx: CGFloat = 0.0
var prevDy: CGFloat = 0.0
var curDx: CGFloat = 0.0
var curDy: CGFloat = 0.0
var prevPrev = entries[minx]
var prev = entries[minx]
var cur = entries[minx]
var next = entries[minx + 1]
// let the spline start
CGPathMoveToPoint(cubicPath, &valueToPixelMatrix, CGFloat(cur.xIndex), CGFloat(cur.value) * phaseY)
prevDx = CGFloat(cur.xIndex - prev.xIndex) * intensity
prevDy = CGFloat(cur.value - prev.value) * intensity
curDx = CGFloat(next.xIndex - cur.xIndex) * intensity
curDy = CGFloat(next.value - cur.value) * intensity
// the first cubic
CGPathAddCurveToPoint(cubicPath, &valueToPixelMatrix,
CGFloat(prev.xIndex) + prevDx, (CGFloat(prev.value) + prevDy) * phaseY,
CGFloat(cur.xIndex) - curDx, (CGFloat(cur.value) - curDy) * phaseY,
CGFloat(cur.xIndex), CGFloat(cur.value) * phaseY)
for (var j = minx + 1, count = min(size, entries.count - 1); j < count; j++)
{
prevPrev = entries[j == 1 ? 0 : j - 2]
prev = entries[j - 1]
cur = entries[j]
next = entries[j + 1]
prevDx = CGFloat(cur.xIndex - prevPrev.xIndex) * intensity
prevDy = CGFloat(cur.value - prevPrev.value) * intensity
curDx = CGFloat(next.xIndex - prev.xIndex) * intensity
curDy = CGFloat(next.value - prev.value) * intensity
CGPathAddCurveToPoint(cubicPath, &valueToPixelMatrix, CGFloat(prev.xIndex) + prevDx, (CGFloat(prev.value) + prevDy) * phaseY,
CGFloat(cur.xIndex) - curDx,
(CGFloat(cur.value) - curDy) * phaseY, CGFloat(cur.xIndex), CGFloat(cur.value) * phaseY)
}
if (size > entries.count - 1)
{
prevPrev = entries[entries.count - (entries.count >= 3 ? 3 : 2)]
prev = entries[entries.count - 2]
cur = entries[entries.count - 1]
next = cur
prevDx = CGFloat(cur.xIndex - prevPrev.xIndex) * intensity
prevDy = CGFloat(cur.value - prevPrev.value) * intensity
curDx = CGFloat(next.xIndex - prev.xIndex) * intensity
curDy = CGFloat(next.value - prev.value) * intensity
// the last cubic
CGPathAddCurveToPoint(cubicPath, &valueToPixelMatrix, CGFloat(prev.xIndex) + prevDx, (CGFloat(prev.value) + prevDy) * phaseY,
CGFloat(cur.xIndex) - curDx,
(CGFloat(cur.value) - curDy) * phaseY, CGFloat(cur.xIndex), CGFloat(cur.value) * phaseY)
}
}
CGContextSaveGState(context)
if (dataSet.isDrawFilledEnabled)
{
drawCubicFill(context: context, dataSet: dataSet, spline: cubicPath, matrix: valueToPixelMatrix, from: minx, to: size)
}
CGContextBeginPath(context)
CGContextAddPath(context, cubicPath)
CGContextSetStrokeColorWithColor(context, drawingColor.CGColor)
CGContextStrokePath(context)
CGContextRestoreGState(context)
}
internal func drawCubicFill(context context: CGContext?, dataSet: LineChartDataSet, spline: CGMutablePath, matrix: CGAffineTransform, from: Int, to: Int)
{
if to - from <= 1
{
return
}
CGContextSaveGState(context)
let fillMin = delegate!.lineChartRendererFillFormatter(self).getFillLinePosition(
dataSet: dataSet,
data: delegate!.lineChartRendererData(self),
chartMaxY: delegate!.lineChartRendererChartYMax(self),
chartMinY: delegate!.lineChartRendererChartYMin(self))
var pt1 = CGPoint(x: CGFloat(to - 1), y: fillMin)
var pt2 = CGPoint(x: CGFloat(from), y: fillMin)
pt1 = CGPointApplyAffineTransform(pt1, matrix)
pt2 = CGPointApplyAffineTransform(pt2, matrix)
CGContextBeginPath(context)
CGContextAddPath(context, spline)
CGContextAddLineToPoint(context, pt1.x, pt1.y)
CGContextAddLineToPoint(context, pt2.x, pt2.y)
CGContextClosePath(context)
CGContextSetFillColorWithColor(context, dataSet.fillColor.CGColor)
CGContextSetAlpha(context, dataSet.fillAlpha)
CGContextFillPath(context)
CGContextRestoreGState(context)
}
private var _lineSegments = [CGPoint](count: 2, repeatedValue: CGPoint())
internal func drawLinear(context context: CGContext?, dataSet: LineChartDataSet, entries: [ChartDataEntry])
{
let trans = delegate!.lineChartRenderer(self, transformerForAxis: dataSet.axisDependency)
let valueToPixelMatrix = trans.valueToPixelMatrix
let phaseX = _animator.phaseX
let phaseY = _animator.phaseY
CGContextSaveGState(context)
let entryFrom = dataSet.entryForXIndex(_minX)
let entryTo = dataSet.entryForXIndex(_maxX)
let minx = max(dataSet.entryIndex(entry: entryFrom!, isEqual: true), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo!, isEqual: true) + 1, entries.count)
// more than 1 color
if (dataSet.colors.count > 1)
{
if (_lineSegments.count != 2)
{
_lineSegments = [CGPoint](count: 2, repeatedValue: CGPoint())
}
for (var j = minx, count = Int(ceil(CGFloat(maxx - minx) * phaseX + CGFloat(minx))); j < count; j++)
{
if (count > 1 && j == count - 1)
{ // Last point, we have already drawn a line to this point
break
}
var e = entries[j]
_lineSegments[0].x = CGFloat(e.xIndex)
_lineSegments[0].y = CGFloat(e.value) * phaseY
_lineSegments[0] = CGPointApplyAffineTransform(_lineSegments[0], valueToPixelMatrix)
if (j + 1 < count)
{
e = entries[j + 1]
_lineSegments[1].x = CGFloat(e.xIndex)
_lineSegments[1].y = CGFloat(e.value) * phaseY
_lineSegments[1] = CGPointApplyAffineTransform(_lineSegments[1], valueToPixelMatrix)
}
else
{
_lineSegments[1] = _lineSegments[0]
}
if (!viewPortHandler.isInBoundsRight(_lineSegments[0].x))
{
break
}
// make sure the lines don't do shitty things outside bounds
if (!viewPortHandler.isInBoundsLeft(_lineSegments[1].x)
|| (!viewPortHandler.isInBoundsTop(_lineSegments[0].y) && !viewPortHandler.isInBoundsBottom(_lineSegments[1].y))
|| (!viewPortHandler.isInBoundsTop(_lineSegments[0].y) && !viewPortHandler.isInBoundsBottom(_lineSegments[1].y)))
{
continue
}
// get the color that is set for this line-segment
CGContextSetStrokeColorWithColor(context, dataSet.colorAt(j).CGColor)
CGContextStrokeLineSegments(context, _lineSegments, 2)
}
}
else
{ // only one color per dataset
var e1: ChartDataEntry!
var e2: ChartDataEntry!
if (_lineSegments.count != max((entries.count - 1) * 2, 2))
{
_lineSegments = [CGPoint](count: max((entries.count - 1) * 2, 2), repeatedValue: CGPoint())
}
e1 = entries[minx]
let count = Int(ceil(CGFloat(maxx - minx) * phaseX + CGFloat(minx)))
for (var x = count > 1 ? minx + 1 : minx, j = 0; x < count; x++)
{
e1 = entries[x == 0 ? 0 : (x - 1)]
e2 = entries[x]
_lineSegments[j++] = CGPointApplyAffineTransform(CGPoint(x: CGFloat(e1.xIndex), y: CGFloat(e1.value) * phaseY), valueToPixelMatrix)
_lineSegments[j++] = CGPointApplyAffineTransform(CGPoint(x: CGFloat(e2.xIndex), y: CGFloat(e2.value) * phaseY), valueToPixelMatrix)
}
let size = max((count - minx - 1) * 2, 2)
CGContextSetStrokeColorWithColor(context, dataSet.colorAt(0).CGColor)
CGContextStrokeLineSegments(context, _lineSegments, size)
}
CGContextRestoreGState(context)
// if drawing filled is enabled
if (dataSet.isDrawFilledEnabled && entries.count > 0)
{
drawLinearFill(context: context, dataSet: dataSet, entries: entries, minx: minx, maxx: maxx, trans: trans)
}
}
internal func drawLinearFill(context context: CGContext?, dataSet: LineChartDataSet, entries: [ChartDataEntry], minx: Int, maxx: Int, trans: ChartTransformer)
{
CGContextSaveGState(context)
CGContextSetFillColorWithColor(context, dataSet.fillColor.CGColor)
// filled is usually drawn with less alpha
CGContextSetAlpha(context, dataSet.fillAlpha)
let filled = generateFilledPath(
entries,
fillMin: delegate!.lineChartRendererFillFormatter(self).getFillLinePosition(
dataSet: dataSet,
data: delegate!.lineChartRendererData(self),
chartMaxY: delegate!.lineChartRendererChartYMax(self),
chartMinY: delegate!.lineChartRendererChartYMin(self)),
from: minx,
to: maxx,
matrix: trans.valueToPixelMatrix)
CGContextBeginPath(context)
CGContextAddPath(context, filled)
CGContextFillPath(context)
CGContextRestoreGState(context)
}
/// Generates the path that is used for filled drawing.
private func generateFilledPath(entries: [ChartDataEntry], fillMin: CGFloat, from: Int, to: Int, var matrix: CGAffineTransform) -> CGPath
{
let phaseX = _animator.phaseX
let phaseY = _animator.phaseY
let filled = CGPathCreateMutable()
CGPathMoveToPoint(filled, &matrix, CGFloat(entries[from].xIndex), fillMin)
CGPathAddLineToPoint(filled, &matrix, CGFloat(entries[from].xIndex), CGFloat(entries[from].value) * phaseY)
// create a new path
for (var x = from + 1, count = Int(ceil(CGFloat(to - from) * phaseX + CGFloat(from))); x < count; x++)
{
let e = entries[x]
CGPathAddLineToPoint(filled, &matrix, CGFloat(e.xIndex), CGFloat(e.value) * phaseY)
}
// close up
CGPathAddLineToPoint(filled, &matrix, CGFloat(entries[max(min(Int(ceil(CGFloat(to - from) * phaseX + CGFloat(from))) - 1, entries.count - 1), 0)].xIndex), fillMin)
CGPathCloseSubpath(filled)
return filled
}
public override func drawValues(context context: CGContext?)
{
let lineData = delegate!.lineChartRendererData(self)
if (lineData === nil)
{
return
}
let defaultValueFormatter = delegate!.lineChartDefaultRendererValueFormatter(self)
if (CGFloat(lineData.yValCount) < CGFloat(delegate!.lineChartRendererMaxVisibleValueCount(self)) * viewPortHandler.scaleX)
{
var dataSets = lineData.dataSets
for (var i = 0; i < dataSets.count; i++)
{
let dataSet = dataSets[i] as! LineChartDataSet
if !dataSet.isDrawValuesEnabled || dataSet.entryCount == 0
{
continue
}
let valueFont = dataSet.valueFont
let valueTextColor = dataSet.valueTextColor
var formatter = dataSet.valueFormatter
if (formatter === nil)
{
formatter = defaultValueFormatter
}
let trans = delegate!.lineChartRenderer(self, transformerForAxis: dataSet.axisDependency)
// make sure the values do not interfear with the circles
var valOffset = Int(dataSet.circleRadius * 1.75)
if (!dataSet.isDrawCirclesEnabled)
{
valOffset = valOffset / 2
}
var entries = dataSet.yVals
let entryFrom = dataSet.entryForXIndex(_minX)
let entryTo = dataSet.entryForXIndex(_maxX)
let minx = max(dataSet.entryIndex(entry: entryFrom!, isEqual: true), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo!, isEqual: true) + 1, entries.count)
var positions = trans.generateTransformedValuesLine(
entries,
phaseX: _animator.phaseX,
phaseY: _animator.phaseY,
from: minx,
to: maxx)
for (var j = 0, count = positions.count; j < count; j++)
{
if (!viewPortHandler.isInBoundsRight(positions[j].x))
{
break
}
if (!viewPortHandler.isInBoundsLeft(positions[j].x) || !viewPortHandler.isInBoundsY(positions[j].y))
{
continue
}
let val = entries[j + minx].value
ChartUtils.drawText(context: context, text: formatter!.stringFromNumber(val)!, point: CGPoint(x: positions[j].x, y: positions[j].y - CGFloat(valOffset) - valueFont.lineHeight), align: .Center, attributes: [NSFontAttributeName: valueFont, NSForegroundColorAttributeName: valueTextColor])
}
}
}
}
public override func drawExtras(context context: CGContext?)
{
drawCircles(context: context)
}
private func drawCircles(context context: CGContext?)
{
let phaseX = _animator.phaseX
let phaseY = _animator.phaseY
let lineData = delegate!.lineChartRendererData(self)
let dataSets = lineData.dataSets
var pt = CGPoint()
var rect = CGRect()
CGContextSaveGState(context)
for (var i = 0, count = dataSets.count; i < count; i++)
{
let dataSet = lineData.getDataSetByIndex(i) as! LineChartDataSet!
if (!dataSet.isVisible || !dataSet.isDrawCirclesEnabled)
{
continue
}
let trans = delegate!.lineChartRenderer(self, transformerForAxis: dataSet.axisDependency)
let valueToPixelMatrix = trans.valueToPixelMatrix
var entries = dataSet.yVals
let circleRadius = dataSet.circleRadius
let circleDiameter = circleRadius * 2.0
let circleHoleDiameter = circleRadius
let circleHoleRadius = circleHoleDiameter / 2.0
let isDrawCircleHoleEnabled = dataSet.isDrawCircleHoleEnabled
let entryFrom = dataSet.entryForXIndex(_minX)!
let entryTo = dataSet.entryForXIndex(_maxX)!
let minx = max(dataSet.entryIndex(entry: entryFrom, isEqual: true), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo, isEqual: true) + 1, entries.count)
for (var j = minx, count = Int(ceil(CGFloat(maxx - minx) * phaseX + CGFloat(minx))); j < count; j++)
{
let e = entries[j]
pt.x = CGFloat(e.xIndex)
pt.y = CGFloat(e.value) * phaseY
pt = CGPointApplyAffineTransform(pt, valueToPixelMatrix)
if (!viewPortHandler.isInBoundsRight(pt.x))
{
break
}
// make sure the circles don't do shitty things outside bounds
if (!viewPortHandler.isInBoundsLeft(pt.x) || !viewPortHandler.isInBoundsY(pt.y))
{
continue
}
CGContextSetFillColorWithColor(context, dataSet.getCircleColor(j)!.CGColor)
rect.origin.x = pt.x - circleRadius
rect.origin.y = pt.y - circleRadius
rect.size.width = circleDiameter
rect.size.height = circleDiameter
CGContextFillEllipseInRect(context, rect)
if (isDrawCircleHoleEnabled)
{
CGContextSetFillColorWithColor(context, dataSet.circleHoleColor.CGColor)
rect.origin.x = pt.x - circleHoleRadius
rect.origin.y = pt.y - circleHoleRadius
rect.size.width = circleHoleDiameter
rect.size.height = circleHoleDiameter
CGContextFillEllipseInRect(context, rect)
}
}
}
CGContextRestoreGState(context)
}
private var _highlightPointBuffer = CGPoint()
public override func drawHighlighted(context context: CGContext?, indices: [ChartHighlight])
{
let lineData = delegate!.lineChartRendererData(self)
let chartXMax = delegate!.lineChartRendererChartXMax(self)
CGContextSaveGState(context)
for (var i = 0; i < indices.count; i++)
{
let set = lineData.getDataSetByIndex(indices[i].dataSetIndex) as! LineChartDataSet!
if (set === nil || !set.isHighlightEnabled)
{
continue
}
CGContextSetStrokeColorWithColor(context, set.highlightColor.CGColor)
CGContextSetLineWidth(context, set.highlightLineWidth)
if (set.highlightLineDashLengths != nil)
{
CGContextSetLineDash(context, set.highlightLineDashPhase, set.highlightLineDashLengths!, set.highlightLineDashLengths!.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
let xIndex = indices[i].xIndex; // get the x-position
if (CGFloat(xIndex) > CGFloat(chartXMax) * _animator.phaseX)
{
continue
}
let yValue = set.yValForXIndex(xIndex)
if (yValue.isNaN)
{
continue
}
let y = CGFloat(yValue) * _animator.phaseY; // get the y-position
_highlightPointBuffer.x = CGFloat(xIndex)
_highlightPointBuffer.y = y
let trans = delegate!.lineChartRenderer(self, transformerForAxis: set.axisDependency)
trans.pointValueToPixel(&_highlightPointBuffer)
// draw the lines
drawHighlightLines(context: context, point: _highlightPointBuffer, set: set)
}
CGContextRestoreGState(context)
}
}

View File

@@ -1,50 +0,0 @@
//
// LineScatterCandleRadarChartRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 29/7/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class LineScatterCandleRadarChartRenderer: ChartDataRendererBase
{
public override init(animator: ChartAnimator?, viewPortHandler: ChartViewPortHandler)
{
super.init(animator: animator, viewPortHandler: viewPortHandler)
}
/// Draws vertical & horizontal highlight-lines if enabled.
/// :param: context
/// :param: points
/// :param: horizontal
/// :param: vertical
public func drawHighlightLines(context context: CGContext?, point: CGPoint, set: LineScatterCandleChartDataSet)
{
// draw vertical highlight lines
if set.isVerticalHighlightIndicatorEnabled
{
CGContextBeginPath(context)
CGContextMoveToPoint(context, point.x, viewPortHandler.contentTop)
CGContextAddLineToPoint(context, point.x, viewPortHandler.contentBottom)
CGContextStrokePath(context)
}
// draw horizontal highlight lines
if set.isHorizontalHighlightIndicatorEnabled
{
CGContextBeginPath(context)
CGContextMoveToPoint(context, viewPortHandler.contentLeft, point.y)
CGContextAddLineToPoint(context, viewPortHandler.contentRight, point.y)
CGContextStrokePath(context)
}
}
}

View File

@@ -1,391 +0,0 @@
//
// PieChartRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class PieChartRenderer: ChartDataRendererBase
{
internal weak var _chart: PieChartView!
public var drawHoleEnabled = true
public var holeTransparent = true
public var holeColor: UIColor? = UIColor.whiteColor()
public var holeRadiusPercent = CGFloat(0.5)
public var transparentCircleRadiusPercent = CGFloat(0.55)
public var centerTextColor = UIColor.blackColor()
public var centerTextFont = UIFont.systemFontOfSize(12.0)
public var drawXLabelsEnabled = true
public var usePercentValuesEnabled = false
public var centerText: String!
public var drawCenterTextEnabled = true
public var centerTextLineBreakMode = NSLineBreakMode.ByTruncatingTail
public var centerTextRadiusPercent: CGFloat = 1.0
public init(chart: PieChartView, animator: ChartAnimator?, viewPortHandler: ChartViewPortHandler)
{
super.init(animator: animator, viewPortHandler: viewPortHandler)
_chart = chart
}
public override func drawData(context context: CGContext?)
{
if (_chart !== nil)
{
let pieData = _chart.data
if (pieData != nil)
{
for set in pieData!.dataSets as! [PieChartDataSet]
{
if set.isVisible && set.entryCount > 0
{
drawDataSet(context: context, dataSet: set)
}
}
}
}
}
internal func drawDataSet(context context: CGContext?, dataSet: PieChartDataSet)
{
var angle = _chart.rotationAngle
var cnt = 0
var entries = dataSet.yVals
var drawAngles = _chart.drawAngles
let circleBox = _chart.circleBox
let radius = _chart.radius
let innerRadius = drawHoleEnabled && holeTransparent ? radius * holeRadiusPercent : 0.0
CGContextSaveGState(context)
for (var j = 0; j < entries.count; j++)
{
let newangle = drawAngles[cnt]
let sliceSpace = dataSet.sliceSpace
let e = entries[j]
// draw only if the value is greater than zero
if ((abs(e.value) > 0.000001))
{
if (!_chart.needsHighlight(xIndex: e.xIndex,
dataSetIndex: _chart.data!.indexOfDataSet(dataSet)))
{
let startAngle = angle + sliceSpace / 2.0
var sweepAngle = newangle * _animator.phaseY
- sliceSpace / 2.0
if (sweepAngle < 0.0)
{
sweepAngle = 0.0
}
let endAngle = startAngle + sweepAngle
let path = CGPathCreateMutable()
CGPathMoveToPoint(path, nil, circleBox.midX, circleBox.midY)
CGPathAddArc(path, nil, circleBox.midX, circleBox.midY, radius, startAngle * ChartUtils.Math.FDEG2RAD, endAngle * ChartUtils.Math.FDEG2RAD, false)
CGPathCloseSubpath(path)
if (innerRadius > 0.0)
{
CGPathMoveToPoint(path, nil, circleBox.midX, circleBox.midY)
CGPathAddArc(path, nil, circleBox.midX, circleBox.midY, innerRadius, startAngle * ChartUtils.Math.FDEG2RAD, endAngle * ChartUtils.Math.FDEG2RAD, false)
CGPathCloseSubpath(path)
}
CGContextBeginPath(context)
CGContextAddPath(context, path)
CGContextSetFillColorWithColor(context, dataSet.colorAt(j).CGColor)
CGContextEOFillPath(context)
}
}
angle += newangle * _animator.phaseX
cnt++
}
CGContextRestoreGState(context)
}
public override func drawValues(context context: CGContext?)
{
let center = _chart.centerCircleBox
// get whole the radius
var r = _chart.radius
let rotationAngle = _chart.rotationAngle
var drawAngles = _chart.drawAngles
var absoluteAngles = _chart.absoluteAngles
var off = r / 10.0 * 3.0
if (drawHoleEnabled)
{
off = (r - (r * _chart.holeRadiusPercent)) / 2.0
}
r -= off; // offset to keep things inside the chart
let data: ChartData! = _chart.data
if (data === nil)
{
return
}
let defaultValueFormatter = _chart.valueFormatter
var dataSets = data.dataSets
let drawXVals = drawXLabelsEnabled
var cnt = 0
for (var i = 0; i < dataSets.count; i++)
{
let dataSet = dataSets[i] as! PieChartDataSet
let drawYVals = dataSet.isDrawValuesEnabled
if (!drawYVals && !drawXVals)
{
continue
}
let valueFont = dataSet.valueFont
let valueTextColor = dataSet.valueTextColor
var formatter = dataSet.valueFormatter
if (formatter === nil)
{
formatter = defaultValueFormatter
}
var entries = dataSet.yVals
for (var j = 0, maxEntry = Int(min(ceil(CGFloat(entries.count) * _animator.phaseX), CGFloat(entries.count))); j < maxEntry; j++)
{
if (drawXVals && !drawYVals && (j >= data.xValCount || data.xVals[j] == nil))
{
continue
}
// offset needed to center the drawn text in the slice
let offset = drawAngles[cnt] / 2.0
// calculate the text position
let x = (r * cos(((rotationAngle + absoluteAngles[cnt] - offset) * _animator.phaseY) * ChartUtils.Math.FDEG2RAD) + center.x)
var y = (r * sin(((rotationAngle + absoluteAngles[cnt] - offset) * _animator.phaseY) * ChartUtils.Math.FDEG2RAD) + center.y)
let value = usePercentValuesEnabled ? entries[j].value / data.yValueSum * 100.0 : entries[j].value
let val = formatter!.stringFromNumber(value)!
let lineHeight = valueFont.lineHeight
y -= lineHeight
// draw everything, depending on settings
if (drawXVals && drawYVals)
{
ChartUtils.drawText(context: context, text: val, point: CGPoint(x: x, y: y), align: .Center, attributes: [NSFontAttributeName: valueFont, NSForegroundColorAttributeName: valueTextColor])
if (j < data.xValCount && data.xVals[j] != nil)
{
ChartUtils.drawText(context: context, text: data.xVals[j]!, point: CGPoint(x: x, y: y + lineHeight), align: .Center, attributes: [NSFontAttributeName: valueFont, NSForegroundColorAttributeName: valueTextColor])
}
}
else if (drawXVals && !drawYVals)
{
ChartUtils.drawText(context: context, text: data.xVals[j]!, point: CGPoint(x: x, y: y + lineHeight / 2.0), align: .Center, attributes: [NSFontAttributeName: valueFont, NSForegroundColorAttributeName: valueTextColor])
}
else if (!drawXVals && drawYVals)
{
ChartUtils.drawText(context: context, text: val, point: CGPoint(x: x, y: y + lineHeight / 2.0), align: .Center, attributes: [NSFontAttributeName: valueFont, NSForegroundColorAttributeName: valueTextColor])
}
cnt++
}
}
}
public override func drawExtras(context context: CGContext?)
{
drawHole(context: context)
drawCenterText(context: context)
}
/// draws the hole in the center of the chart and the transparent circle / hole
private func drawHole(context context: CGContext?)
{
if (_chart.drawHoleEnabled)
{
CGContextSaveGState(context)
let radius = _chart.radius
let holeRadius = radius * holeRadiusPercent
let center = _chart.centerCircleBox
if (holeColor !== nil && holeColor != UIColor.clearColor())
{
// draw the hole-circle
CGContextSetFillColorWithColor(context, holeColor!.CGColor)
CGContextFillEllipseInRect(context, CGRect(x: center.x - holeRadius, y: center.y - holeRadius, width: holeRadius * 2.0, height: holeRadius * 2.0))
}
if (transparentCircleRadiusPercent > holeRadiusPercent)
{
let secondHoleRadius = radius * transparentCircleRadiusPercent
// make transparent
CGContextSetFillColorWithColor(context, holeColor!.colorWithAlphaComponent(CGFloat(0x60) / CGFloat(0xFF)).CGColor)
// draw the transparent-circle
CGContextFillEllipseInRect(context, CGRect(x: center.x - secondHoleRadius, y: center.y - secondHoleRadius, width: secondHoleRadius * 2.0, height: secondHoleRadius * 2.0))
}
CGContextRestoreGState(context)
}
}
/// draws the description text in the center of the pie chart makes most sense when center-hole is enabled
private func drawCenterText(context context: CGContext?)
{
if (drawCenterTextEnabled && centerText != nil && centerText.characters.count > 0)
{
let center = _chart.centerCircleBox
let innerRadius = drawHoleEnabled && holeTransparent ? _chart.radius * holeRadiusPercent : _chart.radius
let holeRect = CGRect(x: center.x - innerRadius, y: center.y - innerRadius, width: innerRadius * 2.0, height: innerRadius * 2.0)
var boundingRect = holeRect
if (centerTextRadiusPercent > 0.0)
{
boundingRect = CGRectInset(boundingRect, (boundingRect.width - boundingRect.width * centerTextRadiusPercent) / 2.0, (boundingRect.height - boundingRect.height * centerTextRadiusPercent) / 2.0)
}
let centerTextNs = self.centerText as NSString
let paragraphStyle = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle
paragraphStyle.lineBreakMode = centerTextLineBreakMode
paragraphStyle.alignment = .Center
let drawingAttrs = [NSFontAttributeName: centerTextFont, NSParagraphStyleAttributeName: paragraphStyle, NSForegroundColorAttributeName: centerTextColor]
let textBounds = centerTextNs.boundingRectWithSize(boundingRect.size, options: [.UsesLineFragmentOrigin, .UsesFontLeading, .TruncatesLastVisibleLine], attributes: drawingAttrs, context: nil)
var drawingRect = boundingRect
drawingRect.origin.x += (boundingRect.size.width - textBounds.size.width) / 2.0
drawingRect.origin.y += (boundingRect.size.height - textBounds.size.height) / 2.0
drawingRect.size = textBounds.size
CGContextSaveGState(context)
let clippingPath = CGPathCreateWithEllipseInRect(holeRect, nil)
CGContextBeginPath(context)
CGContextAddPath(context, clippingPath)
CGContextClip(context)
centerTextNs.drawWithRect(drawingRect, options: [.UsesLineFragmentOrigin, .UsesFontLeading, .TruncatesLastVisibleLine], attributes: drawingAttrs, context: nil)
CGContextRestoreGState(context)
}
}
public override func drawHighlighted(context context: CGContext?, indices: [ChartHighlight])
{
if (_chart.data === nil)
{
return
}
CGContextSaveGState(context)
let rotationAngle = _chart.rotationAngle
var angle = CGFloat(0.0)
var drawAngles = _chart.drawAngles
var absoluteAngles = _chart.absoluteAngles
let innerRadius = drawHoleEnabled && holeTransparent ? _chart.radius * holeRadiusPercent : 0.0
for (var i = 0; i < indices.count; i++)
{
// get the index to highlight
let xIndex = indices[i].xIndex
if (xIndex >= drawAngles.count)
{
continue
}
let set = _chart.data?.getDataSetByIndex(indices[i].dataSetIndex) as! PieChartDataSet!
if (set === nil || !set.isHighlightEnabled)
{
continue
}
if (xIndex == 0)
{
angle = rotationAngle
}
else
{
angle = rotationAngle + absoluteAngles[xIndex - 1]
}
angle *= _animator.phaseY
let sliceDegrees = drawAngles[xIndex]
let shift = set.selectionShift
let circleBox = _chart.circleBox
let highlighted = CGRect(
x: circleBox.origin.x - shift,
y: circleBox.origin.y - shift,
width: circleBox.size.width + shift * 2.0,
height: circleBox.size.height + shift * 2.0)
CGContextSetFillColorWithColor(context, set.colorAt(xIndex).CGColor)
// redefine the rect that contains the arc so that the highlighted pie is not cut off
let startAngle = angle + set.sliceSpace / 2.0
var sweepAngle = sliceDegrees * _animator.phaseY - set.sliceSpace / 2.0
if (sweepAngle < 0.0)
{
sweepAngle = 0.0
}
let endAngle = startAngle + sweepAngle
let path = CGPathCreateMutable()
CGPathMoveToPoint(path, nil, highlighted.midX, highlighted.midY)
CGPathAddArc(path, nil, highlighted.midX, highlighted.midY, highlighted.size.width / 2.0, startAngle * ChartUtils.Math.FDEG2RAD, endAngle * ChartUtils.Math.FDEG2RAD, false)
CGPathCloseSubpath(path)
if (innerRadius > 0.0)
{
CGPathMoveToPoint(path, nil, highlighted.midX, highlighted.midY)
CGPathAddArc(path, nil, highlighted.midX, highlighted.midY, innerRadius, startAngle * ChartUtils.Math.FDEG2RAD, endAngle * ChartUtils.Math.FDEG2RAD, false)
CGPathCloseSubpath(path)
}
CGContextBeginPath(context)
CGContextAddPath(context, path)
CGContextEOFillPath(context)
}
CGContextRestoreGState(context)
}
}

View File

@@ -1,294 +0,0 @@
//
// RadarChartRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
public class RadarChartRenderer: LineScatterCandleRadarChartRenderer
{
internal weak var _chart: RadarChartView!
public init(chart: RadarChartView, animator: ChartAnimator?, viewPortHandler: ChartViewPortHandler)
{
super.init(animator: animator, viewPortHandler: viewPortHandler)
_chart = chart
}
public override func drawData(context context: CGContext?)
{
if (_chart !== nil)
{
let radarData = _chart.data
if (radarData != nil)
{
for set in radarData!.dataSets as! [RadarChartDataSet]
{
if set.isVisible && set.entryCount > 0
{
drawDataSet(context: context, dataSet: set)
}
}
}
}
}
internal func drawDataSet(context context: CGContext?, dataSet: RadarChartDataSet)
{
CGContextSaveGState(context)
let sliceangle = _chart.sliceAngle
// calculate the factor that is needed for transforming the value to pixels
let factor = _chart.factor
let center = _chart.centerOffsets
var entries = dataSet.yVals
let path = CGPathCreateMutable()
var hasMovedToPoint = false
for (var j = 0; j < entries.count; j++)
{
let e = entries[j]
let p = ChartUtils.getPosition(center: center, dist: CGFloat(e.value - _chart.chartYMin) * factor, angle: sliceangle * CGFloat(j) + _chart.rotationAngle)
if (p.x.isNaN)
{
continue
}
if (!hasMovedToPoint)
{
CGPathMoveToPoint(path, nil, p.x, p.y)
hasMovedToPoint = true
}
else
{
CGPathAddLineToPoint(path, nil, p.x, p.y)
}
}
CGPathCloseSubpath(path)
// draw filled
if (dataSet.isDrawFilledEnabled)
{
CGContextSetFillColorWithColor(context, dataSet.colorAt(0).CGColor)
CGContextSetAlpha(context, dataSet.fillAlpha)
CGContextBeginPath(context)
CGContextAddPath(context, path)
CGContextFillPath(context)
}
// draw the line (only if filled is disabled or alpha is below 255)
if (!dataSet.isDrawFilledEnabled || dataSet.fillAlpha < 1.0)
{
CGContextSetStrokeColorWithColor(context, dataSet.colorAt(0).CGColor)
CGContextSetLineWidth(context, dataSet.lineWidth)
CGContextSetAlpha(context, 1.0)
CGContextBeginPath(context)
CGContextAddPath(context, path)
CGContextStrokePath(context)
}
CGContextRestoreGState(context)
}
public override func drawValues(context context: CGContext?)
{
if (_chart.data === nil)
{
return
}
let data = _chart.data!
let defaultValueFormatter = _chart.valueFormatter
let sliceangle = _chart.sliceAngle
// calculate the factor that is needed for transforming the value to pixels
let factor = _chart.factor
let center = _chart.centerOffsets
let yoffset = CGFloat(5.0)
for (var i = 0, count = data.dataSetCount; i < count; i++)
{
let dataSet = data.getDataSetByIndex(i) as! RadarChartDataSet
if !dataSet.isDrawValuesEnabled || dataSet.entryCount == 0
{
continue
}
var entries = dataSet.yVals
for (var j = 0; j < entries.count; j++)
{
let e = entries[j]
let p = ChartUtils.getPosition(center: center, dist: CGFloat(e.value) * factor, angle: sliceangle * CGFloat(j) + _chart.rotationAngle)
let valueFont = dataSet.valueFont
let valueTextColor = dataSet.valueTextColor
var formatter = dataSet.valueFormatter
if (formatter === nil)
{
formatter = defaultValueFormatter
}
ChartUtils.drawText(context: context, text: formatter!.stringFromNumber(e.value)!, point: CGPoint(x: p.x, y: p.y - yoffset - valueFont.lineHeight), align: .Center, attributes: [NSFontAttributeName: valueFont, NSForegroundColorAttributeName: valueTextColor])
}
}
}
public override func drawExtras(context context: CGContext?)
{
drawWeb(context: context)
}
private var _webLineSegmentsBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())
internal func drawWeb(context context: CGContext?)
{
let sliceangle = _chart.sliceAngle
CGContextSaveGState(context)
// calculate the factor that is needed for transforming the value to
// pixels
let factor = _chart.factor
let rotationangle = _chart.rotationAngle
let center = _chart.centerOffsets
// draw the web lines that come from the center
CGContextSetLineWidth(context, _chart.webLineWidth)
CGContextSetStrokeColorWithColor(context, _chart.webColor.CGColor)
CGContextSetAlpha(context, _chart.webAlpha)
let xIncrements = 1 + _chart.skipWebLineCount
for var i = 0, xValCount = _chart.data!.xValCount; i < xValCount; i += xIncrements
{
let p = ChartUtils.getPosition(center: center, dist: CGFloat(_chart.yRange) * factor, angle: sliceangle * CGFloat(i) + rotationangle)
_webLineSegmentsBuffer[0].x = center.x
_webLineSegmentsBuffer[0].y = center.y
_webLineSegmentsBuffer[1].x = p.x
_webLineSegmentsBuffer[1].y = p.y
CGContextStrokeLineSegments(context, _webLineSegmentsBuffer, 2)
}
// draw the inner-web
CGContextSetLineWidth(context, _chart.innerWebLineWidth)
CGContextSetStrokeColorWithColor(context, _chart.innerWebColor.CGColor)
CGContextSetAlpha(context, _chart.webAlpha)
let labelCount = _chart.yAxis.entryCount
for (var j = 0; j < labelCount; j++)
{
for (var i = 0, xValCount = _chart.data!.xValCount; i < xValCount; i++)
{
let r = CGFloat(_chart.yAxis.entries[j] - _chart.chartYMin) * factor
let p1 = ChartUtils.getPosition(center: center, dist: r, angle: sliceangle * CGFloat(i) + rotationangle)
let p2 = ChartUtils.getPosition(center: center, dist: r, angle: sliceangle * CGFloat(i + 1) + rotationangle)
_webLineSegmentsBuffer[0].x = p1.x
_webLineSegmentsBuffer[0].y = p1.y
_webLineSegmentsBuffer[1].x = p2.x
_webLineSegmentsBuffer[1].y = p2.y
CGContextStrokeLineSegments(context, _webLineSegmentsBuffer, 2)
}
}
CGContextRestoreGState(context)
}
private var _highlightPointBuffer = CGPoint()
public override func drawHighlighted(context context: CGContext?, indices: [ChartHighlight])
{
if (_chart.data === nil)
{
return
}
let data = _chart.data as! RadarChartData
CGContextSaveGState(context)
CGContextSetLineWidth(context, data.highlightLineWidth)
if (data.highlightLineDashLengths != nil)
{
CGContextSetLineDash(context, data.highlightLineDashPhase, data.highlightLineDashLengths!, data.highlightLineDashLengths!.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
let sliceangle = _chart.sliceAngle
let factor = _chart.factor
let center = _chart.centerOffsets
for (var i = 0; i < indices.count; i++)
{
let set = _chart.data?.getDataSetByIndex(indices[i].dataSetIndex) as! RadarChartDataSet!
if (set === nil || !set.isHighlightEnabled)
{
continue
}
CGContextSetStrokeColorWithColor(context, set.highlightColor.CGColor)
// get the index to highlight
let xIndex = indices[i].xIndex
let e = set.entryForXIndex(xIndex)
if (e === nil || e!.xIndex != xIndex)
{
continue
}
let j = set.entryIndex(entry: e!, isEqual: true)
let y = (e!.value - _chart.chartYMin)
if (y.isNaN)
{
continue
}
_highlightPointBuffer = ChartUtils.getPosition(center: center, dist: CGFloat(y) * factor,
angle: sliceangle * CGFloat(j) + _chart.rotationAngle)
// draw the lines
drawHighlightLines(context: context, point: _highlightPointBuffer, set: set)
}
CGContextRestoreGState(context)
}
}

View File

@@ -1,299 +0,0 @@
//
// ScatterChartRenderer.swift
// Charts
//
// Created by Daniel Cohen Gindi on 4/3/15.
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/ios-charts
//
import Foundation
import CoreGraphics
import UIKit
@objc
public protocol ScatterChartRendererDelegate
{
func scatterChartRendererData(renderer: ScatterChartRenderer) -> ScatterChartData!
func scatterChartRenderer(renderer: ScatterChartRenderer, transformerForAxis which: ChartYAxis.AxisDependency) -> ChartTransformer!
func scatterChartDefaultRendererValueFormatter(renderer: ScatterChartRenderer) -> NSNumberFormatter!
func scatterChartRendererChartYMax(renderer: ScatterChartRenderer) -> Double
func scatterChartRendererChartYMin(renderer: ScatterChartRenderer) -> Double
func scatterChartRendererChartXMax(renderer: ScatterChartRenderer) -> Double
func scatterChartRendererChartXMin(renderer: ScatterChartRenderer) -> Double
func scatterChartRendererMaxVisibleValueCount(renderer: ScatterChartRenderer) -> Int
}
public class ScatterChartRenderer: LineScatterCandleRadarChartRenderer
{
public weak var delegate: ScatterChartRendererDelegate?
public init(delegate: ScatterChartRendererDelegate?, animator: ChartAnimator?, viewPortHandler: ChartViewPortHandler)
{
super.init(animator: animator, viewPortHandler: viewPortHandler)
self.delegate = delegate
}
public override func drawData(context context: CGContext?)
{
let scatterData = delegate!.scatterChartRendererData(self)
if (scatterData === nil)
{
return
}
for (var i = 0; i < scatterData.dataSetCount; i++)
{
let set = scatterData.getDataSetByIndex(i)
if (set !== nil && set!.isVisible)
{
drawDataSet(context: context, dataSet: set as! ScatterChartDataSet)
}
}
}
private var _lineSegments = [CGPoint](count: 2, repeatedValue: CGPoint())
internal func drawDataSet(context context: CGContext?, dataSet: ScatterChartDataSet)
{
let trans = delegate!.scatterChartRenderer(self, transformerForAxis: dataSet.axisDependency)
let phaseY = _animator.phaseY
var entries = dataSet.yVals
let shapeSize = dataSet.scatterShapeSize
let shapeHalf = shapeSize / 2.0
var point = CGPoint()
let valueToPixelMatrix = trans.valueToPixelMatrix
let shape = dataSet.scatterShape
CGContextSaveGState(context)
for (var j = 0, count = Int(min(ceil(CGFloat(entries.count) * _animator.phaseX), CGFloat(entries.count))); j < count; j++)
{
let e = entries[j]
point.x = CGFloat(e.xIndex)
point.y = CGFloat(e.value) * phaseY
point = CGPointApplyAffineTransform(point, valueToPixelMatrix);
if (!viewPortHandler.isInBoundsRight(point.x))
{
break
}
if (!viewPortHandler.isInBoundsLeft(point.x) || !viewPortHandler.isInBoundsY(point.y))
{
continue
}
if (shape == .Square)
{
CGContextSetFillColorWithColor(context, dataSet.colorAt(j).CGColor)
var rect = CGRect()
rect.origin.x = point.x - shapeHalf
rect.origin.y = point.y - shapeHalf
rect.size.width = shapeSize
rect.size.height = shapeSize
CGContextFillRect(context, rect)
}
else if (shape == .Circle)
{
CGContextSetFillColorWithColor(context, dataSet.colorAt(j).CGColor)
var rect = CGRect()
rect.origin.x = point.x - shapeHalf
rect.origin.y = point.y - shapeHalf
rect.size.width = shapeSize
rect.size.height = shapeSize
CGContextFillEllipseInRect(context, rect)
}
else if (shape == .Cross)
{
CGContextSetStrokeColorWithColor(context, dataSet.colorAt(j).CGColor)
_lineSegments[0].x = point.x - shapeHalf
_lineSegments[0].y = point.y
_lineSegments[1].x = point.x + shapeHalf
_lineSegments[1].y = point.y
CGContextStrokeLineSegments(context, _lineSegments, 2)
_lineSegments[0].x = point.x
_lineSegments[0].y = point.y - shapeHalf
_lineSegments[1].x = point.x
_lineSegments[1].y = point.y + shapeHalf
CGContextStrokeLineSegments(context, _lineSegments, 2)
}
else if (shape == .Triangle)
{
CGContextSetFillColorWithColor(context, dataSet.colorAt(j).CGColor)
// create a triangle path
CGContextBeginPath(context)
CGContextMoveToPoint(context, point.x, point.y - shapeHalf)
CGContextAddLineToPoint(context, point.x + shapeHalf, point.y + shapeHalf)
CGContextAddLineToPoint(context, point.x - shapeHalf, point.y + shapeHalf)
CGContextClosePath(context)
CGContextFillPath(context)
}
else if (shape == .Custom)
{
CGContextSetFillColorWithColor(context, dataSet.colorAt(j).CGColor)
let customShape = dataSet.customScatterShape
if (customShape === nil)
{
return
}
// transform the provided custom path
CGContextSaveGState(context)
CGContextTranslateCTM(context, point.x, point.y)
CGContextBeginPath(context)
CGContextAddPath(context, customShape)
CGContextFillPath(context)
CGContextRestoreGState(context)
}
}
CGContextRestoreGState(context)
}
public override func drawValues(context context: CGContext?)
{
let scatterData = delegate!.scatterChartRendererData(self)
if (scatterData === nil)
{
return
}
let defaultValueFormatter = delegate!.scatterChartDefaultRendererValueFormatter(self)
// if values are drawn
if (scatterData.yValCount < Int(ceil(CGFloat(delegate!.scatterChartRendererMaxVisibleValueCount(self)) * viewPortHandler.scaleX)))
{
var dataSets = scatterData.dataSets as! [ScatterChartDataSet]
for (var i = 0; i < scatterData.dataSetCount; i++)
{
let dataSet = dataSets[i]
if !dataSet.isDrawValuesEnabled || dataSet.entryCount == 0
{
continue
}
let valueFont = dataSet.valueFont
let valueTextColor = dataSet.valueTextColor
var formatter = dataSet.valueFormatter
if (formatter === nil)
{
formatter = defaultValueFormatter
}
var entries = dataSet.yVals
var positions = delegate!.scatterChartRenderer(self, transformerForAxis: dataSet.axisDependency).generateTransformedValuesScatter(entries, phaseY: _animator.phaseY)
let shapeSize = dataSet.scatterShapeSize
let lineHeight = valueFont.lineHeight
for (var j = 0, count = Int(ceil(CGFloat(positions.count) * _animator.phaseX)); j < count; j++)
{
if (!viewPortHandler.isInBoundsRight(positions[j].x))
{
break
}
// make sure the lines don't do shitty things outside bounds
if ((!viewPortHandler.isInBoundsLeft(positions[j].x)
|| !viewPortHandler.isInBoundsY(positions[j].y)))
{
continue
}
let val = entries[j].value
let text = formatter!.stringFromNumber(val)
ChartUtils.drawText(context: context, text: text!, point: CGPoint(x: positions[j].x, y: positions[j].y - shapeSize - lineHeight), align: .Center, attributes: [NSFontAttributeName: valueFont, NSForegroundColorAttributeName: valueTextColor])
}
}
}
}
public override func drawExtras(context context: CGContext?)
{
}
private var _highlightPointBuffer = CGPoint()
public override func drawHighlighted(context context: CGContext?, indices: [ChartHighlight])
{
let scatterData = delegate!.scatterChartRendererData(self)
let chartXMax = delegate!.scatterChartRendererChartXMax(self)
CGContextSaveGState(context)
for (var i = 0; i < indices.count; i++)
{
let set = scatterData.getDataSetByIndex(indices[i].dataSetIndex) as! ScatterChartDataSet!
if (set === nil || !set.isHighlightEnabled)
{
continue
}
CGContextSetStrokeColorWithColor(context, set.highlightColor.CGColor)
CGContextSetLineWidth(context, set.highlightLineWidth)
if (set.highlightLineDashLengths != nil)
{
CGContextSetLineDash(context, set.highlightLineDashPhase, set.highlightLineDashLengths!, set.highlightLineDashLengths!.count)
}
else
{
CGContextSetLineDash(context, 0.0, nil, 0)
}
let xIndex = indices[i].xIndex; // get the x-position
if (CGFloat(xIndex) > CGFloat(chartXMax) * _animator.phaseX)
{
continue
}
let yVal = set.yValForXIndex(xIndex)
if (yVal.isNaN)
{
continue
}
let y = CGFloat(yVal) * _animator.phaseY; // get the y-position
_highlightPointBuffer.x = CGFloat(xIndex)
_highlightPointBuffer.y = y
let trans = delegate!.scatterChartRenderer(self, transformerForAxis: set.axisDependency)
trans.pointValueToPixel(&_highlightPointBuffer)
// draw the lines
drawHighlightLines(context: context, point: _highlightPointBuffer, set: set)
}
CGContextRestoreGState(context)
}
}

Some files were not shown because too many files have changed in this diff Show More