Commit 9ec80311 by Wei Xian Ong

Initial commit

parent 242a4cdf
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (2.3.6)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
atomos (0.1.3)
aws-eventstream (1.1.0)
aws-partitions (1.374.0)
aws-sdk-core (3.107.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.38.0)
aws-sdk-core (~> 3, >= 3.99.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.81.0)
aws-sdk-core (~> 3, >= 3.104.3)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.2)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.3)
claide (1.0.3)
colored (1.2)
colored2 (3.1.2)
commander-fastlane (4.4.6)
highline (~> 1.7.2)
declarative (0.0.20)
declarative-option (0.1.0)
digest-crc (0.6.1)
rake (~> 13.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
emoji_regex (3.0.0)
excon (0.76.0)
faraday (1.0.1)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday_middleware (1.0.0)
faraday (~> 1.0)
fastimage (2.2.0)
fastlane (2.162.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored
commander-fastlane (>= 4.4.6, < 5.0.0)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.37.0, < 0.39.0)
google-cloud-storage (>= 1.15.0, < 2.0.0)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3)
google-api-client (0.38.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.9)
httpclient (>= 2.8.1, < 3.0)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.12)
google-cloud-core (1.5.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.3.3)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.0.1)
google-cloud-storage (1.29.0)
addressable (~> 2.5)
digest-crc (~> 0.4)
google-api-client (~> 0.33)
google-cloud-core (~> 1.2)
googleauth (~> 0.9)
mini_mime (~> 1.0)
googleauth (0.13.1)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.14)
highline (1.7.10)
http-cookie (1.0.3)
domain_name (~> 0.5)
httpclient (2.8.3)
jmespath (1.4.0)
json (2.1.0)
jwt (2.2.2)
memoist (0.16.2)
mini_magick (4.10.1)
mini_mime (1.0.2)
multi_json (1.15.0)
multipart-post (2.0.0)
nanaimo (0.2.6)
naturally (2.2.0)
os (1.1.1)
plist (3.5.0)
public_suffix (4.0.6)
rake (13.0.1)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rouge (2.0.7)
rubyzip (2.3.0)
security (0.1.3)
signet (0.14.0)
addressable (~> 2.3)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.8)
CFPropertyList
naturally
slack-notifier (2.3.2)
terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
tty-cursor (0.7.1)
tty-screen (0.8.1)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
word_wrap (1.0.0)
xcodeproj (1.16.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.2.6)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.0)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
DEPENDENCIES
fastlane
BUNDLED WITH
1.17.2
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'textfield' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for textfield
pod 'Charts'
target 'textfieldTests' do
inherit! :search_paths
# Pods for testing
end
target 'textfieldUITests' do
# Pods for testing
end
end
PODS:
- Charts (3.6.0):
- Charts/Core (= 3.6.0)
- Charts/Core (3.6.0)
DEPENDENCIES:
- Charts
SPEC REPOS:
trunk:
- Charts
SPEC CHECKSUMS:
Charts: b1e3a1f5a1c9ba5394438ca3b91bd8c9076310af
PODFILE CHECKSUM: 54882fa97fb547393958086f2831d38fceff7495
COCOAPODS: 1.9.3
//
// BarChartView.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
/// Chart that draws bars.
open class BarChartView: BarLineChartViewBase, BarChartDataProvider
{
/// if set to true, all values are drawn above their bars, instead of below their top
private var _drawValueAboveBarEnabled = true
/// if set to true, a grey area is drawn behind each bar that indicates the maximum value
private var _drawBarShadowEnabled = false
internal override func initialize()
{
super.initialize()
renderer = BarChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
self.highlighter = BarHighlighter(chart: self)
self.xAxis.spaceMin = 0.5
self.xAxis.spaceMax = 0.5
}
internal override func calcMinMax()
{
guard let data = self.data as? BarChartData
else { return }
if fitBars
{
_xAxis.calculate(
min: data.xMin - data.barWidth / 2.0,
max: data.xMax + data.barWidth / 2.0)
}
else
{
_xAxis.calculate(min: data.xMin, max: data.xMax)
}
// calculate axis range (min / max) according to provided data
leftAxis.calculate(
min: data.getYMin(axis: .left),
max: data.getYMax(axis: .left))
rightAxis.calculate(
min: data.getYMin(axis: .right),
max: data.getYMax(axis: .right))
}
/// - Returns: The Highlight object (contains x-index and DataSet index) of the selected value at the given touch point inside the BarChart.
open override func getHighlightByTouchPoint(_ pt: CGPoint) -> Highlight?
{
if _data === nil
{
Swift.print("Can't select by touch. No data set.")
return nil
}
guard let h = self.highlighter?.getHighlight(x: pt.x, y: pt.y)
else { return nil }
if !isHighlightFullBarEnabled { return h }
// For isHighlightFullBarEnabled, remove stackIndex
return Highlight(
x: h.x, y: h.y,
xPx: h.xPx, yPx: h.yPx,
dataIndex: h.dataIndex,
dataSetIndex: h.dataSetIndex,
stackIndex: -1,
axis: h.axis)
}
/// - Returns: The bounding box of the specified Entry in the specified DataSet. Returns null if the Entry could not be found in the charts data.
@objc open func getBarBounds(entry e: BarChartDataEntry) -> CGRect
{
guard let
data = _data as? BarChartData,
let set = data.getDataSetForEntry(e) as? IBarChartDataSet
else { return CGRect.null }
let y = e.y
let x = e.x
let barWidth = data.barWidth
let left = x - barWidth / 2.0
let right = x + barWidth / 2.0
let top = y >= 0.0 ? y : 0.0
let bottom = y <= 0.0 ? y : 0.0
var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top)
getTransformer(forAxis: set.axisDependency).rectValueToPixel(&bounds)
return bounds
}
/// Groups all BarDataSet objects this data object holds together by modifying the x-value of their entries.
/// Previously set x-values of entries will be overwritten. Leaves space between bars and groups as specified by the parameters.
/// Calls `notifyDataSetChanged()` afterwards.
///
/// - Parameters:
/// - fromX: the starting point on the x-axis where the grouping should begin
/// - groupSpace: the space between groups of bars in values (not pixels) e.g. 0.8f for bar width 1f
/// - barSpace: the space between individual bars in values (not pixels) e.g. 0.1f for bar width 1f
@objc open func groupBars(fromX: Double, groupSpace: Double, barSpace: Double)
{
guard let barData = self.barData
else
{
Swift.print("You need to set data for the chart before grouping bars.", terminator: "\n")
return
}
barData.groupBars(fromX: fromX, groupSpace: groupSpace, barSpace: barSpace)
notifyDataSetChanged()
}
/// Highlights the value at the given x-value in the given DataSet. Provide -1 as the dataSetIndex to undo all highlighting.
///
/// - Parameters:
/// - x:
/// - dataSetIndex:
/// - stackIndex: the index inside the stack - only relevant for stacked entries
@objc open func highlightValue(x: Double, dataSetIndex: Int, stackIndex: Int)
{
highlightValue(Highlight(x: x, dataSetIndex: dataSetIndex, stackIndex: stackIndex))
}
// MARK: Accessors
/// if set to true, all values are drawn above their bars, instead of below their top
@objc open var drawValueAboveBarEnabled: Bool
{
get { return _drawValueAboveBarEnabled }
set
{
_drawValueAboveBarEnabled = newValue
setNeedsDisplay()
}
}
/// if set to true, a grey area is drawn behind each bar that indicates the maximum value
@objc open var drawBarShadowEnabled: Bool
{
get { return _drawBarShadowEnabled }
set
{
_drawBarShadowEnabled = newValue
setNeedsDisplay()
}
}
/// Adds half of the bar width to each side of the x-axis range in order to allow the bars of the barchart to be fully displayed.
/// **default**: false
@objc open var fitBars = false
/// Set this to `true` to make the highlight operation full-bar oriented, `false` to make it highlight single values (relevant only for stacked).
/// If enabled, highlighting operations will highlight the whole bar, even if only a single stack entry was tapped.
@objc open var highlightFullBarEnabled: Bool = false
/// `true` the highlight is be full-bar oriented, `false` ifsingle-value
open var isHighlightFullBarEnabled: Bool { return highlightFullBarEnabled }
// MARK: - BarChartDataProvider
open var barData: BarChartData? { return _data as? BarChartData }
/// `true` if drawing values above bars is enabled, `false` ifnot
open var isDrawValueAboveBarEnabled: Bool { return drawValueAboveBarEnabled }
/// `true` if drawing shadows (maxvalue) for each bar is enabled, `false` ifnot
open var isDrawBarShadowEnabled: Bool { return drawBarShadowEnabled }
}
//
// BubbleChartView.swift
// Charts
//
// Bubble chart implementation:
// Copyright 2015 Pierre-Marc Airoldi
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class BubbleChartView: BarLineChartViewBase, BubbleChartDataProvider
{
open override func initialize()
{
super.initialize()
renderer = BubbleChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
}
// MARK: - BubbleChartDataProvider
open var bubbleData: BubbleChartData? { return _data as? BubbleChartData }
}
//
// CandleStickChartView.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
/// Financial chart type that draws candle-sticks.
open class CandleStickChartView: BarLineChartViewBase, CandleChartDataProvider
{
internal override func initialize()
{
super.initialize()
renderer = CandleStickChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
self.xAxis.spaceMin = 0.5
self.xAxis.spaceMax = 0.5
}
// MARK: - CandleChartDataProvider
open var candleData: CandleChartData?
{
return _data as? CandleChartData
}
}
//
// CombinedChartView.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
/// This chart class allows the combination of lines, bars, scatter and candle data all displayed in one chart area.
open class CombinedChartView: BarLineChartViewBase, CombinedChartDataProvider
{
/// the fill-formatter used for determining the position of the fill-line
internal var _fillFormatter: IFillFormatter!
/// enum that allows to specify the order in which the different data objects for the combined-chart are drawn
@objc(CombinedChartDrawOrder)
public enum DrawOrder: Int
{
case bar
case bubble
case line
case candle
case scatter
}
open override func initialize()
{
super.initialize()
self.highlighter = CombinedHighlighter(chart: self, barDataProvider: self)
// Old default behaviour
self.highlightFullBarEnabled = true
_fillFormatter = DefaultFillFormatter()
renderer = CombinedChartRenderer(chart: self, animator: _animator, viewPortHandler: _viewPortHandler)
}
open override var data: ChartData?
{
get
{
return super.data
}
set
{
super.data = newValue
self.highlighter = CombinedHighlighter(chart: self, barDataProvider: self)
(renderer as? CombinedChartRenderer)?.createRenderers()
renderer?.initBuffers()
}
}
@objc open var fillFormatter: IFillFormatter
{
get
{
return _fillFormatter
}
set
{
_fillFormatter = newValue
if _fillFormatter == nil
{
_fillFormatter = DefaultFillFormatter()
}
}
}
/// - Returns: The Highlight object (contains x-index and DataSet index) of the selected value at the given touch point inside the CombinedChart.
open override func getHighlightByTouchPoint(_ pt: CGPoint) -> Highlight?
{
if _data === nil
{
Swift.print("Can't select by touch. No data set.")
return nil
}
guard let h = self.highlighter?.getHighlight(x: pt.x, y: pt.y)
else { return nil }
if !isHighlightFullBarEnabled { return h }
// For isHighlightFullBarEnabled, remove stackIndex
return Highlight(
x: h.x, y: h.y,
xPx: h.xPx, yPx: h.yPx,
dataIndex: h.dataIndex,
dataSetIndex: h.dataSetIndex,
stackIndex: -1,
axis: h.axis)
}
// MARK: - CombinedChartDataProvider
open var combinedData: CombinedChartData?
{
get
{
return _data as? CombinedChartData
}
}
// MARK: - LineChartDataProvider
open var lineData: LineChartData?
{
get
{
return combinedData?.lineData
}
}
// MARK: - BarChartDataProvider
open var barData: BarChartData?
{
get
{
return combinedData?.barData
}
}
// MARK: - ScatterChartDataProvider
open var scatterData: ScatterChartData?
{
get
{
return combinedData?.scatterData
}
}
// MARK: - CandleChartDataProvider
open var candleData: CandleChartData?
{
get
{
return combinedData?.candleData
}
}
// MARK: - BubbleChartDataProvider
open var bubbleData: BubbleChartData?
{
get
{
return combinedData?.bubbleData
}
}
// MARK: - Accessors
/// if set to true, all values are drawn above their bars, instead of below their top
@objc open var drawValueAboveBarEnabled: Bool
{
get { return (renderer as! CombinedChartRenderer).drawValueAboveBarEnabled }
set { (renderer as! CombinedChartRenderer).drawValueAboveBarEnabled = newValue }
}
/// if set to true, a grey area is drawn behind each bar that indicates the maximum value
@objc open var drawBarShadowEnabled: Bool
{
get { return (renderer as! CombinedChartRenderer).drawBarShadowEnabled }
set { (renderer as! CombinedChartRenderer).drawBarShadowEnabled = newValue }
}
/// `true` if drawing values above bars is enabled, `false` ifnot
open var isDrawValueAboveBarEnabled: Bool { return (renderer as! CombinedChartRenderer).drawValueAboveBarEnabled }
/// `true` if drawing shadows (maxvalue) for each bar is enabled, `false` ifnot
open var isDrawBarShadowEnabled: Bool { return (renderer as! CombinedChartRenderer).drawBarShadowEnabled }
/// the order in which the provided data objects should be drawn.
/// The earlier you place them in the provided array, the further they will be in the background.
/// e.g. if you provide [DrawOrder.Bar, DrawOrder.Line], the bars will be drawn behind the lines.
@objc open var drawOrder: [Int]
{
get
{
return (renderer as! CombinedChartRenderer).drawOrder.map { $0.rawValue }
}
set
{
(renderer as! CombinedChartRenderer).drawOrder = newValue.map { DrawOrder(rawValue: $0)! }
}
}
/// Set this to `true` to make the highlight operation full-bar oriented, `false` to make it highlight single values
@objc open var highlightFullBarEnabled: Bool = false
/// `true` the highlight is be full-bar oriented, `false` ifsingle-value
open var isHighlightFullBarEnabled: Bool { return highlightFullBarEnabled }
// MARK: - ChartViewBase
/// draws all MarkerViews on the highlighted positions
override func drawMarkers(context: CGContext)
{
guard
let marker = marker,
isDrawMarkersEnabled && valuesToHighlight()
else { return }
for i in 0 ..< _indicesToHighlight.count
{
let highlight = _indicesToHighlight[i]
guard
let set = combinedData?.getDataSetByHighlight(highlight),
let e = _data?.entryForHighlight(highlight)
else { continue }
let entryIndex = set.entryIndex(entry: e)
if entryIndex > Int(Double(set.entryCount) * _animator.phaseX)
{
continue
}
let pos = getMarkerPosition(highlight: highlight)
// check bounds
if !_viewPortHandler.isInBounds(x: pos.x, y: pos.y)
{
continue
}
// callbacks to update the content
marker.refreshContent(entry: e, highlight: highlight)
// draw the marker
marker.draw(context: context, point: pos)
}
}
}
//
// HorizontalBarChartView.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
/// BarChart with horizontal bar orientation. In this implementation, x- and y-axis are switched.
open class HorizontalBarChartView: BarChartView
{
internal override func initialize()
{
super.initialize()
_leftAxisTransformer = TransformerHorizontalBarChart(viewPortHandler: _viewPortHandler)
_rightAxisTransformer = TransformerHorizontalBarChart(viewPortHandler: _viewPortHandler)
renderer = HorizontalBarChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
leftYAxisRenderer = YAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, yAxis: leftAxis, transformer: _leftAxisTransformer)
rightYAxisRenderer = YAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, yAxis: rightAxis, transformer: _rightAxisTransformer)
xAxisRenderer = XAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, xAxis: _xAxis, transformer: _leftAxisTransformer, chart: self)
self.highlighter = HorizontalBarHighlighter(chart: self)
}
internal override func calculateLegendOffsets(offsetLeft: inout CGFloat, offsetTop: inout CGFloat, offsetRight: inout CGFloat, offsetBottom: inout CGFloat)
{
guard
let legend = _legend,
legend.isEnabled,
!legend.drawInside
else { return }
// setup offsets for legend
switch legend.orientation
{
case .vertical:
switch legend.horizontalAlignment
{
case .left:
offsetLeft += min(legend.neededWidth, _viewPortHandler.chartWidth * legend.maxSizePercent) + legend.xOffset
case .right:
offsetRight += min(legend.neededWidth, _viewPortHandler.chartWidth * legend.maxSizePercent) + legend.xOffset
case .center:
switch legend.verticalAlignment
{
case .top:
offsetTop += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset
case .bottom:
offsetBottom += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset
default:
break
}
}
case .horizontal:
switch legend.verticalAlignment
{
case .top:
offsetTop += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset
// left axis equals the top x-axis in a horizontal chart
if leftAxis.isEnabled && leftAxis.isDrawLabelsEnabled
{
offsetTop += leftAxis.getRequiredHeightSpace()
}
case .bottom:
offsetBottom += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset
// right axis equals the bottom x-axis in a horizontal chart
if rightAxis.isEnabled && rightAxis.isDrawLabelsEnabled
{
offsetBottom += rightAxis.getRequiredHeightSpace()
}
default:
break
}
}
}
internal override func calculateOffsets()
{
var offsetLeft: CGFloat = 0.0,
offsetRight: CGFloat = 0.0,
offsetTop: CGFloat = 0.0,
offsetBottom: CGFloat = 0.0
calculateLegendOffsets(offsetLeft: &offsetLeft,
offsetTop: &offsetTop,
offsetRight: &offsetRight,
offsetBottom: &offsetBottom)
// offsets for y-labels
if leftAxis.needsOffset
{
offsetTop += leftAxis.getRequiredHeightSpace()
}
if rightAxis.needsOffset
{
offsetBottom += rightAxis.getRequiredHeightSpace()
}
let xlabelwidth = _xAxis.labelRotatedWidth
if _xAxis.isEnabled
{
// offsets for x-labels
if _xAxis.labelPosition == .bottom
{
offsetLeft += xlabelwidth
}
else if _xAxis.labelPosition == .top
{
offsetRight += xlabelwidth
}
else if _xAxis.labelPosition == .bothSided
{
offsetLeft += xlabelwidth
offsetRight += xlabelwidth
}
}
offsetTop += self.extraTopOffset
offsetRight += self.extraRightOffset
offsetBottom += self.extraBottomOffset
offsetLeft += self.extraLeftOffset
_viewPortHandler.restrainViewPort(
offsetLeft: max(self.minOffset, offsetLeft),
offsetTop: max(self.minOffset, offsetTop),
offsetRight: max(self.minOffset, offsetRight),
offsetBottom: max(self.minOffset, offsetBottom))
prepareOffsetMatrix()
prepareValuePxMatrix()
}
internal override func prepareValuePxMatrix()
{
_rightAxisTransformer.prepareMatrixValuePx(chartXMin: rightAxis._axisMinimum, deltaX: CGFloat(rightAxis.axisRange), deltaY: CGFloat(_xAxis.axisRange), chartYMin: _xAxis._axisMinimum)
_leftAxisTransformer.prepareMatrixValuePx(chartXMin: leftAxis._axisMinimum, deltaX: CGFloat(leftAxis.axisRange), deltaY: CGFloat(_xAxis.axisRange), chartYMin: _xAxis._axisMinimum)
}
open override func getMarkerPosition(highlight: Highlight) -> CGPoint
{
return CGPoint(x: highlight.drawY, y: highlight.drawX)
}
open override func getBarBounds(entry e: BarChartDataEntry) -> CGRect
{
guard
let data = _data as? BarChartData,
let set = data.getDataSetForEntry(e) as? IBarChartDataSet
else { return CGRect.null }
let y = e.y
let x = e.x
let barWidth = data.barWidth
let top = x - 0.5 + barWidth / 2.0
let bottom = x + 0.5 - barWidth / 2.0
let left = y >= 0.0 ? y : 0.0
let right = y <= 0.0 ? y : 0.0
var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top)
getTransformer(forAxis: set.axisDependency).rectValueToPixel(&bounds)
return bounds
}
open override func getPosition(entry e: ChartDataEntry, axis: YAxis.AxisDependency) -> CGPoint
{
var vals = CGPoint(x: CGFloat(e.y), y: CGFloat(e.x))
getTransformer(forAxis: axis).pointValueToPixel(&vals)
return vals
}
open override func getHighlightByTouchPoint(_ pt: CGPoint) -> Highlight?
{
if _data === nil
{
Swift.print("Can't select by touch. No data set.", terminator: "\n")
return nil
}
return self.highlighter?.getHighlight(x: pt.y, y: pt.x)
}
/// The lowest x-index (value on the x-axis) that is still visible on he chart.
open override var lowestVisibleX: Double
{
var pt = CGPoint(
x: viewPortHandler.contentLeft,
y: viewPortHandler.contentBottom)
getTransformer(forAxis: .left).pixelToValues(&pt)
return max(xAxis._axisMinimum, Double(pt.y))
}
/// The highest x-index (value on the x-axis) that is still visible on the chart.
open override var highestVisibleX: Double
{
var pt = CGPoint(
x: viewPortHandler.contentLeft,
y: viewPortHandler.contentTop)
getTransformer(forAxis: .left).pixelToValues(&pt)
return min(xAxis._axisMaximum, Double(pt.y))
}
// MARK: - Viewport
open override func setVisibleXRangeMaximum(_ maxXRange: Double)
{
let xScale = xAxis.axisRange / maxXRange
viewPortHandler.setMinimumScaleY(CGFloat(xScale))
}
open override func setVisibleXRangeMinimum(_ minXRange: Double)
{
let xScale = xAxis.axisRange / minXRange
viewPortHandler.setMaximumScaleY(CGFloat(xScale))
}
open override func setVisibleXRange(minXRange: Double, maxXRange: Double)
{
let minScale = xAxis.axisRange / minXRange
let maxScale = xAxis.axisRange / maxXRange
viewPortHandler.setMinMaxScaleY(minScaleY: CGFloat(minScale), maxScaleY: CGFloat(maxScale))
}
open override func setVisibleYRangeMaximum(_ maxYRange: Double, axis: YAxis.AxisDependency)
{
let yScale = getAxisRange(axis: axis) / maxYRange
viewPortHandler.setMinimumScaleX(CGFloat(yScale))
}
open override func setVisibleYRangeMinimum(_ minYRange: Double, axis: YAxis.AxisDependency)
{
let yScale = getAxisRange(axis: axis) / minYRange
viewPortHandler.setMaximumScaleX(CGFloat(yScale))
}
open override func setVisibleYRange(minYRange: Double, maxYRange: Double, axis: YAxis.AxisDependency)
{
let minScale = getAxisRange(axis: axis) / minYRange
let maxScale = getAxisRange(axis: axis) / maxYRange
viewPortHandler.setMinMaxScaleX(minScaleX: CGFloat(minScale), maxScaleX: CGFloat(maxScale))
}
}
//
// LineChartView.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
/// Chart that draws lines, surfaces, circles, ...
open class LineChartView: BarLineChartViewBase, LineChartDataProvider
{
internal override func initialize()
{
super.initialize()
renderer = LineChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
}
// MARK: - LineChartDataProvider
open var lineData: LineChartData? { return _data as? LineChartData }
}
//
// RadarChartView.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
/// Implementation of the RadarChart, a "spidernet"-like chart. It works best
/// when displaying 5-10 entries per DataSet.
open class RadarChartView: PieRadarChartViewBase
{
/// width of the web lines that come from the center.
@objc open var webLineWidth = CGFloat(1.5)
/// width of the web lines that are in between the lines coming from the center
@objc open var innerWebLineWidth = CGFloat(0.75)
/// color for the web lines that come from the center
@objc open var webColor = NSUIColor(red: 122/255.0, green: 122/255.0, blue: 122.0/255.0, alpha: 1.0)
/// color for the web lines in between the lines that come from the center.
@objc open var innerWebColor = NSUIColor(red: 122/255.0, green: 122/255.0, blue: 122.0/255.0, alpha: 1.0)
/// transparency the grid is drawn with (0.0 - 1.0)
@objc open var webAlpha: CGFloat = 150.0 / 255.0
/// flag indicating if the web lines should be drawn or not
@objc open var drawWeb = true
/// modulus that determines how many labels and web-lines are skipped before the next is drawn
private var _skipWebLineCount = 0
/// the object reprsenting the y-axis labels
private var _yAxis: YAxis!
internal var _yAxisRenderer: YAxisRendererRadarChart!
internal var _xAxisRenderer: XAxisRendererRadarChart!
public override init(frame: CGRect)
{
super.init(frame: frame)
}
public required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
internal override func initialize()
{
super.initialize()
_yAxis = YAxis(position: .left)
_yAxis.labelXOffset = 10.0
renderer = RadarChartRenderer(chart: self, animator: _animator, viewPortHandler: _viewPortHandler)
_yAxisRenderer = YAxisRendererRadarChart(viewPortHandler: _viewPortHandler, yAxis: _yAxis, chart: self)
_xAxisRenderer = XAxisRendererRadarChart(viewPortHandler: _viewPortHandler, xAxis: _xAxis, chart: self)
self.highlighter = RadarHighlighter(chart: self)
}
internal override func calcMinMax()
{
super.calcMinMax()
guard let data = _data else { return }
_yAxis.calculate(min: data.getYMin(axis: .left), max: data.getYMax(axis: .left))
_xAxis.calculate(min: 0.0, max: Double(data.maxEntryCountSet?.entryCount ?? 0))
}
open override func notifyDataSetChanged()
{
calcMinMax()
_yAxisRenderer?.computeAxis(min: _yAxis._axisMinimum, max: _yAxis._axisMaximum, inverted: _yAxis.isInverted)
_xAxisRenderer?.computeAxis(min: _xAxis._axisMinimum, max: _xAxis._axisMaximum, inverted: false)
if let data = _data,
let legend = _legend,
!legend.isLegendCustom
{
legendRenderer?.computeLegend(data: data)
}
calculateOffsets()
setNeedsDisplay()
}
open override func draw(_ rect: CGRect)
{
super.draw(rect)
guard data != nil, let renderer = renderer else { return }
let optionalContext = NSUIGraphicsGetCurrentContext()
guard let context = optionalContext else { return }
if _xAxis.isEnabled
{
_xAxisRenderer.computeAxis(min: _xAxis._axisMinimum, max: _xAxis._axisMaximum, inverted: false)
}
_xAxisRenderer?.renderAxisLabels(context: context)
if drawWeb
{
renderer.drawExtras(context: context)
}
if _yAxis.isEnabled && _yAxis.isDrawLimitLinesBehindDataEnabled
{
_yAxisRenderer.renderLimitLines(context: context)
}
renderer.drawData(context: context)
if valuesToHighlight()
{
renderer.drawHighlighted(context: context, indices: _indicesToHighlight)
}
if _yAxis.isEnabled && !_yAxis.isDrawLimitLinesBehindDataEnabled
{
_yAxisRenderer.renderLimitLines(context: context)
}
_yAxisRenderer.renderAxisLabels(context: context)
renderer.drawValues(context: context)
legendRenderer.renderLegend(context: context)
drawDescription(context: context)
drawMarkers(context: context)
}
/// The factor that is needed to transform values into pixels.
@objc open var factor: CGFloat
{
let content = _viewPortHandler.contentRect
return min(content.width / 2.0, content.height / 2.0)
/ CGFloat(_yAxis.axisRange)
}
/// The angle that each slice in the radar chart occupies.
@objc open var sliceAngle: CGFloat
{
return 360.0 / CGFloat(_data?.maxEntryCountSet?.entryCount ?? 0)
}
open override func indexForAngle(_ angle: CGFloat) -> Int
{
// take the current angle of the chart into consideration
let a = (angle - self.rotationAngle).normalizedAngle
let sliceAngle = self.sliceAngle
let max = _data?.maxEntryCountSet?.entryCount ?? 0
return (0..<max).firstIndex {
sliceAngle * CGFloat($0 + 1) - sliceAngle / 2.0 > a
} ?? max
}
/// The object that represents all y-labels of the RadarChart.
@objc open var yAxis: YAxis
{
return _yAxis
}
/// Sets the number of web-lines that should be skipped on chart web before the next one is drawn. This targets the lines that come from the center of the RadarChart.
/// if count = 1 -> 1 line is skipped in between
@objc open var skipWebLineCount: Int
{
get
{
return _skipWebLineCount
}
set
{
_skipWebLineCount = max(0, newValue)
}
}
internal override var requiredLegendOffset: CGFloat
{
return _legend.font.pointSize * 4.0
}
internal override var requiredBaseOffset: CGFloat
{
return _xAxis.isEnabled && _xAxis.isDrawLabelsEnabled ? _xAxis.labelRotatedWidth : 10.0
}
open override var radius: CGFloat
{
let content = _viewPortHandler.contentRect
return min(content.width / 2.0, content.height / 2.0)
}
/// The maximum value this chart can display on it's y-axis.
open override var chartYMax: Double { return _yAxis._axisMaximum }
/// The minimum value this chart can display on it's y-axis.
open override var chartYMin: Double { return _yAxis._axisMinimum }
/// The range of y-values this chart can display.
@objc open var yRange: Double { return _yAxis.axisRange }
}
//
// ScatterChartView.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
/// The ScatterChart. Draws dots, triangles, squares and custom shapes into the chartview.
open class ScatterChartView: BarLineChartViewBase, ScatterChartDataProvider
{
open override func initialize()
{
super.initialize()
renderer = ScatterChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
xAxis.spaceMin = 0.5
xAxis.spaceMax = 0.5
}
// MARK: - ScatterChartDataProvider
open var scatterData: ScatterChartData? { return _data as? ScatterChartData }
}
//
// ChartLimitLine.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
/// The limit line is an additional feature for all Line, Bar and ScatterCharts.
/// It allows the displaying of an additional line in the chart that marks a certain maximum / limit on the specified axis (x- or y-axis).
open class ChartLimitLine: ComponentBase
{
@objc(ChartLimitLabelPosition)
public enum LabelPosition: Int
{
case topLeft
case topRight
case bottomLeft
case bottomRight
}
/// limit / maximum (the y-value or xIndex)
@objc open var limit = Double(0.0)
private var _lineWidth = CGFloat(2.0)
@objc open var lineColor = NSUIColor(red: 237.0/255.0, green: 91.0/255.0, blue: 91.0/255.0, alpha: 1.0)
@objc open var lineDashPhase = CGFloat(0.0)
@objc open var lineDashLengths: [CGFloat]?
@objc open var valueTextColor = NSUIColor.labelOrBlack
@objc open var valueFont = NSUIFont.systemFont(ofSize: 13.0)
@objc open var drawLabelEnabled = true
@objc open var label = ""
@objc open var labelPosition = LabelPosition.topRight
public override init()
{
super.init()
}
@objc public init(limit: Double)
{
super.init()
self.limit = limit
}
@objc public init(limit: Double, label: String)
{
super.init()
self.limit = limit
self.label = label
}
/// set the line width of the chart (min = 0.2, max = 12); default 2
@objc open var lineWidth: CGFloat
{
get
{
return _lineWidth
}
set
{
_lineWidth = newValue.clamped(to: 0.2...12)
}
}
}
//
// ComponentBase.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
/// This class encapsulates everything both Axis, Legend and LimitLines have in common
@objc(ChartComponentBase)
open class ComponentBase: NSObject
{
/// flag that indicates if this component is enabled or not
@objc open var enabled = true
/// The offset this component has on the x-axis
/// **default**: 5.0
@objc open var xOffset = CGFloat(5.0)
/// The offset this component has on the x-axis
/// **default**: 5.0 (or 0.0 on ChartYAxis)
@objc open var yOffset = CGFloat(5.0)
public override init()
{
super.init()
}
@objc open var isEnabled: Bool { return enabled }
}
//
// Description.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
#if canImport(UIKit)
import UIKit
#endif
#if canImport(Cocoa)
import Cocoa
#endif
@objc(ChartDescription)
open class Description: ComponentBase
{
public override init()
{
#if os(tvOS)
// 23 is the smallest recommended font size on the TV
font = .systemFont(ofSize: 23)
#elseif os(OSX)
font = .systemFont(ofSize: NSUIFont.systemFontSize)
#else
font = .systemFont(ofSize: 8.0)
#endif
super.init()
}
/// The text to be shown as the description.
@objc open var text: String?
/// Custom position for the description text in pixels on the screen.
open var position: CGPoint? = nil
/// The text alignment of the description text. Default RIGHT.
@objc open var textAlign: NSTextAlignment = NSTextAlignment.right
/// Font object used for drawing the description text.
@objc open var font: NSUIFont
/// Text color used for drawing the description text
@objc open var textColor = NSUIColor.labelOrBlack
}
//
// ChartMarker.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
@objc(IChartMarker)
public protocol IMarker: class
{
/// - Returns: The desired (general) offset you wish the IMarker to have on the x-axis.
/// By returning x: -(width / 2) you will center the IMarker horizontally.
/// By returning y: -(height / 2) you will center the IMarker vertically.
var offset: CGPoint { get }
/// - Parameters:
/// - point: This is the point at which the marker wants to be drawn. You can adjust the offset conditionally based on this argument.
/// - Returns: The offset for drawing at the specific `point`.
/// This allows conditional adjusting of the Marker position.
/// If you have no adjustments to make, return self.offset().
func offsetForDrawing(atPoint: CGPoint) -> CGPoint
/// This method enables a custom IMarker to update it's content every time the IMarker is redrawn according to the data entry it points to.
///
/// - Parameters:
/// - entry: The Entry the IMarker belongs to. This can also be any subclass of Entry, like BarEntry or CandleEntry, simply cast it at runtime.
/// - highlight: The highlight object contains information about the highlighted value such as it's dataset-index, the selected range or stack-index (only stacked bar entries).
func refreshContent(entry: ChartDataEntry, highlight: Highlight)
/// Draws the IMarker on the given position on the given context
func draw(context: CGContext, point: CGPoint)
}
//
// LegendEntry.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
@objc(ChartLegendEntry)
open class LegendEntry: NSObject
{
public override init()
{
super.init()
}
/// - Parameters:
/// - label: The legend entry text.
/// A `nil` label will start a group.
/// - form: The form to draw for this entry.
/// - formSize: Set to NaN to use the legend's default.
/// - formLineWidth: Set to NaN to use the legend's default.
/// - formLineDashPhase: Line dash configuration.
/// - formLineDashLengths: Line dash configurationas NaN to use the legend's default.
/// - formColor: The color for drawing the form.
@objc public init(label: String?,
form: Legend.Form,
formSize: CGFloat,
formLineWidth: CGFloat,
formLineDashPhase: CGFloat,
formLineDashLengths: [CGFloat]?,
formColor: NSUIColor?)
{
self.label = label
self.form = form
self.formSize = formSize
self.formLineWidth = formLineWidth
self.formLineDashPhase = formLineDashPhase
self.formLineDashLengths = formLineDashLengths
self.formColor = formColor
}
/// The legend entry text.
/// A `nil` label will start a group.
@objc open var label: String?
/// The form to draw for this entry.
///
/// `None` will avoid drawing a form, and any related space.
/// `Empty` will avoid drawing a form, but keep its space.
/// `Default` will use the Legend's default.
@objc open var form: Legend.Form = .default
/// Form size will be considered except for when .None is used
///
/// Set as NaN to use the legend's default
@objc open var formSize: CGFloat = CGFloat.nan
/// Line width used for shapes that consist of lines.
///
/// Set to NaN to use the legend's default.
@objc open var formLineWidth: CGFloat = CGFloat.nan
/// Line dash configuration for shapes that consist of lines.
///
/// This is how much (in pixels) into the dash pattern are we starting from.
///
/// Set to NaN to use the legend's default.
@objc open var formLineDashPhase: CGFloat = 0.0
/// Line dash configuration for shapes that consist of lines.
///
/// This is the actual dash pattern.
/// I.e. [2, 3] will paint [-- -- ]
/// [1, 3, 4, 2] will paint [- ---- - ---- ]
///
/// Set to nil to use the legend's default.
@objc open var formLineDashLengths: [CGFloat]?
/// The color for drawing the form
@objc open var formColor: NSUIColor?
}
//
// ChartMarkerImage.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
@objc(ChartMarkerImage)
open class MarkerImage: NSObject, IMarker
{
/// The marker image to render
@objc open var image: NSUIImage?
open var offset: CGPoint = CGPoint()
@objc open weak var chartView: ChartViewBase?
/// As long as size is 0.0/0.0 - it will default to the image's size
@objc open var size: CGSize = CGSize()
public override init()
{
super.init()
}
open func offsetForDrawing(atPoint point: CGPoint) -> CGPoint
{
var offset = self.offset
let chart = self.chartView
var size = self.size
if size.width == 0.0 && image != nil
{
size.width = image?.size.width ?? 0.0
}
if size.height == 0.0 && image != nil
{
size.height = image?.size.height ?? 0.0
}
let width = size.width
let height = size.height
if point.x + offset.x < 0.0
{
offset.x = -point.x
}
else if chart != nil && point.x + width + offset.x > chart!.bounds.size.width
{
offset.x = chart!.bounds.size.width - point.x - width
}
if point.y + offset.y < 0
{
offset.y = -point.y
}
else if chart != nil && point.y + height + offset.y > chart!.bounds.size.height
{
offset.y = chart!.bounds.size.height - point.y - height
}
return offset
}
open func refreshContent(entry: ChartDataEntry, highlight: Highlight)
{
// Do nothing here...
}
open func draw(context: CGContext, point: CGPoint)
{
guard let image = image else { return }
let offset = offsetForDrawing(atPoint: point)
var size = self.size
if size.width == 0.0
{
size.width = image.size.width
}
if size.height == 0.0
{
size.height = image.size.height
}
let rect = CGRect(
x: point.x + offset.x,
y: point.y + offset.y,
width: size.width,
height: size.height)
NSUIGraphicsPushContext(context)
image.draw(in: rect)
NSUIGraphicsPopContext()
}
}
//
// ChartMarkerView.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
#if canImport(AppKit)
import AppKit
#endif
@objc(ChartMarkerView)
open class MarkerView: NSUIView, IMarker
{
open var offset: CGPoint = CGPoint()
@objc open weak var chartView: ChartViewBase?
open func offsetForDrawing(atPoint point: CGPoint) -> CGPoint
{
guard let chart = chartView else { return self.offset }
var offset = self.offset
let width = self.bounds.size.width
let height = self.bounds.size.height
if point.x + offset.x < 0.0
{
offset.x = -point.x
}
else if point.x + width + offset.x > chart.bounds.size.width
{
offset.x = chart.bounds.size.width - point.x - width
}
if point.y + offset.y < 0
{
offset.y = -point.y
}
else if point.y + height + offset.y > chart.bounds.size.height
{
offset.y = chart.bounds.size.height - point.y - height
}
return offset
}
open func refreshContent(entry: ChartDataEntry, highlight: Highlight)
{
// Do nothing here...
}
open func draw(context: CGContext, point: CGPoint)
{
let offset = self.offsetForDrawing(atPoint: point)
context.saveGState()
context.translateBy(x: point.x + offset.x,
y: point.y + offset.y)
NSUIGraphicsPushContext(context)
self.nsuiLayer?.render(in: context)
NSUIGraphicsPopContext()
context.restoreGState()
}
@objc
open class func viewFromXib(in bundle: Bundle = .main) -> MarkerView?
{
#if !os(OSX)
return bundle.loadNibNamed(
String(describing: self),
owner: nil,
options: nil)?[0] as? MarkerView
#else
var loadedObjects = NSArray()
let loadedObjectsPointer = AutoreleasingUnsafeMutablePointer<NSArray?>(&loadedObjects)
if bundle.loadNibNamed(
NSNib.Name(String(describing: self)),
owner: nil,
topLevelObjects: loadedObjectsPointer)
{
return loadedObjects[0] as? MarkerView
}
return nil
#endif
}
}
//
// XAxis.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
@objc(ChartXAxis)
open class XAxis: AxisBase
{
@objc(XAxisLabelPosition)
public enum LabelPosition: Int
{
case top
case bottom
case bothSided
case topInside
case bottomInside
}
/// width of the x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers
@objc open var labelWidth = CGFloat(1.0)
/// height of the x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers
@objc open var labelHeight = CGFloat(1.0)
/// width of the (rotated) x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers
@objc open var labelRotatedWidth = CGFloat(1.0)
/// height of the (rotated) x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers
@objc open var labelRotatedHeight = CGFloat(1.0)
/// This is the angle for drawing the X axis labels (in degrees)
@objc open var labelRotationAngle = CGFloat(0.0)
/// if set to true, the chart will avoid that the first and last label entry in the chart "clip" off the edge of the chart
@objc open var avoidFirstLastClippingEnabled = false
/// the position of the x-labels relative to the chart
@objc open var labelPosition = LabelPosition.top
/// if set to true, word wrapping the labels will be enabled.
/// word wrapping is done using `(value width * labelRotatedWidth)`
///
/// - Note: currently supports all charts except pie/radar/horizontal-bar*
@objc open var wordWrapEnabled = false
/// `true` if word wrapping the labels is enabled
@objc open var isWordWrapEnabled: Bool { return wordWrapEnabled }
/// the width for wrapping the labels, as percentage out of one value width.
/// used only when isWordWrapEnabled = true.
///
/// **default**: 1.0
@objc open var wordWrapWidthPercent: CGFloat = 1.0
public override init()
{
super.init()
self.yOffset = 4.0
}
@objc open var isAvoidFirstLastClippingEnabled: Bool
{
return avoidFirstLastClippingEnabled
}
}
//
// YAxis.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
#if canImport(UIKit)
import UIKit
#endif
#if canImport(Cocoa)
import Cocoa
#endif
/// Class representing the y-axis labels settings and its entries.
/// Be aware that not all features the YLabels class provides are suitable for the RadarChart.
/// Customizations that affect the value range of the axis need to be applied before setting data for the chart.
@objc(ChartYAxis)
open class YAxis: AxisBase
{
@objc(YAxisLabelPosition)
public enum LabelPosition: Int
{
case outsideChart
case insideChart
}
/// Enum that specifies the axis a DataSet should be plotted against, either Left or Right.
@objc
public enum AxisDependency: Int
{
case left
case right
}
/// indicates if the bottom y-label entry is drawn or not
@objc open var drawBottomYLabelEntryEnabled = true
/// indicates if the top y-label entry is drawn or not
@objc open var drawTopYLabelEntryEnabled = true
/// flag that indicates if the axis is inverted or not
@objc open var inverted = false
/// flag that indicates if the zero-line should be drawn regardless of other grid lines
@objc open var drawZeroLineEnabled = false
/// Color of the zero line
@objc open var zeroLineColor: NSUIColor? = NSUIColor.gray
/// Width of the zero line
@objc open var zeroLineWidth: CGFloat = 1.0
/// This is how much (in pixels) into the dash pattern are we starting from.
@objc open var zeroLineDashPhase = CGFloat(0.0)
/// This is the actual dash pattern.
/// I.e. [2, 3] will paint [-- -- ]
/// [1, 3, 4, 2] will paint [- ---- - ---- ]
@objc open var zeroLineDashLengths: [CGFloat]?
/// axis space from the largest value to the top in percent of the total axis range
@objc open var spaceTop = CGFloat(0.1)
/// axis space from the smallest value to the bottom in percent of the total axis range
@objc open var spaceBottom = CGFloat(0.1)
/// the position of the y-labels relative to the chart
@objc open var labelPosition = LabelPosition.outsideChart
/// the alignment of the text in the y-label
@objc open var labelAlignment: NSTextAlignment = .left
/// the horizontal offset of the y-label
@objc open var labelXOffset: CGFloat = 0.0
/// the side this axis object represents
private var _axisDependency = AxisDependency.left
/// the minimum width that the axis should take
///
/// **default**: 0.0
@objc open var minWidth = CGFloat(0)
/// the maximum width that the axis can take.
/// use Infinity for disabling the maximum.
///
/// **default**: CGFloat.infinity
@objc open var maxWidth = CGFloat(CGFloat.infinity)
public override init()
{
super.init()
self.yOffset = 0.0
}
@objc public init(position: AxisDependency)
{
super.init()
_axisDependency = position
self.yOffset = 0.0
}
@objc open var axisDependency: AxisDependency
{
return _axisDependency
}
@objc open func requiredSize() -> CGSize
{
let label = getLongestLabel() as NSString
var size = label.size(withAttributes: [NSAttributedString.Key.font: labelFont])
size.width += xOffset * 2.0
size.height += yOffset * 2.0
size.width = max(minWidth, min(size.width, maxWidth > 0.0 ? maxWidth : size.width))
return size
}
@objc open func getRequiredHeightSpace() -> CGFloat
{
return requiredSize().height
}
/// `true` if this axis needs horizontal offset, `false` ifno offset is needed.
@objc open var needsOffset: Bool
{
if isEnabled && isDrawLabelsEnabled && labelPosition == .outsideChart
{
return true
}
else
{
return false
}
}
@objc open var isInverted: Bool { return inverted }
open override func calculate(min dataMin: Double, max dataMax: Double)
{
// if custom, use value as is, else use data value
var min = _customAxisMin ? _axisMinimum : dataMin
var max = _customAxisMax ? _axisMaximum : dataMax
// Make sure max is greater than min
// Discussion: https://github.com/danielgindi/Charts/pull/3650#discussion_r221409991
if min > max
{
switch(_customAxisMax, _customAxisMin)
{
case(true, true):
(min, max) = (max, min)
case(true, false):
min = max < 0 ? max * 1.5 : max * 0.5
case(false, true):
max = min < 0 ? min * 0.5 : min * 1.5
case(false, false):
break
}
}
// temporary range (before calculations)
let range = abs(max - min)
// in case all values are equal
if range == 0.0
{
max = max + 1.0
min = min - 1.0
}
// bottom-space only effects non-custom min
if !_customAxisMin
{
let bottomSpace = range * Double(spaceBottom)
_axisMinimum = (min - bottomSpace)
}
// top-space only effects non-custom max
if !_customAxisMax
{
let topSpace = range * Double(spaceTop)
_axisMaximum = (max + topSpace)
}
// calc actual range
axisRange = abs(_axisMaximum - _axisMinimum)
}
@objc open var isDrawBottomYLabelEntryEnabled: Bool { return drawBottomYLabelEntryEnabled }
@objc open var isDrawTopYLabelEntryEnabled: Bool { return drawTopYLabelEntryEnabled }
}
//
// BarChartData.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class BarChartData: BarLineScatterCandleBubbleChartData
{
public override init()
{
super.init()
}
public override init(dataSets: [IChartDataSet]?)
{
super.init(dataSets: dataSets)
}
/// The width of the bars on the x-axis, in values (not pixels)
///
/// **default**: 0.85
@objc open var barWidth = Double(0.85)
/// Groups all BarDataSet objects this data object holds together by modifying the x-value of their entries.
/// Previously set x-values of entries will be overwritten. Leaves space between bars and groups as specified by the parameters.
/// Do not forget to call notifyDataSetChanged() on your BarChart object after calling this method.
///
/// - Parameters:
/// - fromX: the starting point on the x-axis where the grouping should begin
/// - groupSpace: The space between groups of bars in values (not pixels) e.g. 0.8f for bar width 1f
/// - barSpace: The space between individual bars in values (not pixels) e.g. 0.1f for bar width 1f
@objc open func groupBars(fromX: Double, groupSpace: Double, barSpace: Double)
{
let setCount = _dataSets.count
if setCount <= 1
{
print("BarData needs to hold at least 2 BarDataSets to allow grouping.", terminator: "\n")
return
}
let max = maxEntryCountSet
let maxEntryCount = max?.entryCount ?? 0
let groupSpaceWidthHalf = groupSpace / 2.0
let barSpaceHalf = barSpace / 2.0
let barWidthHalf = self.barWidth / 2.0
var fromX = fromX
let interval = groupWidth(groupSpace: groupSpace, barSpace: barSpace)
for i in stride(from: 0, to: maxEntryCount, by: 1)
{
let start = fromX
fromX += groupSpaceWidthHalf
(_dataSets as? [IBarChartDataSet])?.forEach { set in
fromX += barSpaceHalf
fromX += barWidthHalf
if i < set.entryCount
{
if let entry = set.entryForIndex(i)
{
entry.x = fromX
}
}
fromX += barWidthHalf
fromX += barSpaceHalf
}
fromX += groupSpaceWidthHalf
let end = fromX
let innerInterval = end - start
let diff = interval - innerInterval
// correct rounding errors
if diff > 0 || diff < 0
{
fromX += diff
}
}
notifyDataChanged()
}
/// In case of grouped bars, this method returns the space an individual group of bar needs on the x-axis.
///
/// - Parameters:
/// - groupSpace:
/// - barSpace:
@objc open func groupWidth(groupSpace: Double, barSpace: Double) -> Double
{
return Double(_dataSets.count) * (self.barWidth + barSpace) + groupSpace
}
}
//
// BarChartDataEntry.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
open class BarChartDataEntry: ChartDataEntry
{
/// the values the stacked barchart holds
private var _yVals: [Double]?
/// the ranges for the individual stack values - automatically calculated
private var _ranges: [Range]?
/// the sum of all negative values this entry (if stacked) contains
private var _negativeSum: Double = 0.0
/// the sum of all positive values this entry (if stacked) contains
private var _positiveSum: Double = 0.0
public required init()
{
super.init()
}
/// Constructor for normal bars (not stacked).
public override init(x: Double, y: Double)
{
super.init(x: x, y: y)
}
/// Constructor for normal bars (not stacked).
public convenience init(x: Double, y: Double, data: Any?)
{
self.init(x: x, y: y)
self.data = data
}
/// Constructor for normal bars (not stacked).
public convenience init(x: Double, y: Double, icon: NSUIImage?)
{
self.init(x: x, y: y)
self.icon = icon
}
/// Constructor for normal bars (not stacked).
public convenience init(x: Double, y: Double, icon: NSUIImage?, data: Any?)
{
self.init(x: x, y: y)
self.icon = icon
self.data = data
}
/// Constructor for stacked bar entries.
@objc public init(x: Double, yValues: [Double])
{
super.init(x: x, y: BarChartDataEntry.calcSum(values: yValues))
self._yVals = yValues
calcPosNegSum()
calcRanges()
}
/// Constructor for stacked bar entries. One data object for whole stack
@objc public convenience init(x: Double, yValues: [Double], icon: NSUIImage?)
{
self.init(x: x, yValues: yValues)
self.icon = icon
}
/// Constructor for stacked bar entries. One data object for whole stack
@objc public convenience init(x: Double, yValues: [Double], data: Any?)
{
self.init(x: x, yValues: yValues)
self.data = data
}
/// Constructor for stacked bar entries. One data object for whole stack
@objc public convenience init(x: Double, yValues: [Double], icon: NSUIImage?, data: Any?)
{
self.init(x: x, yValues: yValues)
self.icon = icon
self.data = data
}
@objc open func sumBelow(stackIndex :Int) -> Double
{
guard let yVals = _yVals else
{
return 0
}
var remainder: Double = 0.0
var index = yVals.count - 1
while (index > stackIndex && index >= 0)
{
remainder += yVals[index]
index -= 1
}
return remainder
}
/// The sum of all negative values this entry (if stacked) contains. (this is a positive number)
@objc open var negativeSum: Double
{
return _negativeSum
}
/// The sum of all positive values this entry (if stacked) contains.
@objc open var positiveSum: Double
{
return _positiveSum
}
@objc open func calcPosNegSum()
{
(_negativeSum, _positiveSum) = _yVals?.reduce(into: (0,0)) { (result, y) in
if y < 0
{
result.0 += -y
}
else
{
result.1 += y
}
} ?? (0,0)
}
/// Splits up the stack-values of the given bar-entry into Range objects.
///
/// - Parameters:
/// - entry:
/// - Returns:
@objc open func calcRanges()
{
guard let values = yValues, !values.isEmpty else { return }
if _ranges == nil
{
_ranges = [Range]()
}
else
{
_ranges!.removeAll()
}
_ranges!.reserveCapacity(values.count)
var negRemain = -negativeSum
var posRemain: Double = 0.0
for value in values
{
if value < 0
{
_ranges!.append(Range(from: negRemain, to: negRemain - value))
negRemain -= value
}
else
{
_ranges!.append(Range(from: posRemain, to: posRemain + value))
posRemain += value
}
}
}
// MARK: Accessors
/// the values the stacked barchart holds
@objc open var isStacked: Bool { return _yVals != nil }
/// the values the stacked barchart holds
@objc open var yValues: [Double]?
{
get { return self._yVals }
set
{
self.y = BarChartDataEntry.calcSum(values: newValue)
self._yVals = newValue
calcPosNegSum()
calcRanges()
}
}
/// The ranges of the individual stack-entries. Will return null if this entry is not stacked.
@objc open var ranges: [Range]?
{
return _ranges
}
// MARK: NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! BarChartDataEntry
copy._yVals = _yVals
copy.y = y
copy._negativeSum = _negativeSum
copy._positiveSum = _positiveSum
return copy
}
/// Calculates the sum across all values of the given stack.
///
/// - Parameters:
/// - vals:
/// - Returns:
private static func calcSum(values: [Double]?) -> Double
{
guard let values = values
else { return 0.0 }
var sum = 0.0
for f in values
{
sum += f
}
return sum
}
}
//
// BarChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet, IBarChartDataSet
{
private func initialize()
{
self.highlightColor = NSUIColor.black
self.calcStackSize(entries: entries as! [BarChartDataEntry])
self.calcEntryCountIncludingStacks(entries: entries as! [BarChartDataEntry])
}
public required init()
{
super.init()
initialize()
}
public override init(entries: [ChartDataEntry]?, label: String?)
{
super.init(entries: entries, label: label)
initialize()
}
// MARK: - Data functions and accessors
/// the maximum number of bars that are stacked upon each other, this value
/// is calculated from the Entries that are added to the DataSet
private var _stackSize = 1
/// the overall entry count, including counting each stack-value individually
private var _entryCountStacks = 0
/// Calculates the total number of entries this DataSet represents, including
/// stacks. All values belonging to a stack are calculated separately.
private func calcEntryCountIncludingStacks(entries: [BarChartDataEntry])
{
_entryCountStacks = 0
for i in 0 ..< entries.count
{
if let vals = entries[i].yValues
{
_entryCountStacks += vals.count
}
else
{
_entryCountStacks += 1
}
}
}
/// calculates the maximum stacksize that occurs in the Entries array of this DataSet
private func calcStackSize(entries: [BarChartDataEntry])
{
for i in 0 ..< entries.count
{
if let vals = entries[i].yValues
{
if vals.count > _stackSize
{
_stackSize = vals.count
}
}
}
}
open override func calcMinMax(entry e: ChartDataEntry)
{
guard let e = e as? BarChartDataEntry
else { return }
if !e.y.isNaN
{
if e.yValues == nil
{
if e.y < _yMin
{
_yMin = e.y
}
if e.y > _yMax
{
_yMax = e.y
}
}
else
{
if -e.negativeSum < _yMin
{
_yMin = -e.negativeSum
}
if e.positiveSum > _yMax
{
_yMax = e.positiveSum
}
}
calcMinMaxX(entry: e)
}
}
/// The maximum number of bars that can be stacked upon another in this DataSet.
open var stackSize: Int
{
return _stackSize
}
/// `true` if this DataSet is stacked (stacksize > 1) or not.
open var isStacked: Bool
{
return _stackSize > 1 ? true : false
}
/// The overall entry count, including counting each stack-value individually
@objc open var entryCountStacks: Int
{
return _entryCountStacks
}
/// array of labels used to describe the different values of the stacked bars
open var stackLabels: [String] = []
// MARK: - Styling functions and accessors
/// the color used for drawing the bar-shadows. The bar shadows is a surface behind the bar that indicates the maximum value
open var barShadowColor = NSUIColor(red: 215.0/255.0, green: 215.0/255.0, blue: 215.0/255.0, alpha: 1.0)
/// the width used for drawing borders around the bars. If borderWidth == 0, no border will be drawn.
open var barBorderWidth : CGFloat = 0.0
/// the color drawing borders around the bars.
open var barBorderColor = NSUIColor.black
/// the alpha value (transparency) that is used for drawing the highlight indicator bar. min = 0.0 (fully transparent), max = 1.0 (fully opaque)
open var highlightAlpha = CGFloat(120.0 / 255.0)
// MARK: - NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! BarChartDataSet
copy._stackSize = _stackSize
copy._entryCountStacks = _entryCountStacks
copy.stackLabels = stackLabels
copy.barShadowColor = barShadowColor
copy.barBorderWidth = barBorderWidth
copy.barBorderColor = barBorderColor
copy.highlightAlpha = highlightAlpha
return copy
}
}
//
// BarLineScatterCandleBubbleChartData.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
open class BarLineScatterCandleBubbleChartData: ChartData
{
public override init()
{
super.init()
}
public override init(dataSets: [IChartDataSet]?)
{
super.init(dataSets: dataSets)
}
}
//
// BarLineScatterCandleBubbleChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class BarLineScatterCandleBubbleChartDataSet: ChartDataSet, IBarLineScatterCandleBubbleChartDataSet
{
// MARK: - Data functions and accessors
// MARK: - Styling functions and accessors
open var highlightColor = NSUIColor(red: 255.0/255.0, green: 187.0/255.0, blue: 115.0/255.0, alpha: 1.0)
open var highlightLineWidth = CGFloat(0.5)
open var highlightLineDashPhase = CGFloat(0.0)
open var highlightLineDashLengths: [CGFloat]?
// MARK: - NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! BarLineScatterCandleBubbleChartDataSet
copy.highlightColor = highlightColor
copy.highlightLineWidth = highlightLineWidth
copy.highlightLineDashPhase = highlightLineDashPhase
copy.highlightLineDashLengths = highlightLineDashLengths
return copy
}
}
//
// BubbleChartData.swift
// Charts
//
// Bubble chart implementation:
// Copyright 2015 Pierre-Marc Airoldi
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class BubbleChartData: BarLineScatterCandleBubbleChartData
{
public override init()
{
super.init()
}
public override init(dataSets: [IChartDataSet]?)
{
super.init(dataSets: dataSets)
}
/// Sets the width of the circle that surrounds the bubble when highlighted for all DataSet objects this data object contains
@objc open func setHighlightCircleWidth(_ width: CGFloat)
{
(_dataSets as? [IBubbleChartDataSet])?.forEach { $0.highlightCircleWidth = width }
}
}
//
// BubbleDataEntry.swift
// Charts
//
// Bubble chart implementation:
// Copyright 2015 Pierre-Marc Airoldi
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class BubbleChartDataEntry: ChartDataEntry
{
/// The size of the bubble.
@objc open var size = CGFloat(0.0)
public required init()
{
super.init()
}
/// - Parameters:
/// - x: The index on the x-axis.
/// - y: The value on the y-axis.
/// - size: The size of the bubble.
@objc public init(x: Double, y: Double, size: CGFloat)
{
super.init(x: x, y: y)
self.size = size
}
/// - Parameters:
/// - x: The index on the x-axis.
/// - y: The value on the y-axis.
/// - size: The size of the bubble.
/// - data: Spot for additional data this Entry represents.
@objc public convenience init(x: Double, y: Double, size: CGFloat, data: Any?)
{
self.init(x: x, y: y, size: size)
self.data = data
}
/// - Parameters:
/// - x: The index on the x-axis.
/// - y: The value on the y-axis.
/// - size: The size of the bubble.
/// - icon: icon image
@objc public convenience init(x: Double, y: Double, size: CGFloat, icon: NSUIImage?)
{
self.init(x: x, y: y, size: size)
self.icon = icon
}
/// - Parameters:
/// - x: The index on the x-axis.
/// - y: The value on the y-axis.
/// - size: The size of the bubble.
/// - icon: icon image
/// - data: Spot for additional data this Entry represents.
@objc public convenience init(x: Double, y: Double, size: CGFloat, icon: NSUIImage?, data: Any?)
{
self.init(x: x, y: y, size: size)
self.icon = icon
self.data = data
}
// MARK: NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! BubbleChartDataEntry
copy.size = size
return copy
}
}
//
// BubbleChartDataSet.swift
// Charts
//
// Bubble chart implementation:
// Copyright 2015 Pierre-Marc Airoldi
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class BubbleChartDataSet: BarLineScatterCandleBubbleChartDataSet, IBubbleChartDataSet
{
// MARK: - Data functions and accessors
internal var _maxSize = CGFloat(0.0)
open var maxSize: CGFloat { return _maxSize }
@objc open var normalizeSizeEnabled: Bool = true
open var isNormalizeSizeEnabled: Bool { return normalizeSizeEnabled }
open override func calcMinMax(entry e: ChartDataEntry)
{
guard let e = e as? BubbleChartDataEntry
else { return }
super.calcMinMax(entry: e)
let size = e.size
if size > _maxSize
{
_maxSize = size
}
}
// MARK: - Styling functions and accessors
/// Sets/gets the width of the circle that surrounds the bubble when highlighted
open var highlightCircleWidth: CGFloat = 2.5
// MARK: - NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! BubbleChartDataSet
copy._xMin = _xMin
copy._xMax = _xMax
copy._maxSize = _maxSize
copy.normalizeSizeEnabled = normalizeSizeEnabled
copy.highlightCircleWidth = highlightCircleWidth
return copy
}
}
//
// CandleChartData.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
open class CandleChartData: BarLineScatterCandleBubbleChartData
{
public override init()
{
super.init()
}
public override init(dataSets: [IChartDataSet]?)
{
super.init(dataSets: dataSets)
}
}
//
// CandleChartDataEntry.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
open class CandleChartDataEntry: ChartDataEntry
{
/// shadow-high value
@objc open var high = Double(0.0)
/// shadow-low value
@objc open var low = Double(0.0)
/// close value
@objc open var close = Double(0.0)
/// open value
@objc open var open = Double(0.0)
public required init()
{
super.init()
}
@objc public init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double)
{
super.init(x: x, y: (shadowH + shadowL) / 2.0)
self.high = shadowH
self.low = shadowL
self.open = open
self.close = close
}
@objc public convenience init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double, icon: NSUIImage?)
{
self.init(x: x, shadowH: shadowH, shadowL: shadowL, open: open, close: close)
self.icon = icon
}
@objc public convenience init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double, data: Any?)
{
self.init(x: x, shadowH: shadowH, shadowL: shadowL, open: open, close: close)
self.data = data
}
@objc public convenience init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double, icon: NSUIImage?, data: Any?)
{
self.init(x: x, shadowH: shadowH, shadowL: shadowL, open: open, close: close)
self.icon = icon
self.data = data
}
/// The overall range (difference) between shadow-high and shadow-low.
@objc open var shadowRange: Double
{
return abs(high - low)
}
/// The body size (difference between open and close).
@objc open var bodyRange: Double
{
return abs(open - close)
}
/// the center value of the candle. (Middle value between high and low)
open override var y: Double
{
get
{
return super.y
}
set
{
super.y = (high + low) / 2.0
}
}
// MARK: NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! CandleChartDataEntry
copy.high = high
copy.low = low
copy.open = open
copy.close = close
return copy
}
}
//
// CandleChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class CandleChartDataSet: LineScatterCandleRadarChartDataSet, ICandleChartDataSet
{
public required init()
{
super.init()
}
public override init(entries: [ChartDataEntry]?, label: String?)
{
super.init(entries: entries, label: label)
}
// MARK: - Data functions and accessors
open override func calcMinMax(entry e: ChartDataEntry)
{
guard let e = e as? CandleChartDataEntry
else { return }
if e.low < _yMin
{
_yMin = e.low
}
if e.high > _yMax
{
_yMax = e.high
}
calcMinMaxX(entry: e)
}
open override func calcMinMaxY(entry e: ChartDataEntry)
{
guard let e = e as? CandleChartDataEntry
else { return }
if e.high < _yMin
{
_yMin = e.high
}
if e.high > _yMax
{
_yMax = e.high
}
if e.low < _yMin
{
_yMin = e.low
}
if e.low > _yMax
{
_yMax = e.low
}
}
// MARK: - Styling functions and accessors
/// the space between the candle entries
///
/// **default**: 0.1 (10%)
private var _barSpace = CGFloat(0.1)
/// the space that is left out on the left and right side of each candle,
/// **default**: 0.1 (10%), max 0.45, min 0.0
open var barSpace: CGFloat
{
get
{
return _barSpace
}
set
{
_barSpace = newValue.clamped(to: 0...0.45)
}
}
/// should the candle bars show?
/// when false, only "ticks" will show
///
/// **default**: true
open var showCandleBar: Bool = true
/// the width of the candle-shadow-line in pixels.
///
/// **default**: 1.5
open var shadowWidth = CGFloat(1.5)
/// the color of the shadow line
open var shadowColor: NSUIColor?
/// use candle color for the shadow
open var shadowColorSameAsCandle = false
/// Is the shadow color same as the candle color?
open var isShadowColorSameAsCandle: Bool { return shadowColorSameAsCandle }
/// color for open == close
open var neutralColor: NSUIColor?
/// color for open > close
open var increasingColor: NSUIColor?
/// color for open < close
open var decreasingColor: NSUIColor?
/// Are increasing values drawn as filled?
/// increasing candlesticks are traditionally hollow
open var increasingFilled = false
/// Are increasing values drawn as filled?
open var isIncreasingFilled: Bool { return increasingFilled }
/// Are decreasing values drawn as filled?
/// descreasing candlesticks are traditionally filled
open var decreasingFilled = true
/// Are decreasing values drawn as filled?
open var isDecreasingFilled: Bool { return decreasingFilled }
}
//
// ChartDataEntry.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
open class ChartDataEntry: ChartDataEntryBase, NSCopying
{
/// the x value
@objc open var x = 0.0
public required init()
{
super.init()
}
/// An Entry represents one single entry in the chart.
///
/// - Parameters:
/// - x: the x value
/// - y: the y value (the actual value of the entry)
@objc public init(x: Double, y: Double)
{
super.init(y: y)
self.x = x
}
/// An Entry represents one single entry in the chart.
///
/// - Parameters:
/// - x: the x value
/// - y: the y value (the actual value of the entry)
/// - data: Space for additional data this Entry represents.
@objc public convenience init(x: Double, y: Double, data: Any?)
{
self.init(x: x, y: y)
self.data = data
}
/// An Entry represents one single entry in the chart.
///
/// - Parameters:
/// - x: the x value
/// - y: the y value (the actual value of the entry)
/// - icon: icon image
@objc public convenience init(x: Double, y: Double, icon: NSUIImage?)
{
self.init(x: x, y: y)
self.icon = icon
}
/// An Entry represents one single entry in the chart.
///
/// - Parameters:
/// - x: the x value
/// - y: the y value (the actual value of the entry)
/// - icon: icon image
/// - data: Space for additional data this Entry represents.
@objc public convenience init(x: Double, y: Double, icon: NSUIImage?, data: Any?)
{
self.init(x: x, y: y)
self.icon = icon
self.data = data
}
// MARK: NSObject
open override var description: String
{
return "ChartDataEntry, x: \(x), y \(y)"
}
// MARK: NSCopying
open func copy(with zone: NSZone? = nil) -> Any
{
let copy = type(of: self).init()
copy.x = x
copy.y = y
copy.data = data
return copy
}
}
// MARK: Equatable
extension ChartDataEntry/*: Equatable*/ {
open override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? ChartDataEntry else { return false }
if self === object
{
return true
}
return y == object.y
&& x == object.x
}
}
//
// ChartDataEntryBase.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
open class ChartDataEntryBase: NSObject
{
/// the y value
@objc open var y = 0.0
/// optional spot for additional data this Entry represents
@objc open var data: Any?
/// optional icon image
@objc open var icon: NSUIImage?
public override required init()
{
super.init()
}
/// An Entry represents one single entry in the chart.
///
/// - Parameters:
/// - y: the y value (the actual value of the entry)
@objc public init(y: Double)
{
super.init()
self.y = y
}
/// - Parameters:
/// - y: the y value (the actual value of the entry)
/// - data: Space for additional data this Entry represents.
@objc public convenience init(y: Double, data: Any?)
{
self.init(y: y)
self.data = data
}
/// - Parameters:
/// - y: the y value (the actual value of the entry)
/// - icon: icon image
@objc public convenience init(y: Double, icon: NSUIImage?)
{
self.init(y: y)
self.icon = icon
}
/// - Parameters:
/// - y: the y value (the actual value of the entry)
/// - icon: icon image
/// - data: Space for additional data this Entry represents.
@objc public convenience init(y: Double, icon: NSUIImage?, data: Any?)
{
self.init(y: y)
self.icon = icon
self.data = data
}
// MARK: NSObject
open override var description: String
{
return "ChartDataEntryBase, y \(y)"
}
}
// MARK: Equatable
extension ChartDataEntryBase/*: Equatable*/ {
open override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? ChartDataEntryBase else { return false }
if self === object
{
return true
}
return y == object.y
}
}
//
// CombinedChartData.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
open class CombinedChartData: BarLineScatterCandleBubbleChartData
{
private var _lineData: LineChartData!
private var _barData: BarChartData!
private var _scatterData: ScatterChartData!
private var _candleData: CandleChartData!
private var _bubbleData: BubbleChartData!
public override init()
{
super.init()
}
public override init(dataSets: [IChartDataSet]?)
{
super.init(dataSets: dataSets)
}
@objc open var lineData: LineChartData!
{
get
{
return _lineData
}
set
{
_lineData = newValue
notifyDataChanged()
}
}
@objc open var barData: BarChartData!
{
get
{
return _barData
}
set
{
_barData = newValue
notifyDataChanged()
}
}
@objc open var scatterData: ScatterChartData!
{
get
{
return _scatterData
}
set
{
_scatterData = newValue
notifyDataChanged()
}
}
@objc open var candleData: CandleChartData!
{
get
{
return _candleData
}
set
{
_candleData = newValue
notifyDataChanged()
}
}
@objc open var bubbleData: BubbleChartData!
{
get
{
return _bubbleData
}
set
{
_bubbleData = newValue
notifyDataChanged()
}
}
open override func calcMinMax()
{
_dataSets.removeAll()
_yMax = -Double.greatestFiniteMagnitude
_yMin = Double.greatestFiniteMagnitude
_xMax = -Double.greatestFiniteMagnitude
_xMin = Double.greatestFiniteMagnitude
_leftAxisMax = -Double.greatestFiniteMagnitude
_leftAxisMin = Double.greatestFiniteMagnitude
_rightAxisMax = -Double.greatestFiniteMagnitude
_rightAxisMin = Double.greatestFiniteMagnitude
let allData = self.allData
for data in allData
{
data.calcMinMax()
let sets = data.dataSets
_dataSets.append(contentsOf: sets)
if data.yMax > _yMax
{
_yMax = data.yMax
}
if data.yMin < _yMin
{
_yMin = data.yMin
}
if data.xMax > _xMax
{
_xMax = data.xMax
}
if data.xMin < _xMin
{
_xMin = data.xMin
}
for dataset in sets
{
if dataset.axisDependency == .left
{
if dataset.yMax > _leftAxisMax
{
_leftAxisMax = dataset.yMax
}
if dataset.yMin < _leftAxisMin
{
_leftAxisMin = dataset.yMin
}
}
else
{
if dataset.yMax > _rightAxisMax
{
_rightAxisMax = dataset.yMax
}
if dataset.yMin < _rightAxisMin
{
_rightAxisMin = dataset.yMin
}
}
}
}
}
/// All data objects in row: line-bar-scatter-candle-bubble if not null.
@objc open var allData: [ChartData]
{
var data = [ChartData]()
if lineData !== nil
{
data.append(lineData)
}
if barData !== nil
{
data.append(barData)
}
if scatterData !== nil
{
data.append(scatterData)
}
if candleData !== nil
{
data.append(candleData)
}
if bubbleData !== nil
{
data.append(bubbleData)
}
return data
}
@objc open func dataByIndex(_ index: Int) -> ChartData
{
return allData[index]
}
open func dataIndex(_ data: ChartData) -> Int?
{
return allData.firstIndex(of: data)
}
open override func removeDataSet(_ dataSet: IChartDataSet) -> Bool
{
return allData.contains { $0.removeDataSet(dataSet) }
}
open override func removeDataSetByIndex(_ index: Int) -> Bool
{
print("removeDataSet(index) not supported for CombinedData", terminator: "\n")
return false
}
open override func removeEntry(_ entry: ChartDataEntry, dataSetIndex: Int) -> Bool
{
print("removeEntry(entry, dataSetIndex) not supported for CombinedData", terminator: "\n")
return false
}
open override func removeEntry(xValue: Double, dataSetIndex: Int) -> Bool
{
print("removeEntry(xValue, dataSetIndex) not supported for CombinedData", terminator: "\n")
return false
}
open override func notifyDataChanged()
{
if _lineData !== nil
{
_lineData.notifyDataChanged()
}
if _barData !== nil
{
_barData.notifyDataChanged()
}
if _scatterData !== nil
{
_scatterData.notifyDataChanged()
}
if _candleData !== nil
{
_candleData.notifyDataChanged()
}
if _bubbleData !== nil
{
_bubbleData.notifyDataChanged()
}
super.notifyDataChanged() // recalculate everything
}
/// Get the Entry for a corresponding highlight object
///
/// - Parameters:
/// - highlight:
/// - Returns: The entry that is highlighted
open override func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry?
{
if highlight.dataIndex >= allData.count
{
return nil
}
let data = dataByIndex(highlight.dataIndex)
if highlight.dataSetIndex >= data.dataSetCount
{
return nil
}
// The value of the highlighted entry could be NaN - if we are not interested in highlighting a specific value.
let entries = data.getDataSetByIndex(highlight.dataSetIndex).entriesForXValue(highlight.x)
return entries.first { $0.y == highlight.y || highlight.y.isNaN }
}
/// Get dataset for highlight
///
/// - Parameters:
/// - highlight: current highlight
/// - Returns: dataset related to highlight
@objc open func getDataSetByHighlight(_ highlight: Highlight) -> IChartDataSet!
{
if highlight.dataIndex >= allData.count
{
return nil
}
let data = dataByIndex(highlight.dataIndex)
if highlight.dataSetIndex >= data.dataSetCount
{
return nil
}
return data.dataSets[highlight.dataSetIndex]
}
}
//
// LineChartData.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
/// Data object that encapsulates all data associated with a LineChart.
open class LineChartData: ChartData
{
public override init()
{
super.init()
}
public override init(dataSets: [IChartDataSet]?)
{
super.init(dataSets: dataSets)
}
}
//
// LineChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class LineChartDataSet: LineRadarChartDataSet, ILineChartDataSet
{
@objc(LineChartMode)
public enum Mode: Int
{
case linear
case stepped
case cubicBezier
case horizontalBezier
}
private func initialize()
{
// default color
circleColors.append(NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0))
}
public required init()
{
super.init()
initialize()
}
public override init(entries: [ChartDataEntry]?, label: String?)
{
super.init(entries: entries, label: label)
initialize()
}
// MARK: - Data functions and accessors
// MARK: - Styling functions and accessors
/// The drawing mode for this line dataset
///
/// **default**: Linear
open var mode: Mode = Mode.linear
private var _cubicIntensity = CGFloat(0.2)
/// Intensity for cubic lines (min = 0.05, max = 1)
///
/// **default**: 0.2
open var cubicIntensity: CGFloat
{
get
{
return _cubicIntensity
}
set
{
_cubicIntensity = newValue.clamped(to: 0.05...1)
}
}
/// The radius of the drawn circles.
open var circleRadius = CGFloat(8.0)
/// The hole radius of the drawn circles
open var circleHoleRadius = CGFloat(4.0)
open var circleColors = [NSUIColor]()
/// - Returns: The color at the given index of the DataSet's circle-color array.
/// Performs a IndexOutOfBounds check by modulus.
open func getCircleColor(atIndex index: Int) -> NSUIColor?
{
let size = circleColors.count
let index = index % size
if index >= size
{
return nil
}
return circleColors[index]
}
/// Sets the one and ONLY color that should be used for this DataSet.
/// Internally, this recreates the colors array and adds the specified color.
open func setCircleColor(_ color: NSUIColor)
{
circleColors.removeAll(keepingCapacity: false)
circleColors.append(color)
}
open func setCircleColors(_ colors: NSUIColor...)
{
circleColors.removeAll(keepingCapacity: false)
circleColors.append(contentsOf: colors)
}
/// Resets the circle-colors array and creates a new one
open func resetCircleColors(_ index: Int)
{
circleColors.removeAll(keepingCapacity: false)
}
/// If true, drawing circles is enabled
open var drawCirclesEnabled = true
/// `true` if drawing circles for this DataSet is enabled, `false` ifnot
open var isDrawCirclesEnabled: Bool { return drawCirclesEnabled }
/// The color of the inner circle (the circle-hole).
open var circleHoleColor: NSUIColor? = NSUIColor.white
/// `true` if drawing circles for this DataSet is enabled, `false` ifnot
open var drawCircleHoleEnabled = true
/// `true` if drawing the circle-holes is enabled, `false` ifnot.
open var isDrawCircleHoleEnabled: Bool { return drawCircleHoleEnabled }
/// This is how much (in pixels) into the dash pattern are we starting from.
open var lineDashPhase = CGFloat(0.0)
/// This is the actual dash pattern.
/// I.e. [2, 3] will paint [-- -- ]
/// [1, 3, 4, 2] will paint [- ---- - ---- ]
open var lineDashLengths: [CGFloat]?
/// Line cap type, default is CGLineCap.Butt
open var lineCapType = CGLineCap.butt
/// formatter for customizing the position of the fill-line
private var _fillFormatter: IFillFormatter = DefaultFillFormatter()
/// Sets a custom IFillFormatter to the chart that handles the position of the filled-line for each DataSet. Set this to null to use the default logic.
open var fillFormatter: IFillFormatter?
{
get
{
return _fillFormatter
}
set
{
_fillFormatter = newValue ?? DefaultFillFormatter()
}
}
// MARK: NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! LineChartDataSet
copy.circleColors = circleColors
copy.circleHoleColor = circleHoleColor
copy.circleRadius = circleRadius
copy.circleHoleRadius = circleHoleRadius
copy.cubicIntensity = cubicIntensity
copy.lineDashPhase = lineDashPhase
copy.lineDashLengths = lineDashLengths
copy.lineCapType = lineCapType
copy.drawCirclesEnabled = drawCirclesEnabled
copy.drawCircleHoleEnabled = drawCircleHoleEnabled
copy.mode = mode
copy._fillFormatter = _fillFormatter
return copy
}
}
//
// LineRadarChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class LineRadarChartDataSet: LineScatterCandleRadarChartDataSet, ILineRadarChartDataSet
{
// MARK: - Data functions and accessors
// MARK: - Styling functions and accessors
/// The color that is used for filling the line surface area.
private var _fillColor = NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0)
/// The color that is used for filling the line surface area.
open var fillColor: NSUIColor
{
get { return _fillColor }
set
{
_fillColor = newValue
fill = nil
}
}
/// The object that is used for filling the area below the line.
/// **default**: nil
open var fill: Fill?
/// The alpha value that is used for filling the line surface,
/// **default**: 0.33
open var fillAlpha = CGFloat(0.33)
private var _lineWidth = CGFloat(1.0)
/// line width of the chart (min = 0.0, max = 10)
///
/// **default**: 1
open var lineWidth: CGFloat
{
get
{
return _lineWidth
}
set
{
_lineWidth = newValue.clamped(to: 0...10)
}
}
/// Set to `true` if the DataSet should be drawn filled (surface), and not just as a line.
/// Disabling this will give great performance boost.
/// Please note that this method uses the path clipping for drawing the filled area (with images, gradients and layers).
open var drawFilledEnabled = false
/// `true` if filled drawing is enabled, `false` ifnot
open var isDrawFilledEnabled: Bool
{
return drawFilledEnabled
}
// MARK: NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! LineRadarChartDataSet
copy.fill = fill
copy.fillAlpha = fillAlpha
copy._fillColor = _fillColor
copy._lineWidth = _lineWidth
copy.drawFilledEnabled = drawFilledEnabled
return copy
}
}
//
// LineScatterCandleRadarChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
open class LineScatterCandleRadarChartDataSet: BarLineScatterCandleBubbleChartDataSet, ILineScatterCandleRadarChartDataSet
{
// MARK: - Data functions and accessors
// MARK: - Styling functions and accessors
/// Enables / disables the horizontal highlight-indicator. If disabled, the indicator is not drawn.
open var drawHorizontalHighlightIndicatorEnabled = true
/// Enables / disables the vertical highlight-indicator. If disabled, the indicator is not drawn.
open var drawVerticalHighlightIndicatorEnabled = true
/// `true` if horizontal highlight indicator lines are enabled (drawn)
open var isHorizontalHighlightIndicatorEnabled: Bool { return drawHorizontalHighlightIndicatorEnabled }
/// `true` if vertical highlight indicator lines are enabled (drawn)
open var isVerticalHighlightIndicatorEnabled: Bool { return drawVerticalHighlightIndicatorEnabled }
/// Enables / disables both vertical and horizontal highlight-indicators.
/// :param: enabled
open func setDrawHighlightIndicators(_ enabled: Bool)
{
drawHorizontalHighlightIndicatorEnabled = enabled
drawVerticalHighlightIndicatorEnabled = enabled
}
// MARK: NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! LineScatterCandleRadarChartDataSet
copy.drawHorizontalHighlightIndicatorEnabled = drawHorizontalHighlightIndicatorEnabled
copy.drawVerticalHighlightIndicatorEnabled = drawVerticalHighlightIndicatorEnabled
return copy
}
}
//
// PieData.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
open class PieChartData: ChartData
{
public override init()
{
super.init()
}
public override init(dataSets: [IChartDataSet]?)
{
super.init(dataSets: dataSets)
}
/// All DataSet objects this ChartData object holds.
@objc open override var dataSets: [IChartDataSet]
{
get
{
assert(super.dataSets.count <= 1, "Found multiple data sets while pie chart only allows one")
return super.dataSets
}
set
{
super.dataSets = newValue
}
}
@objc var dataSet: IPieChartDataSet?
{
get
{
return dataSets.count > 0 ? dataSets[0] as? IPieChartDataSet : nil
}
set
{
if let newValue = newValue
{
dataSets = [newValue]
}
else
{
dataSets = []
}
}
}
open override func getDataSetByIndex(_ index: Int) -> IChartDataSet?
{
if index != 0
{
return nil
}
return super.getDataSetByIndex(index)
}
open override func getDataSetByLabel(_ label: String, ignorecase: Bool) -> IChartDataSet?
{
if dataSets.count == 0 || dataSets[0].label == nil
{
return nil
}
if ignorecase
{
if let label = dataSets[0].label, label.caseInsensitiveCompare(label) == .orderedSame
{
return dataSets[0]
}
}
else
{
if label == dataSets[0].label
{
return dataSets[0]
}
}
return nil
}
open override func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry?
{
return dataSet?.entryForIndex(Int(highlight.x))
}
open override func addDataSet(_ d: IChartDataSet!)
{
super.addDataSet(d)
}
/// Removes the DataSet at the given index in the DataSet array from the data object.
/// Also recalculates all minimum and maximum values.
///
/// - Returns: `true` if a DataSet was removed, `false` ifno DataSet could be removed.
open override func removeDataSetByIndex(_ index: Int) -> Bool
{
if index >= _dataSets.count || index < 0
{
return false
}
return false
}
/// The total y-value sum across all DataSet objects the this object represents.
@objc open var yValueSum: Double
{
guard let dataSet = dataSet else { return 0.0 }
return (0..<dataSet.entryCount).reduce(into: 0) {
$0 += dataSet.entryForIndex($1)?.y ?? 0
}
}
}
//
// PieChartDataEntry.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class PieChartDataEntry: ChartDataEntry
{
public required init()
{
super.init()
}
/// - Parameters:
/// - value: The value on the y-axis
@objc public init(value: Double)
{
super.init(x: .nan, y: value)
}
/// - Parameters:
/// - value: The value on the y-axis
/// - label: The label for the x-axis
@objc public convenience init(value: Double, label: String?)
{
self.init(value: value)
self.label = label
}
/// - Parameters:
/// - value: The value on the y-axis
/// - label: The label for the x-axis
/// - data: Spot for additional data this Entry represents
@objc public convenience init(value: Double, label: String?, data: Any?)
{
self.init(value: value, label: label, icon: nil, data: data)
}
/// - Parameters:
/// - value: The value on the y-axis
/// - label: The label for the x-axis
/// - icon: icon image
@objc public convenience init(value: Double, label: String?, icon: NSUIImage?)
{
self.init(value: value)
self.label = label
self.icon = icon
}
/// - Parameters:
/// - value: The value on the y-axis
/// - label: The label for the x-axis
/// - icon: icon image
/// - data: Spot for additional data this Entry represents
@objc public convenience init(value: Double, label: String?, icon: NSUIImage?, data: Any?)
{
self.init(value: value)
self.label = label
self.icon = icon
self.data = data
}
/// - Parameters:
/// - value: The value on the y-axis
/// - data: Spot for additional data this Entry represents
@objc public convenience init(value: Double, data: Any?)
{
self.init(value: value)
self.data = data
}
/// - Parameters:
/// - value: The value on the y-axis
/// - icon: icon image
@objc public convenience init(value: Double, icon: NSUIImage?)
{
self.init(value: value)
self.icon = icon
}
/// - Parameters:
/// - value: The value on the y-axis
/// - icon: icon image
/// - data: Spot for additional data this Entry represents
@objc public convenience init(value: Double, icon: NSUIImage?, data: Any?)
{
self.init(value: value)
self.icon = icon
self.data = data
}
// MARK: Data property accessors
@objc open var label: String?
@objc open var value: Double
{
get { return y }
set { y = newValue }
}
// MARK: NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! PieChartDataEntry
copy.label = label
return copy
}
}
//
// PieChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class PieChartDataSet: ChartDataSet, IPieChartDataSet
{
@objc(PieChartValuePosition)
public enum ValuePosition: Int
{
case insideSlice
case outsideSlice
}
private func initialize()
{
self.valueTextColor = NSUIColor.white
self.valueFont = NSUIFont.systemFont(ofSize: 13.0)
}
public required init()
{
super.init()
initialize()
}
public override init(entries: [ChartDataEntry]?, label: String?)
{
super.init(entries: entries, label: label)
initialize()
}
internal override func calcMinMax(entry e: ChartDataEntry)
{
calcMinMaxY(entry: e)
}
// MARK: - Styling functions and accessors
private var _sliceSpace = CGFloat(0.0)
/// the space in pixels between the pie-slices
/// **default**: 0
/// **maximum**: 20
open var sliceSpace: CGFloat
{
get
{
return _sliceSpace
}
set
{
var space = newValue
if space > 20.0
{
space = 20.0
}
if space < 0.0
{
space = 0.0
}
_sliceSpace = space
}
}
/// When enabled, slice spacing will be 0.0 when the smallest value is going to be smaller than the slice spacing itself.
open var automaticallyDisableSliceSpacing: Bool = false
/// indicates the selection distance of a pie slice
open var selectionShift = CGFloat(18.0)
open var xValuePosition: ValuePosition = .insideSlice
open var yValuePosition: ValuePosition = .insideSlice
/// When valuePosition is OutsideSlice, indicates line color
open var valueLineColor: NSUIColor? = NSUIColor.black
/// When valuePosition is OutsideSlice and enabled, line will have the same color as the slice
open var useValueColorForLine: Bool = false
/// When valuePosition is OutsideSlice, indicates line width
open var valueLineWidth: CGFloat = 1.0
/// When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size
open var valueLinePart1OffsetPercentage: CGFloat = 0.75
/// When valuePosition is OutsideSlice, indicates length of first half of the line
open var valueLinePart1Length: CGFloat = 0.3
/// When valuePosition is OutsideSlice, indicates length of second half of the line
open var valueLinePart2Length: CGFloat = 0.4
/// When valuePosition is OutsideSlice, this allows variable line length
open var valueLineVariableLength: Bool = true
/// the font for the slice-text labels
open var entryLabelFont: NSUIFont? = nil
/// the color for the slice-text labels
open var entryLabelColor: NSUIColor? = nil
/// the color for the highlighted sector
open var highlightColor: NSUIColor? = nil
// MARK: - NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! PieChartDataSet
copy._sliceSpace = _sliceSpace
copy.automaticallyDisableSliceSpacing = automaticallyDisableSliceSpacing
copy.selectionShift = selectionShift
copy.xValuePosition = xValuePosition
copy.yValuePosition = yValuePosition
copy.valueLineColor = valueLineColor
copy.valueLineWidth = valueLineWidth
copy.valueLinePart1OffsetPercentage = valueLinePart1OffsetPercentage
copy.valueLinePart1Length = valueLinePart1Length
copy.valueLinePart2Length = valueLinePart2Length
copy.valueLineVariableLength = valueLineVariableLength
copy.entryLabelFont = entryLabelFont
copy.entryLabelColor = entryLabelColor
copy.highlightColor = highlightColor
return copy
}
}
//
// RadarChartData.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class RadarChartData: ChartData
{
@objc open var highlightColor = NSUIColor(red: 255.0/255.0, green: 187.0/255.0, blue: 115.0/255.0, alpha: 1.0)
@objc open var highlightLineWidth = CGFloat(1.0)
@objc open var highlightLineDashPhase = CGFloat(0.0)
@objc open var highlightLineDashLengths: [CGFloat]?
/// Sets labels that should be drawn around the RadarChart at the end of each web line.
@objc open var labels = [String]()
/// Sets the labels that should be drawn around the RadarChart at the end of each web line.
open func setLabels(_ labels: String...)
{
self.labels = labels
}
public override init()
{
super.init()
}
public override init(dataSets: [IChartDataSet]?)
{
super.init(dataSets: dataSets)
}
open override func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry?
{
return getDataSetByIndex(highlight.dataSetIndex)?.entryForIndex(Int(highlight.x))
}
}
//
// RadarChartDataEntry.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class RadarChartDataEntry: ChartDataEntry
{
public required init()
{
super.init()
}
/// - Parameters:
/// - value: The value on the y-axis.
@objc public init(value: Double)
{
super.init(x: .nan, y: value)
}
/// - Parameters:
/// - value: The value on the y-axis.
/// - data: Spot for additional data this Entry represents.
@objc public convenience init(value: Double, data: Any?)
{
self.init(value: value)
self.data = data
}
// MARK: Data property accessors
@objc open var value: Double
{
get { return y }
set { y = newValue }
}
// MARK: NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! RadarChartDataEntry
return copy
}
}
//
// RadarChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class RadarChartDataSet: LineRadarChartDataSet, IRadarChartDataSet
{
private func initialize()
{
self.valueFont = NSUIFont.systemFont(ofSize: 13.0)
}
public required init()
{
super.init()
initialize()
}
public required override init(entries: [ChartDataEntry]?, label: String?)
{
super.init(entries: entries, label: label)
initialize()
}
// MARK: - Data functions and accessors
// MARK: - Styling functions and accessors
/// flag indicating whether highlight circle should be drawn or not
/// **default**: false
open var drawHighlightCircleEnabled: Bool = false
/// `true` if highlight circle should be drawn, `false` ifnot
open var isDrawHighlightCircleEnabled: Bool { return drawHighlightCircleEnabled }
open var highlightCircleFillColor: NSUIColor? = NSUIColor.white
/// The stroke color for highlight circle.
/// If `nil`, the color of the dataset is taken.
open var highlightCircleStrokeColor: NSUIColor?
open var highlightCircleStrokeAlpha: CGFloat = 0.3
open var highlightCircleInnerRadius: CGFloat = 3.0
open var highlightCircleOuterRadius: CGFloat = 4.0
open var highlightCircleStrokeWidth: CGFloat = 2.0
}
//
// ScatterChartData.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class ScatterChartData: BarLineScatterCandleBubbleChartData
{
public override init()
{
super.init()
}
public override init(dataSets: [IChartDataSet]?)
{
super.init(dataSets: dataSets)
}
/// - Returns: The maximum shape-size across all DataSets.
@objc open func getGreatestShapeSize() -> CGFloat
{
return (_dataSets as? [IScatterChartDataSet])?
.max { $0.scatterShapeSize < $1.scatterShapeSize }?
.scatterShapeSize ?? 0
}
}
//
// ScatterChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
open class ScatterChartDataSet: LineScatterCandleRadarChartDataSet, IScatterChartDataSet
{
@objc(ScatterShape)
public enum Shape: Int
{
case square
case circle
case triangle
case cross
case x
case chevronUp
case chevronDown
}
/// The size the scatter shape will have
open var scatterShapeSize = CGFloat(10.0)
/// The radius of the hole in the shape (applies to Square, Circle and Triangle)
/// **default**: 0.0
open var scatterShapeHoleRadius: CGFloat = 0.0
/// Color for the hole in the shape. Setting to `nil` will behave as transparent.
/// **default**: nil
open var scatterShapeHoleColor: NSUIColor? = nil
/// Sets the ScatterShape this DataSet should be drawn with.
/// This will search for an available IShapeRenderer and set this renderer for the DataSet
@objc open func setScatterShape(_ shape: Shape)
{
self.shapeRenderer = ScatterChartDataSet.renderer(forShape: shape)
}
/// The IShapeRenderer responsible for rendering this DataSet.
/// This can also be used to set a custom IShapeRenderer aside from the default ones.
/// **default**: `SquareShapeRenderer`
open var shapeRenderer: IShapeRenderer? = SquareShapeRenderer()
@objc open class func renderer(forShape shape: Shape) -> IShapeRenderer
{
switch shape
{
case .square: return SquareShapeRenderer()
case .circle: return CircleShapeRenderer()
case .triangle: return TriangleShapeRenderer()
case .cross: return CrossShapeRenderer()
case .x: return XShapeRenderer()
case .chevronUp: return ChevronUpShapeRenderer()
case .chevronDown: return ChevronDownShapeRenderer()
}
}
// MARK: NSCopying
open override func copy(with zone: NSZone? = nil) -> Any
{
let copy = super.copy(with: zone) as! ScatterChartDataSet
copy.scatterShapeSize = scatterShapeSize
copy.scatterShapeHoleRadius = scatterShapeHoleRadius
copy.scatterShapeHoleColor = scatterShapeHoleColor
copy.shapeRenderer = shapeRenderer
return copy
}
}
//
// IBarChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
@objc
public protocol IBarChartDataSet: IBarLineScatterCandleBubbleChartDataSet
{
// MARK: - Data functions and accessors
// MARK: - Styling functions and accessors
/// `true` if this DataSet is stacked (stacksize > 1) or not.
var isStacked: Bool { get }
/// The maximum number of bars that can be stacked upon another in this DataSet.
var stackSize: Int { get }
/// the color used for drawing the bar-shadows. The bar shadows is a surface behind the bar that indicates the maximum value
var barShadowColor: NSUIColor { get set }
/// the width used for drawing borders around the bars. If borderWidth == 0, no border will be drawn.
var barBorderWidth : CGFloat { get set }
/// the color drawing borders around the bars.
var barBorderColor: NSUIColor { get set }
/// the alpha value (transparency) that is used for drawing the highlight indicator bar. min = 0.0 (fully transparent), max = 1.0 (fully opaque)
var highlightAlpha: CGFloat { get set }
/// array of labels used to describe the different values of the stacked bars
var stackLabels: [String] { get set }
}
//
// IBarLineScatterCandleBubbleChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
@objc
public protocol IBarLineScatterCandleBubbleChartDataSet: IChartDataSet
{
// MARK: - Data functions and accessors
// MARK: - Styling functions and accessors
var highlightColor: NSUIColor { get set }
var highlightLineWidth: CGFloat { get set }
var highlightLineDashPhase: CGFloat { get set }
var highlightLineDashLengths: [CGFloat]? { get set }
}
//
// IBubbleChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
@objc
public protocol IBubbleChartDataSet: IBarLineScatterCandleBubbleChartDataSet
{
// MARK: - Data functions and accessors
var maxSize: CGFloat { get }
var isNormalizeSizeEnabled: Bool { get }
// MARK: - Styling functions and accessors
/// Sets/gets the width of the circle that surrounds the bubble when highlighted
var highlightCircleWidth: CGFloat { get set }
}
//
// ICandleChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
@objc
public protocol ICandleChartDataSet: ILineScatterCandleRadarChartDataSet
{
// MARK: - Data functions and accessors
// MARK: - Styling functions and accessors
/// the space that is left out on the left and right side of each candle,
/// **default**: 0.1 (10%), max 0.45, min 0.0
var barSpace: CGFloat { get set }
/// should the candle bars show?
/// when false, only "ticks" will show
///
/// **default**: true
var showCandleBar: Bool { get set }
/// the width of the candle-shadow-line in pixels.
///
/// **default**: 3.0
var shadowWidth: CGFloat { get set }
/// the color of the shadow line
var shadowColor: NSUIColor? { get set }
/// use candle color for the shadow
var shadowColorSameAsCandle: Bool { get set }
/// Is the shadow color same as the candle color?
var isShadowColorSameAsCandle: Bool { get }
/// color for open == close
var neutralColor: NSUIColor? { get set }
/// color for open > close
var increasingColor: NSUIColor? { get set }
/// color for open < close
var decreasingColor: NSUIColor? { get set }
/// Are increasing values drawn as filled?
var increasingFilled: Bool { get set }
/// Are increasing values drawn as filled?
var isIncreasingFilled: Bool { get }
/// Are decreasing values drawn as filled?
var decreasingFilled: Bool { get set }
/// Are decreasing values drawn as filled?
var isDecreasingFilled: Bool { get }
}
//
// ILineChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
@objc
public protocol ILineChartDataSet: ILineRadarChartDataSet
{
// MARK: - Data functions and accessors
// MARK: - Styling functions and accessors
/// The drawing mode for this line dataset
///
/// **default**: Linear
var mode: LineChartDataSet.Mode { get set }
/// Intensity for cubic lines (min = 0.05, max = 1)
///
/// **default**: 0.2
var cubicIntensity: CGFloat { get set }
/// The radius of the drawn circles.
var circleRadius: CGFloat { get set }
/// The hole radius of the drawn circles.
var circleHoleRadius: CGFloat { get set }
var circleColors: [NSUIColor] { get set }
/// - Returns: The color at the given index of the DataSet's circle-color array.
/// Performs a IndexOutOfBounds check by modulus.
func getCircleColor(atIndex: Int) -> NSUIColor?
/// Sets the one and ONLY color that should be used for this DataSet.
/// Internally, this recreates the colors array and adds the specified color.
func setCircleColor(_ color: NSUIColor)
/// Resets the circle-colors array and creates a new one
func resetCircleColors(_ index: Int)
/// If true, drawing circles is enabled
var drawCirclesEnabled: Bool { get set }
/// `true` if drawing circles for this DataSet is enabled, `false` ifnot
var isDrawCirclesEnabled: Bool { get }
/// The color of the inner circle (the circle-hole).
var circleHoleColor: NSUIColor? { get set }
/// `true` if drawing circles for this DataSet is enabled, `false` ifnot
var drawCircleHoleEnabled: Bool { get set }
/// `true` if drawing the circle-holes is enabled, `false` ifnot.
var isDrawCircleHoleEnabled: Bool { get }
/// This is how much (in pixels) into the dash pattern are we starting from.
var lineDashPhase: CGFloat { get }
/// This is the actual dash pattern.
/// I.e. [2, 3] will paint [-- -- ]
/// [1, 3, 4, 2] will paint [- ---- - ---- ]
var lineDashLengths: [CGFloat]? { get set }
/// Line cap type, default is CGLineCap.Butt
var lineCapType: CGLineCap { get set }
/// Sets a custom IFillFormatter to the chart that handles the position of the filled-line for each DataSet. Set this to null to use the default logic.
var fillFormatter: IFillFormatter? { get set }
}
//
// ILineRadarChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
import CoreGraphics
@objc
public protocol ILineRadarChartDataSet: ILineScatterCandleRadarChartDataSet
{
// MARK: - Data functions and accessors
// MARK: - Styling functions and accessors
/// The color that is used for filling the line surface area.
var fillColor: NSUIColor { get set }
/// - Returns: The object that is used for filling the area below the line.
/// **default**: nil
var fill: Fill? { get set }
/// The alpha value that is used for filling the line surface.
/// **default**: 0.33
var fillAlpha: CGFloat { get set }
/// line width of the chart (min = 0.0, max = 10)
///
/// **default**: 1
var lineWidth: CGFloat { get set }
/// Set to `true` if the DataSet should be drawn filled (surface), and not just as a line.
/// Disabling this will give great performance boost.
/// Please note that this method uses the path clipping for drawing the filled area (with images, gradients and layers).
var drawFilledEnabled: Bool { get set }
/// `true` if filled drawing is enabled, `false` if not
var isDrawFilledEnabled: Bool { get }
}
//
// ILineScatterCandleRadarChartDataSet.swift
// Charts
//
// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
// A port of MPAndroidChart for iOS
// Licensed under Apache License 2.0
//
// https://github.com/danielgindi/Charts
//
import Foundation
@objc
public protocol ILineScatterCandleRadarChartDataSet: IBarLineScatterCandleBubbleChartDataSet
{
// MARK: - Data functions and accessors
// MARK: - Styling functions and accessors
/// Enables / disables the horizontal highlight-indicator. If disabled, the indicator is not drawn.
var drawHorizontalHighlightIndicatorEnabled: Bool { get set }
/// Enables / disables the vertical highlight-indicator. If disabled, the indicator is not drawn.
var drawVerticalHighlightIndicatorEnabled: Bool { get set }
/// `true` if horizontal highlight indicator lines are enabled (drawn)
var isHorizontalHighlightIndicatorEnabled: Bool { get }
/// `true` if vertical highlight indicator lines are enabled (drawn)
var isVerticalHighlightIndicatorEnabled: Bool { get }
/// Enables / disables both vertical and horizontal highlight-indicators.
/// :param: enabled
func setDrawHighlightIndicators(_ enabled: Bool)
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment